import { createRouter, createWebHistory } from 'vue-router' import { useUserStore } from '@/stores/modules/user' import Layout from '@/components/layout/Layout.vue' import { setRouter, handleRouter } from './handleRouter' import { getStorage, setStorage } from '@/utils/storage' const routes = [ // user路由 { path: '/user', name: 'User', component: () => import('@/views/user/index.vue'), redirect: '/user/login', children: [ { path: 'login', name: 'Login', component: () => import('@/views/user/Login.vue'), meta: { isAuthPage: true, title: '登录', keepAlive: false }, }, { path: 'register', name: 'Register', component: () => import('@/views/user/Register.vue'), meta: { isAuthPage: true, title: '注册', keepAlive: false }, }, { path: 'forgot-password', name: 'ForgotPassword', component: () => import('@/views/user/ForgotPassword.vue'), meta: { isAuthPage: true, title: '忘记密码', keepAlive: false }, }, { path: 'change-password', name: 'ChangePassword', component: () => import('@/views/user/ChangePassword.vue'), meta: { requiresAuth: true, title: '修改密码', keepAlive: false }, }, { path: 'bind-email', name: 'BindEmail', component: () => import('@/views/user/bindEmail.vue'), meta: { requiresAuth: true, title: '绑定邮箱', keepAlive: false }, }, { path: 'bind-phone', name: 'BindPhone', component: () => import('@/views/user/bindPhone.vue'), meta: { requiresAuth: true, title: '绑定手机号', keepAlive: false }, }, ], }, // 带侧边栏布局的核心业务页面 { path: '/', name: 'Layout', component: Layout, // 全局布局(Sidebar + Header + MainContent) redirect: '/dashboard', meta: { requiresAuth: true }, // 需要登录 children: [ // 首页 { path: '/dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { title: '首页', // 左侧菜单显示的标题 keepAlive: false, }, }, ], }, { path: '/realName', name: '实名认证', component: () => import('@/views/realName/index.vue'), meta: { requiresAuth: true, title: '实名认证', keepAlive: false }, }, { path: '/livenessVerification', name: '活体认证', component: () => import('@/views/livenessVerification/index.vue'), meta: { requiresAuth: true, title: '活体认证', keepAlive: false }, }, { path: '/:pathMatch(.*)*', redirect: () => { const token = getStorage('token') return token ? '/dashboard' : '/user/login' }, // 404 重定向到登录页,避免循环 }, ] const router = createRouter({ history: createWebHistory(), routes, }) // 标记:动态路由是否已初始化完成 let dynamicRoutesReady = false router.beforeEach(async (to, _from) => { const userStore = useUserStore() const isLoggedIn = !!userStore.token const isRealNameVerified = userStore.userInfo?.real_check !== 1 console.log('dynamicRoutesReady', userStore.userInfo) console.log('isLoggedIn', isLoggedIn) console.log('isRealNameVerified', isRealNameVerified) console.log('to.meta.requiresAuth', to.meta.requiresAuth) console.log('to.meta.isAuthPage', to.meta.isAuthPage) // 1. 未登录访问需要认证的页 → 登录页 if (!isLoggedIn && to.meta.requiresAuth) { return '/user/login' } // 2. ✅ 动态路由恢复(只执行一次) if (isLoggedIn && !dynamicRoutesReady) { const menuList = (getStorage('menusInfo') as any[]) || [] // 🌟 核心:无论任何角色,始终确保首页路由存在 const hasDashboardRoute = router.getRoutes().some( (route) => route.path === '/dashboard', ) if (!hasDashboardRoute) { router.addRoute('Layout', { path: '/dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index.vue'), meta: { title: '首页', keepAlive: false, }, }) } if (menuList.length > 0) { const routeList = handleRouter(menuList).filter( (item) => item.path && item.path !== '/dashboard', ) routeList.forEach((route) => router.addRoute('Layout', route)) } dynamicRoutesReady = true // 返回目标路由以触发重新匹配 return to.redirectedFrom?.fullPath || true } // 3. 白名单页面(实名认证、活体认证、登录/注册相关页面) // 这些页面即使未实名认证也可以访问 const whiteList = [ '/realName', '/livenessVerification', '/user/login', '/user/register', '/user/forgot-password', ] const isWhiteListPage = whiteList.some((path) => to.path === path) // 4. 已登录但未完成实名认证 → 只能访问白名单页面 if (isLoggedIn && !isRealNameVerified && !isWhiteListPage) { // 未实名认证访问非白名单页面 → 跳转到登录页 return '/user/login' } // 5. 已登录访问登录页(从认证页面退出)→ 允许 if (isLoggedIn && !isRealNameVerified && to.path === '/user/login') { // 未认证用户主动跳转到登录页(用于退出登录),允许放行 return true } // 6. 已登录访问登录/注册页 → 首页(如果已认证)或实名认证页(如果未认证) if (isLoggedIn && to.meta.isAuthPage) { return isRealNameVerified ? '/' : '/realName' } // 7. 已完成认证的用户访问实名认证或活体认证页 → 首页 if (isLoggedIn && isRealNameVerified && isWhiteListPage && (to.path === '/realName' || to.path === '/livenessVerification')) { return '/' } // 8. 其他情况正常放行 return true }) // 可选:设置页面标题 router.afterEach((to) => { if (to.meta.title) { document.title = to.meta.title as string } }) export default router