mirror of
				https://github.com/soybeanjs/soybean-admin.git
				synced 2025-11-04 07:43:42 +08:00 
			
		
		
		
	feat(projects): mock添加权限过滤
This commit is contained in:
		
							
								
								
									
										2
									
								
								.env
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								.env
									
									
									
									
									
								
							@@ -7,7 +7,7 @@ VITE_APP_TITLE=Soybean管理系统
 | 
				
			|||||||
VITE_APP_DESC=SoybeanAdmin是一个中后台管理系统模版
 | 
					VITE_APP_DESC=SoybeanAdmin是一个中后台管理系统模版
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# 权限路由模式: static | dynamic
 | 
					# 权限路由模式: static | dynamic
 | 
				
			||||||
VITE_AUTH_ROUTE_MODE=static
 | 
					VITE_AUTH_ROUTE_MODE=dynamic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VITE_VISUALIZER=false
 | 
					VITE_VISUALIZER=false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								components.d.ts
									
									
									
									
										vendored
									
									
								
							@@ -13,9 +13,14 @@ declare module 'vue' {
 | 
				
			|||||||
    IconAntDesignCloseOutlined: typeof import('~icons/ant-design/close-outlined')['default']
 | 
					    IconAntDesignCloseOutlined: typeof import('~icons/ant-design/close-outlined')['default']
 | 
				
			||||||
    IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
 | 
					    IconAntDesignEnterOutlined: typeof import('~icons/ant-design/enter-outlined')['default']
 | 
				
			||||||
    IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
 | 
					    IconAntDesignSettingOutlined: typeof import('~icons/ant-design/setting-outlined')['default']
 | 
				
			||||||
 | 
					    IconCustomActivity: typeof import('~icons/custom/activity')['default']
 | 
				
			||||||
    IconCustomAvatar: typeof import('~icons/custom/avatar')['default']
 | 
					    IconCustomAvatar: typeof import('~icons/custom/avatar')['default']
 | 
				
			||||||
 | 
					    IconCustomBanner: typeof import('~icons/custom/banner')['default']
 | 
				
			||||||
 | 
					    IconCustomCast: typeof import('~icons/custom/cast')['default']
 | 
				
			||||||
 | 
					    IconCustomEmptyData: typeof import('~icons/custom/empty-data')['default']
 | 
				
			||||||
    IconCustomLogo: typeof import('~icons/custom/logo')['default']
 | 
					    IconCustomLogo: typeof import('~icons/custom/logo')['default']
 | 
				
			||||||
    IconCustomLogoFill: typeof import('~icons/custom/logo-fill')['default']
 | 
					    IconCustomLogoFill: typeof import('~icons/custom/logo-fill')['default']
 | 
				
			||||||
 | 
					    IconCustomNetworkError: typeof import('~icons/custom/network-error')['default']
 | 
				
			||||||
    IconCustomNoPermission: typeof import('~icons/custom/no-permission')['default']
 | 
					    IconCustomNoPermission: typeof import('~icons/custom/no-permission')['default']
 | 
				
			||||||
    IconCustomNotFound: typeof import('~icons/custom/not-found')['default']
 | 
					    IconCustomNotFound: typeof import('~icons/custom/not-found')['default']
 | 
				
			||||||
    IconCustomServiceError: typeof import('~icons/custom/service-error')['default']
 | 
					    IconCustomServiceError: typeof import('~icons/custom/service-error')['default']
 | 
				
			||||||
@@ -50,6 +55,8 @@ declare module 'vue' {
 | 
				
			|||||||
    NColorPicker: typeof import('naive-ui')['NColorPicker']
 | 
					    NColorPicker: typeof import('naive-ui')['NColorPicker']
 | 
				
			||||||
    NConfigProvider: typeof import('naive-ui')['NConfigProvider']
 | 
					    NConfigProvider: typeof import('naive-ui')['NConfigProvider']
 | 
				
			||||||
    NDataTable: typeof import('naive-ui')['NDataTable']
 | 
					    NDataTable: typeof import('naive-ui')['NDataTable']
 | 
				
			||||||
 | 
					    NDescriptions: typeof import('naive-ui')['NDescriptions']
 | 
				
			||||||
 | 
					    NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
 | 
				
			||||||
    NDialogProvider: typeof import('naive-ui')['NDialogProvider']
 | 
					    NDialogProvider: typeof import('naive-ui')['NDialogProvider']
 | 
				
			||||||
    NDivider: typeof import('naive-ui')['NDivider']
 | 
					    NDivider: typeof import('naive-ui')['NDivider']
 | 
				
			||||||
    NDrawer: typeof import('naive-ui')['NDrawer']
 | 
					    NDrawer: typeof import('naive-ui')['NDrawer']
 | 
				
			||||||
@@ -62,18 +69,26 @@ declare module 'vue' {
 | 
				
			|||||||
    NGrid: typeof import('naive-ui')['NGrid']
 | 
					    NGrid: typeof import('naive-ui')['NGrid']
 | 
				
			||||||
    NGridItem: typeof import('naive-ui')['NGridItem']
 | 
					    NGridItem: typeof import('naive-ui')['NGridItem']
 | 
				
			||||||
    NInput: typeof import('naive-ui')['NInput']
 | 
					    NInput: typeof import('naive-ui')['NInput']
 | 
				
			||||||
 | 
					    NInputGroup: typeof import('naive-ui')['NInputGroup']
 | 
				
			||||||
    NInputNumber: typeof import('naive-ui')['NInputNumber']
 | 
					    NInputNumber: typeof import('naive-ui')['NInputNumber']
 | 
				
			||||||
 | 
					    NList: typeof import('naive-ui')['NList']
 | 
				
			||||||
 | 
					    NListItem: typeof import('naive-ui')['NListItem']
 | 
				
			||||||
    NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
 | 
					    NLoadingBarProvider: typeof import('naive-ui')['NLoadingBarProvider']
 | 
				
			||||||
    NMenu: typeof import('naive-ui')['NMenu']
 | 
					    NMenu: typeof import('naive-ui')['NMenu']
 | 
				
			||||||
    NMessageProvider: typeof import('naive-ui')['NMessageProvider']
 | 
					    NMessageProvider: typeof import('naive-ui')['NMessageProvider']
 | 
				
			||||||
    NModal: typeof import('naive-ui')['NModal']
 | 
					    NModal: typeof import('naive-ui')['NModal']
 | 
				
			||||||
    NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
 | 
					    NNotificationProvider: typeof import('naive-ui')['NNotificationProvider']
 | 
				
			||||||
 | 
					    NPopover: typeof import('naive-ui')['NPopover']
 | 
				
			||||||
    NScrollbar: typeof import('naive-ui')['NScrollbar']
 | 
					    NScrollbar: typeof import('naive-ui')['NScrollbar']
 | 
				
			||||||
    NSelect: typeof import('naive-ui')['NSelect']
 | 
					    NSelect: typeof import('naive-ui')['NSelect']
 | 
				
			||||||
    NSpace: typeof import('naive-ui')['NSpace']
 | 
					    NSpace: typeof import('naive-ui')['NSpace']
 | 
				
			||||||
 | 
					    NSpin: typeof import('naive-ui')['NSpin']
 | 
				
			||||||
 | 
					    NStatistic: typeof import('naive-ui')['NStatistic']
 | 
				
			||||||
    NSwitch: typeof import('naive-ui')['NSwitch']
 | 
					    NSwitch: typeof import('naive-ui')['NSwitch']
 | 
				
			||||||
    NTabPane: typeof import('naive-ui')['NTabPane']
 | 
					    NTabPane: typeof import('naive-ui')['NTabPane']
 | 
				
			||||||
    NTabs: typeof import('naive-ui')['NTabs']
 | 
					    NTabs: typeof import('naive-ui')['NTabs']
 | 
				
			||||||
 | 
					    NTag: typeof import('naive-ui')['NTag']
 | 
				
			||||||
 | 
					    NThing: typeof import('naive-ui')['NThing']
 | 
				
			||||||
    NTimeline: typeof import('naive-ui')['NTimeline']
 | 
					    NTimeline: typeof import('naive-ui')['NTimeline']
 | 
				
			||||||
    NTimelineItem: typeof import('naive-ui')['NTimelineItem']
 | 
					    NTimelineItem: typeof import('naive-ui')['NTimelineItem']
 | 
				
			||||||
    NTooltip: typeof import('naive-ui')['NTooltip']
 | 
					    NTooltip: typeof import('naive-ui')['NTooltip']
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
import type { MockMethod } from 'vite-plugin-mock';
 | 
					import type { MockMethod } from 'vite-plugin-mock';
 | 
				
			||||||
 | 
					import { filterAuthRoutesByUserPermission } from '../utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const routes: AuthRoute.Route[] = [
 | 
					const routes: AuthRoute.Route[] = [
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
@@ -241,7 +242,7 @@ const routes: AuthRoute.Route[] = [
 | 
				
			|||||||
        path: '/auth-demo/permission',
 | 
					        path: '/auth-demo/permission',
 | 
				
			||||||
        component: 'self',
 | 
					        component: 'self',
 | 
				
			||||||
        meta: {
 | 
					        meta: {
 | 
				
			||||||
          title: '指令和权限切换',
 | 
					          title: '权限切换',
 | 
				
			||||||
          requiresAuth: true,
 | 
					          requiresAuth: true,
 | 
				
			||||||
          icon: 'ic:round-construction'
 | 
					          icon: 'ic:round-construction'
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -378,12 +379,12 @@ const routes: AuthRoute.Route[] = [
 | 
				
			|||||||
function dataMiddleware(data: AuthRoute.Route[]): ApiRoute.Route {
 | 
					function dataMiddleware(data: AuthRoute.Route[]): ApiRoute.Route {
 | 
				
			||||||
  const routeHomeName: AuthRoute.RouteKey = 'dashboard_analysis';
 | 
					  const routeHomeName: AuthRoute.RouteKey = 'dashboard_analysis';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  function sortRoutes(sorts: AuthRoute.Route[]) {
 | 
					  data.sort((next, pre) => Number(next.meta?.order) - Number(pre.meta?.order));
 | 
				
			||||||
    return sorts.sort((next, pre) => Number(next.meta?.order) - Number(pre.meta?.order));
 | 
					
 | 
				
			||||||
  }
 | 
					  const filters = filterAuthRoutesByUserPermission(data, 'admin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return {
 | 
					  return {
 | 
				
			||||||
    routes: sortRoutes(data),
 | 
					    routes: filters,
 | 
				
			||||||
    home: routeHomeName
 | 
					    home: routeHomeName
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										24
									
								
								mock/utils/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								mock/utils/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 根据用户权限过滤路由
 | 
				
			||||||
 | 
					 * @param routes - 权限路由
 | 
				
			||||||
 | 
					 * @param permission - 权限
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					export function filterAuthRoutesByUserPermission(routes: AuthRoute.Route[], permission: Auth.RoleType) {
 | 
				
			||||||
 | 
					  return routes.map(route => filterAuthRouteByUserPermission(route, permission)).flat(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 根据用户权限过滤单个路由
 | 
				
			||||||
 | 
					 * @param route - 单个权限路由
 | 
				
			||||||
 | 
					 * @param permission - 权限
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					function filterAuthRouteByUserPermission(route: AuthRoute.Route, permission: Auth.RoleType): AuthRoute.Route[] {
 | 
				
			||||||
 | 
					  const hasPermission =
 | 
				
			||||||
 | 
					    !route.meta.permissions || permission === 'super' || route.meta.permissions.includes(permission);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (route.children) {
 | 
				
			||||||
 | 
					    const filterChildren = route.children.map(item => filterAuthRouteByUserPermission(item, permission)).flat(1);
 | 
				
			||||||
 | 
					    Object.assign(route, { children: filterChildren });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return hasPermission ? [route] : [];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,6 @@
 | 
				
			|||||||
import UAParser from 'ua-parser-js';
 | 
					import UAParser from 'ua-parser-js';
 | 
				
			||||||
 | 
					import { useAuthStore } from '@/store';
 | 
				
			||||||
 | 
					import { isArray, isString } from '@/utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface AppInfo {
 | 
					interface AppInfo {
 | 
				
			||||||
  /** 项目名称 */
 | 
					  /** 项目名称 */
 | 
				
			||||||
@@ -26,3 +28,27 @@ export function useDeviceInfo() {
 | 
				
			|||||||
  const result = parser.getResult();
 | 
					  const result = parser.getResult();
 | 
				
			||||||
  return result;
 | 
					  return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** 权限判断 */
 | 
				
			||||||
 | 
					export function usePermission() {
 | 
				
			||||||
 | 
					  const auth = useAuthStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function hasPermission(permission: Auth.RoleType | Auth.RoleType[]) {
 | 
				
			||||||
 | 
					    const { userRole } = auth.userInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let has = userRole === 'super';
 | 
				
			||||||
 | 
					    if (!has) {
 | 
				
			||||||
 | 
					      if (isArray(permission)) {
 | 
				
			||||||
 | 
					        has = (permission as Auth.RoleType[]).includes(userRole);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      if (isString(permission)) {
 | 
				
			||||||
 | 
					        has = (permission as Auth.RoleType) === userRole;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return has;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    hasPermission
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,26 +1,24 @@
 | 
				
			|||||||
import type { App, Directive } from 'vue';
 | 
					import type { App, Directive } from 'vue';
 | 
				
			||||||
import { useAuthStore } from '@/store';
 | 
					import { usePermission } from '@/composables';
 | 
				
			||||||
import { isArray, isString } from '@/utils';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function setupPermissionDirective(app: App) {
 | 
					export default function setupPermissionDirective(app: App) {
 | 
				
			||||||
  const auth = useAuthStore();
 | 
					  const { hasPermission } = usePermission();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  function updateElVisible(el: HTMLElement, permission: Auth.RoleType | Auth.RoleType[]) {
 | 
				
			||||||
 | 
					    if (!permission) {
 | 
				
			||||||
 | 
					      throw new Error(`need roles: like v-permission="'admin'", v-permission="['admin', 'test]"`);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!hasPermission(permission)) {
 | 
				
			||||||
 | 
					      el.parentElement?.removeChild(el);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const permissionDirective: Directive<HTMLElement, Auth.RoleType | Auth.RoleType[]> = {
 | 
					  const permissionDirective: Directive<HTMLElement, Auth.RoleType | Auth.RoleType[]> = {
 | 
				
			||||||
    mounted(el: HTMLElement, binding) {
 | 
					    mounted(el, binding) {
 | 
				
			||||||
      const { userRole } = auth.userInfo;
 | 
					      updateElVisible(el, binding.value);
 | 
				
			||||||
      const elPermission = binding.value;
 | 
					    },
 | 
				
			||||||
      let hasPermission = userRole === 'super';
 | 
					    beforeUpdate(el, binding) {
 | 
				
			||||||
      if (!hasPermission) {
 | 
					      updateElVisible(el, binding.value);
 | 
				
			||||||
        if (isArray(elPermission)) {
 | 
					 | 
				
			||||||
          hasPermission = (elPermission as Auth.RoleType[]).includes(userRole);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (isString(elPermission)) {
 | 
					 | 
				
			||||||
          hasPermission = (elPermission as Auth.RoleType) === userRole;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      if (!hasPermission) {
 | 
					 | 
				
			||||||
        el.remove();
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ const authDemo: AuthRoute.Route = {
 | 
				
			|||||||
      path: '/auth-demo/permission',
 | 
					      path: '/auth-demo/permission',
 | 
				
			||||||
      component: 'self',
 | 
					      component: 'self',
 | 
				
			||||||
      meta: {
 | 
					      meta: {
 | 
				
			||||||
        title: '指令和权限切换',
 | 
					        title: '权限切换',
 | 
				
			||||||
        requiresAuth: true,
 | 
					        requiresAuth: true,
 | 
				
			||||||
        icon: 'ic:round-construction'
 | 
					        icon: 'ic:round-construction'
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,7 +53,7 @@ export const useTabStore = defineStore('tab-store', {
 | 
				
			|||||||
    initHomeTab(routeHomeName: string, router: Router) {
 | 
					    initHomeTab(routeHomeName: string, router: Router) {
 | 
				
			||||||
      const routes = router.getRoutes();
 | 
					      const routes = router.getRoutes();
 | 
				
			||||||
      const findHome = routes.find(item => item.name === routeHomeName);
 | 
					      const findHome = routes.find(item => item.name === routeHomeName);
 | 
				
			||||||
      if (findHome && !findHome.children) {
 | 
					      if (findHome && !findHome.children.length) {
 | 
				
			||||||
        // 有子路由的不能作为Tab
 | 
					        // 有子路由的不能作为Tab
 | 
				
			||||||
        this.homeTab = getTabRouteByVueRoute(findHome);
 | 
					        this.homeTab = getTabRouteByVueRoute(findHome);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,17 +1,9 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
  <div class="h-full">
 | 
					  <div class="h-full">
 | 
				
			||||||
    <n-card title="权限指令 v-permission" class="h-full shadow-sm rounded-16px">
 | 
					    <n-card title="权限切换" class="h-full shadow-sm rounded-16px">
 | 
				
			||||||
      <div class="pb-12px">
 | 
					      <div class="pb-12px">
 | 
				
			||||||
        <n-gradient-text type="primary" :size="20">当前用户的权限:{{ auth.userInfo.userRole }}</n-gradient-text>
 | 
					        <n-gradient-text type="primary" :size="20">当前用户的权限:{{ auth.userInfo.userRole }}</n-gradient-text>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
      <n-space>
 | 
					 | 
				
			||||||
        <n-button v-permission="`super`">super可见</n-button>
 | 
					 | 
				
			||||||
        <n-button v-permission="`admin`">admin可见</n-button>
 | 
					 | 
				
			||||||
        <n-button v-permission="['admin', 'test']">admin和test可见</n-button>
 | 
					 | 
				
			||||||
      </n-space>
 | 
					 | 
				
			||||||
      <div class="py-12px">
 | 
					 | 
				
			||||||
        <n-gradient-text type="primary" :size="20">切换用户权限</n-gradient-text>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
      <n-select
 | 
					      <n-select
 | 
				
			||||||
        :value="auth.userInfo.userRole"
 | 
					        :value="auth.userInfo.userRole"
 | 
				
			||||||
        class="w-120px"
 | 
					        class="w-120px"
 | 
				
			||||||
@@ -19,6 +11,22 @@
 | 
				
			|||||||
        :options="roleList"
 | 
					        :options="roleList"
 | 
				
			||||||
        @update:value="auth.updateUserRole"
 | 
					        @update:value="auth.updateUserRole"
 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
 | 
					      <div class="py-12px">
 | 
				
			||||||
 | 
					        <n-gradient-text type="primary" :size="20">权限指令 v-permission</n-gradient-text>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div>
 | 
				
			||||||
 | 
					        <n-button v-permission="'super'" class="mr-12px">super可见</n-button>
 | 
				
			||||||
 | 
					        <n-button v-permission="'admin'" class="mr-12px">admin可见</n-button>
 | 
				
			||||||
 | 
					        <n-button v-permission="['admin', 'test']">admin和test可见</n-button>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <div class="py-12px">
 | 
				
			||||||
 | 
					        <n-gradient-text type="primary" :size="20">权限函数 hasPermission</n-gradient-text>
 | 
				
			||||||
 | 
					      </div>
 | 
				
			||||||
 | 
					      <n-space>
 | 
				
			||||||
 | 
					        <n-button v-if="hasPermission('super')">super可见</n-button>
 | 
				
			||||||
 | 
					        <n-button v-if="hasPermission('admin')">admin可见</n-button>
 | 
				
			||||||
 | 
					        <n-button v-if="hasPermission(['admin', 'test'])">admin和test可见</n-button>
 | 
				
			||||||
 | 
					      </n-space>
 | 
				
			||||||
    </n-card>
 | 
					    </n-card>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
@@ -26,9 +34,11 @@
 | 
				
			|||||||
<script setup lang="ts">
 | 
					<script setup lang="ts">
 | 
				
			||||||
import { watch } from 'vue';
 | 
					import { watch } from 'vue';
 | 
				
			||||||
import { useAppStore, useAuthStore } from '@/store';
 | 
					import { useAppStore, useAuthStore } from '@/store';
 | 
				
			||||||
 | 
					import { usePermission } from '@/composables';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const app = useAppStore();
 | 
					const app = useAppStore();
 | 
				
			||||||
const auth = useAuthStore();
 | 
					const auth = useAuthStore();
 | 
				
			||||||
 | 
					const { hasPermission } = usePermission();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const roleList = [
 | 
					const roleList = [
 | 
				
			||||||
  { label: '超级管理员', value: 'super' },
 | 
					  { label: '超级管理员', value: 'super' },
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user