mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 22:57:15 +08:00 
			
		
		
		
	refactor: 使用用户选择器组件重构角色分配功能
This commit is contained in:
		| @@ -9,10 +9,7 @@ const BASE_URL = '/common' | |||||||
| export function listDeptTree(query: { description: string }) { | export function listDeptTree(query: { description: string }) { | ||||||
|   return http.get<TreeNodeData[]>(`${BASE_URL}/tree/dept`, query) |   return http.get<TreeNodeData[]>(`${BASE_URL}/tree/dept`, query) | ||||||
| } | } | ||||||
| /** @desc 查询部门用户树 */ |  | ||||||
| export function listDeptWithUsersTree(query: { description?: string, status: number }) { |  | ||||||
|   return http.get<TreeNodeData[]>(`${BASE_URL}/tree/deptWithUsers`, query) |  | ||||||
| } |  | ||||||
| /** @desc 查询菜单树 */ | /** @desc 查询菜单树 */ | ||||||
| export function listMenuTree(query: { description: string }) { | export function listMenuTree(query: { description: string }) { | ||||||
|   return http.get<TreeNodeData[]>(`${BASE_URL}/tree/menu`, query) |   return http.get<TreeNodeData[]>(`${BASE_URL}/tree/menu`, query) | ||||||
|   | |||||||
| @@ -29,11 +29,13 @@ export function updateRole(data: any, id: string) { | |||||||
| export function deleteRole(ids: string | Array<string>) { | export function deleteRole(ids: string | Array<string>) { | ||||||
|   return http.del(`${BASE_URL}/${ids}`) |   return http.del(`${BASE_URL}/${ids}`) | ||||||
| } | } | ||||||
| /** @desc 获取角色绑定的用户列表 */ |  | ||||||
|  | /** @desc 查询角色关联用户 */ | ||||||
| export function listRoleUsers(id: string) { | export function listRoleUsers(id: string) { | ||||||
|   return http.get(`${BASE_URL}/listRoleUsers/${id}`) |   return http.get(`${BASE_URL}/${id}/user`) | ||||||
| } | } | ||||||
|  |  | ||||||
| export function bindUsers(id: string, userIds: Array<string>) { | /** @desc 分配角色给用户 */ | ||||||
|   return http.post(`${BASE_URL}/bindUsers/${id}`, userIds) | export function assignToUsers(id: string, userIds: Array<string>) { | ||||||
|  |   return http.post(`${BASE_URL}/${id}/user`, userIds) | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										71
									
								
								src/views/system/role/RoleAssignModal.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/views/system/role/RoleAssignModal.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | |||||||
|  | <template> | ||||||
|  |   <a-modal | ||||||
|  |     v-model:visible="visible" | ||||||
|  |     title="分配角色" | ||||||
|  |     :mask-closable="false" | ||||||
|  |     :esc-to-close="false" | ||||||
|  |     :width="width >= 1350 ? 1350 : '100%'" | ||||||
|  |     draggable | ||||||
|  |     @before-ok="save" | ||||||
|  |     @close="reset" | ||||||
|  |   > | ||||||
|  |     <UserSelect v-if="visible" ref="UserSelectRef" v-model:value="selectedUsers" @select-user="onSelectUser" /> | ||||||
|  |   </a-modal> | ||||||
|  | </template> | ||||||
|  |  | ||||||
|  | <script lang="ts" setup> | ||||||
|  | import { ref } from 'vue' | ||||||
|  | import { Message } from '@arco-design/web-vue' | ||||||
|  | import { useWindowSize } from '@vueuse/core' | ||||||
|  | import { assignToUsers, listRoleUsers } from '@/apis/system' | ||||||
|  |  | ||||||
|  | const { width } = useWindowSize() | ||||||
|  | const visible = ref(false) | ||||||
|  | const dataId = ref('') | ||||||
|  | const selectedUsers = ref<string[]>([]) | ||||||
|  |  | ||||||
|  | const UserSelectRef = ref() | ||||||
|  | // 重置 | ||||||
|  | const reset = () => { | ||||||
|  |   dataId.value = '' | ||||||
|  |   selectedUsers.value = [] | ||||||
|  |   UserSelectRef.value?.onClearSelected() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 保存 | ||||||
|  | const save = async () => { | ||||||
|  |   try { | ||||||
|  |     const isInvalid = selectedUsers.value.length === 0 | ||||||
|  |     if (isInvalid) { | ||||||
|  |       Message.warning('请选择用户') | ||||||
|  |       return false | ||||||
|  |     } | ||||||
|  |     await assignToUsers(dataId.value, selectedUsers.value) | ||||||
|  |     Message.success('分配成功') | ||||||
|  |     reset() | ||||||
|  |     return true | ||||||
|  |   } catch (error) { | ||||||
|  |     return false | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 用户选择回调 | ||||||
|  | const onSelectUser = (value: string[]) => { | ||||||
|  |   selectedUsers.value = value | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // 打开 | ||||||
|  | const onOpen = async (id: string) => { | ||||||
|  |   dataId.value = id | ||||||
|  |   // 初始化选择的用户 | ||||||
|  |   const { data } = await listRoleUsers(id) | ||||||
|  |   selectedUsers.value = data | ||||||
|  |   visible.value = true | ||||||
|  | } | ||||||
|  |  | ||||||
|  | defineExpose({ | ||||||
|  |   onOpen, | ||||||
|  | }) | ||||||
|  | </script> | ||||||
|  |  | ||||||
|  | <style lang="scss" scoped></style> | ||||||
| @@ -1,113 +0,0 @@ | |||||||
| <template> |  | ||||||
|   <a-modal |  | ||||||
|     v-model:visible="visible" |  | ||||||
|     title="关联用户" |  | ||||||
|     :mask-closable="false" |  | ||||||
|     :esc-to-close="false" |  | ||||||
|     :modal-style="{ maxWidth: '625px' }" |  | ||||||
|     :body-style="{ maxHeight: '70vh' }" |  | ||||||
|     width="90%" |  | ||||||
|     draggable |  | ||||||
|     @before-ok="save" |  | ||||||
|     @close="close" |  | ||||||
|   > |  | ||||||
|     <a-transfer :data="transferData" :model-value="values" :title="['未选择', '已选择']" @change="handleChange"> |  | ||||||
|       <template #source="{ selectedKeys, onSelect }"> |  | ||||||
|         <a-tree |  | ||||||
|           size="medium" |  | ||||||
|           :checkable="true" |  | ||||||
|           checked-strategy="child" |  | ||||||
|           :checked-keys="selectedKeys" |  | ||||||
|           :data="getTreeData()" |  | ||||||
|           @check="(keys) => onSelect(keys)" |  | ||||||
|         /> |  | ||||||
|       </template> |  | ||||||
|     </a-transfer> |  | ||||||
|   </a-modal> |  | ||||||
| </template> |  | ||||||
|  |  | ||||||
| <script lang="ts" setup> |  | ||||||
| import { ref } from 'vue' |  | ||||||
| import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface' |  | ||||||
| import { Message, type TreeNodeData } from '@arco-design/web-vue' |  | ||||||
| import { bindUsers, listDeptWithUsersTree, listRoleUsers } from '@/apis' |  | ||||||
|  |  | ||||||
| const visible = ref(false) |  | ||||||
| const roleId = ref('') |  | ||||||
| const treeData = ref<TreeNodeData[]>([]) |  | ||||||
| const transferData = ref<TransferItem[]>([]) |  | ||||||
| const values = ref<string[]>(['']) |  | ||||||
| const close = () => { |  | ||||||
|   visible.value = false |  | ||||||
| } |  | ||||||
| const save = async () => { |  | ||||||
|   const newValues = values.value.map((item) => item.replace('user_', '')) |  | ||||||
|   const res = await bindUsers(roleId.value, newValues) |  | ||||||
|   if (res.success) { |  | ||||||
|     Message.success('修改成功') |  | ||||||
|     visible.value = false |  | ||||||
|     return false |  | ||||||
|   } else { |  | ||||||
|     Message.error(res.msg) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| const handleChange = (value: string[]) => { |  | ||||||
|   values.value = value |  | ||||||
| } |  | ||||||
| const getTransferData = (treeData: TreeNodeData[], transferDataSource: TransferItem[] = []) => { |  | ||||||
|   treeData.forEach((item) => { |  | ||||||
|     if (item.isUser === true) { |  | ||||||
|       transferDataSource.push({ label: item.title ?? '', value: String(item.key) ?? '', disabled: false }) |  | ||||||
|     } |  | ||||||
|     if (item.children) { |  | ||||||
|       getTransferData(item.children, transferDataSource) |  | ||||||
|     } |  | ||||||
|   }) |  | ||||||
|   return transferDataSource |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const getTreeData = () => { |  | ||||||
|   const travel = (_treeData: TreeNodeData[] = []) => { |  | ||||||
|     const treeDataSource: TreeNodeData[] = [] |  | ||||||
|     _treeData.forEach((item) => { |  | ||||||
|       const disabled = values.value.filter((v) => v === item.key).length > 0 |  | ||||||
|       treeDataSource.push({ title: item.title, key: item.key, children: travel(item.children), disabled }) |  | ||||||
|     }) |  | ||||||
|     return treeDataSource |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   return travel(treeData.value) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const listUsers = async (roleId: string) => { |  | ||||||
|   const res = await listRoleUsers(roleId) |  | ||||||
|   res.data.forEach((item) => { |  | ||||||
|     values.value.push(`user_${item}`) |  | ||||||
|   }) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const getDeptList = async () => { |  | ||||||
|   const res = await listDeptWithUsersTree({ status: 1 }) |  | ||||||
|   treeData.value = res.data |  | ||||||
|   transferData.value = getTransferData(treeData.value) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| const onAssociation = async (id: string) => { |  | ||||||
|   visible.value = true |  | ||||||
|   roleId.value = id |  | ||||||
|   values.value = [] |  | ||||||
|   await getDeptList() |  | ||||||
|   await listUsers(roleId.value) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| defineExpose({ |  | ||||||
|   onAssociation, |  | ||||||
| }) |  | ||||||
| </script> |  | ||||||
|  |  | ||||||
| <style lang="scss" scoped> |  | ||||||
| :deep(.arco-transfer-view) { |  | ||||||
|     height: 40vh; |  | ||||||
|     width: 300px; |  | ||||||
| } |  | ||||||
| </style> |  | ||||||
| @@ -51,7 +51,7 @@ | |||||||
|       <template #action="{ record }"> |       <template #action="{ record }"> | ||||||
|         <a-space> |         <a-space> | ||||||
|           <a-link v-permission="['system:role:update']" @click="onUpdate(record)">修改</a-link> |           <a-link v-permission="['system:role:update']" @click="onUpdate(record)">修改</a-link> | ||||||
|           <a-link v-permission="['system:role:bindUsers']" @click="onAssociation(record)">关联用户</a-link> |           <a-link v-permission="['system:role:assign']" @click="onAssign(record)">分配</a-link> | ||||||
|           <a-link |           <a-link | ||||||
|             v-permission="['system:role:delete']" |             v-permission="['system:role:delete']" | ||||||
|             status="danger" |             status="danger" | ||||||
| @@ -68,7 +68,7 @@ | |||||||
|     <RoleAddModal ref="RoleAddModalRef" @save-success="search" /> |     <RoleAddModal ref="RoleAddModalRef" @save-success="search" /> | ||||||
|     <RoleUpdateDrawer ref="RoleUpdateDrawerRef" @save-success="search" /> |     <RoleUpdateDrawer ref="RoleUpdateDrawerRef" @save-success="search" /> | ||||||
|     <RoleDetailDrawer ref="RoleDetailDrawerRef" /> |     <RoleDetailDrawer ref="RoleDetailDrawerRef" /> | ||||||
|     <RoleUserAssociation ref="RoleUserAssociationRef" /> |     <RoleAssignModal ref="RoleAssignModalRef" /> | ||||||
|   </div> |   </div> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| @@ -76,7 +76,7 @@ | |||||||
| import RoleUpdateDrawer from './RoleUpdateDrawer.vue' | import RoleUpdateDrawer from './RoleUpdateDrawer.vue' | ||||||
| import RoleDetailDrawer from './RoleDetailDrawer.vue' | import RoleDetailDrawer from './RoleDetailDrawer.vue' | ||||||
| import RoleAddModal from './RoleAddModal.vue' | import RoleAddModal from './RoleAddModal.vue' | ||||||
| import RoleUserAssociation from './RoleUserAssociation.vue' | import RoleAssignModal from './RoleAssignModal.vue' | ||||||
| import { type RoleQuery, type RoleResp, deleteRole, listRole } from '@/apis/system' | import { type RoleQuery, type RoleResp, deleteRole, listRole } from '@/apis/system' | ||||||
| import type { TableInstanceColumns } from '@/components/GiTable/type' | import type { TableInstanceColumns } from '@/components/GiTable/type' | ||||||
| import { useTable } from '@/hooks' | import { useTable } from '@/hooks' | ||||||
| @@ -156,10 +156,10 @@ const onDetail = (record: RoleResp) => { | |||||||
|   RoleDetailDrawerRef.value?.onDetail(record.id) |   RoleDetailDrawerRef.value?.onDetail(record.id) | ||||||
| } | } | ||||||
|  |  | ||||||
| const RoleUserAssociationRef = ref<InstanceType<typeof RoleUserAssociation>>() | const RoleAssignModalRef = ref<InstanceType<typeof RoleAssignModal>>() | ||||||
| // 关联用户 | // 分配 | ||||||
| const onAssociation = (record: RoleResp) => { | const onAssign = (record: RoleResp) => { | ||||||
|   RoleUserAssociationRef.value?.onAssociation(record.id) |   RoleAssignModalRef.value?.onOpen(record.id) | ||||||
| } | } | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -109,7 +109,7 @@ import { DisEnableStatusList } from '@/constant/common' | |||||||
| defineOptions({ name: 'SystemUser' }) | defineOptions({ name: 'SystemUser' }) | ||||||
|  |  | ||||||
| const queryForm = reactive<UserQuery>({ | const queryForm = reactive<UserQuery>({ | ||||||
|   sort: ['t1.createTime,desc'], |   sort: ['t1.createTime,desc', 't1.id,desc'], | ||||||
| }) | }) | ||||||
| const { | const { | ||||||
|   tableData: dataList, |   tableData: dataList, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user