本系統實(shí)現了基于后端菜單權限數據的前端路由過(guò)濾功能,確保用戶(hù)只能訪(fǎng)問(wèn)有權限的頁(yè)面和功能。
graph TD
A[后端菜單數據 MenuItemData[]] --> B[extractPermissionPaths]
B --> C[提取權限路徑列表]
C --> D[filterRoutesByPermissions]
D --> E[與 MenuData 進(jìn)行匹配]
E --> F[過(guò)濾無(wú)權限路由]
F --> G[返回 RouteItem[]]
G --> H[前端路由系統]
transformObjectToRoute(asyncRoutes: MenuItemData[]): RouteItem[]
主要轉換方法
export function transformObjectToRoute(asyncRoutes: Array<MenuItemData>): Array<RouteItem> {
// 1. 提取用戶(hù)權限路徑
const userPermissionPaths = extractPermissionPaths(asyncRoutes);
// 2. 過(guò)濾路由數據
const filteredRoutes = filterRoutesByPermissions(MenuData, userPermissionPaths);
return filteredRoutes;
}
extractPermissionPaths(menuList: MenuItemData[]): string[]
權限路徑提取方法
提取條件:
if (menu.Path && menu.IsEnabled === 1 && menu.IsDetete === 0) {
paths.push(menu.Path);
}
filterRoutesByPermissions(routes: RouteItem[], permissionPaths: string[]): RouteItem[]
路由過(guò)濾方法
過(guò)濾邏輯:
// 檢查路由是否在權限列表中
if (permissionPaths.includes(route.path)) {
// 遞歸過(guò)濾子路由
const filteredChildren = filterChildrenRoutes(route.children, permissionPaths, route.path);
// 只有有權限或有可訪(fǎng)問(wèn)子路由時(shí)才保留
}
filterChildrenRoutes(children: RouteItem[], permissionPaths: string[], parentPath: string): RouteItem[]
子路由過(guò)濾方法
路徑匹配策略:
const fullChildPath = `${parentPath}/${child.path}`;
// 支持多種匹配方式
const hasPermission = permissionPaths.includes(child.path) || // 相對路徑
permissionPaths.includes(fullChildPath) || // 完整路徑
permissionPaths.some(path => path.endsWith(`/${child.path}`)); // 后綴匹配
{
MenuId: "001",
Path: "/list/base", // ?? 關(guān)鍵匹配字段
Name: "基礎列表",
IsEnabled: 1, // ?? 啟用狀態(tài)檢查
IsDetete: 0, // ?? 刪除狀態(tài)檢查
childrenList: [...] // ?? 子菜單遞歸處理
}
{
path: "/list", // ?? 匹配目標字段
name: "list",
component: "LAYOUT",
children: [ // ?? 過(guò)濾后的子路由
{
path: "base",
name: "ListBase",
component: "/list/base/index"
}
]
}
// 后端菜單路徑: "/list/base"
// 前端路由路徑: "/list" + "base"
// 匹配結果: ? 通過(guò)
// 后端菜單路徑: "base"
// 前端子路由路徑: "base"
// 匹配結果: ? 通過(guò)
// 后端菜單路徑: "/dashboard/base"
// 前端路由路徑: "base"
// 匹配條件: path.endsWith("/base")
// 匹配結果: ? 通過(guò)
[
{
"Path": "/list",
"IsEnabled": 1,
"IsDetete": 0,
"childrenList": [
{
"Path": "/list/base",
"IsEnabled": 1,
"IsDetete": 0
}
]
}
]
["/list", "/list/base"]
[
{
"path": "/list",
"name": "list",
"component": "LAYOUT",
"children": [
{
"path": "base",
"name": "ListBase",
"component": "/list/base/index"
}
]
}
]
// 只處理啟用且未刪除的菜單
if (menu.IsEnabled === 1 && menu.IsDetete === 0) {
// 處理邏輯
}
// 確保權限路徑唯一性
return [...new Set(paths)];
import { transformObjectToRoute } from '@/api/permission';
// 獲取并轉換菜單數據
async buildAsyncRoutes() {
try {
// 獲取后端菜單數據
const menuData = await showUserMenus();
// 轉換為前端路由格式
this.asyncRoutes = transformObjectToRoute(menuData.DataValue);
await this.initRoutes();
return this.asyncRoutes;
} catch (error) {
throw new Error("Can't build routes", error);
}
}
// 開(kāi)啟詳細日志
console.log('?? 開(kāi)始轉換菜單數據為路由數據...');
console.log('?? 輸入的菜單數據:', asyncRoutes);
console.log('?? 用戶(hù)權限路徑列表:', userPermissionPaths);
console.log('? 過(guò)濾后的路由數據:', filteredRoutes);
// 可以擴展更復雜的匹配邏輯
function customPathMatcher(menuPath: string, routePath: string): boolean {
// 自定義匹配算法
return menuPath.toLowerCase() === routePath.toLowerCase();
}
// 根據用戶(hù)級別過(guò)濾菜單
function filterByUserLevel(menu: MenuItemData, userLevel: number): boolean {
return menu.RequiredLevel <= userLevel;
}
// 根據菜單數據動(dòng)態(tài)生成新路由
function generateDynamicRoute(menu: MenuItemData): RouteItem {
return {
path: menu.Path,
name: menu.Code,
component: menu.Component || 'LAYOUT',
meta: {
title: { zh_CN: menu.ZhCn, en_US: menu.EnUs },
icon: menu.Icon
}
};
}
現在您的菜單權限過(guò)濾系統可以根據后端真實(shí)權限數據動(dòng)態(tài)過(guò)濾前端路由,確保用戶(hù)只能訪(fǎng)問(wèn)有權限的功能!??