sujunling 2 роки тому
батько
коміт
d5b63f4060

+ 22 - 0
src/mock/menu.json

@@ -1104,6 +1104,28 @@
                             "hideMenu": false,
                             "status": "0"
                         }
+                    },
+                    {
+                        "id": "246ddwec-d414-4c38-85a0-86104d21b172",
+                        "createTime": "2021-11-16 19:17:48",
+                        "updateTime": "2021-12-20 11:46:16",
+                        "name": "职位管理",
+                        "parentId": "a8ffa8c5-637e-471b-a9e6-b60cebe95713",
+                        "children": [],
+                        "path": "/system/zhiwei",
+                        "type": "SYSADMIN",
+                        "permission": "system:zhiwei:view",
+                        "sort": 2,
+                        "component": "/systemAdmin/system/zhiwei/index",
+                        "meta": {
+                            "icon": "ant-design:gold-outlined",
+                            "title": "职位管理",
+                            "isLink": false,
+                            "menuType": "1",
+                            "ignoreKeepAlive": false,
+                            "hideMenu": false,
+                            "status": "0"
+                        }
                     }
                 ],
                 "meta": {

+ 1 - 0
src/mock/menu_get_ids.json

@@ -10,6 +10,7 @@
     "502c9897-4abe-44ad-92cf-a74d402f7fe3",
     "4ce99298-d100-4479-ac61-3f6762ade2c4",
     "50843259-c2de-442a-9da2-9a17f161a970",
+    "246ddwec-d414-4c38-85a0-86104d21b172",
     "8a8ed060-c22b-425c-93dc-d2bca8249e92",
     "dccbd1ba-f506-4837-ada1-6675261471e8",
     "7cda452a-a8f9-43f3-8fb1-974f169244a7",

+ 1 - 0
src/mock/role_me_permissions.json

@@ -14,6 +14,7 @@
     "disasterTemplateManagement:manage:view",
     "system:menu:view",
     "map:upload:view",
+    "system:zhiwei:view",
     "dataAdmin",
     "dataAdmin:dataAdmin:resourceCataloging",
     "dataAdmin:dataAdmin",

+ 225 - 0
src/views/systemAdmin/system/zhiwei/RoleDrawer.vue

@@ -0,0 +1,225 @@
+<template>
+  <BasicDrawer v-bind="$attrs" @register="registerDrawer" showFooter :title="getTitle" width="500px" @ok="handleSubmit">
+    <BasicForm @register="registerForm">
+      <template #menu>
+        <Spin :spinning="spinning"></Spin>
+      </template>
+    </BasicForm>
+  </BasicDrawer>
+</template>
+<script lang="ts">
+import { defineComponent, ref, computed, unref, nextTick } from 'vue';
+import { BasicForm, useForm } from '/@/components/Form/index';
+import { formSchema, KeysTypeEnum, RoleMenuDictEnum } from './role.data';
+import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
+import { BasicTree, TreeItem } from '/@/components/Tree';
+import { useMessage } from '/@/hooks/web/useMessage';
+const { t } = useI18n(); //加载国际化
+// 加载菜单数据
+import { getMenuList } from '/@/api/sys/menu';
+import { useI18n } from '/@/hooks/web/useI18n';
+import { MenuRecord } from '/@/api/sys/model/menuModel';
+import { saveOrUpdateRoleInfoWithMenu } from '/@/api/system/system';
+import { findDictItemByCode } from '/@/api/system/dict';
+import { RoleEnum } from '/@/enums/roleEnum';
+import { Spin } from 'ant-design-vue';
+import { useUserStore } from '/@/store/modules/user';
+import { session } from '/@/utils/Memory';
+import { v4 as uuidv4 } from 'uuid';
+
+
+type TreeData = MenuRecord & TreeItem;
+
+export default defineComponent({
+  name: 'RoleDrawer',
+  components: { BasicDrawer, BasicForm, BasicTree, Spin },
+  emits: ['success', 'register'],
+  setup(_, { emit }) {
+    const isUpdate = ref<boolean>(true);
+    const treeData = ref<TreeData[]>([]);
+    const roleMenus = ref<string[]>([]);
+    const roleId = ref<string>('');
+    const checked = ref<string[]>([]); //需要选中的节点
+    const spinning = ref(false);
+    var nowRole = null;
+
+    const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
+      labelWidth: 100,
+      schemas: formSchema,
+      showActionButtonGroup: false,
+    });
+
+    const transformName = (data: TreeData[]) => {
+      return data.map((item) => {
+        item.name = t(item.name);
+        if (item.children && item.children.length) {
+          item.children = transformName(item.children as unknown as TreeData[]);
+        }
+        return item;
+      });
+    };
+
+    const userStore = useUserStore();
+    const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
+      resetFields();
+      roleId.value = '';
+      // 在打开弹窗时清除所有选择的菜单
+      isUpdate.value = data.isUpdate;
+      const roleType = data?.record?.roleType || userStore.getRoleList.at(0);
+
+      try {
+        spinning.value = true;
+        // 需要在setFieldsValue之前先填充treeData,否则Tree组件可能会报key not exist警告
+
+        if (!unref(treeData).length) {
+          // 获取全部的菜单
+          const menuListModel = await getMenuList();
+          treeData.value = transformName(menuListModel as unknown as TreeData[]);
+        }
+
+        const keys = await getPermissionByRole(roleType);
+        const { keyType } = RoleMenuDictEnum[roleType];
+        treeData.value = getPermissionTreeData(
+          unref(treeData) as unknown as TreeData[],
+          keys,
+          keyType
+        );
+        // 更新
+        if (unref(isUpdate)) {
+          checked.value = [];
+          roleId.value = data.record.id;
+          nowRole = data.record;
+          setFieldsValue(data.record);
+        } else {
+        }
+      } catch (error) {
+        throw error;
+      } finally {
+        spinning.value = false;
+      }
+    });
+
+    const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
+
+    async function handleSubmit() {
+      setDrawerProps({ confirmLoading: true });
+      const { createMessage } = useMessage();
+      try {
+        const values = await validate();
+        const req = {
+          groupName: values.groupName,
+          sort: values.sort
+        };
+        if (unref(isUpdate)) {
+          if (nowRole) {
+            req.updateuser = session.getItem("userInfo").EMPLOYEE.EMPLOYEE_ID;
+            req.groupid = nowRole.groupid;
+          }
+        } else {
+          req.groupid = uuidv4()
+        }
+        saveOrUpdateRoleInfoWithMenu(req).then(() => {
+          closeDrawer();
+          emit('success');
+          nowRole = null;
+          createMessage.success(`${unref(isUpdate) ? '编辑' : '新增'}成功`);
+        });
+      } finally {
+        setTimeout(() => {
+          setDrawerProps({ confirmLoading: false });
+        }, 300);
+      }
+    }
+
+    const getPermissionByRole = async (roleType: RoleEnum) => {
+      try {
+        const { key } = RoleMenuDictEnum[roleType];
+        const res = await findDictItemByCode({ dictCode: key });
+        return res.map((item) => item.itemValue);
+      } catch (error) { }
+      return [];
+    };
+
+    const getPermissionTreeData = (
+      data: MenuRecord[],
+      permissionKeys: string[],
+      keysType: KeysTypeEnum
+    ) => {
+      const setDisabled = (data: MenuRecord[], flag: boolean) => {
+        return data.map((item) => {
+          item.name = t(item.name);
+          if (item.children && item.children.length) {
+            item.children = setDisabled(item.children, flag);
+          }
+          return {
+            ...item,
+            disabled: flag,
+            icon: item.meta.icon,
+          } as TreeData;
+        });
+      };
+
+      const permissionCompare = (
+        data: MenuRecord[],
+        permissionKeys: string[],
+        keysType: KeysTypeEnum
+      ) => {
+        return data.map((item) => {
+          item.name = t(item.name);
+          const findFlag = permissionKeys.includes(item.permission);
+          if (findFlag) item.isDictCompareDisabled = true;
+          const disabledFlag = keysType === KeysTypeEnum.DISABLED ? findFlag : !findFlag;
+          item.disabled = disabledFlag;
+
+          if (item.isDictCompareDisabled && item.children && item.children.length) {
+            setDisabled(item.children, disabledFlag);
+          } else {
+            if (item.children && item.children.length) {
+              item.children = permissionCompare(item.children, permissionKeys, keysType);
+              item.disabled = item.children.every((temp) => temp.disabled);
+            }
+          }
+          return {
+            ...item,
+            icon: item.meta.icon,
+          } as TreeData;
+        });
+      };
+
+      const result = permissionCompare(data, permissionKeys, keysType).map((item) => {
+        if (item.children && item.children.length) {
+          const rootDisabledFlag = item.children.every((temp) => temp.disabled);
+          item.disabled = rootDisabledFlag;
+        }
+        return item;
+      });
+
+      return result;
+    };
+
+    return {
+      spinning,
+      registerDrawer,
+      registerForm,
+      getTitle,
+      handleSubmit,
+      treeData,
+      roleMenus,
+    };
+  },
+});
+</script>
+
+<style scoped lang="less">
+:deep(.vben-basic-tree) {
+  width: 100% !important;
+}
+
+:deep(.is-unflod) {
+  display: none !important;
+}
+
+:deep(.is-flod) {
+  display: none !important;
+}
+</style>

+ 147 - 0
src/views/systemAdmin/system/zhiwei/index.vue

@@ -0,0 +1,147 @@
+<template>
+  <div>
+    <BasicTable :rowSelection="{ type: 'checkbox' }" @register="registerTable" :clickToRowSelect="false">
+      <template #toolbar>
+        <Authority>
+          <a-button type="primary" @click="handleCreate">新增角色</a-button>
+        </Authority>
+        <Authority>
+          <Popconfirm title="您确定要批量删除数据" ok-text="确定" cancel-text="取消" @confirm="handleDeleteOrBatchDelete(null)">
+            <a-button type="primary" color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
+          </Popconfirm>
+        </Authority>
+      </template>
+      <template #status="{ record }">
+        <Switch :checked="record.status === 1" :loading="record.pendingStatus" checkedChildren="启用" unCheckedChildren="禁用"
+          @change="(checked: boolean) => statusChange(checked, record)" />
+      </template>
+      <template #action="{ record }">
+        <TableAction :actions="[
+          {
+            label: '编辑',
+            icon: 'clarity:note-edit-line',
+            onClick: handleEdit.bind(null, record),
+          },
+          {
+            label: '删除',
+            icon: 'ant-design:delete-outlined',
+            color: 'error',
+            ifShow: record.roleType != RoleEnum.SYS_ADMIN,
+            popConfirm: {
+              title: '是否确认删除',
+              confirm: handleDeleteOrBatchDelete.bind(null, record),
+            },
+          },
+        ]" />
+      </template>
+    </BasicTable>
+    <RoleDrawer @register="registerDrawer" @success="handleSuccess" />
+  </div>
+</template>
+<script lang="ts">
+import { defineComponent, nextTick } from 'vue';
+import { BasicTable, useTable, TableAction } from '/@/components/Table';
+import { delRole, getRoleListByPage, setRoleStatus } from '/@/api/system/system';
+import { useDrawer } from '/@/components/Drawer';
+import RoleDrawer from './RoleDrawer.vue';
+import { columns, searchFormSchema } from './role.data';
+import { RoleEnum } from '/@/enums/roleEnum';
+import { Authority } from '/@/components/Authority';
+import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
+import { useMessage } from '/@/hooks/web/useMessage';
+import { Switch, Popconfirm } from 'ant-design-vue';
+import { roleList } from '/@/api/sys/user';
+
+export default defineComponent({
+  name: 'RoleManagement',
+  components: { BasicTable, RoleDrawer, TableAction, Authority, Switch, Popconfirm },
+  setup() {
+    const [registerDrawer, { openDrawer }] = useDrawer();
+    function handleSuccess() {
+      reload();
+    }
+    const [registerTable, { setProps, reload, setSelectedRowKeys }] = useTable({
+      title: '角色列表',
+      api: roleList,
+      columns,
+      formConfig: {
+        labelWidth: 120,
+        schemas: searchFormSchema,
+      },
+      useSearchForm: true,
+      showTableSetting: true,
+      bordered: true,
+      showIndexColumn: false,
+      actionColumn: {
+        width: 200,
+        title: '操作',
+        dataIndex: 'action',
+        slots: { customRender: 'action' },
+        fixed: 'right',
+      },
+    });
+    const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions, resetSelectedRowKeys } =
+      useBatchDelete(delRole, handleSuccess, setProps);
+    selectionOptions.rowSelection.getCheckboxProps = (record: Recordable) => {
+      // Demo:status为1的选择框禁用
+      if (record.status === 1) {
+        return { disabled: true };
+      } else {
+        return { disabled: false };
+      }
+    };
+    nextTick(() => {
+      setProps(selectionOptions);
+    });
+
+    function handleCreate() {
+      openDrawer(true, {
+        isUpdate: false,
+      });
+    }
+
+    function handleEdit(record: Recordable) {
+      openDrawer(true, {
+        record,
+        isUpdate: true,
+      });
+      console.log(record)
+    }
+
+    const statusChange = async (checked, record) => {
+      setProps({
+        loading: true,
+      });
+      setSelectedRowKeys([]);
+      resetSelectedRowKeys();
+      const newStatus = checked ? 1 : 0;
+      const { createMessage } = useMessage();
+      try {
+        await setRoleStatus(record.id, newStatus);
+        if (newStatus) {
+          createMessage.success(`启用成功`);
+        } else {
+          createMessage.success('禁用成功');
+        }
+      } finally {
+        setProps({
+          loading: false,
+        });
+        reload();
+      }
+    };
+
+    return {
+      registerTable,
+      registerDrawer,
+      handleCreate,
+      handleEdit,
+      handleSuccess,
+      RoleEnum,
+      hasBatchDelete,
+      handleDeleteOrBatchDelete,
+      statusChange,
+    };
+  },
+});
+</script>

+ 90 - 0
src/views/systemAdmin/system/zhiwei/role.data.ts

@@ -0,0 +1,90 @@
+import { BasicColumn } from '/@/components/Table';
+import { FormSchema } from '/@/components/Table';
+import { RoleEnum } from '/@/enums/roleEnum';
+
+export enum KeysTypeEnum {
+  DISABLED = 'disabled',
+  ENABLED = 'enabled',
+}
+
+export const RoleMenuDictEnum: Recordable<{ key: string; keyType: KeysTypeEnum }> = {
+  [RoleEnum.PLATFORM_ADMIN]: { key: 'enabled_platform_admin_auth', keyType: KeysTypeEnum.ENABLED },
+  [RoleEnum.SYS_ADMIN]: { key: 'enabled_sysadmin_auth', keyType: KeysTypeEnum.ENABLED },
+  [RoleEnum.TENANT_ADMIN]: { key: 'disabled_tenant_auth', keyType: KeysTypeEnum.DISABLED },
+  [RoleEnum.CUSTOMER_USER]: { key: 'disabled_tenant_auth', keyType: KeysTypeEnum.DISABLED },
+};
+
+export const columns: BasicColumn[] = [
+  {
+    title: '角色名称',
+    dataIndex: 'groupName',
+    width: 200,
+  },
+  {
+    title: '角色Code',
+    dataIndex: 'groupid',
+    width: 200,
+  },
+  {
+    title: '类型',
+    dataIndex: 'groupType',
+    width: 120,
+  },
+
+  {
+    title: '备注',
+    dataIndex: 'memo',
+    width: 240,
+  },
+  {
+    title: '排序',
+    dataIndex: 'sort',
+    width: 180,
+  },
+];
+
+export const searchFormSchema: FormSchema[] = [
+  {
+    field: 'roleName',
+    label: '角色名称',
+    component: 'Input',
+    colProps: { span: 6 },
+    componentProps: {
+      maxLength: 255,
+    },
+  },
+  {
+    field: 'status',
+    label: '状态',
+    component: 'Select',
+    componentProps: {
+      options: [
+        { label: '启用', value: 1 },
+        { label: '停用', value: 0 },
+      ],
+    },
+    colProps: { span: 6 },
+  },
+];
+
+export const formSchema: FormSchema[] = [
+  {
+    field: 'groupName',
+    label: '角色名称',
+    required: true,
+    component: 'Input',
+    componentProps: {
+      maxLength: 255,
+      placeholder: '请输入角色名称',
+    },
+  },
+  {
+    label: '排序',
+    field: 'sort',
+    component: 'Input',
+    componentProps: {
+      maxLength: 255,
+      placeholder: '请输入排序',
+    },
+  }
+];