Commit a5e25f294b9650bdaf2151ae746f3e047bd539f2

Authored by dev001
1 parent fd848201

feat: 新增权限页面

... ... @@ -72,7 +72,7 @@
72 72 import { TOption } from '/@/views/rule/linkedge/config/config.data';
73 73 import { PlusOutlined } from '@ant-design/icons-vue';
74 74 import { useDrawer } from '/@/components/Drawer';
75   - import RoleDrawer from '../../role/RoleDrawer.vue';
  75 + import RoleDrawer from '../../role/CustomRoleDrawer.vue';
76 76 import OrganizationDrawer from '/@/views/system/organization/OrganizationDrawer.vue';
77 77
78 78 export default defineComponent({
... ...
  1 +<template>
  2 + <BasicDrawer
  3 + v-bind="$attrs"
  4 + @register="registerDrawer"
  5 + showFooter
  6 + :title="getTitle"
  7 + width="500px"
  8 + @ok="handleSubmit"
  9 + >
  10 + <BasicForm @register="registerForm">
  11 + <template #menu>
  12 + <Spin :spinning="spinning">
  13 + <BasicTree
  14 + v-if="treeData.length"
  15 + checkable
  16 + toolbar
  17 + ref="treeRef"
  18 + :treeData="treeData"
  19 + @check="handleCheckClick"
  20 + :replace-fields="{ title: 'name', key: 'id' }"
  21 + :checkedKeys="roleMenus"
  22 + title="菜单分配"
  23 + />
  24 + </Spin>
  25 + </template>
  26 + </BasicForm>
  27 + </BasicDrawer>
  28 +</template>
  29 +<script lang="ts">
  30 + import { defineComponent, ref, computed, unref, nextTick } from 'vue';
  31 + import { BasicForm, useForm } from '/@/components/Form/index';
  32 + import { formSchema, KeysTypeEnum, RoleMenuDictEnum } from './role.data';
  33 + import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  34 + import { BasicTree, TreeActionType, TreeItem } from '/@/components/Tree';
  35 + import { useMessage } from '/@/hooks/web/useMessage';
  36 + const { t } = useI18n(); // 加载国际化
  37 + // 加载菜单数据
  38 + import { getMeMenuList, getMenusIdsByRoleId } from '/@/api/sys/menu';
  39 + import { useI18n } from '/@/hooks/web/useI18n';
  40 + import { MenuRecord } from '/@/api/sys/model/menuModel';
  41 + import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system';
  42 + import { findDictItemByCode } from '/@/api/system/dict';
  43 + import { RoleEnum } from '/@/enums/roleEnum';
  44 + import { Spin } from 'ant-design-vue';
  45 + import { useRole } from '/@/hooks/business/useRole';
  46 + import { RoleListItem } from '/@/api/system/model/systemModel';
  47 +
  48 + type TreeData = MenuRecord & TreeItem;
  49 +
  50 + export default defineComponent({
  51 + name: 'RoleDrawer',
  52 + components: { BasicDrawer, BasicForm, BasicTree, Spin },
  53 + emits: ['success', 'register'],
  54 + setup(_, { emit }) {
  55 + const isUpdate = ref<boolean>(true);
  56 + const treeData = ref<TreeData[]>([]);
  57 + const roleMenus = ref<string[]>([]);
  58 + const roleId = ref<string>('');
  59 + const treeRef = ref<Nullable<TreeActionType>>();
  60 + const checked = ref<string[]>([]); //需要选中的节点
  61 + const spinning = ref(false);
  62 + const checkedKeysWithHalfChecked = ref<string[]>([]);
  63 +
  64 + const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
  65 + labelWidth: 100,
  66 + schemas: formSchema,
  67 + showActionButtonGroup: false,
  68 + });
  69 +
  70 + const transformName = (data: TreeData[]) => {
  71 + return data.map((item) => {
  72 + item.name = t(item.name);
  73 + if (item.children && item.children.length) {
  74 + item.children = transformName(item.children as unknown as TreeData[]);
  75 + }
  76 + return item;
  77 + });
  78 + };
  79 +
  80 + const { isTenantAdmin, isSysadmin, getRole } = useRole();
  81 + const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(
  82 + async (data: { isUpdate: boolean; record: RoleListItem }) => {
  83 + resetFields();
  84 + roleId.value = '';
  85 + // 在打开弹窗时清除所有选择的菜单
  86 + treeRef.value && treeRef.value?.setCheckedKeys([]);
  87 + isUpdate.value = data.isUpdate;
  88 + let roleType = unref(getRole) || RoleEnum.SYS_ADMIN;
  89 +
  90 + // 租户管理员创建角色时 菜单分配为客户菜单
  91 + if (unref(isTenantAdmin)) {
  92 + roleType = RoleEnum.CUSTOMER_USER;
  93 + }
  94 +
  95 + try {
  96 + spinning.value = true;
  97 + // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告
  98 +
  99 + // if (!unref(treeData).length) {
  100 + // 获取全部的菜单
  101 + const menuListModel = await getMeMenuList();
  102 + treeData.value = transformName(menuListModel as unknown as TreeData[]);
  103 + // }
  104 +
  105 + const keys = await getPermissionByRole(roleType);
  106 + const { keyType } = RoleMenuDictEnum[roleType];
  107 + treeData.value = filterPermissionTreeData(
  108 + unref(treeData) as unknown as TreeData[],
  109 + keys,
  110 + keyType
  111 + );
  112 +
  113 + // 如果编辑的是超级管理员 则不再过滤平台管理员禁用的权限
  114 + // 如果是超级管理员创建角色 创建角色属于平台管理员 因此过滤平台管理员禁用的权限
  115 + if (data?.record?.roleType !== RoleEnum.SYS_ADMIN && unref(isSysadmin)) {
  116 + const keys = await getPermissionByRole(RoleEnum.PLATFORM_ADMIN);
  117 + const { keyType } = RoleMenuDictEnum[RoleEnum.PLATFORM_ADMIN];
  118 + treeData.value = filterPermissionTreeData(
  119 + unref(treeData) as unknown as TreeData[],
  120 + keys,
  121 + keyType
  122 + );
  123 + }
  124 +
  125 + // 更新
  126 + if (unref(isUpdate)) {
  127 + checked.value = [];
  128 + roleId.value = data.record.id;
  129 +
  130 + //通过角色id去获取角色对应的菜单的ids
  131 + checkedKeysWithHalfChecked.value = roleMenus.value = await getMenusIdsByRoleId(
  132 + data.record.id
  133 + );
  134 + excludeHalfCheckedKeys(unref(treeData));
  135 + await nextTick();
  136 + unref(treeRef)?.setCheckedKeys(roleMenus.value);
  137 + setFieldsValue(data.record);
  138 + } else {
  139 + }
  140 + } catch (error) {
  141 + throw error;
  142 + } finally {
  143 + spinning.value = false;
  144 + }
  145 + }
  146 + );
  147 +
  148 + const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
  149 +
  150 + async function handleSubmit() {
  151 + setDrawerProps({ confirmLoading: true });
  152 + const { createMessage } = useMessage();
  153 + try {
  154 + const values = await validate();
  155 + const treeCheckedKeys: string[] = (unref(treeRef)?.getCheckedKeys() as string[]) || [];
  156 + const menu = [...new Set([...unref(checkedKeysWithHalfChecked), ...treeCheckedKeys])];
  157 + const req = {
  158 + id: roleId.value,
  159 + name: values.name,
  160 + remark: values.remark,
  161 + status: values.status,
  162 + menu,
  163 + };
  164 + if (req.menu == undefined) return createMessage.error('请勾选权限菜单');
  165 + saveOrUpdateRoleInfoWithMenu(req).then(() => {
  166 + closeDrawer();
  167 + emit('success');
  168 + createMessage.success(`${unref(isUpdate) ? '编辑' : '新增'}成功`);
  169 + });
  170 + } finally {
  171 + setTimeout(() => {
  172 + setDrawerProps({ confirmLoading: false });
  173 + }, 300);
  174 + }
  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 filterPermissionTreeData = (
  187 + data: MenuRecord[],
  188 + permissionKeys: string[],
  189 + keysType: KeysTypeEnum
  190 + ): TreeData[] => {
  191 + const permissionCompare = (
  192 + data: MenuRecord[],
  193 + permissionKeys: string[],
  194 + keysType: KeysTypeEnum
  195 + ): TreeData[] => {
  196 + return data.filter((item) => {
  197 + item.name = t(item.name);
  198 + const findFlag = permissionKeys.includes(item.permission);
  199 +
  200 + item.show = findFlag ? keysType === KeysTypeEnum.ENABLED : undefined;
  201 +
  202 + if (item.children && item.children.length) {
  203 + if (item.show) return true;
  204 + if (item.show === undefined) {
  205 + item.children = permissionCompare(item.children, permissionKeys, keysType);
  206 + item.show = item.children.some((item) =>
  207 + keysType === KeysTypeEnum.ENABLED
  208 + ? item.show
  209 + : item.show === undefined
  210 + ? true
  211 + : item.show
  212 + );
  213 + return item.show;
  214 + }
  215 + }
  216 +
  217 + return keysType === KeysTypeEnum.ENABLED
  218 + ? item.show
  219 + : item.show === undefined
  220 + ? true
  221 + : item.show;
  222 + }) as unknown as TreeData[];
  223 + };
  224 +
  225 + return permissionCompare(data, permissionKeys, keysType);
  226 + };
  227 +
  228 + const excludeHalfCheckedKeys = (treeData: MenuRecord[]) => {
  229 + const needExcludeKeys: string[] = [];
  230 + const query = (data: MenuRecord[]) => {
  231 + data.forEach((item) => {
  232 + item.checked = roleMenus.value.includes(item.id);
  233 + if (item.children && item.children.length) {
  234 + query(item.children);
  235 + item.checked = item.children.every((item) => item.checked);
  236 + }
  237 + if (!item.checked) {
  238 + needExcludeKeys.push(item.id);
  239 + }
  240 + });
  241 + };
  242 + query(treeData);
  243 + roleMenus.value = unref(roleMenus).filter((key) => !needExcludeKeys.includes(key));
  244 + return needExcludeKeys;
  245 + };
  246 +
  247 + const handleCheckClick = (selectedKeys: string[], event: CheckEvent) => {
  248 + checkedKeysWithHalfChecked.value = [
  249 + ...selectedKeys,
  250 + ...(event.halfCheckedKeys as string[]),
  251 + ];
  252 + };
  253 +
  254 + return {
  255 + spinning,
  256 + registerDrawer,
  257 + registerForm,
  258 + getTitle,
  259 + handleSubmit,
  260 + treeData,
  261 + roleMenus,
  262 + treeRef,
  263 + handleCheckClick,
  264 + };
  265 + },
  266 + });
  267 +</script>
  268 +
  269 +<style scoped lang="less">
  270 + :deep(.vben-basic-tree) {
  271 + width: 100% !important;
  272 + }
  273 +
  274 + :deep(.is-unflod) {
  275 + display: none !important;
  276 + }
  277 +
  278 + :deep(.is-flod) {
  279 + display: none !important;
  280 + }
  281 +</style>
... ...
... ... @@ -89,7 +89,7 @@
89 89
90 90 // 租户管理员创建角色时 菜单分配为客户菜单
91 91 if (unref(isTenantAdmin)) {
92   - roleType = RoleEnum.CUSTOMER_USER;
  92 + roleType = RoleEnum.TENANT_ADMIN;
93 93 }
94 94
95 95 try {
... ...