mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 22:57:17 +08:00 
			
		
		
		
	新增:新增系统管理/用户管理(列表、查看详情、新增、修改、删除、导出)
This commit is contained in:
		
							
								
								
									
										1
									
								
								continew-admin-ui/components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								continew-admin-ui/components.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -75,6 +75,7 @@ declare module '@vue/runtime-core' { | ||||
|     ATag: typeof import('@arco-design/web-vue')['Tag'] | ||||
|     ATextarea: typeof import('@arco-design/web-vue')['Textarea'] | ||||
|     ATooltip: typeof import('@arco-design/web-vue')['Tooltip'] | ||||
|     ATree: typeof import('@arco-design/web-vue')['Tree'] | ||||
|     ATreeSelect: typeof import('@arco-design/web-vue')['TreeSelect'] | ||||
|     ATypographyParagraph: typeof import('@arco-design/web-vue')['TypographyParagraph'] | ||||
|     ATypographyText: typeof import('@arco-design/web-vue')['TypographyText'] | ||||
|   | ||||
| @@ -2,6 +2,7 @@ import axios from 'axios'; | ||||
| import qs from 'query-string'; | ||||
| import { DeptParam } from '@/api/system/dept'; | ||||
| import { MenuParam } from '@/api/system/menu'; | ||||
| import { RoleParam } from '@/api/system/role'; | ||||
| import { TreeNodeData } from '@arco-design/web-vue'; | ||||
|  | ||||
| export function listDeptTree(params: DeptParam) { | ||||
| @@ -21,3 +22,12 @@ export function listMenuTree(params: MenuParam) { | ||||
|     }, | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function listRoleTree(params: RoleParam) { | ||||
|   return axios.get<TreeNodeData[]>('/common/tree/role', { | ||||
|     params, | ||||
|     paramsSerializer: (obj) => { | ||||
|       return qs.stringify(obj); | ||||
|     }, | ||||
|   }); | ||||
| } | ||||
|   | ||||
| @@ -36,7 +36,7 @@ export function getDept(id: number) { | ||||
|   return axios.get<DeptRecord>(`${BASE_URL}/${id}`); | ||||
| } | ||||
|  | ||||
| export function createDept(req: DeptRecord) { | ||||
| export function addDept(req: DeptRecord) { | ||||
|   return axios.post(BASE_URL, req); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -44,7 +44,7 @@ export function getMenu(id: number) { | ||||
|   return axios.get<MenuRecord>(`${BASE_URL}/${id}`); | ||||
| } | ||||
|  | ||||
| export function createMenu(req: MenuRecord) { | ||||
| export function addMenu(req: MenuRecord) { | ||||
|   return axios.post(BASE_URL, req); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -23,9 +23,9 @@ export interface RoleRecord { | ||||
| export interface RoleParam { | ||||
|   roleName?: string; | ||||
|   status?: number; | ||||
|   page: number; | ||||
|   size: number; | ||||
|   sort: Array<string>; | ||||
|   page?: number; | ||||
|   size?: number; | ||||
|   sort?: Array<string>; | ||||
| } | ||||
|  | ||||
| export interface RoleListRes { | ||||
| @@ -46,7 +46,7 @@ export function getRole(id: number) { | ||||
|   return axios.get<RoleRecord>(`${BASE_URL}/${id}`); | ||||
| } | ||||
|  | ||||
| export function createRole(req: RoleRecord) { | ||||
| export function addRole(req: RoleRecord) { | ||||
|   return axios.post(BASE_URL, req); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										63
									
								
								continew-admin-ui/src/api/system/user.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								continew-admin-ui/src/api/system/user.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| import axios from 'axios'; | ||||
| import qs from 'query-string'; | ||||
|  | ||||
| const BASE_URL = '/system/user'; | ||||
|  | ||||
| export interface UserRecord { | ||||
|   userId?: number; | ||||
|   username: string; | ||||
|   nickname: string; | ||||
|   gender: number; | ||||
|   email?: string; | ||||
|   phone?: string; | ||||
|   description?: string; | ||||
|   roleIds?: Array<number>; | ||||
|   deptId?: number; | ||||
|   status?: number; | ||||
|   createUserString?: string; | ||||
|   createTime?: string; | ||||
|   updateUserString?: string; | ||||
|   updateTime?: string; | ||||
|   deptName?: string; | ||||
|   roleNames?: Array<string>; | ||||
|   disabled?: boolean; | ||||
| } | ||||
|  | ||||
| export interface UserParam { | ||||
|   username?: string; | ||||
|   status?: number; | ||||
|   createTime?: Array<string>; | ||||
|   page?: number; | ||||
|   size?: number; | ||||
|   sort?: Array<string>; | ||||
| } | ||||
|  | ||||
| export interface UserListRes { | ||||
|   list: UserRecord[]; | ||||
|   total: number; | ||||
| } | ||||
|  | ||||
| export function listUser(params: UserParam) { | ||||
|   return axios.get<UserListRes>(`${BASE_URL}`, { | ||||
|     params, | ||||
|     paramsSerializer: (obj) => { | ||||
|       return qs.stringify(obj); | ||||
|     }, | ||||
|   }); | ||||
| } | ||||
|  | ||||
| export function getUser(id: number) { | ||||
|   return axios.get<UserRecord>(`${BASE_URL}/${id}`); | ||||
| } | ||||
|  | ||||
| export function addUser(req: UserRecord) { | ||||
|   return axios.post(BASE_URL, req); | ||||
| } | ||||
|  | ||||
| export function updateUser(req: UserRecord) { | ||||
|   return axios.put(BASE_URL, req); | ||||
| } | ||||
|  | ||||
| export function deleteUser(ids: number | Array<number>) { | ||||
|   return axios.delete(`${BASE_URL}/${ids}`); | ||||
| } | ||||
| @@ -147,7 +147,7 @@ | ||||
|             :size="32" | ||||
|             :style="{ marginRight: '8px', cursor: 'pointer' }" | ||||
|           > | ||||
|             <img alt="avatar" :src="getAvatar(loginStore)" /> | ||||
|             <img alt="avatar" :src="getAvatar(loginStore.avatar, loginStore.gender)" /> | ||||
|           </a-avatar> | ||||
|           <template #content> | ||||
|             <a-doption> | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import localeWorkplace from '@/views/dashboard/workplace/locale/en-US'; | ||||
|  | ||||
| import localeUser from '@/views/system/user/locale/en-US'; | ||||
| import localeRole from '@/views/system/role/locale/en-US'; | ||||
| import localeMenu from '@/views/system/menu/locale/en-US'; | ||||
| import localeDept from '@/views/system/dept/locale/en-US'; | ||||
| @@ -50,6 +51,7 @@ export default { | ||||
|  | ||||
|   ...localeWorkplace, | ||||
|  | ||||
|   ...localeUser, | ||||
|   ...localeRole, | ||||
|   ...localeMenu, | ||||
|   ...localeDept, | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| import localeWorkplace from '@/views/dashboard/workplace/locale/zh-CN'; | ||||
|  | ||||
| import localeUser from '@/views/system/user/locale/zh-CN'; | ||||
| import localeRole from '@/views/system/role/locale/zh-CN'; | ||||
| import localeMenu from '@/views/system/menu/locale/zh-CN'; | ||||
| import localeDept from '@/views/system/dept/locale/zh-CN'; | ||||
| @@ -50,6 +51,7 @@ export default { | ||||
|  | ||||
|   ...localeWorkplace, | ||||
|  | ||||
|   ...localeUser, | ||||
|   ...localeRole, | ||||
|   ...localeMenu, | ||||
|   ...localeDept, | ||||
|   | ||||
| @@ -12,6 +12,16 @@ const System: AppRouteRecordRaw = { | ||||
|     order: 1, | ||||
|   }, | ||||
|   children: [ | ||||
|     { | ||||
|       path: '/system/user', | ||||
|       name: 'User', | ||||
|       component: () => import('@/views/system/user/index.vue'), | ||||
|       meta: { | ||||
|         locale: 'menu.system.user.list', | ||||
|         requiresAuth: true, | ||||
|         roles: ['*'], | ||||
|       }, | ||||
|     }, | ||||
|     { | ||||
|       path: '/system/role', | ||||
|       name: 'Role', | ||||
|   | ||||
| @@ -1,20 +1,17 @@ | ||||
| import { UserState } from '@/store/modules/login/types'; | ||||
| import Unknown from '../assets/images/avatar/unknown.png'; | ||||
| import Male from '../assets/images/avatar/male.png'; | ||||
| import Female from '../assets/images/avatar/female.png'; | ||||
|  | ||||
| export default function getAvatar(loginStore: UserState) { | ||||
|   const userAvatar = loginStore.avatar; | ||||
|   if (userAvatar) { | ||||
| export default function getAvatar(avatar: string | undefined, gender: number | undefined) { | ||||
|   if (avatar) { | ||||
|     const baseUrl = import.meta.env.VITE_API_BASE_URL; | ||||
|     return `${baseUrl}/avatar/${userAvatar}`; | ||||
|     return `${baseUrl}/avatar/${avatar}`; | ||||
|   } | ||||
|  | ||||
|   const userGender = loginStore.gender; | ||||
|   if (userGender === 1) { | ||||
|   if (gender === 1) { | ||||
|     return Male; | ||||
|   } | ||||
|   if (userGender === 2) { | ||||
|   if (gender === 2) { | ||||
|     return Female; | ||||
|   } | ||||
|   return Unknown; | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
|         <div v-if="userInfo"> | ||||
|           <a-space :size="12"> | ||||
|             <a-avatar :size="24"> | ||||
|               <img :src="getAvatar(userInfo)" /> | ||||
|               <img :src="getAvatar(userInfo.avatar, userInfo.gender)" /> | ||||
|             </a-avatar> | ||||
|             <a-typography-text> | ||||
|               {{ userInfo.nickname }} {{ $t('monitor.studioPreview.studio') }} | ||||
|   | ||||
| @@ -89,7 +89,7 @@ | ||||
|       <a-drawer | ||||
|         title="日志详情" | ||||
|         :visible="visible" | ||||
|         :width="570" | ||||
|         :width="580" | ||||
|         :footer="false" | ||||
|         unmount-on-close | ||||
|         render-to-body | ||||
| @@ -233,7 +233,7 @@ | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
|   import { getCurrentInstance, ref, toRefs, reactive, } from 'vue'; | ||||
|   import { getCurrentInstance, ref, toRefs, reactive } from 'vue'; | ||||
|   import { | ||||
|     SystemLogParam, | ||||
|     SystemLogRecord, | ||||
| @@ -245,7 +245,7 @@ | ||||
|   import 'vue-json-pretty/lib/styles.css'; | ||||
|  | ||||
|   const { proxy } = getCurrentInstance() as any; | ||||
|    | ||||
|  | ||||
|   const systemLogList = ref<SystemLogRecord[]>([]); | ||||
|   const systemLog = ref<SystemLogDetailRecord>({ | ||||
|     requestUrl: '', | ||||
|   | ||||
| @@ -210,7 +210,7 @@ | ||||
|       <a-drawer | ||||
|         title="部门详情" | ||||
|         :visible="detailVisible" | ||||
|         :width="570" | ||||
|         :width="580" | ||||
|         :footer="false" | ||||
|         unmount-on-close | ||||
|         render-to-body | ||||
| @@ -292,7 +292,7 @@ | ||||
|     DeptParam, | ||||
|     listDept, | ||||
|     getDept, | ||||
|     createDept, | ||||
|     addDept, | ||||
|     updateDept, | ||||
|     deleteDept, | ||||
|   } from '@/api/system/dept'; | ||||
| @@ -431,7 +431,7 @@ | ||||
|             proxy.$message.success(res.msg); | ||||
|           }); | ||||
|         } else { | ||||
|           createDept(form.value).then((res) => { | ||||
|           addDept(form.value).then((res) => { | ||||
|             handleCancel(); | ||||
|             getList(); | ||||
|             proxy.$message.success(res.msg); | ||||
|   | ||||
| @@ -345,7 +345,7 @@ | ||||
|     MenuParam, | ||||
|     listMenu, | ||||
|     getMenu, | ||||
|     createMenu, | ||||
|     addMenu, | ||||
|     updateMenu, | ||||
|     deleteMenu, | ||||
|   } from '@/api/system/menu'; | ||||
| @@ -482,7 +482,7 @@ | ||||
|             proxy.$message.success(res.msg); | ||||
|           }); | ||||
|         } else { | ||||
|           createMenu(form.value).then((res) => { | ||||
|           addMenu(form.value).then((res) => { | ||||
|             handleCancel(); | ||||
|             getList(); | ||||
|             proxy.$message.success(res.msg); | ||||
|   | ||||
| @@ -181,7 +181,7 @@ | ||||
|       <a-drawer | ||||
|         :title="title" | ||||
|         :visible="visible" | ||||
|         :width="570" | ||||
|         :width="580" | ||||
|         :mask-closable="false" | ||||
|         unmount-on-close | ||||
|         render-to-body | ||||
| @@ -275,7 +275,7 @@ | ||||
|       <a-drawer | ||||
|         title="角色详情" | ||||
|         :visible="detailVisible" | ||||
|         :width="570" | ||||
|         :width="580" | ||||
|         :footer="false" | ||||
|         unmount-on-close | ||||
|         render-to-body | ||||
| @@ -384,7 +384,7 @@ | ||||
|     RoleParam, | ||||
|     listRole, | ||||
|     getRole, | ||||
|     createRole, | ||||
|     addRole, | ||||
|     updateRole, | ||||
|     deleteRole, | ||||
|   } from '@/api/system/role'; | ||||
| @@ -621,7 +621,7 @@ | ||||
|         } else { | ||||
|           form.value.menuIds = getMenuAllCheckedKeys(); | ||||
|           form.value.deptIds = getDeptAllCheckedKeys(); | ||||
|           createRole(form.value).then((res) => { | ||||
|           addRole(form.value).then((res) => { | ||||
|             handleCancel(); | ||||
|             getList(); | ||||
|             proxy.$message.success(res.msg); | ||||
|   | ||||
| @@ -12,7 +12,11 @@ | ||||
|         <template #upload-button> | ||||
|           <a-avatar :size="100" class="info-avatar"> | ||||
|             <template #trigger-icon><icon-camera /></template> | ||||
|             <img v-if="avatarList.length" :src="avatarList[0].url" :alt="$t('userCenter.panel.avatar')" /> | ||||
|             <img | ||||
|               v-if="avatarList.length" | ||||
|               :src="avatarList[0].url" | ||||
|               :alt="$t('userCenter.panel.avatar')" | ||||
|             /> | ||||
|           </a-avatar> | ||||
|         </template> | ||||
|       </a-upload> | ||||
| @@ -32,22 +36,33 @@ | ||||
|         align="right" | ||||
|         layout="inline-horizontal" | ||||
|       > | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.nickname')">{{ loginStore.nickname }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.nickname')">{{ | ||||
|           loginStore.nickname | ||||
|         }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.gender')"> | ||||
|           <div v-if="loginStore.gender === 1"> | ||||
|             {{ $t('userCenter.panel.male') }} | ||||
|             <icon-man style="color: #19BBF1" /> | ||||
|             <icon-man style="color: #19bbf1" /> | ||||
|           </div> | ||||
|           <div v-else-if="loginStore.gender === 2"> | ||||
|             {{ $t('userCenter.panel.female') }} | ||||
|             <icon-woman style="color: #FA7FA9" /> | ||||
|             <icon-woman style="color: #fa7fa9" /> | ||||
|           </div> | ||||
|           <div v-else>{{ $t('userCenter.panel.unknown') }}</div> | ||||
|         </a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.phone')">{{ loginStore.phone }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.email')">{{ loginStore.email }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.deptName')">{{ loginStore.deptName }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.registrationDate')">{{ loginStore.registrationDate }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.phone')">{{ | ||||
|           loginStore.phone | ||||
|         }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.email')">{{ | ||||
|           loginStore.email | ||||
|         }}</a-descriptions-item> | ||||
|         <a-descriptions-item :label="$t('userCenter.panel.label.deptName')">{{ | ||||
|           loginStore.deptName | ||||
|         }}</a-descriptions-item> | ||||
|         <a-descriptions-item | ||||
|           :label="$t('userCenter.panel.label.registrationDate')" | ||||
|           >{{ loginStore.registrationDate }}</a-descriptions-item | ||||
|         > | ||||
|       </a-descriptions> | ||||
|     </a-space> | ||||
|   </a-card> | ||||
| @@ -66,7 +81,7 @@ | ||||
|   const avatar = { | ||||
|     uid: '-2', | ||||
|     name: 'avatar.png', | ||||
|     url: getAvatar(loginStore), | ||||
|     url: getAvatar(loginStore.avatar, loginStore.gender), | ||||
|   }; | ||||
|   const avatarList = ref<FileItem[]>([avatar]); | ||||
|  | ||||
| @@ -88,13 +103,15 @@ | ||||
|       onProgress(20); | ||||
|       const formData = new FormData(); | ||||
|       formData.append(name as string, fileItem.file as Blob); | ||||
|       uploadAvatar(formData).then((res) => { | ||||
|         onSuccess(res); | ||||
|         loginStore.avatar = res.data.avatar; | ||||
|         proxy.$message.success(res.msg); | ||||
|       }).catch((error) => { | ||||
|         onError(error); | ||||
|       }); | ||||
|       uploadAvatar(formData) | ||||
|         .then((res) => { | ||||
|           onSuccess(res); | ||||
|           loginStore.avatar = res.data.avatar; | ||||
|           proxy.$message.success(res.msg); | ||||
|         }) | ||||
|         .catch((error) => { | ||||
|           onError(error); | ||||
|         }); | ||||
|     })(); | ||||
|     return { | ||||
|       abort() { | ||||
| @@ -109,7 +126,10 @@ | ||||
|    * @param fileItemList 文件列表 | ||||
|    * @param currentFile 当前文件 | ||||
|    */ | ||||
|   const handleAvatarChange = (fileItemList: FileItem[], currentFile: FileItem) => { | ||||
|   const handleAvatarChange = ( | ||||
|     fileItemList: FileItem[], | ||||
|     currentFile: FileItem | ||||
|   ) => { | ||||
|     avatarList.value = [currentFile]; | ||||
|   }; | ||||
| </script> | ||||
|   | ||||
							
								
								
									
										804
									
								
								continew-admin-ui/src/views/system/user/index.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										804
									
								
								continew-admin-ui/src/views/system/user/index.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,804 @@ | ||||
| <template> | ||||
|   <div class="app-container"> | ||||
|     <Breadcrumb :items="['menu.system', 'menu.system.user.list']" /> | ||||
|     <a-card class="general-card" :title="$t('menu.system.user.list')"> | ||||
|       <a-row> | ||||
|         <a-col :xs="9" :sm="6" :md="5" :lg="4" :xl="4" style="margin-right: 12px"> | ||||
|           <a-input-search | ||||
|             v-model="deptName" | ||||
|             placeholder="输入部门名称搜索" | ||||
|             style="margin-bottom: 8px; max-width: 240px" | ||||
|             allow-clear | ||||
|           /> | ||||
|           <a-tree | ||||
|             ref="deptTreeRef" | ||||
|             :data="deptTree" | ||||
|             default-expand-all | ||||
|             show-line | ||||
|             @select="handleSelectNode" | ||||
|           /> | ||||
|         </a-col> | ||||
|         <a-col :xs="15" :sm="18" :md="19" :lg="20" :xl="19"> | ||||
|           <!-- 头部区域 --> | ||||
|           <div class="header"> | ||||
|             <!-- 搜索栏 --> | ||||
|             <div v-if="showQuery" class="header-query"> | ||||
|               <a-form ref="queryRef" :model="queryParams" layout="inline"> | ||||
|                 <a-form-item field="username" hide-label> | ||||
|                   <a-input | ||||
|                     v-model="queryParams.username" | ||||
|                     placeholder="输入用户名搜索" | ||||
|                     allow-clear | ||||
|                     style="width: 150px" | ||||
|                     @press-enter="handleQuery" | ||||
|                   /> | ||||
|                 </a-form-item> | ||||
|                 <a-form-item field="status" hide-label> | ||||
|                   <a-select | ||||
|                     v-model="queryParams.status" | ||||
|                     :options="statusOptions" | ||||
|                     placeholder="状态搜索" | ||||
|                     allow-clear | ||||
|                     style="width: 150px" | ||||
|                   /> | ||||
|                 </a-form-item> | ||||
|                 <a-form-item field="createTime" hide-label> | ||||
|                   <date-range-picker v-model="queryParams.createTime" /> | ||||
|                 </a-form-item> | ||||
|                 <a-form-item hide-label> | ||||
|                   <a-space> | ||||
|                     <a-button type="primary" @click="handleQuery"> | ||||
|                       <template #icon><icon-search /></template>查询 | ||||
|                     </a-button> | ||||
|                     <a-button @click="resetQuery"> | ||||
|                       <template #icon><icon-refresh /></template>重置 | ||||
|                     </a-button> | ||||
|                   </a-space> | ||||
|                 </a-form-item> | ||||
|               </a-form> | ||||
|             </div> | ||||
|             <!-- 操作栏 --> | ||||
|             <div class="header-operation"> | ||||
|               <a-row> | ||||
|                 <a-col :span="12"> | ||||
|                   <a-space> | ||||
|                     <a-button type="primary" @click="toCreate"> | ||||
|                       <template #icon><icon-plus /></template>新增 | ||||
|                     </a-button> | ||||
|                     <a-button | ||||
|                       type="primary" | ||||
|                       status="success" | ||||
|                       :disabled="single" | ||||
|                       :title="single ? '请选择一条要修改的数据' : ''" | ||||
|                       @click="toUpdate(ids[0])" | ||||
|                     > | ||||
|                       <template #icon><icon-edit /></template>修改 | ||||
|                     </a-button> | ||||
|                     <a-button | ||||
|                       type="primary" | ||||
|                       status="danger" | ||||
|                       :disabled="multiple" | ||||
|                       :title="multiple ? '请选择要删除的数据' : ''" | ||||
|                       @click="handleBatchDelete" | ||||
|                     > | ||||
|                       <template #icon><icon-delete /></template>删除 | ||||
|                     </a-button> | ||||
|                     <a-button | ||||
|                       :loading="exportLoading" | ||||
|                       type="primary" | ||||
|                       status="warning" | ||||
|                       @click="handleExport" | ||||
|                     > | ||||
|                       <template #icon><icon-download /></template>导出 | ||||
|                     </a-button> | ||||
|                   </a-space> | ||||
|                 </a-col> | ||||
|                 <a-col :span="12"> | ||||
|                   <right-toolbar | ||||
|                     v-model:show-query="showQuery" | ||||
|                     @refresh="getList" | ||||
|                   /> | ||||
|                 </a-col> | ||||
|               </a-row> | ||||
|             </div> | ||||
|           </div> | ||||
|  | ||||
|           <!-- 列表区域 --> | ||||
|           <a-table | ||||
|             ref="tableRef" | ||||
|             :data="userList" | ||||
|             :row-selection="{ | ||||
|               type: 'checkbox', | ||||
|               showCheckedAll: true, | ||||
|               onlyCurrent: false, | ||||
|             }" | ||||
|             :pagination="{ | ||||
|               showTotal: true, | ||||
|               showPageSize: true, | ||||
|               total: total, | ||||
|               current: queryParams.page, | ||||
|             }" | ||||
|             row-key="userId" | ||||
|             :bordered="false" | ||||
|             :stripe="true" | ||||
|             :loading="loading" | ||||
|             size="large" | ||||
|             :scroll="{ | ||||
|               x: '120%', | ||||
|             }" | ||||
|             @page-change="handlePageChange" | ||||
|             @page-size-change="handlePageSizeChange" | ||||
|             @selection-change="handleSelectionChange" | ||||
|           > | ||||
|             <template #columns> | ||||
|               <a-table-column title="ID" data-index="userId" /> | ||||
|               <a-table-column title="用户名"> | ||||
|                 <template #cell="{ record }"> | ||||
|                   <a-link @click="toDetail(record.userId)">{{ | ||||
|                     record.username | ||||
|                   }}</a-link> | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|               <a-table-column title="昵称" data-index="nickname" :width="120" /> | ||||
|               <a-table-column title="性别"> | ||||
|                 <template #cell="{ record }"> | ||||
|                   <span v-if="record.gender === 1">男</span> | ||||
|                   <span v-else-if="record.gender === 2">女</span> | ||||
|                   <span v-else>未知</span> | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|               <a-table-column title="头像" align="center"> | ||||
|                 <template #cell="{ record }"> | ||||
|                   <a-avatar> | ||||
|                     <img :src="getAvatar(record.avatar, record.gender)" alt="头像" /> | ||||
|                   </a-avatar> | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|               <a-table-column title="联系方式" :width="175"> | ||||
|                 <template #cell="{ record }"> | ||||
|                   {{ record.email }}<br v-if="record.email && record.phone"> | ||||
|                   {{ record.phone }} | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|               <a-table-column title="状态" align="center"> | ||||
|                 <template #cell="{ record }"> | ||||
|                   <a-switch | ||||
|                     v-model="record.status" | ||||
|                     :checked-value="1" | ||||
|                     :unchecked-value="2" | ||||
|                     :disabled="record.disabled" | ||||
|                     @change="handleChangeStatus(record)" | ||||
|                   /> | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|               <a-table-column title="描述" data-index="description" ellipsis tooltip /> | ||||
|               <a-table-column title="创建人/创建时间" :width="175"> | ||||
|                 <template #cell="{ record }"> | ||||
|                   {{ record.createUserString }}<br> | ||||
|                   {{ record.createTime }} | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|               <a-table-column | ||||
|                 title="操作" | ||||
|                 align="center" | ||||
|                 fixed="right" | ||||
|                 :width="120" | ||||
|               > | ||||
|                 <template #cell="{ record }"> | ||||
|                   <a-button | ||||
|                     v-permission="['admin']" | ||||
|                     type="text" | ||||
|                     size="small" | ||||
|                     title="修改" | ||||
|                     @click="toUpdate(record.userId)" | ||||
|                   > | ||||
|                     <template #icon><icon-edit /></template>修改 | ||||
|                   </a-button> | ||||
|                   <a-popconfirm | ||||
|                     content="确定要删除当前选中的数据吗?" | ||||
|                     type="warning" | ||||
|                     @ok="handleDelete([record.userId])" | ||||
|                   > | ||||
|                     <a-button | ||||
|                       v-permission="['admin']" | ||||
|                       type="text" | ||||
|                       size="small" | ||||
|                       title="删除" | ||||
|                       :disabled="record.disabled" | ||||
|                     > | ||||
|                       <template #icon><icon-delete /></template>删除 | ||||
|                     </a-button> | ||||
|                   </a-popconfirm> | ||||
|                 </template> | ||||
|               </a-table-column> | ||||
|             </template> | ||||
|           </a-table> | ||||
|         </a-col> | ||||
|       </a-row> | ||||
|  | ||||
|       <!-- 表单区域 --> | ||||
|       <a-modal | ||||
|         :title="title" | ||||
|         :visible="visible" | ||||
|         :width="580" | ||||
|         :mask-closable="false" | ||||
|         unmount-on-close | ||||
|         render-to-body | ||||
|         @ok="handleOk" | ||||
|         @cancel="handleCancel" | ||||
|       > | ||||
|         <a-form | ||||
|           ref="formRef" | ||||
|           :model="form" | ||||
|           :rules="rules" | ||||
|           :label-col-style="{ width: '84px' }" | ||||
|           size="large" | ||||
|           layout="inline" | ||||
|         > | ||||
|           <a-form-item label="用户名" field="username"> | ||||
|             <a-input | ||||
|               v-model="form.username" | ||||
|               placeholder="请输入用户名" | ||||
|               style="width: 162px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="昵称" field="nickname"> | ||||
|             <a-input | ||||
|               v-model="form.nickname" | ||||
|               placeholder="请输入昵称" | ||||
|               style="width: 162px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="邮箱" field="email"> | ||||
|             <a-input | ||||
|               v-model="form.email" | ||||
|               placeholder="请输入邮箱" | ||||
|               style="width: 162px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="手机号码" field="phone"> | ||||
|             <a-input | ||||
|               v-model="form.phone" | ||||
|               placeholder="请输入手机号码" | ||||
|               style="width: 162px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="性别" field="gender"> | ||||
|             <a-radio-group v-model="form.gender"> | ||||
|               <a-radio :value="1">男</a-radio> | ||||
|               <a-radio :value="2">女</a-radio> | ||||
|               <a-radio :value="0" disabled>未知</a-radio> | ||||
|             </a-radio-group> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="所属角色" field="roleIds"> | ||||
|             <a-select | ||||
|               v-model="form.roleIds" | ||||
|               :options="roleOptions" | ||||
|               :field-names="{ | ||||
|                 label: 'title', | ||||
|                 value: 'key', | ||||
|               }" | ||||
|               placeholder="请选择所属角色" | ||||
|               :loading="roleLoading" | ||||
|               multiple | ||||
|               allow-clear | ||||
|               :allow-search="{ retainInputValue: true }" | ||||
|               style="width: 416px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="所属部门" field="deptId"> | ||||
|             <a-tree-select | ||||
|               v-model="form.deptId" | ||||
|               :data="deptOptions" | ||||
|               placeholder="请选择所属部门" | ||||
|               allow-clear | ||||
|               allow-search | ||||
|               :filter-tree-node="filterDeptOptions" | ||||
|               style="width: 416px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|           <a-form-item label="描述" field="description"> | ||||
|             <a-textarea | ||||
|               v-model="form.description" | ||||
|               :max-length="200" | ||||
|               placeholder="请输入描述" | ||||
|               :auto-size="{ | ||||
|                 minRows: 3, | ||||
|               }" | ||||
|               show-word-limit | ||||
|               style="width: 416px" | ||||
|             /> | ||||
|           </a-form-item> | ||||
|         </a-form> | ||||
|       </a-modal> | ||||
|  | ||||
|       <!-- 详情区域 --> | ||||
|       <a-drawer | ||||
|         title="用户详情" | ||||
|         :visible="detailVisible" | ||||
|         :width="580" | ||||
|         :footer="false" | ||||
|         unmount-on-close | ||||
|         render-to-body | ||||
|         @cancel="handleDetailCancel" | ||||
|       > | ||||
|         <a-descriptions title="基础信息" :column="2" bordered size="large"> | ||||
|           <a-descriptions-item label="用户名"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.username }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="昵称"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.nickname }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="性别"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else> | ||||
|               <span v-if="user.gender === 1">男</span> | ||||
|               <span v-else>女</span> | ||||
|             </span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="状态"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else> | ||||
|               <a-tag v-if="user.status === 1" color="green">启用</a-tag> | ||||
|               <a-tag v-else color="red">禁用</a-tag> | ||||
|             </span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="邮箱"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.email || '无' }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="手机号码"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.phone || '无' }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="所属角色"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.roleNames }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="所属部门"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.deptName }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="创建人"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.createUserString }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="创建时间"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.createTime }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="修改人"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.updateUserString }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="修改时间"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.updateTime }}</span> | ||||
|           </a-descriptions-item> | ||||
|           <a-descriptions-item label="描述"> | ||||
|             <a-skeleton v-if="detailLoading" :animation="true"> | ||||
|               <a-skeleton-line :rows="1" /> | ||||
|             </a-skeleton> | ||||
|             <span v-else>{{ user.description }}</span> | ||||
|           </a-descriptions-item> | ||||
|         </a-descriptions> | ||||
|       </a-drawer> | ||||
|     </a-card> | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
|   import { getCurrentInstance, ref, toRefs, reactive, watch } from 'vue'; | ||||
|   import { SelectOptionData, TreeNodeData } from '@arco-design/web-vue'; | ||||
|   import { | ||||
|     UserRecord, | ||||
|     UserParam, | ||||
|     listUser, | ||||
|     getUser, | ||||
|     addUser, | ||||
|     updateUser, | ||||
|     deleteUser, | ||||
|   } from '@/api/system/user'; | ||||
|   import { listRoleTree, listDeptTree } from '@/api/common'; | ||||
|   import getAvatar from '@/utils/avatar'; | ||||
|  | ||||
|   const { proxy } = getCurrentInstance() as any; | ||||
|  | ||||
|   const userList = ref<UserRecord[]>([]); | ||||
|   const user = ref<UserRecord>({ | ||||
|     username: '', | ||||
|     nickname: '', | ||||
|     gender: 1, | ||||
|     email: undefined, | ||||
|     phone: undefined, | ||||
|     status: 1, | ||||
|     createUserString: '', | ||||
|     createTime: '', | ||||
|     updateUserString: '', | ||||
|     updateTime: '', | ||||
|     description: '', | ||||
|     roleIds: undefined, | ||||
|     deptId: undefined, | ||||
|   }); | ||||
|   const total = ref(0); | ||||
|   const ids = ref<Array<number>>([]); | ||||
|   const title = ref(''); | ||||
|   const single = ref(true); | ||||
|   const multiple = ref(true); | ||||
|   const showQuery = ref(true); | ||||
|   const loading = ref(false); | ||||
|   const detailLoading = ref(false); | ||||
|   const exportLoading = ref(false); | ||||
|   const visible = ref(false); | ||||
|   const detailVisible = ref(false); | ||||
|   const statusOptions = ref<SelectOptionData[]>([ | ||||
|     { label: '启用', value: 1 }, | ||||
|     { label: '禁用', value: 2 }, | ||||
|   ]); | ||||
|   const roleLoading = ref(false); | ||||
|   const deptLoading = ref(false); | ||||
|   const roleOptions = ref<TreeNodeData[]>([]); | ||||
|   const deptOptions = ref<TreeNodeData[]>([]); | ||||
|   const deptTree = ref<TreeNodeData[]>([]); | ||||
|   const deptName = ref(''); | ||||
|  | ||||
|   const data = reactive({ | ||||
|     // 查询参数 | ||||
|     queryParams: { | ||||
|       username: undefined, | ||||
|       status: undefined, | ||||
|       createTime: undefined, | ||||
|       deptId: undefined, | ||||
|       page: 1, | ||||
|       size: 10, | ||||
|       sort: ['createTime,desc'], | ||||
|     }, | ||||
|     // 表单数据 | ||||
|     form: {} as UserRecord, | ||||
|     // 表单验证规则 | ||||
|     rules: { | ||||
|       username: [{ required: true, message: '请输入用户名' }], | ||||
|       nickname: [{ required: true, message: '请输入昵称' }], | ||||
|       roleIds: [{ required: true, message: '请选择所属角色' }], | ||||
|       deptId: [{ required: true, message: '请选择所属部门' }], | ||||
|     }, | ||||
|   }); | ||||
|   const { queryParams, form, rules } = toRefs(data); | ||||
|  | ||||
|   /** | ||||
|    * 查询部门树 | ||||
|    * | ||||
|    * @param name 名称 | ||||
|    */ | ||||
|   const getDeptTree = (name: string) => { | ||||
|     listDeptTree({ deptName: name }).then((res) => { | ||||
|       deptTree.value = res.data; | ||||
|       setTimeout(() => { | ||||
|         proxy.$refs.deptTreeRef.expandAll(); | ||||
|       }, 0); | ||||
|     }); | ||||
|   }; | ||||
|   getDeptTree(''); | ||||
|   watch(deptName, (val) => { | ||||
|     getDeptTree(val); | ||||
|   }); | ||||
|  | ||||
|   /** | ||||
|    * 查询列表 | ||||
|    * | ||||
|    * @param params 查询参数 | ||||
|    */ | ||||
|   const getList = (params: UserParam = { ...queryParams.value }) => { | ||||
|     loading.value = true; | ||||
|     listUser(params) | ||||
|       .then((res) => { | ||||
|         userList.value = res.data.list; | ||||
|         total.value = res.data.total; | ||||
|       }) | ||||
|       .finally(() => { | ||||
|         loading.value = false; | ||||
|       }); | ||||
|   }; | ||||
|   getList(); | ||||
|  | ||||
|   /** | ||||
|    * 打开新增对话框 | ||||
|    */ | ||||
|   const toCreate = () => { | ||||
|     reset(); | ||||
|     getRoleOptions(); | ||||
|     getDeptOptions(); | ||||
|     title.value = '新增用户'; | ||||
|     visible.value = true; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 打开修改对话框 | ||||
|    * | ||||
|    * @param id ID | ||||
|    */ | ||||
|   const toUpdate = (id: number) => { | ||||
|     reset(); | ||||
|     getRoleOptions(); | ||||
|     getDeptOptions(); | ||||
|     getUser(id).then((res) => { | ||||
|       form.value = res.data; | ||||
|       title.value = '修改用户'; | ||||
|       visible.value = true; | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 查询角色列表 | ||||
|    */ | ||||
|   const getRoleOptions = () => { | ||||
|     roleLoading.value = true; | ||||
|     listRoleTree({}) | ||||
|       .then((res) => { | ||||
|         roleOptions.value = res.data; | ||||
|       }) | ||||
|       .finally(() => { | ||||
|         roleLoading.value = false; | ||||
|       }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 查询部门列表 | ||||
|    */ | ||||
|   const getDeptOptions = () => { | ||||
|     deptLoading.value = true; | ||||
|     listDeptTree({}) | ||||
|       .then((res) => { | ||||
|         deptOptions.value = res.data; | ||||
|       }) | ||||
|       .finally(() => { | ||||
|         deptLoading.value = false; | ||||
|       }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 重置表单 | ||||
|    */ | ||||
|   const reset = () => { | ||||
|     form.value = { | ||||
|       userId: undefined, | ||||
|       username: '', | ||||
|       nickname: '', | ||||
|       gender: 1, | ||||
|       email: undefined, | ||||
|       phone: undefined, | ||||
|       description: '', | ||||
|       status: 1, | ||||
|       roleIds: [], | ||||
|       deptId: undefined, | ||||
|     }; | ||||
|     proxy.$refs.formRef?.resetFields(); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 取消 | ||||
|    */ | ||||
|   const handleCancel = () => { | ||||
|     visible.value = false; | ||||
|     proxy.$refs.formRef.resetFields(); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 确定 | ||||
|    */ | ||||
|   const handleOk = () => { | ||||
|     proxy.$refs.formRef.validate((valid: any) => { | ||||
|       if (!valid) { | ||||
|         if (form.value.userId !== undefined) { | ||||
|           updateUser(form.value).then((res) => { | ||||
|             handleCancel(); | ||||
|             getList(); | ||||
|             proxy.$message.success(res.msg); | ||||
|           }); | ||||
|         } else { | ||||
|           addUser(form.value).then((res) => { | ||||
|             handleCancel(); | ||||
|             getList(); | ||||
|             proxy.$message.success(res.msg); | ||||
|           }); | ||||
|         } | ||||
|       } | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 查看详情 | ||||
|    * | ||||
|    * @param id ID | ||||
|    */ | ||||
|   const toDetail = async (id: number) => { | ||||
|     if (detailLoading.value) return; | ||||
|     detailLoading.value = true; | ||||
|     detailVisible.value = true; | ||||
|     getUser(id) | ||||
|       .then((res) => { | ||||
|         user.value = res.data; | ||||
|       }) | ||||
|       .finally(() => { | ||||
|         detailLoading.value = false; | ||||
|       }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 关闭详情 | ||||
|    */ | ||||
|   const handleDetailCancel = () => { | ||||
|     detailVisible.value = false; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 批量删除 | ||||
|    */ | ||||
|   const handleBatchDelete = () => { | ||||
|     if (ids.value.length === 0) { | ||||
|       proxy.$message.info('请选择要删除的数据'); | ||||
|     } else { | ||||
|       proxy.$modal.warning({ | ||||
|         title: '警告', | ||||
|         titleAlign: 'start', | ||||
|         content: '确定要删除当前选中的数据吗?', | ||||
|         hideCancel: false, | ||||
|         onOk: () => { | ||||
|           handleDelete(ids.value); | ||||
|         }, | ||||
|       }); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 删除 | ||||
|    * | ||||
|    * @param ids ID 列表 | ||||
|    */ | ||||
|   const handleDelete = (ids: Array<number>) => { | ||||
|     deleteUser(ids).then((res) => { | ||||
|       proxy.$message.success(res.msg); | ||||
|       getList(); | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 已选择的数据行发生改变时触发 | ||||
|    * | ||||
|    * @param rowKeys ID 列表 | ||||
|    */ | ||||
|   const handleSelectionChange = (rowKeys: Array<any>) => { | ||||
|     ids.value = rowKeys; | ||||
|     single.value = rowKeys.length !== 1; | ||||
|     multiple.value = !rowKeys.length; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 导出 | ||||
|    */ | ||||
|   const handleExport = () => { | ||||
|     if (exportLoading.value) return; | ||||
|     exportLoading.value = true; | ||||
|     proxy | ||||
|       .download('/system/user/export', { ...queryParams.value }, '用户数据') | ||||
|       .finally(() => { | ||||
|         exportLoading.value = false; | ||||
|       }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 修改状态 | ||||
|    * | ||||
|    * @param record 记录信息 | ||||
|    */ | ||||
|   const handleChangeStatus = (record: UserRecord) => { | ||||
|     const tip = record.status === 1 ? '启用' : '禁用'; | ||||
|     updateUser(record) | ||||
|       .then(() => { | ||||
|         proxy.$message.success(`${tip}成功`); | ||||
|       }) | ||||
|       .catch(() => { | ||||
|         record.status = record.status === 1 ? 2 : 1; | ||||
|       }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 过滤部门列表 | ||||
|    * | ||||
|    * @param searchValue 搜索值 | ||||
|    * @param nodeData 节点值 | ||||
|    */ | ||||
|   const filterDeptOptions = (searchValue: string, nodeData: TreeNodeData) => { | ||||
|     if (nodeData.title) { | ||||
|       return ( | ||||
|         nodeData.title.toLowerCase().indexOf(searchValue.toLowerCase()) > -1 | ||||
|       ); | ||||
|     } | ||||
|     return false; | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 根据选中部门查询 | ||||
|    * | ||||
|    * @param keys 选中节点 key | ||||
|    */ | ||||
|   const handleSelectNode = (keys: Array<any>) => { | ||||
|     if (queryParams.value.deptId === keys[0]) { | ||||
|       queryParams.value.deptId = undefined; | ||||
|       // 如已选中,再次点击则取消选中 | ||||
|       proxy.$refs.deptTreeRef.selectNode(keys, false); | ||||
|     } else { | ||||
|       queryParams.value.deptId = keys.length === 1 ? keys[0] : undefined; | ||||
|     } | ||||
|     handleQuery(); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 查询 | ||||
|    */ | ||||
|   const handleQuery = () => { | ||||
|     getList(); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 重置 | ||||
|    */ | ||||
|   const resetQuery = () => { | ||||
|     proxy.$refs.queryRef.resetFields(); | ||||
|     handleQuery(); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 切换页码 | ||||
|    * | ||||
|    * @param current 页码 | ||||
|    */ | ||||
|   const handlePageChange = (current: number) => { | ||||
|     queryParams.value.page = current; | ||||
|     getList(); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 切换每页条数 | ||||
|    * | ||||
|    * @param pageSize 每页条数 | ||||
|    */ | ||||
|   const handlePageSizeChange = (pageSize: number) => { | ||||
|     queryParams.value.size = pageSize; | ||||
|     getList(); | ||||
|   }; | ||||
| </script> | ||||
|  | ||||
| <script lang="ts"> | ||||
|   export default { | ||||
|     name: 'User', | ||||
|   }; | ||||
| </script> | ||||
|  | ||||
| <style scoped lang="less"></style> | ||||
							
								
								
									
										3
									
								
								continew-admin-ui/src/views/system/user/locale/en-US.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								continew-admin-ui/src/views/system/user/locale/en-US.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| export default { | ||||
|   'menu.system.user.list': 'User management', | ||||
| }; | ||||
							
								
								
									
										3
									
								
								continew-admin-ui/src/views/system/user/locale/zh-CN.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								continew-admin-ui/src/views/system/user/locale/zh-CN.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| export default { | ||||
|   'menu.system.user.list': '用户管理', | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user