Explorar o código

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

* fix: 修复路由重复

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

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

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

* fix: error Forbidden non-null assertion

* refactor(access): 调整可访问性判断逻辑
Leo hai 3 meses
pai
achega
83a0c9662d
Modificáronse 1 ficheiros con 61 adicións e 2 borrados
  1. 61 2
      packages/effects/access/src/accessible.ts

+ 61 - 2
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<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 };