From 7fd43755d7ec99eca7117813f1a3dfa10dd0f034 Mon Sep 17 00:00:00 2001 From: Leo <98382335+gaoziman@users.noreply.github.com> Date: Mon, 7 Jul 2025 01:13:29 +0800 Subject: [PATCH] =?UTF-8?q?feat(permissions):=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=A3=80=E6=9F=A5=E5=92=8C=E6=8C=87=E4=BB=A4?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 扩展超级管理员标识符支持多种格式 - 修复权限指令使用display:none而非删除元素 - 增强按钮权限检查逻辑 - 优化权限检查的实时性和准确性 --- src/directives/permission.ts | 83 +++++++++++++++++++++++++++++---- src/hooks/usePermission.ts | 89 +++++++++++++++++++++++++++++++----- 2 files changed, 152 insertions(+), 20 deletions(-) diff --git a/src/directives/permission.ts b/src/directives/permission.ts index 27e2449..08b7309 100644 --- a/src/directives/permission.ts +++ b/src/directives/permission.ts @@ -2,23 +2,88 @@ import type { App, Directive } from 'vue' import { usePermission } from '@/hooks' export function install(app: App) { - const { hasPermission } = usePermission() - - function updatapermission(el: HTMLElement, permission: Entity.RoleType | Entity.RoleType[]) { + // 角色权限指令 + function updateRolePermission(el: HTMLElement, permission: Entity.RoleType | Entity.RoleType[]) { if (!permission) - throw new Error('v-permissson Directive with no explicit role attached') + throw new Error('v-role Directive with no explicit role attached') - if (!hasPermission(permission)) - el.parentElement?.removeChild(el) + // 每次检查时重新获取权限函数,确保使用最新的用户状态 + const { hasRole } = usePermission() + + // 使用显示/隐藏而不是删除元素 + if (hasRole(permission)) { + el.style.display = '' + } + else { + el.style.display = 'none' + } } - const permissionDirective: Directive = { + // 按钮权限指令 + function updateButtonPermission(el: HTMLElement, permission: string | string[]) { + if (!permission) + throw new Error('v-button Directive with no explicit permission attached') + + // 每次检查时重新获取权限函数,确保使用最新的用户状态 + const { hasButton } = usePermission() + + // 使用显示/隐藏而不是删除元素 + if (hasButton(permission)) { + el.style.display = '' + } + else { + el.style.display = 'none' + } + } + + // 通用权限指令(向后兼容) + function updatePermission(el: HTMLElement, permission: Entity.RoleType | Entity.RoleType[]) { + if (!permission) + throw new Error('v-permission Directive with no explicit role attached') + + // 每次检查时重新获取权限函数,确保使用最新的用户状态 + const { hasPermission } = usePermission() + + // 使用显示/隐藏而不是删除元素 + if (hasPermission(permission)) { + el.style.display = '' + } + else { + el.style.display = 'none' + } + } + + // 角色权限指令 + const roleDirective: Directive = { mounted(el, binding) { - updatapermission(el, binding.value) + updateRolePermission(el, binding.value) }, updated(el, binding) { - updatapermission(el, binding.value) + updateRolePermission(el, binding.value) }, } + + // 按钮权限指令 + const buttonDirective: Directive = { + mounted(el, binding) { + updateButtonPermission(el, binding.value) + }, + updated(el, binding) { + updateButtonPermission(el, binding.value) + }, + } + + // 通用权限指令(向后兼容) + const permissionDirective: Directive = { + mounted(el, binding) { + updatePermission(el, binding.value) + }, + updated(el, binding) { + updatePermission(el, binding.value) + }, + } + app.directive('permission', permissionDirective) + app.directive('role', roleDirective) + app.directive('button', buttonDirective) } diff --git a/src/hooks/usePermission.ts b/src/hooks/usePermission.ts index 27fcab3..6a9a4ee 100644 --- a/src/hooks/usePermission.ts +++ b/src/hooks/usePermission.ts @@ -5,7 +5,25 @@ import { isArray, isString } from 'radash' export function usePermission() { const authStore = useAuthStore() - function hasPermission( + /** + * 检查是否为超级管理员 + */ + function isSuperAdmin() { + if (!authStore.userInfo) + return false + + const { role } = authStore.userInfo + + // 支持多种超级管理员标识 + const superAdminIdentifiers = ['super', 'admin', '超级管理员', 'ADMIN', 'coder_ADMIN'] + return superAdminIdentifiers.some(identifier => role.includes(identifier)) + } + + /** + * 检查角色权限 + * @param permission 角色类型或角色类型数组 + */ + function hasRole( permission?: Entity.RoleType | Entity.RoleType[], ) { if (!permission) @@ -15,21 +33,70 @@ export function usePermission() { return false const { role } = authStore.userInfo - // 角色为super可直接通过 - let has = role.includes('super') - if (!has) { - if (isArray(permission)) - // 角色为数组, 判断是否有交集 - has = permission.some(i => role.includes(i)) + // 超级管理员可直接通过 + if (isSuperAdmin()) + return true + + let has = false + if (isArray(permission)) + // 角色为数组, 判断是否有交集 + has = permission.some(i => role.includes(i)) + + if (isString(permission)) + // 角色为字符串, 判断是否包含 + has = role.includes(permission) - if (isString(permission)) - // 角色为字符串, 判断是否包含 - has = role.includes(permission) - } return has } + /** + * 检查按钮权限 + * @param permission 权限标识或权限标识数组 + */ + function hasButton( + permission?: string | string[], + ) { + if (!permission) + return true + + if (!authStore.userInfo) + return false + + // 超级管理员拥有所有权限 + if (isSuperAdmin()) + return true + + const { buttons } = authStore.userInfo + + // 检查具体权限标识 + if (!buttons || buttons.length === 0) + return false + + if (isArray(permission)) + // 权限为数组, 判断是否有交集 + return permission.some(i => buttons.includes(i)) + + if (isString(permission)) + // 权限为字符串, 判断是否包含 + return buttons.includes(permission) + + return false + } + + /** + * 通用权限检查 (向后兼容) + * @param permission 角色类型或角色类型数组 + */ + function hasPermission( + permission?: Entity.RoleType | Entity.RoleType[], + ) { + return hasRole(permission) + } + return { hasPermission, + hasRole, + hasButton, + isSuperAdmin, } }