mirror of
				https://github.com/continew-org/continew-admin-ui.git
				synced 2025-10-31 10:57:10 +08:00 
			
		
		
		
	feat: 角色管理增加授权用户功能 (#33)
This commit is contained in:
		| @@ -9,7 +9,10 @@ const BASE_URL = '/common' | ||||
| export function listDeptTree(query: { description: string }) { | ||||
|   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 查询菜单树 */ | ||||
| export function listMenuTree(query: { description: string }) { | ||||
|   return http.get<TreeNodeData[]>(`${BASE_URL}/tree/menu`, query) | ||||
|   | ||||
| @@ -29,3 +29,11 @@ export function updateRole(data: any, id: string) { | ||||
| export function deleteRole(ids: string | Array<string>) { | ||||
|   return http.del(`${BASE_URL}/${ids}`) | ||||
| } | ||||
| /** @desc 获取角色绑定的用户列表 */ | ||||
| export function listRoleUsers(id: string) { | ||||
|   return http.get(`${BASE_URL}/listRoleUsers/${id}`) | ||||
| } | ||||
|  | ||||
| export function bindUsers(id: string, userIds : Array<string>) { | ||||
|   return http.post(`${BASE_URL}/bindUsers/${id}`,userIds) | ||||
| } | ||||
|   | ||||
							
								
								
									
										6
									
								
								src/types/auto-imports.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								src/types/auto-imports.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -46,6 +46,7 @@ declare global { | ||||
|   const onServerPrefetch: typeof import('vue')['onServerPrefetch'] | ||||
|   const onUnmounted: typeof import('vue')['onUnmounted'] | ||||
|   const onUpdated: typeof import('vue')['onUpdated'] | ||||
|   const onWatcherCleanup: typeof import('vue')['onWatcherCleanup'] | ||||
|   const provide: typeof import('vue')['provide'] | ||||
|   const reactive: typeof import('vue')['reactive'] | ||||
|   const readonly: typeof import('vue')['readonly'] | ||||
| @@ -66,10 +67,13 @@ declare global { | ||||
|   const useAttrs: typeof import('vue')['useAttrs'] | ||||
|   const useCssModule: typeof import('vue')['useCssModule'] | ||||
|   const useCssVars: typeof import('vue')['useCssVars'] | ||||
|   const useId: typeof import('vue')['useId'] | ||||
|   const useLink: typeof import('vue-router')['useLink'] | ||||
|   const useModel: typeof import('vue')['useModel'] | ||||
|   const useRoute: typeof import('vue-router')['useRoute'] | ||||
|   const useRouter: typeof import('vue-router')['useRouter'] | ||||
|   const useSlots: typeof import('vue')['useSlots'] | ||||
|   const useTemplateRef: typeof import('vue')['useTemplateRef'] | ||||
|   const watch: typeof import('vue')['watch'] | ||||
|   const watchEffect: typeof import('vue')['watchEffect'] | ||||
|   const watchPostEffect: typeof import('vue')['watchPostEffect'] | ||||
| @@ -78,6 +82,6 @@ declare global { | ||||
| // for type re-export | ||||
| declare global { | ||||
|   // @ts-ignore | ||||
|   export type { Component, ComponentPublicInstance, ComputedRef, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, VNode, WritableComputedRef } from 'vue' | ||||
|   export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' | ||||
|   import('vue') | ||||
| } | ||||
|   | ||||
							
								
								
									
										116
									
								
								src/views/system/role/RoleUserAssociation.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/views/system/role/RoleUserAssociation.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <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="{ data, 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 { bindUsers, listDeptWithUsersTree, listRoleUsers } from '@/apis';   | ||||
| import { ref } from 'vue';   | ||||
| import type { TransferItem } from '@arco-design/web-vue/es/transfer/interface'; | ||||
| import { Message, type TreeNodeData } from '@arco-design/web-vue'; | ||||
|  | ||||
| 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: disabled});   | ||||
|         }); | ||||
|         return treeDataSource;   | ||||
|     }; | ||||
|      | ||||
|     return travel(treeData.value);   | ||||
| };   | ||||
|  | ||||
| const onAssociation = async (id: string) => { | ||||
|     console.log(1); | ||||
|      | ||||
|     visible.value = true;   | ||||
|     roleId.value = id; | ||||
|     values.value = [] | ||||
|     getDeptList(); | ||||
|     listUsers(roleId.value); | ||||
| };   | ||||
| const getDeptList = async () => { | ||||
|     const res = await listDeptWithUsersTree({ status: 1 });   | ||||
|     treeData.value = res.data;   | ||||
|     transferData.value = getTransferData(treeData.value);   | ||||
| }; | ||||
|  | ||||
| const listUsers = async (roleId: string) => { | ||||
|     const res = await listRoleUsers(roleId);    | ||||
|     res.data.forEach(item => { | ||||
|         values.value.push( "user_" + item) | ||||
|     }) | ||||
|      | ||||
| }; | ||||
|  | ||||
|  | ||||
| defineExpose({   | ||||
|     onAssociation   | ||||
| });   | ||||
| </script>   | ||||
|  | ||||
| <style lang="scss" scoped>   | ||||
| :deep(.arco-transfer-view) {   | ||||
|     height: 40vh;   | ||||
|     width: 300px;   | ||||
| }   | ||||
| </style> | ||||
| @@ -51,6 +51,7 @@ | ||||
|       <template #action="{ record }"> | ||||
|         <a-space> | ||||
|           <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:delete']" | ||||
|             status="danger" | ||||
| @@ -67,6 +68,8 @@ | ||||
|     <RoleAddModal ref="RoleAddModalRef" @save-success="search" /> | ||||
|     <RoleUpdateDrawer ref="RoleUpdateDrawerRef" @save-success="search" /> | ||||
|     <RoleDetailDrawer ref="RoleDetailDrawerRef" /> | ||||
|     <RoleUserAssociation ref="RoleUserAssociationRef" /> | ||||
|  | ||||
|   </div> | ||||
| </template> | ||||
|  | ||||
| @@ -74,6 +77,7 @@ | ||||
| import RoleUpdateDrawer from './RoleUpdateDrawer.vue' | ||||
| import RoleDetailDrawer from './RoleDetailDrawer.vue' | ||||
| import RoleAddModal from './RoleAddModal.vue' | ||||
| import RoleUserAssociation from './RoleUserAssociation.vue' | ||||
| import { type RoleQuery, type RoleResp, deleteRole, listRole } from '@/apis/system' | ||||
| import type { TableInstanceColumns } from '@/components/GiTable/type' | ||||
| import { useTable } from '@/hooks' | ||||
| @@ -152,6 +156,12 @@ const RoleDetailDrawerRef = ref<InstanceType<typeof RoleDetailDrawer>>() | ||||
| const onDetail = (record: RoleResp) => { | ||||
|   RoleDetailDrawerRef.value?.onDetail(record.id) | ||||
| } | ||||
|  | ||||
| const RoleUserAssociationRef = ref<InstanceType<typeof RoleUserAssociation>>() | ||||
| // 关联用户 | ||||
| const onAssociation = (record: RoleResp) => { | ||||
|   RoleUserAssociationRef.value?.onAssociation(record.id) | ||||
| } | ||||
| </script> | ||||
|  | ||||
| <style lang="scss" scoped></style> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Wanghy
					Wanghy