mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-10-31 02:08:45 +08:00 
			
		
		
		
	REVIEW 角色管理(设置数据权限)
This commit is contained in:
		| @@ -22,12 +22,12 @@ export const getRoleMenuList = async (roleId: number) => { | ||||
| } | ||||
|  | ||||
| // 赋予角色菜单权限 | ||||
| export const assignRoleMenuApi = async (data: PermissionAssignRoleMenuReqVO) => { | ||||
| export const assignRoleMenu = async (data: PermissionAssignRoleMenuReqVO) => { | ||||
|   return await request.post({ url: '/system/permission/assign-role-menu', data }) | ||||
| } | ||||
|  | ||||
| // 赋予角色数据权限 | ||||
| export const assignRoleDataScopeApi = async (data: PermissionAssignRoleDataScopeReqVO) => { | ||||
| export const assignRoleDataScope = async (data: PermissionAssignRoleDataScopeReqVO) => { | ||||
|   return await request.post({ url: '/system/permission/assign-role-data-scope', data }) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,8 @@ export interface RoleVO { | ||||
|   sort: number | ||||
|   status: number | ||||
|   type: number | ||||
|   dataScope: number | ||||
|   dataScopeDeptIds: number[] | ||||
|   createTime: Date | ||||
| } | ||||
|  | ||||
| @@ -49,6 +51,7 @@ export const updateRoleStatus = async (data: UpdateStatusReqVO) => { | ||||
| export const deleteRole = async (id: number) => { | ||||
|   return await request.delete({ url: '/system/role/delete?id=' + id }) | ||||
| } | ||||
|  | ||||
| // 导出角色 | ||||
| export const exportRole = (params) => { | ||||
|   return request.download({ | ||||
|   | ||||
| @@ -1,174 +0,0 @@ | ||||
| <template> | ||||
|   <Dialog :title="dialogScopeTitle" v-model="dialogScopeVisible" width="800"> | ||||
|     <el-form | ||||
|       ref="dataPermissionFormRef" | ||||
|       :model="dataScopeForm" | ||||
|       :inline="true" | ||||
|       label-width="80px" | ||||
|       v-loading="formLoading" | ||||
|     > | ||||
|       <el-form-item label="角色名称"> | ||||
|         <el-tag>{{ dataScopeForm.name }}</el-tag> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="角色标识"> | ||||
|         <el-tag>{{ dataScopeForm.code }}</el-tag> | ||||
|       </el-form-item> | ||||
|       <!-- 分配角色的数据权限对话框 --> | ||||
|       <el-form-item label="权限范围"> | ||||
|         <el-select v-model="dataScopeForm.dataScope"> | ||||
|           <el-option | ||||
|             v-for="item in dataScopeDictDatas" | ||||
|             :key="item.value" | ||||
|             :label="item.label" | ||||
|             :value="item.value" | ||||
|           /> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <!-- 分配角色的菜单权限对话框 --> | ||||
|     <el-row> | ||||
|       <el-col :span="24"> | ||||
|         <el-form-item | ||||
|           label="权限范围" | ||||
|           v-if=" | ||||
|             actionScopeType === 'menu' || | ||||
|             dataScopeForm.dataScope === SystemDataScopeEnum.DEPT_CUSTOM | ||||
|           " | ||||
|           style="display: flex" | ||||
|         > | ||||
|           <el-card class="card" shadow="never"> | ||||
|             <template #header> | ||||
|               父子联动(选中父节点,自动选择子节点): | ||||
|               <el-switch | ||||
|                 v-model="checkStrictly" | ||||
|                 inline-prompt | ||||
|                 active-text="是" | ||||
|                 inactive-text="否" | ||||
|               /> | ||||
|               全选/全不选: | ||||
|               <el-switch | ||||
|                 v-model="treeNodeAll" | ||||
|                 inline-prompt | ||||
|                 active-text="是" | ||||
|                 inactive-text="否" | ||||
|                 @change="handleCheckedTreeNodeAll()" | ||||
|               /> | ||||
|             </template> | ||||
|             <el-tree | ||||
|               ref="treeRef" | ||||
|               node-key="id" | ||||
|               show-checkbox | ||||
|               :check-strictly="!checkStrictly" | ||||
|               :props="defaultProps" | ||||
|               :data="treeOptions" | ||||
|               empty-text="加载中,请稍后" | ||||
|             /> | ||||
|           </el-card> | ||||
|         </el-form-item> </el-col | ||||
|     ></el-row> | ||||
|  | ||||
|     <!-- 操作按钮 --> | ||||
|     <template #footer> | ||||
|       <div class="dialog-footer"> | ||||
|         <el-button | ||||
|           :title="t('action.save')" | ||||
|           :loading="actionLoading" | ||||
|           @click="submitScope()" | ||||
|           type="primary" | ||||
|           :disabled="formLoading" | ||||
|         > | ||||
|           保存 | ||||
|         </el-button> | ||||
|         <el-button | ||||
|           :loading="actionLoading" | ||||
|           :title="t('dialog.close')" | ||||
|           @click="dialogScopeVisible = false" | ||||
|           >取 消</el-button | ||||
|         > | ||||
|       </div> | ||||
|     </template> | ||||
|   </Dialog> | ||||
| </template> | ||||
|  | ||||
| <script setup lang="ts"> | ||||
| import * as RoleApi from '@/api/system/role' | ||||
| import type { ElTree } from 'element-plus' | ||||
| import type { FormExpose } from '@/components/Form' | ||||
| import { handleTree, defaultProps } from '@/utils/tree' | ||||
| import { SystemDataScopeEnum } from '@/utils/constants' | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import * as DeptApi from '@/api/system/dept' | ||||
| import * as PermissionApi from '@/api/system/permission' | ||||
| // ========== CRUD 相关 ========== | ||||
| const actionLoading = ref(false) // 遮罩层 | ||||
| const dataPermissionFormRef = ref<FormExpose>() // 表单 Ref | ||||
| const { t } = useI18n() // 国际化 | ||||
| const dialogScopeTitle = ref('菜单权限') | ||||
| const dataScopeDictDatas = ref() | ||||
| const message = useMessage() // 消息弹窗 | ||||
| const actionScopeType = ref('') | ||||
| // 选项 | ||||
| const treeNodeAll = ref(false) | ||||
| const checkStrictly = ref(true) | ||||
| const dialogScopeVisible = ref(false) // 弹窗的是否展示 | ||||
| const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | ||||
| const treeOptions = ref<any[]>([]) // 菜单树形结构 | ||||
| const treeRef = ref<InstanceType<typeof ElTree>>() | ||||
| // ========== 数据权限 ========== | ||||
| const dataScopeForm = reactive({ | ||||
|   id: 0, | ||||
|   name: '', | ||||
|   code: '', | ||||
|   dataScope: 0, | ||||
|   checkList: [] | ||||
| }) | ||||
|  | ||||
| /** 打开弹窗 */ | ||||
| const openModal = async (type: string, row: RoleApi.RoleVO) => { | ||||
|   dataScopeForm.id = row.id | ||||
|   dataScopeForm.name = row.name | ||||
|   dataScopeForm.code = row.code | ||||
|   actionScopeType.value = type | ||||
|   dialogScopeVisible.value = true | ||||
|   const deptRes = await DeptApi.getSimpleDeptList() | ||||
|   treeOptions.value = handleTree(deptRes) | ||||
|   const role = await RoleApi.getRole(row.id) | ||||
|   dataScopeForm.dataScope = role.dataScope | ||||
|   if (role.dataScopeDeptIds) { | ||||
|     role.dataScopeDeptIds?.forEach((item: any) => { | ||||
|       unref(treeRef)?.setChecked(item, true, false) | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|  | ||||
| // 保存权限 | ||||
| const submitScope = async () => { | ||||
|   const data = ref<PermissionApi.PermissionAssignRoleDataScopeReqVO>({ | ||||
|     roleId: dataScopeForm.id, | ||||
|     dataScope: dataScopeForm.dataScope, | ||||
|     dataScopeDeptIds: | ||||
|       dataScopeForm.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM | ||||
|         ? [] | ||||
|         : (treeRef.value!.getCheckedKeys(false) as unknown as Array<number>) | ||||
|   }) | ||||
|   await PermissionApi.assignRoleDataScopeApi(data.value) | ||||
|  | ||||
|   message.success(t('common.updateSuccess')) | ||||
|   dialogScopeVisible.value = false | ||||
| } | ||||
|  | ||||
| // 全选/全不选 | ||||
| const handleCheckedTreeNodeAll = () => { | ||||
|   treeRef.value!.setCheckedNodes(treeNodeAll.value ? treeOptions.value : []) | ||||
| } | ||||
|  | ||||
| const init = () => { | ||||
|   dataScopeDictDatas.value = getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE) | ||||
| } | ||||
|  | ||||
| defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗 | ||||
| // ========== 初始化 ========== | ||||
| onMounted(() => { | ||||
|   init() | ||||
| }) | ||||
| </script> | ||||
| @@ -1,12 +1,6 @@ | ||||
| <template> | ||||
|   <Dialog title="菜单权限" v-model="modelVisible"> | ||||
|     <el-form | ||||
|       ref="formRef" | ||||
|       :model="formData" | ||||
|       :inline="true" | ||||
|       label-width="80px" | ||||
|       v-loading="formLoading" | ||||
|     > | ||||
|     <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading"> | ||||
|       <el-form-item label="角色名称"> | ||||
|         <el-tag>{{ formData.name }}</el-tag> | ||||
|       </el-form-item> | ||||
| @@ -53,7 +47,6 @@ | ||||
| <script setup lang="ts"> | ||||
| import { handleTree, defaultProps } from '@/utils/tree' | ||||
| import * as RoleApi from '@/api/system/role' | ||||
| import type { ElTree } from 'element-plus' | ||||
| import * as MenuApi from '@/api/system/menu' | ||||
| import * as PermissionApi from '@/api/system/permission' | ||||
| const { t } = useI18n() // 国际化 | ||||
| @@ -70,7 +63,7 @@ const formData = reactive({ | ||||
| const formRef = ref() // 表单 Ref | ||||
| const menuOptions = ref<any[]>([]) // 菜单树形结构 | ||||
| const menuExpand = ref(false) // 展开/折叠 | ||||
| const treeRef = ref<InstanceType<typeof ElTree>>() // 树组件 Ref | ||||
| const treeRef = ref() // 菜单树组件 Ref | ||||
| const treeNodeAll = ref(false) // 全选/全不选 | ||||
|  | ||||
| /** 打开弹窗 */ | ||||
| @@ -112,7 +105,7 @@ const submitForm = async () => { | ||||
|         ...(treeRef.value.getHalfCheckedKeys() as unknown as Array<number>) // 获得半选中的父节点 | ||||
|       ] | ||||
|     } | ||||
|     await PermissionApi.assignRoleMenuApi(data) | ||||
|     await PermissionApi.assignRoleMenu(data) | ||||
|     message.success(t('common.updateSuccess')) | ||||
|     modelVisible.value = false | ||||
|   } finally { | ||||
|   | ||||
							
								
								
									
										161
									
								
								src/views/system/role/RoleDataPermissionForm.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								src/views/system/role/RoleDataPermissionForm.vue
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| <template> | ||||
|   <Dialog title="菜单权限" v-model="modelVisible" width="800"> | ||||
|     <el-form ref="formRef" :model="formData" label-width="80px" v-loading="formLoading"> | ||||
|       <el-form-item label="角色名称"> | ||||
|         <el-tag>{{ formData.name }}</el-tag> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="角色标识"> | ||||
|         <el-tag>{{ formData.code }}</el-tag> | ||||
|       </el-form-item> | ||||
|       <el-form-item label="权限范围"> | ||||
|         <el-select v-model="formData.dataScope"> | ||||
|           <el-option | ||||
|             v-for="item in getIntDictOptions(DICT_TYPE.SYSTEM_DATA_SCOPE)" | ||||
|             :key="item.value" | ||||
|             :label="item.label" | ||||
|             :value="item.value" | ||||
|           /> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|     <el-form-item | ||||
|       label="权限范围" | ||||
|       v-if="formData.dataScope === SystemDataScopeEnum.DEPT_CUSTOM" | ||||
|       style="display: flex" | ||||
|     > | ||||
|       <el-card class="card" shadow="never"> | ||||
|         <template #header> | ||||
|           全选/全不选: | ||||
|           <el-switch | ||||
|             v-model="treeNodeAll" | ||||
|             inline-prompt | ||||
|             active-text="是" | ||||
|             inactive-text="否" | ||||
|             @change="handleCheckedTreeNodeAll()" | ||||
|           /> | ||||
|           全部展开/折叠: | ||||
|           <el-switch | ||||
|             v-model="deptExpand" | ||||
|             inline-prompt | ||||
|             active-text="展开" | ||||
|             inactive-text="折叠" | ||||
|             @change="handleCheckedTreeExpand" | ||||
|           /> | ||||
|           父子联动(选中父节点,自动选择子节点): | ||||
|           <el-switch v-model="checkStrictly" inline-prompt active-text="是" inactive-text="否" /> | ||||
|         </template> | ||||
|         <el-tree | ||||
|           ref="treeRef" | ||||
|           node-key="id" | ||||
|           show-checkbox | ||||
|           :check-strictly="!checkStrictly" | ||||
|           :props="defaultProps" | ||||
|           :data="deptOptions" | ||||
|           empty-text="加载中,请稍后" | ||||
|           default-expand-all | ||||
|         /> | ||||
|       </el-card> | ||||
|     </el-form-item> | ||||
|     <template #footer> | ||||
|       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button> | ||||
|       <el-button @click="modelVisible = false">取 消</el-button> | ||||
|     </template> | ||||
|   </Dialog> | ||||
| </template> | ||||
| <script setup lang="ts"> | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| import { handleTree, defaultProps } from '@/utils/tree' | ||||
| import { SystemDataScopeEnum } from '@/utils/constants' | ||||
| import * as RoleApi from '@/api/system/role' | ||||
| import * as DeptApi from '@/api/system/dept' | ||||
| import * as PermissionApi from '@/api/system/permission' | ||||
| const { t } = useI18n() // 国际化 | ||||
| const message = useMessage() // 消息弹窗 | ||||
|  | ||||
| const modelVisible = ref(false) // 弹窗的是否展示 | ||||
| const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用 | ||||
| const formData = reactive({ | ||||
|   id: 0, | ||||
|   name: '', | ||||
|   code: '', | ||||
|   dataScope: undefined, | ||||
|   dataScopeDeptIds: [] | ||||
| }) | ||||
| const formRef = ref() // 表单 Ref | ||||
| const deptOptions = ref<any[]>([]) // 部门树形结构 | ||||
| const deptExpand = ref(false) // 展开/折叠 | ||||
| const treeRef = ref() // 菜单树组件 Ref | ||||
| const treeNodeAll = ref(false) // 全选/全不选 | ||||
| const checkStrictly = ref(true) // 是否严格模式,即父子不关联 | ||||
|  | ||||
| /** 打开弹窗 */ | ||||
| const open = async (row: RoleApi.RoleVO) => { | ||||
|   modelVisible.value = true | ||||
|   resetForm() | ||||
|   // 加载 Dept 列表。注意,必须放在前面,不然下面 setChecked 没数据节点 | ||||
|   deptOptions.value = handleTree(await DeptApi.getSimpleDeptList()) | ||||
|   // 设置数据 | ||||
|   formData.id = row.id | ||||
|   formData.name = row.name | ||||
|   formData.code = row.code | ||||
|   formData.dataScope = row.dataScope | ||||
|   row.dataScopeDeptIds?.forEach((deptId: number) => { | ||||
|     treeRef.value.setChecked(deptId, true, false) | ||||
|   }) | ||||
| } | ||||
| defineExpose({ open }) // 提供 open 方法,用于打开弹窗 | ||||
|  | ||||
| /** 提交表单 */ | ||||
| const submitForm = async () => { | ||||
|   formLoading.value = true | ||||
|   try { | ||||
|     const data = { | ||||
|       roleId: formData.id, | ||||
|       dataScope: formData.dataScope, | ||||
|       dataScopeDeptIds: | ||||
|         formData.dataScope !== SystemDataScopeEnum.DEPT_CUSTOM | ||||
|           ? [] | ||||
|           : treeRef.value.getCheckedKeys(false) | ||||
|     } | ||||
|     await PermissionApi.assignRoleDataScope(data) | ||||
|     message.success(t('common.updateSuccess')) | ||||
|     modelVisible.value = false | ||||
|   } finally { | ||||
|     formLoading.value = false | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** 重置表单 */ | ||||
| const resetForm = () => { | ||||
|   // 重置选项 | ||||
|   treeNodeAll.value = false | ||||
|   deptExpand.value = false | ||||
|   checkStrictly.value = true | ||||
|   // 重置表单 | ||||
|   formData.value = { | ||||
|     id: 0, | ||||
|     name: '', | ||||
|     code: '', | ||||
|     dataScope: undefined, | ||||
|     dataScopeDeptIds: [] | ||||
|   } | ||||
|   treeRef.value?.setCheckedNodes([]) | ||||
|   formRef.value?.resetFields() | ||||
| } | ||||
|  | ||||
| /** 全选/全不选 */ | ||||
| const handleCheckedTreeNodeAll = () => { | ||||
|   treeRef.value.setCheckedNodes(treeNodeAll.value ? deptOptions.value : []) | ||||
| } | ||||
|  | ||||
| /** 展开/折叠全部 */ | ||||
| const handleCheckedTreeExpand = () => { | ||||
|   const nodes = treeRef.value?.store.nodesMap | ||||
|   for (let node in nodes) { | ||||
|     if (nodes[node].expanded === deptExpand.value) { | ||||
|       continue | ||||
|     } | ||||
|     nodes[node].expanded = deptExpand.value | ||||
|   } | ||||
| } | ||||
| </script> | ||||
| @@ -118,7 +118,7 @@ | ||||
|             preIcon="ep:coin" | ||||
|             title="数据权限" | ||||
|             v-hasPermi="['system:permission:assign-role-data-scope']" | ||||
|             @click="handleScope('data', scope.row)" | ||||
|             @click="openDataPermissionForm(scope.row)" | ||||
|           > | ||||
|             数据权限 | ||||
|           </el-button> | ||||
| @@ -145,9 +145,9 @@ | ||||
|   <!-- 表单弹窗:添加/修改 --> | ||||
|   <RoleForm ref="formRef" @success="getList" /> | ||||
|   <!-- 表单弹窗:菜单权限 --> | ||||
|   <RoleAssignMenuForm ref="assignMenuFormRef" @success="getList" /> | ||||
|   <RoleAssignMenuForm ref="assignMenuFormRef" /> | ||||
|   <!-- 表单弹窗:数据权限 --> | ||||
|   <DataPermissionForm ref="dataPermissionFormRef" @success="getList" /> | ||||
|   <RoleDataPermissionForm ref="dataPermissionFormRef" /> | ||||
| </template> | ||||
| <script setup lang="tsx"> | ||||
| import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' | ||||
| @@ -156,7 +156,7 @@ import download from '@/utils/download' | ||||
| import * as RoleApi from '@/api/system/role' | ||||
| import RoleForm from './RoleForm.vue' | ||||
| import RoleAssignMenuForm from './RoleAssignMenuForm.vue' | ||||
| import DataPermissionForm from './DataPermissionForm.vue' | ||||
| import RoleDataPermissionForm from './RoleDataPermissionForm.vue' | ||||
| const message = useMessage() // 消息弹窗 | ||||
| const { t } = useI18n() // 国际化 | ||||
|  | ||||
| @@ -206,13 +206,8 @@ const openForm = (type: string, id?: number) => { | ||||
|  | ||||
| /** 数据权限操作 */ | ||||
| const dataPermissionFormRef = ref() | ||||
|  | ||||
| const handleScope = async (type: string, row: RoleApi.RoleVO) => { | ||||
|   if (type === 'menu') { | ||||
|     assignMenuFormRef.value.openModal(type, row) | ||||
|   } else if (type === 'data') { | ||||
|     dataPermissionFormRef.value.openModal(type, row) | ||||
|   } | ||||
| const openDataPermissionForm = async (row: RoleApi.RoleVO) => { | ||||
|   dataPermissionFormRef.value.open(row) | ||||
| } | ||||
|  | ||||
| /** 菜单权限操作 */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV