Commit cb97b1cfc358a6934328bceffdb653cabda7d54e
Merge branch 'dev-fix-ww' into 'main_dev'
perf: 优化角色管理可分配菜单 See merge request yunteng/thingskit-front!552
Showing
8 changed files
with
83 additions
and
94 deletions
| ... | ... | @@ -7,4 +7,12 @@ export enum DictEnum { |
| 7 | 7 | DATA_VALIDATE = 'data_validate', |
| 8 | 8 | // 设备类型 |
| 9 | 9 | DEVICE_TYPE = 'device_type', |
| 10 | + // 平台管理员启用的权限 | |
| 11 | + ENABLED_PLATFORM_ADMIN_AUTH = 'enabled_platform_admin_auth', | |
| 12 | + // 系统管理员启用的权限 | |
| 13 | + ENABLED_SYSADMIN_AUTH = 'enabled_sysadmin_auth', | |
| 14 | + // 租户禁用的权限 | |
| 15 | + DISABLED_TENANT_AUTH = 'disabled_tenant_auth', | |
| 16 | + // 客户禁用的权限 | |
| 17 | + DISABLE_CUSTOMER_AUTH = 'disabled_customer_auth', | |
| 10 | 18 | } | ... | ... |
| ... | ... | @@ -17,7 +17,7 @@ function joinParentPath(menus: Menu[], parentPath = '') { |
| 17 | 17 | // https://next.router.vuejs.org/guide/essentials/nested-routes.html |
| 18 | 18 | // Note that nested paths that start with / will be treated as a root path. |
| 19 | 19 | // This allows you to leverage the component nesting without having to use a nested URL. |
| 20 | - if (!(menu.path.startsWith('/') || isUrl(menu.path))) { | |
| 20 | + if (!(menu?.path?.startsWith('/') || isUrl(menu.path))) { | |
| 21 | 21 | // path doesn't start with /, nor is it a url, join parent path |
| 22 | 22 | menu.path = `${parentPath}/${menu.path}`; |
| 23 | 23 | } | ... | ... |
| ... | ... | @@ -204,7 +204,7 @@ export const useUserStore = defineStore({ |
| 204 | 204 | const roleList = roles.map((item) => item) as RoleEnum[]; |
| 205 | 205 | this.setRoleList(roleList); |
| 206 | 206 | try { |
| 207 | - if (roleList[0] !== 'SYS_ADMIN') { | |
| 207 | + if (roleList[0] !== RoleEnum.SYS_ADMIN && roleList[0] !== RoleEnum.PLATFORM_ADMIN) { | |
| 208 | 208 | const res = await getEntitiesId(); |
| 209 | 209 | const entityId = res.data[0]?.entityId; |
| 210 | 210 | window.localStorage.setItem('entityId', JSON.stringify(entityId)); | ... | ... |
| ... | ... | @@ -84,8 +84,11 @@ |
| 84 | 84 | // 在打开弹窗时清除所有选择的菜单 |
| 85 | 85 | treeRef.value && treeRef.value?.setCheckedKeys([]); |
| 86 | 86 | isUpdate.value = data.isUpdate; |
| 87 | - const roleType = data?.record?.roleType || userStore.getRoleList.at(0); | |
| 88 | - | |
| 87 | + let roleType = (userStore.getUserInfo.roles![0] as RoleEnum) || RoleEnum.SYS_ADMIN; | |
| 88 | + // 租户管理员创建角色时 菜单分配为客户菜单 | |
| 89 | + if (roleType === RoleEnum.TENANT_ADMIN) { | |
| 90 | + roleType = RoleEnum.CUSTOMER_USER; | |
| 91 | + } | |
| 89 | 92 | try { |
| 90 | 93 | spinning.value = true; |
| 91 | 94 | // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 |
| ... | ... | @@ -98,7 +101,7 @@ |
| 98 | 101 | |
| 99 | 102 | const keys = await getPermissionByRole(roleType); |
| 100 | 103 | const { keyType } = RoleMenuDictEnum[roleType]; |
| 101 | - treeData.value = getPermissionTreeData( | |
| 104 | + treeData.value = filterPermissionTreeData( | |
| 102 | 105 | unref(treeData) as unknown as TreeData[], |
| 103 | 106 | keys, |
| 104 | 107 | keyType |
| ... | ... | @@ -164,61 +167,46 @@ |
| 164 | 167 | return []; |
| 165 | 168 | }; |
| 166 | 169 | |
| 167 | - const getPermissionTreeData = ( | |
| 170 | + const filterPermissionTreeData = ( | |
| 168 | 171 | data: MenuRecord[], |
| 169 | 172 | permissionKeys: string[], |
| 170 | 173 | keysType: KeysTypeEnum |
| 171 | - ) => { | |
| 172 | - const setDisabled = (data: MenuRecord[], flag: boolean) => { | |
| 173 | - return data.map((item) => { | |
| 174 | - item.name = t(item.name); | |
| 175 | - if (item.children && item.children.length) { | |
| 176 | - item.children = setDisabled(item.children, flag); | |
| 177 | - } | |
| 178 | - return { | |
| 179 | - ...item, | |
| 180 | - disabled: flag, | |
| 181 | - icon: item.meta.icon, | |
| 182 | - } as TreeData; | |
| 183 | - }); | |
| 184 | - }; | |
| 185 | - | |
| 174 | + ): TreeData[] => { | |
| 186 | 175 | const permissionCompare = ( |
| 187 | 176 | data: MenuRecord[], |
| 188 | 177 | permissionKeys: string[], |
| 189 | 178 | keysType: KeysTypeEnum |
| 190 | - ) => { | |
| 191 | - return data.map((item) => { | |
| 179 | + ): TreeData[] => { | |
| 180 | + return data.filter((item) => { | |
| 192 | 181 | item.name = t(item.name); |
| 193 | 182 | const findFlag = permissionKeys.includes(item.permission); |
| 194 | - if (findFlag) item.isDictCompareDisabled = true; | |
| 195 | - const disabledFlag = keysType === KeysTypeEnum.DISABLED ? findFlag : !findFlag; | |
| 196 | - item.disabled = disabledFlag; | |
| 197 | 183 | |
| 198 | - if (item.isDictCompareDisabled && item.children && item.children.length) { | |
| 199 | - setDisabled(item.children, disabledFlag); | |
| 200 | - } else { | |
| 201 | - if (item.children && item.children.length) { | |
| 184 | + item.show = findFlag ? keysType === KeysTypeEnum.ENABLED : undefined; | |
| 185 | + | |
| 186 | + if (item.children && item.children.length) { | |
| 187 | + if (item.show) return true; | |
| 188 | + if (item.show === undefined) { | |
| 202 | 189 | item.children = permissionCompare(item.children, permissionKeys, keysType); |
| 203 | - item.disabled = item.children.every((temp) => temp.disabled); | |
| 190 | + item.show = item.children.some((item) => | |
| 191 | + keysType === KeysTypeEnum.ENABLED | |
| 192 | + ? item.show | |
| 193 | + : item.show === undefined | |
| 194 | + ? true | |
| 195 | + : item.show | |
| 196 | + ); | |
| 197 | + return item.show; | |
| 204 | 198 | } |
| 205 | 199 | } |
| 206 | - return { | |
| 207 | - ...item, | |
| 208 | - icon: item.meta.icon, | |
| 209 | - } as TreeData; | |
| 210 | - }); | |
| 211 | - }; | |
| 212 | 200 | |
| 213 | - const result = permissionCompare(data, permissionKeys, keysType).map((item) => { | |
| 214 | - if (item.children && item.children.length) { | |
| 215 | - const rootDisabledFlag = item.children.every((temp) => temp.disabled); | |
| 216 | - item.disabled = rootDisabledFlag; | |
| 217 | - } | |
| 218 | - return item; | |
| 219 | - }); | |
| 201 | + return keysType === KeysTypeEnum.ENABLED | |
| 202 | + ? item.show | |
| 203 | + : item.show === undefined | |
| 204 | + ? true | |
| 205 | + : item.show; | |
| 206 | + }) as unknown as TreeData[]; | |
| 207 | + }; | |
| 220 | 208 | |
| 221 | - return result; | |
| 209 | + return permissionCompare(data, permissionKeys, keysType); | |
| 222 | 210 | }; |
| 223 | 211 | |
| 224 | 212 | const excludeHalfCheckedKeys = (treeData: MenuRecord[]) => { | ... | ... |
| 1 | 1 | import { BasicColumn } from '/@/components/Table'; |
| 2 | 2 | import { FormSchema } from '/@/components/Table'; |
| 3 | +import { DictEnum } from '/@/enums/dictEnum'; | |
| 3 | 4 | import { RoleEnum } from '/@/enums/roleEnum'; |
| 4 | 5 | |
| 5 | 6 | export enum KeysTypeEnum { |
| ... | ... | @@ -8,10 +9,13 @@ export enum KeysTypeEnum { |
| 8 | 9 | } |
| 9 | 10 | |
| 10 | 11 | export const RoleMenuDictEnum: Recordable<{ key: string; keyType: KeysTypeEnum }> = { |
| 11 | - [RoleEnum.PLATFORM_ADMIN]: { key: 'enabled_platform_admin_auth', keyType: KeysTypeEnum.ENABLED }, | |
| 12 | - [RoleEnum.SYS_ADMIN]: { key: 'enabled_sysadmin_auth', keyType: KeysTypeEnum.ENABLED }, | |
| 13 | - [RoleEnum.TENANT_ADMIN]: { key: 'disabled_tenant_auth', keyType: KeysTypeEnum.DISABLED }, | |
| 14 | - [RoleEnum.CUSTOMER_USER]: { key: 'disabled_tenant_auth', keyType: KeysTypeEnum.DISABLED }, | |
| 12 | + [RoleEnum.PLATFORM_ADMIN]: { | |
| 13 | + key: DictEnum.ENABLED_PLATFORM_ADMIN_AUTH, | |
| 14 | + keyType: KeysTypeEnum.ENABLED, | |
| 15 | + }, | |
| 16 | + [RoleEnum.SYS_ADMIN]: { key: DictEnum.ENABLED_SYSADMIN_AUTH, keyType: KeysTypeEnum.ENABLED }, | |
| 17 | + [RoleEnum.TENANT_ADMIN]: { key: DictEnum.DISABLED_TENANT_AUTH, keyType: KeysTypeEnum.DISABLED }, | |
| 18 | + [RoleEnum.CUSTOMER_USER]: { key: DictEnum.DISABLE_CUSTOMER_AUTH, keyType: KeysTypeEnum.DISABLED }, | |
| 15 | 19 | }; |
| 16 | 20 | |
| 17 | 21 | export const columns: BasicColumn[] = [ | ... | ... |
| ... | ... | @@ -43,6 +43,7 @@ |
| 43 | 43 | import { KeysTypeEnum, RoleMenuDictEnum } from '../../system/role/role.data'; |
| 44 | 44 | import { findDictItemByCode } from '/@/api/system/dict'; |
| 45 | 45 | import { Spin } from 'ant-design-vue'; |
| 46 | + import { useUserStore } from '/@/store/modules/user'; | |
| 46 | 47 | |
| 47 | 48 | type TreeData = MenuRecord & TreeItem; |
| 48 | 49 | |
| ... | ... | @@ -76,6 +77,7 @@ |
| 76 | 77 | }); |
| 77 | 78 | }; |
| 78 | 79 | |
| 80 | + const userStore = useUserStore(); | |
| 79 | 81 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { |
| 80 | 82 | allCheckedKeys.value = []; |
| 81 | 83 | resetFields(); |
| ... | ... | @@ -83,7 +85,11 @@ |
| 83 | 85 | // 在打开弹窗时清除所有选择的菜单 |
| 84 | 86 | treeRef.value && treeRef.value?.setCheckedKeys([]); |
| 85 | 87 | isUpdate.value = data.isUpdate; |
| 86 | - const roleType = data?.record?.roleType || RoleEnum.TENANT_ADMIN; | |
| 88 | + let roleType = (userStore.getUserInfo.roles![0] as RoleEnum) || RoleEnum.SYS_ADMIN; | |
| 89 | + // 平台管理员创建角色时 菜单分配为租户管理员可分配的菜单 | |
| 90 | + if (roleType === RoleEnum.PLATFORM_ADMIN) { | |
| 91 | + roleType = RoleEnum.TENANT_ADMIN; | |
| 92 | + } | |
| 87 | 93 | try { |
| 88 | 94 | spinning.value = true; |
| 89 | 95 | // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 |
| ... | ... | @@ -93,10 +99,9 @@ |
| 93 | 99 | const menuListModel = await getMenuList(); |
| 94 | 100 | treeData.value = transformName(menuListModel as unknown as TreeData[]); |
| 95 | 101 | } |
| 96 | - | |
| 97 | 102 | const keys = await getPermissionByRole(roleType); |
| 98 | 103 | const { keyType } = RoleMenuDictEnum[roleType]; |
| 99 | - treeData.value = getPermissionTreeData( | |
| 104 | + treeData.value = filterPermissionTreeData( | |
| 100 | 105 | unref(treeData) as unknown as TreeData[], |
| 101 | 106 | keys, |
| 102 | 107 | keyType |
| ... | ... | @@ -168,61 +173,46 @@ |
| 168 | 173 | return []; |
| 169 | 174 | }; |
| 170 | 175 | |
| 171 | - const getPermissionTreeData = ( | |
| 176 | + const filterPermissionTreeData = ( | |
| 172 | 177 | data: MenuRecord[], |
| 173 | 178 | permissionKeys: string[], |
| 174 | 179 | keysType: KeysTypeEnum |
| 175 | - ) => { | |
| 176 | - const setDisabled = (data: MenuRecord[], flag: boolean) => { | |
| 177 | - return data.map((item) => { | |
| 178 | - item.name = t(item.name); | |
| 179 | - if (item.children && item.children.length) { | |
| 180 | - item.children = setDisabled(item.children, flag); | |
| 181 | - } | |
| 182 | - return { | |
| 183 | - ...item, | |
| 184 | - disabled: flag, | |
| 185 | - icon: item.meta.icon, | |
| 186 | - } as TreeData; | |
| 187 | - }); | |
| 188 | - }; | |
| 189 | - | |
| 180 | + ): TreeData[] => { | |
| 190 | 181 | const permissionCompare = ( |
| 191 | 182 | data: MenuRecord[], |
| 192 | 183 | permissionKeys: string[], |
| 193 | 184 | keysType: KeysTypeEnum |
| 194 | - ) => { | |
| 195 | - return data.map((item) => { | |
| 185 | + ): TreeData[] => { | |
| 186 | + return data.filter((item) => { | |
| 196 | 187 | item.name = t(item.name); |
| 197 | 188 | const findFlag = permissionKeys.includes(item.permission); |
| 198 | - if (findFlag) item.isDictCompareDisabled = true; | |
| 199 | - const disabledFlag = keysType === KeysTypeEnum.DISABLED ? findFlag : !findFlag; | |
| 200 | - item.disabled = disabledFlag; | |
| 201 | 189 | |
| 202 | - if (item.isDictCompareDisabled && item.children && item.children.length) { | |
| 203 | - setDisabled(item.children, disabledFlag); | |
| 204 | - } else { | |
| 205 | - if (item.children && item.children.length) { | |
| 190 | + item.show = findFlag ? keysType === KeysTypeEnum.ENABLED : undefined; | |
| 191 | + | |
| 192 | + if (item.children && item.children.length) { | |
| 193 | + if (item.show) return true; | |
| 194 | + if (item.show === undefined) { | |
| 206 | 195 | item.children = permissionCompare(item.children, permissionKeys, keysType); |
| 207 | - item.disabled = item.children.every((temp) => temp.disabled); | |
| 196 | + item.show = item.children.some((item) => | |
| 197 | + keysType === KeysTypeEnum.ENABLED | |
| 198 | + ? item.show | |
| 199 | + : item.show === undefined | |
| 200 | + ? true | |
| 201 | + : item.show | |
| 202 | + ); | |
| 203 | + return item.show; | |
| 208 | 204 | } |
| 209 | 205 | } |
| 210 | - return { | |
| 211 | - ...item, | |
| 212 | - icon: item.meta.icon, | |
| 213 | - } as TreeData; | |
| 214 | - }); | |
| 215 | - }; | |
| 216 | 206 | |
| 217 | - const result = permissionCompare(data, permissionKeys, keysType).map((item) => { | |
| 218 | - if (item.children && item.children.length) { | |
| 219 | - const rootDisabledFlag = item.children.every((temp) => temp.disabled); | |
| 220 | - item.disabled = rootDisabledFlag; | |
| 221 | - } | |
| 222 | - return item; | |
| 223 | - }); | |
| 207 | + return keysType === KeysTypeEnum.ENABLED | |
| 208 | + ? item.show | |
| 209 | + : item.show === undefined | |
| 210 | + ? true | |
| 211 | + : item.show; | |
| 212 | + }) as unknown as TreeData[]; | |
| 213 | + }; | |
| 224 | 214 | |
| 225 | - return result; | |
| 215 | + return permissionCompare(data, permissionKeys, keysType); | |
| 226 | 216 | }; |
| 227 | 217 | |
| 228 | 218 | const excludeHalfCheckedKeys = (treeData: MenuRecord[]) => { | ... | ... |