Skip to content

Commit d0829fb

Browse files
authored
Merge pull request #2123 from Azir-11/dev-286
refactor(路由管理): 优化路由添加逻辑,增强路径处理和顶级路由注册
2 parents fd03e44 + c7f3504 commit d0829fb

File tree

1 file changed

+58
-10
lines changed

1 file changed

+58
-10
lines changed

web/src/permission.js

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,82 @@ function isExternalUrl(val) {
1919
return typeof val === 'string' && /^(https?:)?\/\//.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

Comments
 (0)