import { createRouter, createWebHashHistory } from "vue-router"; import { convertMenusToRoutes } from "./dynamicRoutes"; // 静态子路由:需要在 Main 框架内显示的页面 const staticMainChildren = [ { path: "/user/userProfile", name: "userProfile", component: () => import("@/views/user/userProfile.vue"), meta: { requiresAuth: true, title: "用户中心" } }, // 兼容拼写错误的路径重定向 { path: "/apps/erp/dashborad", redirect: "/apps/erp/dashboard" } ]; // 静态路由:登录页独立、home 导航门户独立、404 页面独立 const staticRoutes = [ { path: "/login", name: "Login", component: () => import("@/views/login/index.vue"), meta: { requiresAuth: false } }, { path: "/register", name: "Register", component: () => import("@/views/login/register.vue"), meta: { requiresAuth: false } }, { path: "/forget", name: "ForgetPassword", component: () => import("@/views/login/forget.vue"), meta: { requiresAuth: false } }, { path: "/home", name: "Home", component: () => import("@/views/home/index.vue"), meta: { requiresAuth: true, title: "系统导航", isStandalone: true } }, // 兼容路径拼写错误:dashborad -> dashboard { path: "/apps/erp/dashborad", redirect: "/apps/erp/dashboard" }, { path: "/:pathMatch(.*)*", name: "NotFound", component: () => import("@/views/404/404.vue"), meta: { requiresAuth: false } } ]; const router = createRouter({ history: createWebHashHistory(), routes: staticRoutes }); let dynamicRoutesAdded = false; let dynamicRoutesData = []; let routesLoadingPromise = null; export function resetDynamicRoutes() { dynamicRoutesAdded = false; routesLoadingPromise = null; } export async function loadAndAddDynamicRoutes() { if (routesLoadingPromise) { return routesLoadingPromise; } if (dynamicRoutesAdded) { return Promise.resolve(); } routesLoadingPromise = (async () => { try { const { useMenuStore } = await import("@/stores/menu"); const menuStore = useMenuStore(); const menuData = await menuStore.fetchMenus(); if (menuData && menuData.length > 0) { addDynamicRoutes(menuData); dynamicRoutesAdded = true; routesLoadingPromise = null; return Promise.resolve(); } else { dynamicRoutesAdded = true; routesLoadingPromise = null; return Promise.resolve(); } } catch (error) { console.error('加载动态路由失败:', error); dynamicRoutesAdded = true; routesLoadingPromise = null; throw error; } })(); return routesLoadingPromise; } // 核心修改:移除扁平化,直接使用嵌套菜单生成路由 function addDynamicRoutes(menus) { if (!menus?.length) { return; } // 直接转换嵌套菜单为嵌套路由(不再扁平化) const dynamicRoutes = convertMenusToRoutes(menus); if (router.hasRoute('Main')) { router.removeRoute('Main'); } // 重新添加主路由,合并静态子路由和动态路由 router.addRoute({ path: "/", name: "Main", component: () => import("@/views/Main.vue"), redirect: "/dashboard", meta: { requiresAuth: true }, children: [...staticMainChildren, ...dynamicRoutes] // 合并静态和动态子路由 }); dynamicRoutesAdded = true; } function findRouteByName(routes, routeName) { for (const route of routes) { if (route.name === routeName) { return route; } if (route.children) { const found = findRouteByName(route.children, routeName); if (found) { return found; } } } return null; } function findFirstValidRoute(routes) { for (const route of routes) { if (route.component) { return route; } if (route.children && route.children.length > 0) { const childRoute = findFirstValidRoute(route.children); if (childRoute) { return childRoute; } } } return null; } router.beforeEach(async (to, from, next) => { const token = localStorage.getItem("token"); const publicPaths = ["/login", "/register", "/forget"]; if (publicPaths.includes(to.path)) { if (token) { if (!dynamicRoutesAdded) { await loadAndAddDynamicRoutes(); } next({ path: "/home" }); } else { next(); } return; } if (!token) { next({ path: "/login", query: { redirect: to.path } }); return; } if (!dynamicRoutesAdded) { await loadAndAddDynamicRoutes(); // 路由加载后重新导航,确保路由匹配正确 next({ path: to.path, replace: true }); return; } next(); }); export default router;