fix: 修复路由重复 (#7590)

* fix: 修复路由重复

优化mixed模式路由合并逻辑。以backend 为基础,并从frontend补充

* fix: 修复名称冲突时子项合并顺序/覆盖(后端子项可能会丢失)。

* fix: 优化可访问性判断逻辑

* fix: error Forbidden non-null assertion

* refactor(access): 调整可访问性判断逻辑
pull/336/head
Leo 2026-03-10 05:09:48 +08:00 committed by GitHub
parent a4736a49f8
commit 83a0c9662d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 61 additions and 2 deletions

View File

@ -25,6 +25,7 @@ async function generateAccessible(
const { router } = options;
options.routes = cloneDeep(options.routes);
// 生成路由
const accessibleRoutes = await generateRoutes(mode, options);
@ -101,8 +102,10 @@ async function generateRoutes(
generateRoutesByFrontend(routes, roles || [], forbiddenComponent),
generateRoutesByBackend(options),
]);
resultRoutes = [...frontend_resultRoutes, ...backend_resultRoutes];
resultRoutes = mergeRoutesByName(
backend_resultRoutes,
frontend_resultRoutes,
);
break;
}
}
@ -153,4 +156,60 @@ async function generateRoutes(
return resultRoutes;
}
/**
* name
* @param baseRoutes
* @param extraRoutes
*/
function mergeRoutesByName(
baseRoutes: RouteRecordRaw[],
extraRoutes: RouteRecordRaw[],
): RouteRecordRaw[] {
const result: RouteRecordRaw[] = [];
const routeMap = new Map<string, RouteRecordRaw>();
for (const route of baseRoutes) {
const clone = { ...route } as RouteRecordRaw;
result.push(clone);
if (clone.name && isString(clone.name)) {
routeMap.set(clone.name as string, clone);
}
}
for (const route of extraRoutes) {
if (
route.name &&
isString(route.name) &&
routeMap.has(route.name as string)
) {
const existing = routeMap.get(route.name as string)!;
const existingChildren = existing.children ?? [];
const routeChildren = route.children ?? [];
const merged = {
...route,
...existing, // keep backend as base
meta: {
...route.meta,
...existing.meta, // backend meta wins on conflicts
},
} as RouteRecordRaw;
if (existingChildren.length > 0 || routeChildren.length > 0) {
merged.children = mergeRoutesByName(existingChildren, routeChildren);
}
Object.assign(existing, merged);
} else {
const clone = { ...route } as RouteRecordRaw;
result.push(clone);
if (clone.name && isString(clone.name)) {
routeMap.set(clone.name as string, clone);
}
}
}
return result;
}
export { generateAccessible };