58 lines
2.1 KiB
TypeScript
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);
|
|
}
|