Bladeren bron

角色管理首页、创建和创建drawer。api部分对接

lfeish 1 jaar geleden
bovenliggende
commit
5bc88edaa7

+ 12 - 2
src/api/system/menu.ts

@@ -2,7 +2,7 @@ import { http } from '@/utils/http/axios';
 import { MenuDetailTree, MenuDetailItem } from '@/types/menu/type';
 
 /**
- * @description: 获取动态菜单
+ * 获取当前用户可访问态菜单
  */
 export function getRouters() {
   return http.request({
@@ -13,7 +13,7 @@ export function getRouters() {
 
 
 /**
- * v4:获取整个菜单树
+ * 获取整个菜单树
  */
 export function queryFullMenuTree() {
   return http.request<MenuDetailTree>({
@@ -22,6 +22,16 @@ export function queryFullMenuTree() {
   });
 }
 
+/**
+ * 获取当前用户拥有的菜单树
+ */
+export function queryOwnedMenuTree() {
+  return http.request<MenuDetailTree>({
+    url: '/admin/menu/queryOwnedMenuTree',
+    method: 'post',
+  }); 
+}
+
 /**
  * 添加菜单
  * @param params

+ 12 - 1
src/api/system/permission.ts

@@ -2,7 +2,7 @@ import { http } from '@/utils/http/axios';
 import { PermissionTree, PermissionItem } from '@/types/permission/type';
 
 /**
- * 获取整个权限树
+ * 获取整个功能权限树
  */
 export function getPermissionTree() {
   return http.request<PermissionTree>({
@@ -11,6 +11,17 @@ export function getPermissionTree() {
   });
 };
 
+/**
+ * 获取当前用户拥有的功能权限树
+ */
+export function getOwnedPermissionTree() {
+  return http.request<PermissionTree>({
+    url: '/admin/perm/queryOwnedPermissionList',
+    method: 'post'
+  });
+}
+
+
 /**
  * 添加权限
  */

+ 65 - 1
src/api/system/role.ts

@@ -1,4 +1,5 @@
 import { http } from '@/utils/http/axios';
+import { Role, RolePageRequest, RolePageResponse, RoleForm, AssignedPermissions } from '@/types/role/type';
 
 /**
  * @description: 添加管理角色
@@ -107,7 +108,6 @@ export function delUserRole(params) {
 export function roleList(params?) {
   return http.request({
     url: '/role/pageList',
-
     params,
   });
 }
@@ -140,3 +140,67 @@ export function getFeaturePermissions() {
 
   });
 }
+
+
+/**
+ * v4: 获取自己拥有的和自己创建的角色
+ */
+export function getRolesPage(params: RolePageRequest) {
+  return http.request<RolePageResponse>({
+    url: '/admin/role/queryRolePage',
+    method: 'POST',
+    data: params,
+  });
+}
+
+/**
+ * v4: 获取自己拥有和自己创建的角色
+ */
+export function getRoles() {
+  return http.request<Role[]>({
+    url: '/admin/role/getRoleList',
+    method: 'GET'
+  });
+}
+
+/**
+ * v4: 创建角色
+ */
+export function createRole(data: RoleForm) {
+  return http.request({
+    url: '/admin/role/addRole',
+    method: 'POST',
+    data,
+  });
+}
+
+/**
+ * v4: 编辑角色
+ */
+export function editRole(data: RoleForm) {
+  return http.request({
+    url: '/admin/role/updateRole',
+    method: 'POST',
+    data,
+  });
+}
+
+/**
+ * v4:删除菜单角色
+ */
+export function deleteRole(roleId: number) {
+  return http.request({
+    url: `/admin/role/deleteRole?roleId=${roleId}`,
+    method: 'POST',
+  });
+}
+
+/**
+ * v4:获取角色已分配的权限(相机、菜单、功能)
+ */
+export function getAssignedPerms(roleId: number) {
+  return http.request<AssignedPermissions>({
+    url: `/admin/role/getSelectedPerm?roleId=${roleId}`,
+    method: 'GET',
+  }); 
+}

+ 3 - 1
src/types/permission/type.ts

@@ -34,9 +34,11 @@ export type PermissionTree = Permission[];
 /**
  * 权限显示项目,用于生成 el-tree
  */
+export type PermissionTreeKey = number | string;
+
 export interface PermissionViewItem {
   label: string;
-  value: number | string;
+  value: PermissionTreeKey;
 }
 
 export type PermissionView = PermissionViewItem & { children?: PermissionViewItem[] | null };

+ 53 - 0
src/types/role/type.ts

@@ -0,0 +1,53 @@
+import { PaginationRequest, PaginationResponse } from '@/types/common/type';
+import { PermissionTreeKey } from '../permission/type';
+
+/**
+ * 角色列表row
+ */
+export interface Role {
+  // 主键ID
+  id: number;
+  // 角色名
+  roleName: string;
+  // 备注
+  remark: string;
+  // 租户ID
+  tenantId?: number; 
+  isDeleted?: number;
+  createdAt?: string;
+  createdBy?: string;
+  updatedAt?: string;
+  updatedBy?: string;
+}
+
+/**
+ * 角色列表请求参数
+ */
+export interface RolePageRequest extends PaginationRequest {
+  queryParam?: {
+    roleName: Role['roleName'];
+    tenantId?: Role['tenantId'];
+  };
+}
+
+/**
+ * 角色列表数据
+ */
+export type RolePageResponse = PaginationResponse<Role>;
+
+
+/**
+ * 角色表单
+ */
+export interface RoleForm {
+  id: number | null;
+  roleName: string;
+  remark: string;
+  cameraIds: PermissionTreeKey[];
+  menuIds: PermissionTreeKey[];
+  permIds: PermissionTreeKey[];
+  tenantId?: number;
+}
+
+export type AssignedPermissions = Pick<RoleForm, 'cameraIds' | 'menuIds' | 'permIds'>;
+

+ 111 - 0
src/views/system/role/components/PermissionTreeCard.vue

@@ -0,0 +1,111 @@
+<template>
+  <el-card style="width: 100%">
+    <template #header>
+      <section class="title">{{ title }}</section>
+      <section>
+        <el-checkbox label="全部展开 / 全部收起" @change="expandAll"  />
+        <el-checkbox label="全选 / 全不选" @change="checkAll" />
+      </section>
+    </template>
+
+    <el-tree
+      ref="treeInstance"
+      :data="treeData" 
+      node-key="value" 
+      show-checkbox
+      :expand-on-click-node="false"
+      @check="onNodeCheck"
+    />
+  </el-card>
+</template>
+
+<script setup lang="ts">
+  import { ref, shallowRef } from 'vue';
+  import { ElTree } from 'element-plus';
+  import { PermissionViewTree, PermissionTreeKey } from '@/types/permission/type';
+
+  defineProps<{
+    title: string;
+    treeData: PermissionViewTree;
+  }>();
+  
+  const treeInstance = ref<InstanceType<typeof ElTree>>();
+  const leafCheckedKeys = shallowRef<PermissionTreeKey[]>([]);
+
+  /**
+   * 当check树节点时,获取其下的所有leaf节点的值
+   */
+  const onNodeCheck = () => {
+    leafCheckedKeys.value = treeInstance.value?.getCheckedKeys(true)!;
+  };
+
+  /**
+   * 全部展开 / 全部收起
+   * @param expanded 
+   */
+  const expandAll = (expanded: boolean) => {
+    treeInstance.value?.store._getAllNodes().forEach(node => node.expanded = expanded);
+  };
+
+  
+  /**
+   * 全选 / 全不选
+   * @param checked 
+   */
+  const checkAll = (checked: boolean) => {
+    leafCheckedKeys.value = checked ? getAllLeafKeys() : [];
+    treeInstance.value?.setCheckedKeys(leafCheckedKeys.value);
+  };
+
+  /**
+   * 获取所有叶子节点的 node-key
+   */
+  const getAllLeafKeys = () => {
+    return treeInstance.value?.store._getAllNodes()
+      .filter(node => node.isLeaf)
+      .map(node => node.data.value) as PermissionTreeKey[];
+  };
+
+  /**
+   * 编辑角色时,勾选已分配的权限
+   */
+  const setAssignedPermissions = (keys: PermissionTreeKey[]) => {
+    treeInstance.value?.setCheckedKeys(keys, true);
+    leafCheckedKeys.value = keys;
+  };
+
+  
+  /**
+   * 返回选择的权限值.
+   * 权限值可能是 相机ID、菜单ID、或 权限ID
+   */
+  const getSelectedPermissions = (): PermissionTreeKey[] => {
+    return [ ...leafCheckedKeys.value ];
+  };
+
+
+  /**
+   * 重置
+   */
+  const reset = () => {
+    checkAll(false);
+  }
+
+  defineExpose({ getSelectedPermissions, reset, setAssignedPermissions });
+</script>
+
+<style scoped>
+  .el-card + .el-card {
+    margin-top: 10px;
+  }
+
+  :deep(.el-card__header) {
+    padding: 10px;
+  }
+
+  .title:before {
+    content: '';
+    margin-right: 10px;
+    border-left: 3px solid #1890ff;
+  }
+</style>

+ 142 - 0
src/views/system/role/components/RoleDrawer.vue

@@ -0,0 +1,142 @@
+<template>
+  <el-drawer :title="title" v-model="drawerOpened" @close="reset">
+    <el-form 
+      label-position="left" 
+      label-width="80px" 
+      :model="formData" 
+      :rules="formRules"
+      ref="formInstance"
+    >
+      <el-form-item label="角色名称" prop="roleName">
+        <el-input placeholder="角色名称" v-model="formData.roleName" />
+      </el-form-item>
+
+      <el-form-item label="角色权限">
+        <PermissioTreenCard title="相机权限" :tree-data="[]" ref="cameraCardInstance" />
+        <PermissioTreenCard title="菜单权限" :tree-data="menuPermTreeData" ref="menuCardInstance" />
+        <PermissioTreenCard title="功能权限" :tree-data="funcPermTreeData" ref="funcCardInstance" />
+      </el-form-item>
+
+      <el-form-item label="备注" prop="remark">
+        <el-input type="textarea" placeholder="备注" v-model="formData.remark" />
+      </el-form-item>
+    </el-form>
+
+    <template #footer>
+      <el-button @click="reset">重置</el-button>
+      <el-button type="primary" @click="submit">提交</el-button>
+    </template>
+  </el-drawer>
+</template>
+
+<script setup lang="ts">
+  import { reactive, ref, computed, toRaw } from 'vue';
+  import PermissioTreenCard from './PermissionTreeCard.vue';
+  import { RoleForm, Role, AssignedPermissions } from '@/types/role/type';
+  import { FormRules, FormInstance, ElMessage } from 'element-plus';
+  import useMenuPermTree from '../hooks/useMenuPermissionTree';
+  import useFuncPermTree from '../hooks/useFunctionPermissionTree';
+  import { createRole, editRole, getAssignedPerms } from '@/api/system/role';
+
+  defineProps<{
+    title: string;
+  }>();
+
+  const emits = defineEmits<{
+    (e: 'submitted'): void;  // 提交之后触发的事件
+  }>();
+
+  const { menuPermTreeData } = useMenuPermTree();
+  const { funcPermTreeData} = useFuncPermTree();
+
+  const drawerOpened = ref(false);
+  const cameraCardInstance = ref<InstanceType<typeof PermissioTreenCard>>();
+  const menuCardInstance = ref<InstanceType<typeof PermissioTreenCard>>();
+  const funcCardInstance = ref<InstanceType<typeof PermissioTreenCard>>();   
+
+  // 表单相关
+  const defaultFormData = (): RoleForm => ({
+    id: null,
+    roleName: '',
+    remark: '',
+    cameraIds: [],
+    menuIds: [],
+    permIds: [],
+  });
+  const formData = reactive<RoleForm>(defaultFormData());
+  const formRules: FormRules = {
+    roleName: { required: true, trigger: 'blur', message: '请填写角色名称' },
+    remark: {},
+  };
+  const formInstance = ref<FormInstance>();
+  
+  const isEditing = computed(() => formData.id != null);
+
+  /**
+   * 打开 drawer。如果未传递 roleId,表示创建角色;反之,表示编辑角色
+   * @param roleId 可选
+   */
+  const open = (role?: Role) => {
+    if (role) {
+      formData.id = role.id;
+      formData.roleName = role.roleName;
+      formData.remark = role.remark;
+      getAssignedPermissions(role.id);
+
+      // TODO: 获取已拥有的权限
+    }
+
+    drawerOpened.value = true;
+  };
+
+  /**
+   * 获取当前角色已分配的权限数据,并更新相应的权限数
+   */
+  const getAssignedPermissions = async (roleId: number) => {
+    try {
+      const result = await getAssignedPerms(roleId);
+      displayAssignedPermissions(result);
+    } catch (e) {
+      console.error(e);
+    }
+  }
+
+  const displayAssignedPermissions = (result: AssignedPermissions) => {
+    cameraCardInstance.value?.setAssignedPermissions(result.cameraIds ?? []);
+    menuCardInstance.value?.setAssignedPermissions(result.menuIds ?? []);
+    funcCardInstance.value?.setAssignedPermissions(result.permIds ?? []);
+  }
+
+  /**
+   * 重置表单
+   */
+  const reset = () => {
+    formInstance.value?.resetFields();
+    Object.assign(formData, defaultFormData());
+    cameraCardInstance.value?.reset();
+    menuCardInstance.value?.reset();
+    funcCardInstance.value?.reset();
+  };
+
+  /**
+   * 提交。创建和编辑统一
+   */
+  const submit = async () => {
+    formData.cameraIds = cameraCardInstance.value!.getSelectedPermissions();
+    formData.menuIds = menuCardInstance.value!.getSelectedPermissions();
+    formData.permIds = funcCardInstance.value!.getSelectedPermissions();
+
+    const api = isEditing.value ? editRole : createRole;
+    try {
+      await api(toRaw(formData));
+      drawerOpened.value = false;
+      ElMessage.success('提交成功');
+      // 让父组件更新列表
+      emits('submitted');
+    } catch (e) {
+      console.error(e);
+    }
+  }
+
+  defineExpose({ open });
+</script>

+ 0 - 0
src/views/system/role/hooks/useCameraPermissionTree.ts


+ 19 - 0
src/views/system/role/hooks/useFunctionPermissionTree.ts

@@ -0,0 +1,19 @@
+import {shallowRef, onMounted } from 'vue';
+import { getOwnedPermissionTree } from "@/api/system/permission";
+import { PermissionViewTree } from "@/types/permission/type";
+import { transformToViewTree } from '../utils/tree';
+export default function useMenuPermissionTree() {
+  const funcPermTreeData = shallowRef<PermissionViewTree>([]);
+  const buildPermissionTree = async () => {
+    try {
+      const result = await getOwnedPermissionTree();
+      funcPermTreeData.value = transformToViewTree(result, 'permissionName', 'id');
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  onMounted(() => buildPermissionTree());
+
+  return { funcPermTreeData };
+}

+ 19 - 0
src/views/system/role/hooks/useMenuPermissionTree.ts

@@ -0,0 +1,19 @@
+import { shallowRef, onMounted } from 'vue';
+import { queryOwnedMenuTree } from "@/api/system/menu";
+import { PermissionViewTree } from "@/types/permission/type";
+import { transformToViewTree } from '../utils/tree';
+export default function useMenuPermissionTree() {
+  const menuPermTreeData = shallowRef<PermissionViewTree>([]);
+  const buildPermissionTree = async () => {
+    try {
+      const result = await queryOwnedMenuTree();
+      menuPermTreeData.value = transformToViewTree(result, 'menuName', 'id');
+    } catch (e) {
+      console.error(e);
+    }
+  };
+
+  onMounted(() => buildPermissionTree());
+
+  return { menuPermTreeData };
+}

+ 65 - 0
src/views/system/role/hooks/useRolesQuery.ts

@@ -0,0 +1,65 @@
+import { reactive, shallowRef, toRaw, ref } from 'vue';
+import { DEFAULT_PAGE_SIZE } from '@/types/common/constants';
+import { Role, RolePageRequest } from '@/types/role/type';
+import { cloneDeep } from 'lodash-es';
+import { getRolesPage, getRoles } from '@/api/system/role';
+
+const defaultRolePageRequest: RolePageRequest = {
+  pageNumber: 1,
+  pageSize: DEFAULT_PAGE_SIZE,
+  queryParam: {
+    roleName: '',
+  }
+}
+
+
+export default function useRolesQuery() {
+  const requestParams = reactive<RolePageRequest>(cloneDeep(defaultRolePageRequest));
+  const roleList = shallowRef<Role[]>([]);
+  const total = ref(0);
+  const loading = ref(false);
+
+  const setRequestParams = (params: Partial<RolePageRequest>) => {
+    Object.assign(requestParams, params);
+  }
+
+  const resetRequestParams = () => {
+    Object.assign(requestParams, defaultRolePageRequest)
+  }
+
+
+  const queryRolesPage = async () => {
+    try {
+      loading.value = true;
+      const result = await getRolesPage(toRaw(requestParams));
+      roleList.value = result.records;
+      total.value = result.totalRow;
+    } catch (e) {
+      console.error(e);
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  const queryRoles = async () => {
+    try {
+      loading.value = true;
+      roleList.value = await getRoles();
+    } catch (e) {
+      console.error(e);
+    } finally {
+      loading.value = false;
+    }
+  };
+
+  return {
+    requestParams,
+    roleList,
+    total,
+    loading,
+    setRequestParams,
+    resetRequestParams,
+    queryRolesPage,
+    queryRoles,
+  };
+}

+ 58 - 167
src/views/system/role/role.vue

@@ -1,190 +1,81 @@
 <template>
-  <page-wrapper>
-    <el-card :bordered="false" class="mb-3 proCard">
+  <div>
+    <el-card class="mb-3 proCard">
       <el-space align="center">
         <el-input
           :style="{ width: '320px' }"
-          v-model="params.roleName"
+          v-model="requestParams.queryParam!.roleName"
           clearable
           placeholder="请输入角色名称"
-          @keyup.enter="reloadTable"
+          @keyup.enter="queryRolesPage"
         />
-        <el-button type="primary" @click="reloadTable">
-          <template #icon>
-            <el-icon>
-              <SearchOutlined />
-            </el-icon>
-          </template>
-          查询
-        </el-button>
+        <el-button type="primary" :icon="Search" @click="queryRolesPage">查询</el-button>
       </el-space>
     </el-card>
-    <el-card :bordered="false" class="proCard">
-      <BasicTable
-        :columns="columns"
-        :request="loadDataTable"
-        :row-key="(row) => row.id"
-        :pagination="{ hideOnSinglePage: false }"
-        :tableSetting="{
-          size: false,
-          redo: false,
-          fullscreen: false,
-          striped: false,
-          setting: false,
-        }"
-        ref="tableRef"
-        :actionColumn="actionColumn"
-        @update:checked-row-keys="onCheckedRow"
-      >
-        <template #tableTitle>
-          <el-button type="primary" @click="openCreateUserDrawer">
-            <template #icon>
-              <el-icon>
-                <FileAddOutlined />
-              </el-icon>
-            </template>
-            用户角色
-          </el-button>
-          <el-button type="primary" @click="openCreateDrawer">
-            <template #icon>
-              <el-icon>
-                <FileAddOutlined />
-              </el-icon>
-            </template>
-            管理员角色
-          </el-button>
-        </template>
 
-        <template #action>
-          <TableAction />
-        </template>
-      </BasicTable>
-    </el-card>
+    <el-card>
+      <template #header>
+        <el-button type="primary" @click="openDrawer()">添加角色</el-button>
+      </template>
+
+      <el-table height="calc(100vh - 340px)" :data="roleList">
+        <el-table-column label="角色ID" width="100" prop="id" />
+        <el-table-column label="角色名称" prop="roleName" />
+        <el-table-column label="备注" prop="remark" />
+        <el-table-column label="创建时间" width="200" prop="createdAt" />
+        <el-table-column label="操作" width="160">
+          <template #default="{ row }">
+            <el-space>
+              <el-button type="primary" :icon="Edit" text @click="openDrawer(row)" />
+              <el-button :icon="Delete" text />
+            </el-space>
+          </template>
+        </el-table-column>
+      </el-table>
 
-    <CreateDrawer
-      ref="createDrawerRef"
-      :title="drawerTitle"
-      :permissionList="treeData"
-      @change="reloadTable"
-    />
+      <section class="mt-4 flex justify-end">
+        <el-pagination
+          background
+          layout="total, sizes, prev, pager, next"
+          :page-sizes="[10, 30, 50]"
+          :total="total"
+          v-model:page-size="requestParams.pageSize"
+          v-model:current-page="requestParams.pageNumber"
+          @change="queryRolesPage"
+        />
+      </section>
+    </el-card>
 
-    <CreateUserDrawer ref="createUserDrawerRef" :title="drawerTitle" @change="reloadTable" />
-  </page-wrapper>
+    <RoleDrawer :title="drawerTitle" ref="drawerInstance" @submitted="onSubmitRole" />
+  </div>
 </template>
 
 <script lang="ts" setup>
-  import { reactive, ref, unref, h, onMounted } from 'vue';
-  import { ElMessage } from 'element-plus';
-  import { BasicTable, TableAction, BasicColumn } from '@/components/Table';
-  import { roleList, permissionList, delAdminRole, delUserRole } from '@/api/system/role';
-  import { columns } from './columns';
-  import { FileAddOutlined, SearchOutlined } from '@vicons/antd';
-  import CreateDrawer from './CreateDrawer.vue';
-  import CreateUserDrawer from './CreateUserDrawer.vue';
-  import { useUserStore } from '@/store/modules/user';
+  import { ref, onMounted } from 'vue';
+  import { Edit, Delete, Search } from '@element-plus/icons-vue';
+  import RoleDrawer from './components/RoleDrawer.vue';
+  import useRolesQuery from './hooks/useRolesQuery';
+  import { Role } from '@/types/role/type';
 
-  const message = ElMessage;
-  const tableRef = ref();
-  const createDrawerRef = ref();
-  const createUserDrawerRef = ref();
-  const drawerTitle = ref('添加角色');
-  const treeData = ref([]);
-  const userStore = useUserStore();
+  const { roleList, total, queryRolesPage, requestParams } = useRolesQuery();
 
-  const params = reactive({
-    roleName: '',
-  });
+  // drawer 相关变量
+  const drawerTitle = ref('');
+  const drawerInstance = ref<InstanceType<typeof RoleDrawer>>();
 
-  const actionColumn: BasicColumn = reactive({
-    width: 150,
-    title: '操作',
-    key: 'action',
-    fixed: 'right',
-    render(record) {
-      return h(TableAction as any, {
-        style: 'button',
-        actions: [
-          {
-            label: '删除',
-            isConfirm: true,
-            popConfirm: {
-              onConfirm: handleDelete.bind(null, record.row),
-              title: '您确定要删除吗?',
-              confirmButtonText: '确定',
-              cancelButtonText: '取消',
-            },
-          },
-          {
-            label: '编辑',
-            onClick: handleEdit.bind(null, record.row),
-          },
-        ],
-      });
-    },
-  });
-
-  const loadDataTable = async (res: any) => {
-    let _params = {
-      ...unref(params),
-      ...res,
-    };
-    return await roleList(_params);
+  const openDrawer = (row?: Role) => {
+    drawerTitle.value = row ? '编辑角色' : '添加角色';
+    drawerInstance.value?.open(row);
   };
 
-  function openCreateDrawer() {
-    drawerTitle.value = '添加角色';
-    const { openDrawer } = createDrawerRef.value;
-    openDrawer();
-  }
-
-  function openCreateUserDrawer() {
-    drawerTitle.value = '添加角色';
-    const { openDrawer } = createUserDrawerRef.value;
-    openDrawer();
-  }
-
-  function onCheckedRow(rowKeys: any[]) {
-    console.log(rowKeys);
-  }
-
-  function reloadTable() {
-    tableRef.value.reload();
-  }
-
-  function handleEdit(record: Recordable) {
-    console.log('点击了编辑', record);
-    console.log('record.roleType', record.roleType);
-    drawerTitle.value = '编辑角色';
-    if (record.roleType === 1 || record.roleType === 2) {
-      const { openDrawer } = createDrawerRef.value;
-      openDrawer(record.roleId);
-    } else {
-      const { openDrawer } = createUserDrawerRef.value;
-      openDrawer(record.roleId);
-    }
-  }
-
-  function handleDelete(record: Recordable) {
-    console.log('record.roleType', record.roleType);
-    // if (userStore.getRoleTypes.includes(String(record.roleId))) {
-    //   message.error('不能删除自己的角色');
-    //   return;
-    // }
-    if (record.roleType === 1 || record.roleType === 2) {
-      delAdminRole({ roleId: record.roleId }).then(() => {
-        message.success('删除成功');
-        reloadTable();
-      });
-    } else {
-      delUserRole({ roleId: record.roleId }).then(() => {
-        message.success('删除成功');
-        reloadTable();
-      });
-    }
-  }
+  /**
+   * 创建或编辑角色后重新获取列表
+   */
+  const onSubmitRole = () => {
+    queryRolesPage();
+  };
 
-  onMounted(async () => {
-    const list = await permissionList();
-    treeData.value = list.filter((item) => item.label !== '功能权限');
+  onMounted(() => {
+    queryRolesPage();
   });
 </script>

+ 30 - 0
src/views/system/role/utils/tree.ts

@@ -0,0 +1,30 @@
+import { PermissionView, PermissionViewTree } from "@/types/permission/type";
+
+export function transformToViewTree<T>(rawTree: Array<T>, labelKey='label', valueKey='value', childrenKey='children'): PermissionViewTree {
+  if (rawTree == null || !Array.isArray(rawTree) ) {
+    throw 'Tree data must be an array';
+  }
+
+  if (!rawTree.length) {
+    return [];
+  }
+
+  const viewTree: PermissionViewTree = [];
+
+  for (const item of rawTree) {
+    const viewItem: PermissionView = {
+      value: item[valueKey],
+      label: item[labelKey],
+      children: [],
+    };
+
+    if (Array.isArray(item[childrenKey]) && item[childrenKey].length) {
+      viewItem.children = transformToViewTree(item[childrenKey], labelKey, valueKey, childrenKey);
+      viewTree.push(viewItem);
+    } else {
+      viewTree.push(viewItem);
+    }
+  }
+
+  return viewTree;
+}