Files
kaidi/frontend/src/store/modules/menu-access.ts
T
2026-08-17 14:08:40 +08:00

58 lines
2.1 KiB
TypeScript

import type { RouteRecordRaw } from 'vue-router';
export interface MenuAccessIdentity {
currentRole: string | null;
permissions: string[];
}
export function hasRoleAccess(roles: string[], currentRole: string | null): boolean {
return roles.length === 0 || currentRole === 'SYSTEM_ADMIN' || roles.includes(currentRole || '');
}
export function hasPermissionAccess(
currentRole: string | null,
permissions: string[],
required: string | string[],
): boolean {
if (currentRole === 'SYSTEM_ADMIN') return true;
return Array.isArray(required)
? required.some((permission) => permissions.includes(permission))
: permissions.includes(required);
}
export function canAccess(route: RouteRecordRaw, user: MenuAccessIdentity): boolean {
const meta = route.meta || {};
const roles = (meta.roleCodes || []) as string[];
const permission = meta.permission as string | string[] | undefined;
if (!hasRoleAccess(roles, user.currentRole)) return false;
if (permission && !hasPermissionAccess(user.currentRole, user.permissions, permission)) return false;
return true;
}
function childLocation(parentPath: string, childPath: string): string {
if (childPath.startsWith('/')) return childPath;
if (!childPath) return parentPath;
return `${parentPath}/${childPath}`.replace(/\/{2,}/g, '/');
}
export function filterMenu(routes: RouteRecordRaw[], user: MenuAccessIdentity): RouteRecordRaw[] {
return routes
.map((route) => {
const children = route.children ? filterMenu(route.children, user) : [];
const selfAllowed = canAccess(route, user);
if (route.children && children.length === 0) return null;
if (!route.children && !selfAllowed) return null;
const copy: RouteRecordRaw = {
...route,
meta: route.meta ? { ...route.meta } : undefined,
...(route.children ? { children } : {}),
} as RouteRecordRaw;
if (route.children) {
const firstChild = children[0];
if (firstChild) copy.redirect = childLocation(route.path, firstChild.path);
}
return copy;
})
.filter((route): route is RouteRecordRaw => route !== null);
}