From 83a0c9662d5615942954736b70e1a9ae14c8070b Mon Sep 17 00:00:00 2001 From: Leo Date: Tue, 10 Mar 2026 05:09:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=B7=AF=E7=94=B1?= =?UTF-8?q?=E9=87=8D=E5=A4=8D=20(#7590)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: 修复路由重复 优化mixed模式路由合并逻辑。以backend 为基础,并从frontend补充 * fix: 修复名称冲突时子项合并顺序/覆盖(后端子项可能会丢失)。 * fix: 优化可访问性判断逻辑 * fix: error Forbidden non-null assertion * refactor(access): 调整可访问性判断逻辑 --- packages/effects/access/src/accessible.ts | 63 ++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/packages/effects/access/src/accessible.ts b/packages/effects/access/src/accessible.ts index eb9081486..24cd9fa3d 100644 --- a/packages/effects/access/src/accessible.ts +++ b/packages/effects/access/src/accessible.ts @@ -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(); + + 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 };