foreign-admin-ui/src/router/index.ts

194 lines
5.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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