first commit
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import { constantRoute, registerDynamicRoutes } from './routes';
|
||||
|
||||
// 先创建路由,但不立即匹配
|
||||
const router = createRouter({
|
||||
history: createWebHistory(),
|
||||
routes: constantRoute,
|
||||
// 延迟路由匹配,等待动态路由注册完成
|
||||
strict: false,
|
||||
});
|
||||
|
||||
// 在应用启动时加载菜单并注册路由
|
||||
let routesLoaded = false;
|
||||
let routesLoadingPromise: Promise<void> | null = null;
|
||||
|
||||
export async function loadAndRegisterRoutes() {
|
||||
// 如果已经加载过,直接返回
|
||||
if (routesLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果正在加载,等待加载完成
|
||||
if (routesLoadingPromise) {
|
||||
return routesLoadingPromise;
|
||||
}
|
||||
|
||||
return routesLoadingPromise;
|
||||
}
|
||||
|
||||
// 路由守卫:确保路由已加载
|
||||
router.beforeEach(async (to, _from, next) => {
|
||||
// 如果路由还未加载,先加载路由
|
||||
if (!routesLoaded) {
|
||||
|
||||
// 等待路由加载完成
|
||||
await routesLoadingPromise;
|
||||
|
||||
// 路由加载完成后,如果当前路径不匹配,尝试重新匹配
|
||||
const matched = router.resolve(to.path).matched;
|
||||
if (matched.length === 0 && to.path !== '/404') {
|
||||
// 路由已加载但当前路径不匹配,可能是通配符路由
|
||||
// 继续导航,让通配符路由处理
|
||||
next();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 路由已加载,继续导航
|
||||
next();
|
||||
});
|
||||
|
||||
export default router;
|
||||
@@ -0,0 +1,124 @@
|
||||
import { createComponentLoader } from '@/utils/pathResolver'
|
||||
|
||||
// 对外暴漏配置路由,常量路由
|
||||
export const constantRoute = [
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/views/theme/index.vue'),
|
||||
name: '首页',
|
||||
meta: {
|
||||
title: '首页',
|
||||
hidden: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/404',
|
||||
component: () => import('@/views/404/index.vue'),
|
||||
name: '404',
|
||||
meta: {
|
||||
title: '404',
|
||||
hidden: true,
|
||||
icon: 'DocumentDelete',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
// 动态路由注册函数
|
||||
export function registerDynamicRoutes(router: any, menus: any[]) {
|
||||
if (!menus || menus.length === 0) return
|
||||
|
||||
// 统一处理菜单路径大小写
|
||||
const normalizeMenuPaths = (menus: any[]) => {
|
||||
return menus.map(menu => {
|
||||
const normalizedMenu = { ...menu }
|
||||
// 将路径中的 /newscenter/ 替换为 /newsCenter/
|
||||
if (normalizedMenu.path) {
|
||||
normalizedMenu.path = normalizedMenu.path.replace(/\/newscenter\//g, '/newsCenter/')
|
||||
}
|
||||
// 递归处理子菜单
|
||||
if (normalizedMenu.children && normalizedMenu.children.length > 0) {
|
||||
normalizedMenu.children = normalizeMenuPaths(normalizedMenu.children)
|
||||
}
|
||||
return normalizedMenu
|
||||
})
|
||||
}
|
||||
|
||||
// 先规范化菜单路径
|
||||
const normalizedMenus = normalizeMenuPaths(menus)
|
||||
|
||||
// 收集所有需要注册的路由
|
||||
const routesToAdd: any[] = []
|
||||
|
||||
// 递归处理菜单,收集路由
|
||||
const processMenu = (menu: any) => {
|
||||
// type 2: 页面 - 根据 component_path 加载组件
|
||||
if (menu.type === 2 && menu.path && menu.component_path) {
|
||||
const path = menu.path
|
||||
// 检查路由是否已存在
|
||||
const existingRoute = router.getRoutes().find((r: any) => r.path === path)
|
||||
if (!existingRoute) {
|
||||
try {
|
||||
// 使用 pathResolver 来解析 component_path
|
||||
// component_path 可能的格式:
|
||||
// 1. /views/newsCenter/companyNews/index.vue
|
||||
// 2. views/newsCenter/companyNews/index.vue
|
||||
// 3. newsCenter/companyNews/index.vue
|
||||
const componentLoader = createComponentLoader(menu.component_path)
|
||||
|
||||
if (!componentLoader) {
|
||||
console.error(`Failed to create component loader for: ${menu.component_path}`)
|
||||
return
|
||||
}
|
||||
|
||||
routesToAdd.push({
|
||||
path: path,
|
||||
name: `menu_${menu.id}`,
|
||||
component: componentLoader,
|
||||
meta: {
|
||||
title: menu.title,
|
||||
menuId: menu.id,
|
||||
menuType: menu.type,
|
||||
},
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(`Failed to prepare route for path ${path}, component_path: ${menu.component_path}`, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
// type 4: 单页 - 使用通配符路由处理,不需要单独注册
|
||||
|
||||
// 递归处理子菜单
|
||||
if (menu.children && menu.children.length > 0) {
|
||||
menu.children.forEach((child: any) => processMenu(child))
|
||||
}
|
||||
}
|
||||
|
||||
// 处理所有菜单
|
||||
normalizedMenus.forEach((menu) => processMenu(menu))
|
||||
|
||||
// 先移除通配符路由(如果存在),以便重新添加
|
||||
const catchAllRoute = router.getRoutes().find((r: any) => r.path === '/:pathMatch(.*)*')
|
||||
if (catchAllRoute) {
|
||||
router.removeRoute('OnePage')
|
||||
}
|
||||
|
||||
// 注册 type 2 的路由(必须在通配符路由之前)
|
||||
routesToAdd.forEach((route) => {
|
||||
router.addRoute(route)
|
||||
})
|
||||
|
||||
// 最后添加通配符路由(用于单页和其他未匹配的路径)
|
||||
const catchAllExists = router.getRoutes().find((r: any) => r.path === '/:pathMatch(.*)*')
|
||||
if (!catchAllExists) {
|
||||
router.addRoute({
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('@/views/onepage/index.vue'),
|
||||
name: 'OnePage',
|
||||
meta: {
|
||||
title: '单页',
|
||||
hidden: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user