| | |
| | | return new Promise(resolve => { |
| | | // 向后端请求路由数据 |
| | | getRouters().then(res => { |
| | | const sdata = JSON.parse(JSON.stringify(res.data)) |
| | | const rdata = JSON.parse(JSON.stringify(res.data)) |
| | | const defaultData = JSON.parse(JSON.stringify(res.data)) |
| | | // 三份数据各自深拷贝后分别构建,normalizeRouteNames 是确定性的, |
| | | // 因此三处得到的 name 完全一致,页签缓存不会对不上。 |
| | | const sdata = normalizeRouteNames(JSON.parse(JSON.stringify(res.data))) |
| | | const rdata = normalizeRouteNames(JSON.parse(JSON.stringify(res.data))) |
| | | const defaultData = normalizeRouteNames(JSON.parse(JSON.stringify(res.data))) |
| | | const sidebarRoutes = filterAsyncRouter(sdata) |
| | | const rewriteRoutes = filterAsyncRouter(rdata, false, true) |
| | | const defaultRoutes = filterAsyncRouter(defaultData) |
| | |
| | | } |
| | | }) |
| | | |
| | | const isContainerRoute = (route) => |
| | | route.component === 'Layout' || route.component === 'ParentView' || route.component === 'InnerLink' |
| | | |
| | | /** |
| | | * 修正后端菜单里的路由重名。 |
| | | * |
| | | * 两种情况 vue-router 4 会因重名丢路由或直接报错: |
| | | * 1. 父容器与后代页面同名(如 /standardMaterial 容器与其下的标准物质清单页都叫 |
| | | * StandardMaterial)——vue-router 3 允许,vue-router 4 抛 |
| | | * "A route named X has been added as a child of a route with the same name"; |
| | | * 2. 两个不同菜单项取了同一个 name(如两个「报告结果」都叫 ReportResults)—— |
| | | * addRoute 时后者会把前者挤掉,被挤掉的那条路径就点不开了。 |
| | | * |
| | | * 处理策略:先保留第一次出现的 name,后续重名一律加数字后缀。容器与后代叶子重名 |
| | | * 时优先改容器名(页面 name 与组件 name 一致,是页签缓存的键,尽量不动)。 |
| | | */ |
| | | function normalizeRouteNames(routes) { |
| | | const leafNames = new Set() |
| | | const collectLeafNames = (list) => { |
| | | list.forEach(route => { |
| | | if (route.name && !isContainerRoute(route)) leafNames.add(route.name) |
| | | if (route.children && route.children.length) collectLeafNames(route.children) |
| | | }) |
| | | } |
| | | collectLeafNames(routes) |
| | | |
| | | const used = new Set() |
| | | const walk = (list) => { |
| | | list.forEach(route => { |
| | | if (route.name) { |
| | | const conflict = used.has(route.name) || |
| | | (isContainerRoute(route) && leafNames.has(route.name)) |
| | | if (conflict) { |
| | | let suffix = 2 |
| | | while (leafNames.has(`${route.name}${suffix}`) || used.has(`${route.name}${suffix}`)) suffix++ |
| | | route.name = `${route.name}${suffix}` |
| | | } |
| | | used.add(route.name) |
| | | } |
| | | if (route.children && route.children.length) walk(route.children) |
| | | }) |
| | | } |
| | | walk(routes) |
| | | return routes |
| | | } |
| | | |
| | | // 遍历后台传来的路由字符串,转换为组件对象 |
| | | function filterAsyncRouter(asyncRouterMap, lastRouter = false, type = false) { |
| | | return asyncRouterMap.filter(route => { |