import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router' import { useUserStore } from '@/stores/modules/user' import { useAuthStore } from '@/stores/modules/auth' import { useHomeStore } from '@/stores/modules/home' import { LOGIN_URL, ROUTER_WHITE_LIST } from '@/config' import { initDynamicRouter } from '@/routers/modules/dynamicRouter' import { staticRouter } from '@/routers/modules/staticRouter' import NProgress from '@/config/nprogress' import { createHomeMenuMap, getHomeValidPaths, HOME_EXCLUDED_PATHS } from '@/utils/home' const WHITE_LIST_SET = new Set(ROUTER_WHITE_LIST) const mode = import.meta.env.VITE_ROUTER_MODE const ROUTER_PERF_DEBUG = import.meta.env.DEV const perfNow = () => (typeof performance !== 'undefined' ? performance.now() : Date.now()) const logRouterPerf = (label: string, start: number, extra?: Record) => { if (!ROUTER_PERF_DEBUG) return const duration = Math.round((perfNow() - start) * 100) / 100 console.info(`[router-perf] ${label}`, { duration, ...extra }) } let routePerfStart = 0 const routerMode = { hash: () => createWebHashHistory(), history: () => createWebHistory() } const router = createRouter({ history: routerMode[mode]?.() || createWebHashHistory(), routes: [...staticRouter], strict: false, scrollBehavior: () => ({ left: 0, top: 0 }) }) const syncHomeStateWithMenus = () => { const authStore = useAuthStore() const homeStore = useHomeStore() const start = perfNow() const flatMenuList = authStore.flatMenuListGet homeStore.syncWithMenus(getHomeValidPaths(flatMenuList)) logRouterPerf('sync-home-state', start, { menuCount: flatMenuList.length }) } router.beforeEach(async (to, from, next) => { const guardStart = perfNow() routePerfStart = guardStart const userStore = useUserStore() const authStore = useAuthStore() NProgress.start() const title = import.meta.env.VITE_GLOB_APP_TITLE document.title = to.meta.title ? `${to.meta.title} - ${title}` : title if (to.path.toLocaleLowerCase() === LOGIN_URL) { if (userStore.accessToken) { return next('/') } resetRouter() return next() } if (WHITE_LIST_SET.has(to.path)) return next() if (!userStore.accessToken) return next({ path: LOGIN_URL, replace: true }) if (!authStore.authMenuListGet.length) { try { const initStart = perfNow() await initDynamicRouter() logRouterPerf('init-dynamic-router', initStart) const syncStart = perfNow() syncHomeStateWithMenus() logRouterPerf('first-sync-home-state', syncStart) logRouterPerf('before-each-first-init', guardStart, { path: to.path, from: from.path }) return next({ ...to, replace: true }) } catch (error) { console.error('Dynamic router initialization failed', error) await userStore.logout() return next({ path: LOGIN_URL, replace: true }) } } syncHomeStateWithMenus() logRouterPerf('before-each-menu-sync', guardStart, { path: to.path, from: from.path, hasActivateInfo: authStore.activateInfoLoadedGet }) await authStore.setRouteName(to.name as string) if (!authStore.activateInfoLoadedGet) { const activateStart = perfNow() await authStore.setActivateInfo() logRouterPerf('load-activate-info', activateStart) } logRouterPerf('before-each-total', guardStart, { path: to.path, from: from.path }) next() }) export const resetRouter = () => { const authStore = useAuthStore() authStore.flatMenuListGet.forEach(route => { const { name } = route if (name && router.hasRoute(name)) router.removeRoute(name) }) } router.onError(error => { NProgress.done() console.error('[router] route error', { message: error.message, currentPath: router.currentRoute.value.fullPath }) }) router.afterEach((to, from) => { NProgress.done() const afterEachStart = perfNow() if (routePerfStart) { logRouterPerf('navigation-total', routePerfStart, { path: to.path, from: from.path }) } if (HOME_EXCLUDED_PATHS.has(to.path)) return const authStore = useAuthStore() const homeStore = useHomeStore() const menuMap = createHomeMenuMap(authStore.flatMenuListGet) if (!menuMap[to.path]) return homeStore.addRecentVisited(to.path) logRouterPerf('after-each-home-recent', afterEachStart, { path: to.path, menuCount: Object.keys(menuMap).length }) }) export default router