front/src/utils/rbac-permission.ts
zzh cf4d2c4a3f feat: 新增 9610 申报页与批量清单/报关单操作
同步 SPA 回退、权限目录、拣货绑定组件及相关系统页调整。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-30 17:46:04 +08:00

112 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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),
)
}