From f9ef71f0c781a66337f00d9a62119784090ef8be Mon Sep 17 00:00:00 2001 From: chansee97 Date: Fri, 5 Sep 2025 00:49:41 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E5=96=84=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/directives/permission.ts | 44 ++++++++++- src/hooks/usePermission.ts | 74 +++++++++++++++++-- src/store/auth.ts | 4 + src/typings/entities/user.d.ts | 2 + .../components/NotificationSettings.vue | 3 + .../components/PreferenceSettings.vue | 7 +- src/views/build-in/user-center/index.vue | 2 +- src/views/system/menu/components/PageForm.vue | 2 +- .../system/menu/components/PermissionForm.vue | 2 +- src/views/system/menu/index.vue | 3 - src/views/system/role/columns.tsx | 62 ++++++++-------- 11 files changed, 154 insertions(+), 51 deletions(-) diff --git a/src/directives/permission.ts b/src/directives/permission.ts index de85412..f171d3b 100644 --- a/src/directives/permission.ts +++ b/src/directives/permission.ts @@ -1,21 +1,57 @@ import type { App, Directive } from 'vue' -import { usePermission } from '@/hooks' +import { useMenuPermission, usePermission, useRolePermission } from '@/hooks' export function install(app: App) { const { hasPermission } = usePermission() + const { hasMenuPermission } = useMenuPermission() + const { hasRolePermission } = useRolePermission() - function updatapermission(el: HTMLElement, permission: string | string[]) { + function updatePermission(el: HTMLElement, permission: string | string[]) { if (!permission) - throw new Error('v-permissson Directive with no explicit role attached') + throw new Error('v-permission Directive with no explicit permission attached') if (!hasPermission(permission)) el.parentElement?.removeChild(el) } + function updateMenuPermission(el: HTMLElement, permission: string | string[]) { + if (!permission) + throw new Error('v-menu Directive with no explicit menu permission attached') + + if (!hasMenuPermission(permission)) + el.parentElement?.removeChild(el) + } + + function updateRolePermission(el: HTMLElement, role: string | string[]) { + if (!role) + throw new Error('v-role Directive with no explicit role attached') + + if (!hasRolePermission(role)) + el.parentElement?.removeChild(el) + } + + // 通用权限指令(兼容旧版本) const permissionDirective: Directive = { mounted(el, binding) { - updatapermission(el, binding.value) + updatePermission(el, binding.value) }, } + + // 菜单权限指令 + const menuPermissionDirective: Directive = { + mounted(el, binding) { + updateMenuPermission(el, binding.value) + }, + } + + // 角色权限指令 + const rolePermissionDirective: Directive = { + mounted(el, binding) { + updateRolePermission(el, binding.value) + }, + } + app.directive('permission', permissionDirective) + app.directive('menu', menuPermissionDirective) + app.directive('role', rolePermissionDirective) } diff --git a/src/hooks/usePermission.ts b/src/hooks/usePermission.ts index 9a1977d..511ff00 100644 --- a/src/hooks/usePermission.ts +++ b/src/hooks/usePermission.ts @@ -1,6 +1,60 @@ import { useAuthStore } from '@/store' -/** 权限判断 */ +/** 菜单权限判断 */ +export function useMenuPermission() { + const authStore = useAuthStore() + + function hasMenuPermission( + permissions?: string | string[], + ) { + if (!permissions) + return true + + // 确保 permissions 是数组 + const permissionArray = Array.isArray(permissions) ? permissions : [permissions] + + // 全部权限 + if (permissionArray.includes('admin')) + return true + + const { permissions: userPermissions } = authStore + + return permissionArray.some(i => userPermissions.includes(i)) + } + + return { + hasMenuPermission, + } +} + +/** 角色权限判断 */ +export function useRolePermission() { + const authStore = useAuthStore() + + function hasRolePermission( + roles?: string | string[], + ) { + if (!roles) + return true + + // 确保 roles 是数组 + const roleArray = Array.isArray(roles) ? roles : [roles] + + // 全部权限 + if (roleArray.includes('admin')) + return true + + const { roles: userRoles } = authStore + + return roleArray.some(i => userRoles.includes(i)) + } + + return { + hasRolePermission, + } +} + +/** 合并权限判断 */ export function usePermission() { const authStore = useAuthStore() @@ -10,16 +64,20 @@ export function usePermission() { if (!permissions) return true - // 全部权限 - if (permissions === '*:*:*') - return true - - const { permissions: userPermissions } = authStore - // 确保 permissions 是数组 const permissionArray = Array.isArray(permissions) ? permissions : [permissions] - return permissionArray.some(i => userPermissions.includes(i)) + // 全部权限 + if (permissionArray.includes('admin')) + return true + + const { permissions: userPermissions, roles: userRoles } = authStore + + const hasPermission = permissionArray.some(i => userPermissions.includes(i)) + if (hasPermission) + return true + + return permissionArray.some(i => userRoles.includes(i)) } return { diff --git a/src/store/auth.ts b/src/store/auth.ts index 0c0f8a3..5e79dca 100644 --- a/src/store/auth.ts +++ b/src/store/auth.ts @@ -6,12 +6,14 @@ import { useTabStore } from './tab' interface AuthStatus { userInfo: Entity.User | Record + roles: string[] permissions: string[] } export const useAuthStore = defineStore('auth-store', { state: (): AuthStatus => { return { userInfo: {}, + roles: [], permissions: [], } }, @@ -71,6 +73,8 @@ export const useAuthStore = defineStore('auth-store', { async updataUserInfo() { const { data } = await fetchUserInfo() this.userInfo = data + this.roles = data.roles.map((role: Entity.Role) => role.roleKey) + this.permissions = data.permissions }, /* 处理登录返回的数据 */ async handleLoginInfo(data: any) { diff --git a/src/typings/entities/user.d.ts b/src/typings/entities/user.d.ts index 98ac71b..b809464 100644 --- a/src/typings/entities/user.d.ts +++ b/src/typings/entities/user.d.ts @@ -33,5 +33,7 @@ namespace Entity { roles: Entity.Role[] /** 所属部门 */ dept: Entity.Dept + /** 用户权限, 登陆时返回该字段 */ + permissions: string[] } } diff --git a/src/views/build-in/user-center/components/NotificationSettings.vue b/src/views/build-in/user-center/components/NotificationSettings.vue index 8bceb4f..2deb812 100644 --- a/src/views/build-in/user-center/components/NotificationSettings.vue +++ b/src/views/build-in/user-center/components/NotificationSettings.vue @@ -8,6 +8,9 @@ const settings = ref({