Commit ee0eb18114ebd977e677721223a8510ede9770cf
1 parent
195ab9cb
fix: role assign disabled not has permission menu item
Showing
5 changed files
with
339 additions
and
157 deletions
@@ -18,3 +18,32 @@ export interface RouteItem { | @@ -18,3 +18,32 @@ export interface RouteItem { | ||
18 | * @description: Get menu return value | 18 | * @description: Get menu return value |
19 | */ | 19 | */ |
20 | export type getMenuListResultModel = RouteItem[]; | 20 | export type getMenuListResultModel = RouteItem[]; |
21 | + | ||
22 | +export interface Meta { | ||
23 | + title: string; | ||
24 | + menuType: string; | ||
25 | + status: string; | ||
26 | + icon: string; | ||
27 | + isLink: boolean; | ||
28 | + ignoreKeepAlive: boolean; | ||
29 | + hideMenu: boolean; | ||
30 | +} | ||
31 | + | ||
32 | +export interface MenuRecord { | ||
33 | + id: string; | ||
34 | + createTime: string; | ||
35 | + updateTime: string; | ||
36 | + name: string; | ||
37 | + children: MenuRecord[]; | ||
38 | + path: string; | ||
39 | + type: string; | ||
40 | + permission: string; | ||
41 | + sort: number; | ||
42 | + component: string; | ||
43 | + meta: Meta; | ||
44 | + disabled?: boolean; | ||
45 | + isDictCompareDisabled?: boolean; | ||
46 | + icon?: string; | ||
47 | + title?: string; | ||
48 | + key?: string; | ||
49 | +} |
@@ -9,18 +9,20 @@ | @@ -9,18 +9,20 @@ | ||
9 | > | 9 | > |
10 | <BasicForm @register="registerForm"> | 10 | <BasicForm @register="registerForm"> |
11 | <template #menu> | 11 | <template #menu> |
12 | - <BasicTree | ||
13 | - v-if="treeData.length" | ||
14 | - checkable | ||
15 | - toolbar | ||
16 | - :expandedKeys="treeExpandData" | ||
17 | - ref="treeRef" | ||
18 | - :treeData="treeData" | ||
19 | - :replaceFields="{ title: 'menuName' }" | ||
20 | - :checkedKeys="roleMenus" | ||
21 | - @check="handleCheckClick" | ||
22 | - title="菜单分配" | ||
23 | - /> | 12 | + <Spin :spinning="spinning"> |
13 | + <BasicTree | ||
14 | + v-if="treeData.length" | ||
15 | + checkable | ||
16 | + toolbar | ||
17 | + :expandedKeys="treeExpandData" | ||
18 | + ref="treeRef" | ||
19 | + :treeData="treeData" | ||
20 | + :replace-fields="{ title: 'name', key: 'id' }" | ||
21 | + :checkedKeys="roleMenus" | ||
22 | + @check="handleCheckClick" | ||
23 | + title="菜单分配" | ||
24 | + /> | ||
25 | + </Spin> | ||
24 | </template> | 26 | </template> |
25 | </BasicForm> | 27 | </BasicForm> |
26 | </BasicDrawer> | 28 | </BasicDrawer> |
@@ -28,7 +30,7 @@ | @@ -28,7 +30,7 @@ | ||
28 | <script lang="ts"> | 30 | <script lang="ts"> |
29 | import { defineComponent, ref, computed, unref, nextTick } from 'vue'; | 31 | import { defineComponent, ref, computed, unref, nextTick } from 'vue'; |
30 | import { BasicForm, useForm } from '/@/components/Form/index'; | 32 | import { BasicForm, useForm } from '/@/components/Form/index'; |
31 | - import { formSchema } from './role.data'; | 33 | + import { formSchema, KeysTypeEnum, RoleMenuDictEnum } from './role.data'; |
32 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | 34 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
33 | import { BasicTree, TreeItem } from '/@/components/Tree'; | 35 | import { BasicTree, TreeItem } from '/@/components/Tree'; |
34 | import { useMessage } from '/@/hooks/web/useMessage'; | 36 | import { useMessage } from '/@/hooks/web/useMessage'; |
@@ -36,22 +38,28 @@ | @@ -36,22 +38,28 @@ | ||
36 | // 加载菜单数据 | 38 | // 加载菜单数据 |
37 | import { getMenuList, getMenusIdsByRoleId } from '/@/api/sys/menu'; | 39 | import { getMenuList, getMenusIdsByRoleId } from '/@/api/sys/menu'; |
38 | import { useI18n } from '/@/hooks/web/useI18n'; | 40 | import { useI18n } from '/@/hooks/web/useI18n'; |
39 | - import { RouteItem } from '/@/api/sys/model/menuModel'; | 41 | + import { MenuRecord } from '/@/api/sys/model/menuModel'; |
40 | import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system'; | 42 | import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system'; |
43 | + import { findDictItemByCode } from '/@/api/system/dict'; | ||
44 | + import { RoleEnum } from '/@/enums/roleEnum'; | ||
45 | + import { Spin } from 'ant-design-vue'; | ||
46 | + | ||
47 | + type TreeData = MenuRecord & TreeItem; | ||
48 | + | ||
41 | export default defineComponent({ | 49 | export default defineComponent({ |
42 | name: 'RoleDrawer', | 50 | name: 'RoleDrawer', |
43 | - components: { BasicDrawer, BasicForm, BasicTree }, | 51 | + components: { BasicDrawer, BasicForm, BasicTree, Spin }, |
44 | emits: ['success', 'register'], | 52 | emits: ['success', 'register'], |
45 | setup(_, { emit }) { | 53 | setup(_, { emit }) { |
46 | - const treeExpandData = ref([]); | 54 | + const treeExpandData = ref<string[]>([]); |
47 | const isUpdate = ref<boolean>(true); | 55 | const isUpdate = ref<boolean>(true); |
48 | - const treeData = ref<TreeItem[]>([]); | 56 | + const treeData = ref<TreeData[]>([]); |
49 | const roleMenus = ref<string[]>([]); | 57 | const roleMenus = ref<string[]>([]); |
50 | const allCheckedKeys = ref<string[]>([]); | 58 | const allCheckedKeys = ref<string[]>([]); |
51 | const roleId = ref<string>(''); | 59 | const roleId = ref<string>(''); |
52 | const treeRef = ref(); | 60 | const treeRef = ref(); |
53 | - const checked: any = ref([]); //需要选中的节点 | ||
54 | - const pidArr: any = ref([]); //获取父节点 | 61 | + const checked = ref<string[]>([]); //需要选中的节点 |
62 | + const spinning = ref(false); | ||
55 | 63 | ||
56 | const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({ | 64 | const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({ |
57 | labelWidth: 100, | 65 | labelWidth: 100, |
@@ -59,24 +67,18 @@ | @@ -59,24 +67,18 @@ | ||
59 | showActionButtonGroup: false, | 67 | showActionButtonGroup: false, |
60 | }); | 68 | }); |
61 | 69 | ||
62 | - // 递归函数,将RouteItem里面的字段换名称 | ||
63 | - function processChildren(items: RouteItem[]) { | ||
64 | - items.forEach((item) => { | ||
65 | - item.menuName = t(item.meta.title); | ||
66 | - item.icon = item.meta.icon; | ||
67 | - item.key = item.id; | ||
68 | - if (item.children) { | ||
69 | - processChildren(item.children); | 70 | + const originMenus = ref(); |
71 | + | ||
72 | + const transformName = (data: TreeData[]) => { | ||
73 | + return data.map((item) => { | ||
74 | + item.name = t(item.name); | ||
75 | + if (item.children && item.children.length) { | ||
76 | + item.children = transformName(item.children as unknown as TreeData[]); | ||
70 | } | 77 | } |
78 | + return item; | ||
71 | }); | 79 | }); |
72 | - } | ||
73 | - function lookForAllId(data = [], arr = []) { | ||
74 | - for (const item of data) { | ||
75 | - arr.push(item.id); | ||
76 | - } | ||
77 | - return arr; | ||
78 | - } | ||
79 | - const originMenus = ref(); | 80 | + }; |
81 | + | ||
80 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | 82 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { |
81 | allCheckedKeys.value = []; | 83 | allCheckedKeys.value = []; |
82 | originMenus.value = []; | 84 | originMenus.value = []; |
@@ -84,53 +86,52 @@ | @@ -84,53 +86,52 @@ | ||
84 | resetFields(); | 86 | resetFields(); |
85 | roleId.value = ''; | 87 | roleId.value = ''; |
86 | // 在打开弹窗时清除所有选择的菜单 | 88 | // 在打开弹窗时清除所有选择的菜单 |
87 | - treeRef.value && treeRef.value.checkAll(false); | 89 | + treeRef.value && treeRef.value?.setCheckedKeys([]); |
88 | isUpdate.value = data.isUpdate; | 90 | isUpdate.value = data.isUpdate; |
89 | - // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 | ||
90 | - if (!unref(treeData).length) { | ||
91 | - // 获取全部的菜单 | ||
92 | - const menuListModel = await getMenuList(); | ||
93 | - processChildren(menuListModel); | ||
94 | - treeData.value = menuListModel; | ||
95 | - //修复角色菜单新增-全部展开问题-只展开第一级即可 | ||
96 | - nextTick(() => { | ||
97 | - const getAllIds = lookForAllId(treeData.value, []); | ||
98 | - treeExpandData.value = getAllIds; | ||
99 | - }); | ||
100 | - } | ||
101 | - // 更新 | ||
102 | - if (unref(isUpdate)) { | ||
103 | - allCheckedKeys.value = []; | ||
104 | - checked.value = []; | ||
105 | - //通过角色id去获取角色对应的菜单的ids | ||
106 | - roleMenus.value = await getMenusIdsByRoleId(data.record.id); | ||
107 | - originMenus.value = [...roleMenus.value]; | ||
108 | - | ||
109 | - const getAllIds = lookForAllId(treeData.value, []); | ||
110 | - treeExpandData.value = getAllIds; | ||
111 | - for (let item of treeData.value) { | ||
112 | - if (item?.children != 0) { | ||
113 | - pidArr.value.push(item.key); | ||
114 | - } | ||
115 | - for (let item1 of item?.children) { | ||
116 | - if (item1?.children != 0) { | ||
117 | - pidArr.value.push(item1.key); | ||
118 | - } | ||
119 | - } | 91 | + const roleType = data?.record?.roleType || RoleEnum.SYS_ADMIN; |
92 | + try { | ||
93 | + spinning.value = true; | ||
94 | + // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 | ||
95 | + | ||
96 | + if (!unref(treeData).length) { | ||
97 | + // 获取全部的菜单 | ||
98 | + const menuListModel = await getMenuList(); | ||
99 | + treeData.value = transformName(menuListModel as unknown as TreeData[]); | ||
100 | + //修复角色菜单新增-全部展开问题-只展开第一级即可 | ||
101 | + await nextTick(); | ||
102 | + const getExpandKeys = unref(treeData).map((item) => item.id); | ||
103 | + treeExpandData.value = getExpandKeys; | ||
120 | } | 104 | } |
121 | - for (let item of roleMenus.value) { | ||
122 | - let isP = pidArr.value.includes(item); | ||
123 | - if (!isP) { | ||
124 | - checked.value.push(item); | ||
125 | - } | 105 | + |
106 | + const keys = await getPermissionByRole(roleType); | ||
107 | + const { keyType } = RoleMenuDictEnum[roleType]; | ||
108 | + treeData.value = getPermissionTreeData( | ||
109 | + unref(treeData) as unknown as TreeData[], | ||
110 | + keys, | ||
111 | + keyType | ||
112 | + ); | ||
113 | + | ||
114 | + // 更新 | ||
115 | + if (unref(isUpdate)) { | ||
116 | + allCheckedKeys.value = []; | ||
117 | + checked.value = []; | ||
118 | + roleId.value = data.record.id; | ||
119 | + | ||
120 | + //通过角色id去获取角色对应的菜单的ids | ||
121 | + originMenus.value = roleMenus.value = await getMenusIdsByRoleId(data.record.id); | ||
122 | + | ||
123 | + const getExpandKeys = unref(treeData).map((item) => item.id); | ||
124 | + treeExpandData.value = getExpandKeys; | ||
125 | + | ||
126 | + await nextTick(); | ||
127 | + treeRef.value.setCheckedKeys(roleMenus.value); | ||
128 | + setFieldsValue(data.record); | ||
129 | + } else { | ||
126 | } | 130 | } |
127 | - nextTick(() => { | ||
128 | - treeRef.value.setCheckedKeys(checked.value); | ||
129 | - // const expandTreeIds = lookForAllId(treeData.value); | ||
130 | - // treeRef.value.setExpandedKeys(expandTreeIds); | ||
131 | - }); | ||
132 | - roleId.value = data.record.id; | ||
133 | - setFieldsValue(data.record); | 131 | + } catch (error) { |
132 | + throw error; | ||
133 | + } finally { | ||
134 | + spinning.value = false; | ||
134 | } | 135 | } |
135 | }); | 136 | }); |
136 | 137 | ||
@@ -146,7 +147,7 @@ | @@ -146,7 +147,7 @@ | ||
146 | name: values.name, | 147 | name: values.name, |
147 | remark: values.remark, | 148 | remark: values.remark, |
148 | status: values.status, | 149 | status: values.status, |
149 | - menu: allCheckedKeys.value.length ? allCheckedKeys.value : originMenus.value, | 150 | + menu: unref(treeRef).getCheckedKeys() || [], |
150 | }; | 151 | }; |
151 | if (req.menu == undefined) return createMessage.error('请勾选权限菜单'); | 152 | if (req.menu == undefined) return createMessage.error('请勾选权限菜单'); |
152 | saveOrUpdateRoleInfoWithMenu(req).then(() => { | 153 | saveOrUpdateRoleInfoWithMenu(req).then(() => { |
@@ -165,7 +166,74 @@ | @@ -165,7 +166,74 @@ | ||
165 | allCheckedKeys.value = [...checkedNodes, ...halfCheckedKeys]; | 166 | allCheckedKeys.value = [...checkedNodes, ...halfCheckedKeys]; |
166 | }; | 167 | }; |
167 | 168 | ||
169 | + const getPermissionByRole = async (roleType: RoleEnum) => { | ||
170 | + try { | ||
171 | + const { key } = RoleMenuDictEnum[roleType]; | ||
172 | + const res = await findDictItemByCode({ dictCode: key }); | ||
173 | + return res.map((item) => item.itemValue); | ||
174 | + } catch (error) {} | ||
175 | + return []; | ||
176 | + }; | ||
177 | + | ||
178 | + const getPermissionTreeData = ( | ||
179 | + data: MenuRecord[], | ||
180 | + permissionKeys: string[], | ||
181 | + keysType: KeysTypeEnum | ||
182 | + ) => { | ||
183 | + const setDisabled = (data: MenuRecord[], flag: boolean) => { | ||
184 | + return data.map((item) => { | ||
185 | + item.name = t(item.name); | ||
186 | + if (item.children && item.children.length) { | ||
187 | + item.children = setDisabled(item.children, flag); | ||
188 | + } | ||
189 | + return { | ||
190 | + ...item, | ||
191 | + disabled: flag, | ||
192 | + icon: item.meta.icon, | ||
193 | + } as TreeData; | ||
194 | + }); | ||
195 | + }; | ||
196 | + | ||
197 | + const permissionCompare = ( | ||
198 | + data: MenuRecord[], | ||
199 | + permissionKeys: string[], | ||
200 | + keysType: KeysTypeEnum | ||
201 | + ) => { | ||
202 | + return data.map((item) => { | ||
203 | + item.name = t(item.name); | ||
204 | + const findFlag = permissionKeys.includes(item.permission); | ||
205 | + if (findFlag) item.isDictCompareDisabled = true; | ||
206 | + const disabledFlag = keysType === KeysTypeEnum.DISABLED ? findFlag : !findFlag; | ||
207 | + item.disabled = disabledFlag; | ||
208 | + | ||
209 | + if (item.isDictCompareDisabled && item.children && item.children.length) { | ||
210 | + setDisabled(item.children, disabledFlag); | ||
211 | + } else { | ||
212 | + if (item.children && item.children.length) { | ||
213 | + item.children = permissionCompare(item.children, permissionKeys, keysType); | ||
214 | + item.disabled = item.children.every((temp) => temp.disabled); | ||
215 | + } | ||
216 | + } | ||
217 | + return { | ||
218 | + ...item, | ||
219 | + icon: item.meta.icon, | ||
220 | + } as TreeData; | ||
221 | + }); | ||
222 | + }; | ||
223 | + | ||
224 | + const result = permissionCompare(data, permissionKeys, keysType).map((item) => { | ||
225 | + if (item.children && item.children.length) { | ||
226 | + const rootDisabledFlag = item.children.every((temp) => temp.disabled); | ||
227 | + item.disabled = rootDisabledFlag; | ||
228 | + } | ||
229 | + return item; | ||
230 | + }); | ||
231 | + | ||
232 | + return result; | ||
233 | + }; | ||
234 | + | ||
168 | return { | 235 | return { |
236 | + spinning, | ||
169 | registerDrawer, | 237 | registerDrawer, |
170 | registerForm, | 238 | registerForm, |
171 | getTitle, | 239 | getTitle, |
@@ -185,9 +253,11 @@ | @@ -185,9 +253,11 @@ | ||
185 | :deep(.vben-basic-tree) { | 253 | :deep(.vben-basic-tree) { |
186 | width: 100% !important; | 254 | width: 100% !important; |
187 | } | 255 | } |
256 | + | ||
188 | :deep(.is-unflod) { | 257 | :deep(.is-unflod) { |
189 | display: none !important; | 258 | display: none !important; |
190 | } | 259 | } |
260 | + | ||
191 | :deep(.is-flod) { | 261 | :deep(.is-flod) { |
192 | display: none !important; | 262 | display: none !important; |
193 | } | 263 | } |
1 | import { BasicColumn } from '/@/components/Table'; | 1 | import { BasicColumn } from '/@/components/Table'; |
2 | import { FormSchema } from '/@/components/Table'; | 2 | import { FormSchema } from '/@/components/Table'; |
3 | +import { RoleEnum } from '/@/enums/roleEnum'; | ||
4 | + | ||
5 | +export enum KeysTypeEnum { | ||
6 | + DISABLED = 'disabled', | ||
7 | + ENABLED = 'enabled', | ||
8 | +} | ||
9 | + | ||
10 | +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 | +}; | ||
3 | 15 | ||
4 | export const columns: BasicColumn[] = [ | 16 | export const columns: BasicColumn[] = [ |
5 | { | 17 | { |
@@ -9,19 +9,21 @@ | @@ -9,19 +9,21 @@ | ||
9 | > | 9 | > |
10 | <BasicForm @register="registerForm"> | 10 | <BasicForm @register="registerForm"> |
11 | <template #menu> | 11 | <template #menu> |
12 | - <BasicTree | ||
13 | - v-if="treeData.length > 0" | ||
14 | - :treeData="treeData" | ||
15 | - :expandedKeys="treeExpandData" | ||
16 | - :replaceFields="{ title: 'menuName' }" | ||
17 | - :checkedKeys="roleMenus" | ||
18 | - @check="handleCheckClick" | ||
19 | - checkable | ||
20 | - toolbar | ||
21 | - ref="treeRef" | ||
22 | - title="权限分配" | ||
23 | - :defaultExpandAll="true" | ||
24 | - /> | 12 | + <Spin :spinning="spinning"> |
13 | + <BasicTree | ||
14 | + v-if="treeData.length" | ||
15 | + :treeData="treeData" | ||
16 | + :expandedKeys="treeExpandData" | ||
17 | + :replaceFields="{ title: 'name', key: 'id' }" | ||
18 | + :checkedKeys="roleMenus" | ||
19 | + @check="handleCheckClick" | ||
20 | + checkable | ||
21 | + toolbar | ||
22 | + ref="treeRef" | ||
23 | + title="权限分配" | ||
24 | + :defaultExpandAll="true" | ||
25 | + /> | ||
26 | + </Spin> | ||
25 | </template> | 27 | </template> |
26 | </BasicForm> | 28 | </BasicForm> |
27 | </BasicDrawer> | 29 | </BasicDrawer> |
@@ -36,17 +38,22 @@ | @@ -36,17 +38,22 @@ | ||
36 | // 加载菜单数据 | 38 | // 加载菜单数据 |
37 | import { getMenuList, getMenusIdsByRoleId } from '/@/api/sys/menu'; | 39 | import { getMenuList, getMenusIdsByRoleId } from '/@/api/sys/menu'; |
38 | import { useI18n } from '/@/hooks/web/useI18n'; | 40 | import { useI18n } from '/@/hooks/web/useI18n'; |
39 | - import { RouteItem } from '/@/api/sys/model/menuModel'; | 41 | + import { MenuRecord } from '/@/api/sys/model/menuModel'; |
40 | import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system'; | 42 | import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system'; |
41 | import { RoleEnum } from '/@/enums/roleEnum'; | 43 | import { RoleEnum } from '/@/enums/roleEnum'; |
42 | import { useMessage } from '/@/hooks/web/useMessage'; | 44 | import { useMessage } from '/@/hooks/web/useMessage'; |
45 | + import { KeysTypeEnum, RoleMenuDictEnum } from '../../system/role/role.data'; | ||
46 | + import { findDictItemByCode } from '/@/api/system/dict'; | ||
47 | + import { Spin } from 'ant-design-vue'; | ||
48 | + | ||
49 | + type TreeData = MenuRecord & TreeItem; | ||
43 | 50 | ||
44 | export default defineComponent({ | 51 | export default defineComponent({ |
45 | name: 'RoleDrawer', | 52 | name: 'RoleDrawer', |
46 | - components: { BasicDrawer, BasicForm, BasicTree }, | 53 | + components: { BasicDrawer, BasicForm, BasicTree, Spin }, |
47 | emits: ['success', 'register'], | 54 | emits: ['success', 'register'], |
48 | setup(_, { emit }) { | 55 | setup(_, { emit }) { |
49 | - const treeExpandData = ref([]); | 56 | + const treeExpandData = ref<string[]>([]); |
50 | 57 | ||
51 | const isUpdate = ref(true); | 58 | const isUpdate = ref(true); |
52 | const treeData = ref<TreeItem[]>([]); | 59 | const treeData = ref<TreeItem[]>([]); |
@@ -54,8 +61,8 @@ | @@ -54,8 +61,8 @@ | ||
54 | const allCheckedKeys = ref<string[]>([]); | 61 | const allCheckedKeys = ref<string[]>([]); |
55 | const roleId = ref(''); | 62 | const roleId = ref(''); |
56 | const treeRef = ref(); | 63 | const treeRef = ref(); |
57 | - const checked: any = ref([]); //需要选中的节点 | ||
58 | - const pidArr: any = ref([]); //获取父节点 | 64 | + const checked = ref<string[]>([]); //需要选中的节点 |
65 | + const spinning = ref(false); | ||
59 | 66 | ||
60 | const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({ | 67 | const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({ |
61 | labelWidth: 90, | 68 | labelWidth: 90, |
@@ -63,77 +70,71 @@ | @@ -63,77 +70,71 @@ | ||
63 | showActionButtonGroup: false, | 70 | showActionButtonGroup: false, |
64 | }); | 71 | }); |
65 | 72 | ||
66 | - function processChildren(items: RouteItem[]) { | ||
67 | - items.map((item) => { | ||
68 | - item.menuName = t(item.meta.title); | ||
69 | - item.icon = item.meta.icon; | ||
70 | - item.key = item.id; | ||
71 | - if (item.children) { | ||
72 | - processChildren(item.children); | 73 | + const originMenus = ref(); |
74 | + | ||
75 | + const transformName = (data: TreeData[]) => { | ||
76 | + return data.map((item) => { | ||
77 | + item.name = t(item.name); | ||
78 | + if (item.children && item.children.length) { | ||
79 | + item.children = transformName(item.children as unknown as TreeData[]); | ||
73 | } | 80 | } |
81 | + return item; | ||
74 | }); | 82 | }); |
75 | - } | ||
76 | - function lookForAllId(data = [], arr = []) { | ||
77 | - for (const item of data) { | ||
78 | - arr.push(item.id); | ||
79 | - } | ||
80 | - return arr; | ||
81 | - } | 83 | + }; |
82 | 84 | ||
83 | - const originMenus = ref(); | ||
84 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { | 85 | const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => { |
85 | - setDrawerProps({ confirmLoading: false }); | ||
86 | allCheckedKeys.value = []; | 86 | allCheckedKeys.value = []; |
87 | originMenus.value = []; | 87 | originMenus.value = []; |
88 | - treeExpandData.value; | ||
89 | allCheckedKeys.value.length = 0; | 88 | allCheckedKeys.value.length = 0; |
90 | resetFields(); | 89 | resetFields(); |
91 | roleId.value = ''; | 90 | roleId.value = ''; |
92 | // 在打开弹窗时清除所有选择的菜单 | 91 | // 在打开弹窗时清除所有选择的菜单 |
93 | - treeRef.value && treeRef.value.checkAll(false); | 92 | + treeRef.value && treeRef.value?.setCheckedKeys([]); |
94 | isUpdate.value = data.isUpdate; | 93 | isUpdate.value = data.isUpdate; |
95 | - // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 | ||
96 | - if (!unref(treeData).length) { | ||
97 | - // 获取全部的菜单 | ||
98 | - const menuListModel = await getMenuList(); | ||
99 | - processChildren(menuListModel); | ||
100 | - treeData.value = menuListModel; | ||
101 | - //修复角色菜单新增-全部展开问题-只展开第一级即可 | ||
102 | - nextTick(() => { | ||
103 | - const getAllIds = lookForAllId(treeData.value, []); | ||
104 | - treeExpandData.value = getAllIds; | ||
105 | - }); | ||
106 | - } | ||
107 | - // 更新 | ||
108 | - if (unref(isUpdate)) { | ||
109 | - allCheckedKeys.value = []; | ||
110 | - checked.value = []; | ||
111 | - //通过角色id去获取角色对应的菜单的ids | ||
112 | - roleMenus.value = await getMenusIdsByRoleId(data.record.id); | ||
113 | - originMenus.value = [...roleMenus.value]; | ||
114 | - const getAllIds = lookForAllId(treeData.value, []); | ||
115 | - treeExpandData.value = getAllIds; | ||
116 | - for (let item of treeData.value) { | ||
117 | - if (item?.children != 0) { | ||
118 | - pidArr.value.push(item.key); | ||
119 | - } | ||
120 | - for (let item1 of item?.children) { | ||
121 | - if (item1?.children != 0) { | ||
122 | - pidArr.value.push(item1.key); | ||
123 | - } | ||
124 | - } | 94 | + const roleType = data?.record?.roleType || RoleEnum.TENANT_ADMIN; |
95 | + try { | ||
96 | + spinning.value = true; | ||
97 | + // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告 | ||
98 | + | ||
99 | + if (!unref(treeData).length) { | ||
100 | + // 获取全部的菜单 | ||
101 | + const menuListModel = await getMenuList(); | ||
102 | + treeData.value = transformName(menuListModel as unknown as TreeData[]); | ||
103 | + //修复角色菜单新增-全部展开问题-只展开第一级即可 | ||
104 | + await nextTick(); | ||
105 | + const getExpandKeys = unref(treeData).map((item) => item.id); | ||
106 | + treeExpandData.value = getExpandKeys; | ||
125 | } | 107 | } |
126 | - for (let item of roleMenus.value) { | ||
127 | - let isP = pidArr.value.includes(item); | ||
128 | - if (!isP) { | ||
129 | - checked.value.push(item); | ||
130 | - } | 108 | + |
109 | + const keys = await getPermissionByRole(roleType); | ||
110 | + const { keyType } = RoleMenuDictEnum[roleType]; | ||
111 | + treeData.value = getPermissionTreeData( | ||
112 | + unref(treeData) as unknown as TreeData[], | ||
113 | + keys, | ||
114 | + keyType | ||
115 | + ); | ||
116 | + | ||
117 | + // 更新 | ||
118 | + if (unref(isUpdate)) { | ||
119 | + allCheckedKeys.value = []; | ||
120 | + checked.value = []; | ||
121 | + roleId.value = data.record.id; | ||
122 | + | ||
123 | + //通过角色id去获取角色对应的菜单的ids | ||
124 | + originMenus.value = roleMenus.value = await getMenusIdsByRoleId(data.record.id); | ||
125 | + | ||
126 | + const getExpandKeys = unref(treeData).map((item) => item.id); | ||
127 | + treeExpandData.value = getExpandKeys; | ||
128 | + | ||
129 | + await nextTick(); | ||
130 | + treeRef.value.setCheckedKeys(roleMenus.value); | ||
131 | + setFieldsValue(data.record); | ||
132 | + } else { | ||
131 | } | 133 | } |
132 | - nextTick(() => { | ||
133 | - treeRef.value.setCheckedKeys(checked.value); | ||
134 | - }); | ||
135 | - roleId.value = data.record.id; | ||
136 | - setFieldsValue(data.record); | 134 | + } catch (error) { |
135 | + throw error; | ||
136 | + } finally { | ||
137 | + spinning.value = false; | ||
137 | } | 138 | } |
138 | }); | 139 | }); |
139 | const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色')); | 140 | const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色')); |
@@ -150,7 +151,7 @@ | @@ -150,7 +151,7 @@ | ||
150 | remark: values.remark, | 151 | remark: values.remark, |
151 | status: values.status, | 152 | status: values.status, |
152 | roleType: RoleEnum.TENANT_ADMIN, | 153 | roleType: RoleEnum.TENANT_ADMIN, |
153 | - menu: allCheckedKeys.value.length ? allCheckedKeys.value : originMenus.value, | 154 | + menu: unref(treeRef).getCheckedKeys() || [], |
154 | }; | 155 | }; |
155 | if (req.menu == undefined) return createMessage.error('请勾选权限菜单'); | 156 | if (req.menu == undefined) return createMessage.error('请勾选权限菜单'); |
156 | const res = await saveOrUpdateRoleInfoWithMenu(req); | 157 | const res = await saveOrUpdateRoleInfoWithMenu(req); |
@@ -173,7 +174,74 @@ | @@ -173,7 +174,74 @@ | ||
173 | allCheckedKeys.value = [...checkedNodes, ...halfCheckedKeys]; | 174 | allCheckedKeys.value = [...checkedNodes, ...halfCheckedKeys]; |
174 | }; | 175 | }; |
175 | 176 | ||
177 | + const getPermissionByRole = async (roleType: RoleEnum) => { | ||
178 | + try { | ||
179 | + const { key } = RoleMenuDictEnum[roleType]; | ||
180 | + const res = await findDictItemByCode({ dictCode: key }); | ||
181 | + return res.map((item) => item.itemValue); | ||
182 | + } catch (error) {} | ||
183 | + return []; | ||
184 | + }; | ||
185 | + | ||
186 | + const getPermissionTreeData = ( | ||
187 | + data: MenuRecord[], | ||
188 | + permissionKeys: string[], | ||
189 | + keysType: KeysTypeEnum | ||
190 | + ) => { | ||
191 | + const setDisabled = (data: MenuRecord[], flag: boolean) => { | ||
192 | + return data.map((item) => { | ||
193 | + item.name = t(item.name); | ||
194 | + if (item.children && item.children.length) { | ||
195 | + item.children = setDisabled(item.children, flag); | ||
196 | + } | ||
197 | + return { | ||
198 | + ...item, | ||
199 | + disabled: flag, | ||
200 | + icon: item.meta.icon, | ||
201 | + } as TreeData; | ||
202 | + }); | ||
203 | + }; | ||
204 | + | ||
205 | + const permissionCompare = ( | ||
206 | + data: MenuRecord[], | ||
207 | + permissionKeys: string[], | ||
208 | + keysType: KeysTypeEnum | ||
209 | + ) => { | ||
210 | + return data.map((item) => { | ||
211 | + item.name = t(item.name); | ||
212 | + const findFlag = permissionKeys.includes(item.permission); | ||
213 | + if (findFlag) item.isDictCompareDisabled = true; | ||
214 | + const disabledFlag = keysType === KeysTypeEnum.DISABLED ? findFlag : !findFlag; | ||
215 | + item.disabled = disabledFlag; | ||
216 | + | ||
217 | + if (item.isDictCompareDisabled && item.children && item.children.length) { | ||
218 | + setDisabled(item.children, disabledFlag); | ||
219 | + } else { | ||
220 | + if (item.children && item.children.length) { | ||
221 | + item.children = permissionCompare(item.children, permissionKeys, keysType); | ||
222 | + item.disabled = item.children.every((temp) => temp.disabled); | ||
223 | + } | ||
224 | + } | ||
225 | + return { | ||
226 | + ...item, | ||
227 | + icon: item.meta.icon, | ||
228 | + } as TreeData; | ||
229 | + }); | ||
230 | + }; | ||
231 | + | ||
232 | + const result = permissionCompare(data, permissionKeys, keysType).map((item) => { | ||
233 | + if (item.children && item.children.length) { | ||
234 | + const rootDisabledFlag = item.children.every((temp) => temp.disabled); | ||
235 | + item.disabled = rootDisabledFlag; | ||
236 | + } | ||
237 | + return item; | ||
238 | + }); | ||
239 | + | ||
240 | + return result; | ||
241 | + }; | ||
242 | + | ||
176 | return { | 243 | return { |
244 | + spinning, | ||
177 | registerDrawer, | 245 | registerDrawer, |
178 | registerForm, | 246 | registerForm, |
179 | getTitle, | 247 | getTitle, |
@@ -192,9 +260,11 @@ | @@ -192,9 +260,11 @@ | ||
192 | :deep(.vben-basic-tree) { | 260 | :deep(.vben-basic-tree) { |
193 | width: 100% !important; | 261 | width: 100% !important; |
194 | } | 262 | } |
263 | + | ||
195 | :deep(.is-unflod) { | 264 | :deep(.is-unflod) { |
196 | display: none !important; | 265 | display: none !important; |
197 | } | 266 | } |
267 | + | ||
198 | :deep(.is-flod) { | 268 | :deep(.is-flod) { |
199 | display: none !important; | 269 | display: none !important; |
200 | } | 270 | } |