@@ -19,35 +19,82 @@ function isExternalUrl(val) {
1919 return typeof val === 'string' && / ^ ( h t t p s ? : ) ? \/ \/ / . test ( val )
2020}
2121
22- // 将 n 级菜单扁平化为:一级 layout + 二级页面组件
23- function addRouteByChildren ( route , segments = [ ] ) {
22+ // 工具函数:统一路径归一化
23+ function normalizeAbsolutePath ( p ) {
24+ const s = '/' + String ( p || '' )
25+ return s . replace ( / \/ + / g, '/' )
26+ }
27+
28+ function normalizeRelativePath ( p ) {
29+ return String ( p || '' ) . replace ( / ^ \/ + / , '' )
30+ }
31+
32+ // 安全注册:仅在路由名未存在时注册顶级路由
33+ function addTopLevelIfAbsent ( r ) {
34+ if ( ! router . hasRoute ( r . name ) ) {
35+ router . addRoute ( r )
36+ }
37+ }
38+
39+ // 将 n 级菜单扁平化为:
40+ // - 常规:一级 layout + 二级页面组件
41+ // - 若某节点 meta.defaultMenu === true:该节点为顶级(不包裹在 layout 下),其子节点作为该顶级的二级页面组件
42+ function addRouteByChildren ( route , segments = [ ] , parentName = null ) {
2443 // 跳过外链根节点
2544 if ( isExternalUrl ( route ?. path ) || isExternalUrl ( route ?. name ) || isExternalUrl ( route ?. component ) ) {
2645 return
2746 }
2847
2948 // 顶层 layout 仅用于承载,不参与路径拼接
3049 if ( route ?. name === 'layout' ) {
31- route . children ?. forEach ( ( child ) => addRouteByChildren ( child , [ ] ) )
50+ route . children ?. forEach ( ( child ) => addRouteByChildren ( child , [ ] , null ) )
51+ return
52+ }
53+
54+ // 如果标记为 defaultMenu,则该路由应作为顶级路由(不包裹在 layout 下)
55+ if ( route ?. meta ?. defaultMenu === true && parentName === null ) {
56+ const fullPath = [ ...segments , route . path ] . filter ( Boolean ) . join ( '/' )
57+ const children = route . children ? [ ...route . children ] : [ ]
58+ const newRoute = { ...route , path : fullPath }
59+ delete newRoute . children
60+ delete newRoute . parent
61+ // 顶级路由使用绝对路径
62+ newRoute . path = normalizeAbsolutePath ( newRoute . path )
63+
64+ // 若已存在同名路由则整体跳过(之前应已处理过其子节点)
65+ if ( router . hasRoute ( newRoute . name ) ) return
66+ addTopLevelIfAbsent ( newRoute )
67+
68+ // 若该 defaultMenu 节点仍有子节点,继续递归处理其子节点(挂载到该顶级路由下)
69+ if ( children . length ) {
70+ // 重置片段,使其成为顶级下的二级相对路径
71+ children . forEach ( ( child ) => addRouteByChildren ( child , [ ] , newRoute . name ) )
72+ }
3273 return
3374 }
3475
3576 // 还有子节点,继续向下收集路径片段(忽略外链片段)
3677 if ( route ?. children && route . children . length ) {
3778 const nextSegments = isExternalUrl ( route . path ) ? segments : [ ...segments , route . path ]
38- route . children . forEach ( ( child ) => addRouteByChildren ( child , nextSegments ) )
79+ route . children . forEach ( ( child ) => addRouteByChildren ( child , nextSegments , parentName ) )
3980 return
4081 }
4182
42- // 叶子节点:注册为 layout 的二级子路由
83+ // 叶子节点:注册为其父(defaultMenu 顶级或 layout) 的二级子路由
4384 const fullPath = [ ...segments , route . path ] . filter ( Boolean ) . join ( '/' )
4485 const newRoute = { ...route , path : fullPath }
4586 delete newRoute . children
4687 delete newRoute . parent
4788 // 子路由使用相对路径,避免 /layout/layout/... 的问题
48- newRoute . path = newRoute . path . replace ( / ^ \/ + / , '' )
49-
50- router . addRoute ( 'layout' , newRoute )
89+ newRoute . path = normalizeRelativePath ( newRoute . path )
90+
91+ if ( parentName ) {
92+ // 挂载到 defaultMenu 顶级路由下
93+ router . addRoute ( parentName , newRoute )
94+ } else {
95+ // 常规:挂载到 layout 下
96+ router . addRoute ( 'layout' , newRoute )
97+ }
5198}
5299
53100// 处理路由加载
@@ -60,7 +107,8 @@ const setupRouter = async (userStore) => {
60107 const baseRouters = routerStore . asyncRouters || [ ]
61108 const layoutRoute = baseRouters [ 0 ]
62109 if ( layoutRoute ?. name === 'layout' && ! router . hasRoute ( 'layout' ) ) {
63- router . addRoute ( layoutRoute )
110+ const bareLayout = { ...layoutRoute , children : [ ] }
111+ router . addRoute ( bareLayout )
64112 }
65113
66114 // 扁平化:将 layout.children 与其余顶层异步路由一并作为二级子路由注册到 layout 下
@@ -73,7 +121,7 @@ const setupRouter = async (userStore) => {
73121 if ( r ?. name !== 'layout' ) toRegister . push ( r )
74122 } )
75123 }
76- toRegister . forEach ( ( r ) => addRouteByChildren ( r , [ ] ) )
124+ toRegister . forEach ( ( r ) => addRouteByChildren ( r , [ ] , null ) )
77125 return true
78126 } catch ( error ) {
79127 console . error ( 'Setup router failed:' , error )
0 commit comments