112 lines
3.3 KiB
TypeScript
112 lines
3.3 KiB
TypeScript
import { useRbacUserStore } from '@/store/modules/rbac-user'
|
||
import {
|
||
normalizeResourcePermissionCode,
|
||
PAGE_BUTTON_PARENT_ALIASES,
|
||
} from '@/constants/pageButtonCatalog'
|
||
|
||
/** 页面级动作后缀:有资源码或动作码之一即可进页 */
|
||
const PAGE_ACTION_SUFFIX = /\.(Query|Use|View)$/i
|
||
|
||
/**
|
||
* 展开权限码候选(含资源级、动作级、历史别名),用于路由/按钮校验互认。
|
||
*
|
||
* 例:
|
||
* - `System.BatchEmail.Use` ↔ `System.BatchEmail` ↔ `Rbac.email`
|
||
* - `Rbac.Roles.Query` ↔ `Rbac.Roles`
|
||
*/
|
||
function expandPermissionCandidates(permission: string): string[] {
|
||
const code = permission.trim()
|
||
if (!code) return []
|
||
|
||
const set = new Set<string>([code])
|
||
|
||
const addAliasFamily = (raw: string) => {
|
||
if (!raw) return
|
||
set.add(raw)
|
||
const mapped = PAGE_BUTTON_PARENT_ALIASES[raw]
|
||
if (mapped) set.add(mapped)
|
||
|
||
if (PAGE_ACTION_SUFFIX.test(raw)) {
|
||
const resource = raw.replace(PAGE_ACTION_SUFFIX, '')
|
||
set.add(resource)
|
||
const mappedResource = PAGE_BUTTON_PARENT_ALIASES[resource]
|
||
if (mappedResource) set.add(mappedResource)
|
||
} else {
|
||
set.add(`${raw}.Query`)
|
||
set.add(`${raw}.Use`)
|
||
set.add(`${raw}.View`)
|
||
}
|
||
}
|
||
|
||
addAliasFamily(code)
|
||
|
||
// 反向:别名表里指向同一资源的历史菜单码
|
||
const resources = Array.from(set)
|
||
for (const [from, to] of Object.entries(PAGE_BUTTON_PARENT_ALIASES)) {
|
||
if (resources.includes(to) || resources.includes(from)) {
|
||
addAliasFamily(from)
|
||
addAliasFamily(to)
|
||
}
|
||
}
|
||
|
||
// normalizeResourcePermissionCode 仅剥 .Query,这里再补一层
|
||
for (const item of Array.from(set)) {
|
||
const normalized = normalizeResourcePermissionCode(item)
|
||
if (normalized) set.add(normalized)
|
||
}
|
||
|
||
return Array.from(set)
|
||
}
|
||
|
||
/**
|
||
* 检查是否有权限(三级按钮 / 路由 meta.permission)
|
||
*
|
||
* 兼容菜单同步后的编码差异:
|
||
* - 二级菜单可能是资源码 `Operation.PrintLabel`
|
||
* - 路由 meta 可能是 `Operation.PrintLabel.Query`
|
||
* - 历史菜单码如 `Rbac.email` 与目录码 `System.BatchEmail.Use`
|
||
* 以上互相视为可访问。
|
||
*/
|
||
export function hasPermission(permission: string): boolean {
|
||
const userStore = useRbacUserStore()
|
||
if (!permission?.trim()) return true
|
||
// Admin 角色默认全权限,无需在角色管理中逐项分配
|
||
if (hasRole('Admin')) return true
|
||
const granted = userStore.permissions
|
||
return expandPermissionCandidates(permission).some((code) => granted.includes(code))
|
||
}
|
||
|
||
/**
|
||
* 检查是否有任一权限
|
||
*/
|
||
export function hasAnyPermission(permissions: string[]): boolean {
|
||
if (!permissions?.length) return true
|
||
return permissions.some((p) => hasPermission(p))
|
||
}
|
||
|
||
/**
|
||
* 检查是否有所有权限
|
||
*/
|
||
export function hasAllPermissions(permissions: string[]): boolean {
|
||
if (!permissions?.length) return true
|
||
return permissions.every((p) => hasPermission(p))
|
||
}
|
||
|
||
/**
|
||
* 检查是否有角色
|
||
*/
|
||
export function hasRole(roleCode: string): boolean {
|
||
const userStore = useRbacUserStore()
|
||
return userStore.userInfo?.roles?.some((r) => r.code === roleCode) || false
|
||
}
|
||
|
||
/**
|
||
* 检查是否有任一角色
|
||
*/
|
||
export function hasAnyRole(roleCodes: string[]): boolean {
|
||
const userStore = useRbacUserStore()
|
||
return roleCodes.some((code) =>
|
||
userStore.userInfo?.roles?.some((r) => r.code === code),
|
||
)
|
||
}
|