refactor: user manage add filter

This commit is contained in:
wxg0103 2025-06-25 18:39:06 +08:00
parent a26c4320dd
commit c4bf19c92b
4 changed files with 123 additions and 71 deletions

View File

@ -1,8 +1,9 @@
import { Result } from '@/request/Result' import {Result} from '@/request/Result'
import { get, put, post, del } from '@/request/index' import {get, put, post, del} from '@/request/index'
import type { pageRequest, PageList } from '@/api/type/common' import type {pageRequest, PageList} from '@/api/type/common'
import type { ChatUserItem } from '@/api/type/systemChatUser' import type {ChatUserItem} from '@/api/type/systemChatUser'
import type { Ref } from 'vue' import type {Ref} from 'vue'
const prefix = '/system/chat_user' const prefix = '/system/chat_user'
@ -20,12 +21,12 @@ const getChatUserList: (loading?: Ref<boolean>) => Promise<Result<ChatUserItem[]
*/ */
const getUserManage: ( const getUserManage: (
page: pageRequest, page: pageRequest,
username_or_nickname: string, params?: any,
loading?: Ref<boolean>, loading?: Ref<boolean>,
) => Promise<Result<PageList<ChatUserItem[]>>> = (page, username_or_nickname, loading) => { ) => Promise<Result<PageList<ChatUserItem[]>>> = (page, params, loading) => {
return get( return get(
`${prefix}/user_manage/${page.current_page}/${page.page_size}`, `${prefix}/user_manage/${page.current_page}/${page.page_size}`,
username_or_nickname ? { username_or_nickname } : undefined, params ? params : undefined,
loading, loading,
) )
} }

View File

@ -12,12 +12,12 @@ const prefix = '/user_manage'
*/ */
const getUserManage: ( const getUserManage: (
page: pageRequest, page: pageRequest,
email_or_username: string, params?: any,
loading?: Ref<boolean>, loading?: Ref<boolean>,
) => Promise<Result<any>> = (page, email_or_username, loading) => { ) => Promise<Result<any>> = (page, params, loading) => {
return get( return get(
`${prefix}/${page.current_page}/${page.page_size}`, `${prefix}/${page.current_page}/${page.page_size}`,
email_or_username ? {email_or_username} : undefined, params ? params : undefined,
loading, loading,
) )
} }

View File

@ -38,23 +38,31 @@
<div class="flex-between complex-search"> <div class="flex-between complex-search">
<el-select class="complex-search__left" v-model="search_type" style="width: 120px" <el-select class="complex-search__left" v-model="search_type" style="width: 120px"
@change="search_type_change"> @change="search_type_change">
<el-option :label="$t('views.login.loginForm.username.label')" value="name" /> <el-option :label="$t('views.login.loginForm.username.label')" value="username"/>
<el-option :label="$t('views.userManage.userForm.nick_name.label')"
value="nick_name"/>
</el-select> </el-select>
<el-input v-if="search_type === 'name'" v-model="search_form.name" @change="getList" <el-input v-if="search_type === 'username'" v-model="search_form.username"
:placeholder="$t('common.searchBar.placeholder')" style="width: 220px" clearable /> @change="getList"
style="width: 220px"
clearable/>
<el-input v-if="search_type === 'nick_name'" v-model="search_form.nick_name"
@change="getList"
style="width: 220px" clearable/>
</div> </div>
</div> </div>
<app-table class="mt-16" :data="userTableData" :pagination-config="paginationConfig" <app-table class="mt-16" :data="userTableData" :pagination-config="paginationConfig"
@sizeChange="handleSizeChange" @changePage="getList" v-loading="loading" @sizeChange="handleSizeChange" @changePage="getList" v-loading="loading"
@selection-change="handleSelectionChange" @sort-change="handleSortChange"> @selection-change="handleSelectionChange" @sort-change="handleSortChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55"/>
<el-table-column prop="nick_name" :label="$t('views.userManage.userForm.nick_name.label')" /> <el-table-column prop="nick_name"
<el-table-column prop="username" :label="$t('common.username')" /> :label="$t('views.userManage.userForm.nick_name.label')"/>
<el-table-column prop="username" :label="$t('common.username')"/>
<el-table-column prop="is_active" :label="$t('common.status.label')"> <el-table-column prop="is_active" :label="$t('common.status.label')">
<template #default="{ row }"> <template #default="{ row }">
<div v-if="row.is_active" class="flex align-center"> <div v-if="row.is_active" class="flex align-center">
<el-icon class="color-success mr-8" style="font-size: 16px"> <el-icon class="color-success mr-8" style="font-size: 16px">
<SuccessFilled /> <SuccessFilled/>
</el-icon> </el-icon>
<span class="color-secondary"> <span class="color-secondary">
{{ $t('common.status.enabled') }} {{ $t('common.status.enabled') }}
@ -69,7 +77,8 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="email" :label="$t('views.login.loginForm.email.label')" show-overflow-tooltip> <el-table-column prop="email" :label="$t('views.login.loginForm.email.label')"
show-overflow-tooltip>
<template #default="{ row }"> <template #default="{ row }">
{{ row.email || '-' }} {{ row.email || '-' }}
</template> </template>
@ -79,9 +88,10 @@
{{ row.phone || '-' }} {{ row.phone || '-' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="user_group_names" :label="$t('views.chatUser.group.title')" min-width="100"> <el-table-column prop="user_group_names" :label="$t('views.chatUser.group.title')"
min-width="100">
<template #default="{ row }"> <template #default="{ row }">
<TagGroup :tags="row.user_group_names" /> <TagGroup :tags="row.user_group_names"/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="source" :label="$t('views.userManage.source.label')"> <el-table-column prop="source" :label="$t('views.userManage.source.label')">
@ -111,16 +121,18 @@
<el-table-column :label="$t('common.operation')" width="160" align="left" fixed="right"> <el-table-column :label="$t('common.operation')" width="160" align="left" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<span @click.stop> <span @click.stop>
<el-switch size="small" v-model="row.is_active" :before-change="() => changeState(row)" /> <el-switch size="small" v-model="row.is_active"
:before-change="() => changeState(row)"/>
</span> </span>
<el-divider direction="vertical" /> <el-divider direction="vertical"/>
<span class="mr-8"> <span class="mr-8">
<el-button type="primary" text @click.stop="editUser(row)" :title="$t('common.edit')" <el-button type="primary" text @click.stop="editUser(row)"
:title="$t('common.edit')"
v-hasPermission="new ComplexPermission([RoleConst.ADMIN, RoleConst.WORKSPACE_MANAGE.getWorkspaceRole, RoleConst.USER.getWorkspaceRole,], v-hasPermission="new ComplexPermission([RoleConst.ADMIN, RoleConst.WORKSPACE_MANAGE.getWorkspaceRole, RoleConst.USER.getWorkspaceRole,],
[PermissionConst.WORKSPACE_CHAT_USER_EDIT.getWorkspacePermission],[],'OR')" [PermissionConst.WORKSPACE_CHAT_USER_EDIT.getWorkspacePermission],[],'OR')"
> >
<el-icon> <el-icon>
<EditPen /> <EditPen/>
</el-icon> </el-icon>
</el-button> </el-button>
</span> </span>
@ -132,18 +144,19 @@
[PermissionConst.WORKSPACE_CHAT_USER_EDIT.getWorkspacePermission],[],'OR')" [PermissionConst.WORKSPACE_CHAT_USER_EDIT.getWorkspacePermission],[],'OR')"
> >
<el-icon> <el-icon>
<Lock /> <Lock/>
</el-icon> </el-icon>
</el-button> </el-button>
</span> </span>
<span> <span>
<el-button :disabled="row.role === 'ADMIN'" type="primary" text @click.stop="deleteUserManage(row)" <el-button :disabled="row.role === 'ADMIN'" type="primary" text
@click.stop="deleteUserManage(row)"
:title="$t('common.delete')" :title="$t('common.delete')"
v-hasPermission="new ComplexPermission([RoleConst.ADMIN, RoleConst.WORKSPACE_MANAGE.getWorkspaceRole, RoleConst.USER.getWorkspaceRole,], v-hasPermission="new ComplexPermission([RoleConst.ADMIN, RoleConst.WORKSPACE_MANAGE.getWorkspaceRole, RoleConst.USER.getWorkspaceRole,],
[PermissionConst.WORKSPACE_CHAT_USER_DELETE.getWorkspacePermission],[],'OR')" [PermissionConst.WORKSPACE_CHAT_USER_DELETE.getWorkspacePermission],[],'OR')"
> >
<el-icon> <el-icon>
<Delete /> <Delete/>
</el-icon> </el-icon>
</el-button> </el-button>
</span> </span>
@ -153,47 +166,52 @@
</el-card> </el-card>
</ContentContainer> </ContentContainer>
<UserDrawer :title="title" :optionLoading="optionLoading" :chatGroupList="chatGroupList" ref="UserDrawerRef" <UserDrawer :title="title" :optionLoading="optionLoading" :chatGroupList="chatGroupList"
@refresh="refresh" /> ref="UserDrawerRef"
<UserPwdDialog ref="UserPwdDialogRef" @refresh="refresh" /> @refresh="refresh"/>
<SetUserGroupsDialog :optionLoading="optionLoading" :chatGroupList="chatGroupList" ref="setUserGroupsRef" <UserPwdDialog ref="UserPwdDialogRef" @refresh="refresh"/>
@refresh="refresh" /> <SetUserGroupsDialog :optionLoading="optionLoading" :chatGroupList="chatGroupList"
<SyncUsersDialog ref="syncUsersDialogRef" @refresh="refresh" /> ref="setUserGroupsRef"
@refresh="refresh"/>
<SyncUsersDialog ref="syncUsersDialogRef" @refresh="refresh"/>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onMounted, ref, reactive } from 'vue' import {onMounted, ref, reactive} from 'vue'
import UserDrawer from './component/UserDrawer.vue' import UserDrawer from './component/UserDrawer.vue'
import UserPwdDialog from './component/UserPwdDialog.vue' import UserPwdDialog from './component/UserPwdDialog.vue'
import SetUserGroupsDialog from './component/SetUserGroupsDialog.vue' import SetUserGroupsDialog from './component/SetUserGroupsDialog.vue'
import SyncUsersDialog from './component/SyncUsersDialog.vue' import SyncUsersDialog from './component/SyncUsersDialog.vue'
import userManageApi from '@/api/system/chat-user' import userManageApi from '@/api/system/chat-user'
import { datetimeFormat } from '@/utils/time' import {datetimeFormat} from '@/utils/time'
import { MsgSuccess, MsgConfirm } from '@/utils/message' import {MsgSuccess, MsgConfirm} from '@/utils/message'
import { t } from '@/locales' import {t} from '@/locales'
import iconMap from '@/components/app-icon/icons/common' import iconMap from '@/components/app-icon/icons/common'
import type { ChatUserItem } from '@/api/type/systemChatUser' import type {ChatUserItem} from '@/api/type/systemChatUser'
import SystemGroupApi from '@/api/system/user-group' import SystemGroupApi from '@/api/system/user-group'
import type { ListItem } from '@/api/type/common' import type {ListItem} from '@/api/type/common'
import { PermissionConst, RoleConst } from '@/utils/permission/data' import {PermissionConst, RoleConst} from '@/utils/permission/data'
import { ComplexPermission } from '@/utils/permission/type' import {ComplexPermission} from '@/utils/permission/type'
const rightOutlined = iconMap['right-outlined'].iconReader() const rightOutlined = iconMap['right-outlined'].iconReader()
const search_type = ref('name') const search_type = ref('name')
const search_form = ref<{ const search_form = ref<{
name: string username: string,
nick_name?: string,
}>({ }>({
name: '', username: '',
nick_name: '',
}) })
const search_type_change = () => { const search_type_change = () => {
search_form.value = { name: '' } search_form.value = {username: '', nick_name: ''}
} }
const loading = ref(false) const loading = ref(false)
const multipleSelection = ref<any[]>([]) const multipleSelection = ref<any[]>([])
function handleSelectionChange(val: any[]) { function handleSelectionChange(val: any[]) {
multipleSelection.value = val multipleSelection.value = val
} }
@ -207,8 +225,11 @@ const paginationConfig = reactive({
const userTableData = ref<ChatUserItem[]>([]) const userTableData = ref<ChatUserItem[]>([])
function getList() { function getList() {
const params = {
[search_type.value]: search_form.value[search_type.value as keyof typeof search_form.value],
}
return userManageApi return userManageApi
.getUserManage(paginationConfig, search_form.value.name, loading) .getUserManage(paginationConfig, params, loading)
.then((res) => { .then((res) => {
userTableData.value = res.data.records userTableData.value = res.data.records
paginationConfig.total = res.data.total paginationConfig.total = res.data.total
@ -216,7 +237,8 @@ function getList() {
} }
const orderBy = ref<string>('') const orderBy = ref<string>('')
function handleSortChange({ prop, order }: { prop: string; order: string }) {
function handleSortChange({prop, order}: { prop: string; order: string }) {
orderBy.value = order === 'ascending' ? prop : `-${prop}` orderBy.value = order === 'ascending' ? prop : `-${prop}`
getList() getList()
} }
@ -246,6 +268,7 @@ function changeState(row: ChatUserItem) {
const title = ref('') const title = ref('')
const UserDrawerRef = ref() const UserDrawerRef = ref()
function editUser(row: ChatUserItem) { function editUser(row: ChatUserItem) {
title.value = t('views.userManage.editUser') title.value = t('views.userManage.editUser')
UserDrawerRef.value.open(row) UserDrawerRef.value.open(row)
@ -277,6 +300,7 @@ function deleteUserManage(row: ChatUserItem) {
} }
const UserPwdDialogRef = ref() const UserPwdDialogRef = ref()
function editPwdUser(row: ChatUserItem) { function editPwdUser(row: ChatUserItem) {
UserPwdDialogRef.value.open(row) UserPwdDialogRef.value.open(row)
} }
@ -292,6 +316,7 @@ onMounted(() => {
const optionLoading = ref(false) const optionLoading = ref(false)
const chatGroupList = ref<ListItem[]>([]) const chatGroupList = ref<ListItem[]>([])
async function getChatGroupList() { async function getChatGroupList() {
try { try {
const res = await SystemGroupApi.getUserGroup(optionLoading) const res = await SystemGroupApi.getUserGroup(optionLoading)
@ -303,7 +328,7 @@ async function getChatGroupList() {
function handleBatchDelete() { function handleBatchDelete() {
MsgConfirm( MsgConfirm(
t('views.chatUser.batchDeleteUser', { count: multipleSelection.value.length }), t('views.chatUser.batchDeleteUser', {count: multipleSelection.value.length}),
'', '',
{ {
confirmButtonText: t('common.confirm'), confirmButtonText: t('common.confirm'),
@ -321,11 +346,13 @@ function handleBatchDelete() {
} }
const setUserGroupsRef = ref<InstanceType<typeof SetUserGroupsDialog>>() const setUserGroupsRef = ref<InstanceType<typeof SetUserGroupsDialog>>()
function setUserGroups() { function setUserGroups() {
setUserGroupsRef.value?.open(multipleSelection.value.map(item => (item.id))) setUserGroupsRef.value?.open(multipleSelection.value.map(item => (item.id)))
} }
const syncUsersDialogRef = ref<InstanceType<typeof SyncUsersDialog>>() const syncUsersDialogRef = ref<InstanceType<typeof SyncUsersDialog>>()
function syncUsers() { function syncUsers() {
syncUsersDialogRef.value?.open() syncUsersDialogRef.value?.open()
} }

View File

@ -14,13 +14,28 @@
style="width: 120px" style="width: 120px"
@change="search_type_change" @change="search_type_change"
> >
<el-option :label="$t('views.login.loginForm.username.label')" value="name"/> <el-option :label="$t('views.login.loginForm.username.label')" value="username"/>
<el-option :label="$t('views.userManage.userForm.nick_name.label')" value="nick_name"/>
<el-option :label="$t('views.login.loginForm.email.label')" value="email"/>
</el-select> </el-select>
<el-input <el-input
v-if="search_type === 'name'" v-if="search_type === 'username'"
v-model="search_form.name" v-model="search_form.username"
@change="getList"
style="width: 220px"
clearable
/>
<el-input
v-else-if="search_type === 'nick_name'"
v-model="search_form.nick_name"
@change="getList"
style="width: 220px"
clearable
/>
<el-input
v-else-if="search_type === 'email'"
v-model="search_form.email"
@change="getList" @change="getList"
:placeholder="$t('common.searchBar.placeholder')"
style="width: 220px" style="width: 220px"
clearable clearable
/> />
@ -71,7 +86,8 @@
{{ row.phone || '-' }} {{ row.phone || '-' }}
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="role" :label="$t('views.role.member.role')" min-width="100" v-if="user.isEE()"> <el-table-column prop="role" :label="$t('views.role.member.role')" min-width="100"
v-if="user.isEE()">
<template #default="{ row }"> <template #default="{ row }">
<TagGroup :tags="row.role"/> <TagGroup :tags="row.role"/>
</template> </template>
@ -157,12 +173,17 @@ import {MsgSuccess, MsgConfirm} from '@/utils/message'
import {t} from '@/locales' import {t} from '@/locales'
import {ValidCount, ValidType} from "@/enums/common.ts"; import {ValidCount, ValidType} from "@/enums/common.ts";
import useStore from "@/stores"; import useStore from "@/stores";
const {user, common} = useStore() const {user, common} = useStore()
const search_type = ref('name') const search_type = ref('username')
const search_form = ref<{ const search_form = ref<{
name: string username: string,
nick_name?: string,
email?: string
}>({ }>({
name: '', username: '',
nick_name: '',
email: ''
}) })
const UserDrawerRef = ref() const UserDrawerRef = ref()
@ -178,7 +199,7 @@ const paginationConfig = reactive({
const userTableData = ref<any[]>([]) const userTableData = ref<any[]>([])
const search_type_change = () => { const search_type_change = () => {
search_form.value = {name: ''} search_form.value = {username: '', nick_name: '', email: ''}
} }
function handleSizeChange() { function handleSizeChange() {
@ -187,8 +208,11 @@ function handleSizeChange() {
} }
function getList() { function getList() {
const params = {
[search_type.value]: search_form.value[search_type.value as keyof typeof search_form.value],
}
return userManageApi return userManageApi
.getUserManage(paginationConfig, search_form.value.name, loading) .getUserManage(paginationConfig, params, loading)
.then((res) => { .then((res) => {
userTableData.value = res.data.records userTableData.value = res.data.records
paginationConfig.total = res.data.total paginationConfig.total = res.data.total