271 lines
6.1 KiB
TypeScript
271 lines
6.1 KiB
TypeScript
/**
|
|
* 路由守卫
|
|
*/
|
|
|
|
import type { Router, RouteLocationNormalized, NavigationGuardNext } from 'vue-router'
|
|
import { ElMessage } from 'element-plus'
|
|
import { useAuthStore } from '@/stores/auth'
|
|
import { envConfig } from '@/config/env'
|
|
|
|
// 不需要登录的路由白名单
|
|
const whiteList = [
|
|
'/login',
|
|
'/register',
|
|
'/forgot-password',
|
|
'/reset-password',
|
|
'/',
|
|
'/404',
|
|
'/403',
|
|
'/500'
|
|
]
|
|
|
|
// 需要登录的路由
|
|
const authRequiredRoutes = [
|
|
'/chat',
|
|
'/chat-history',
|
|
'/diary',
|
|
'/life-milestones',
|
|
'/life-trajectory',
|
|
'/messages',
|
|
'/personal-dashboard',
|
|
'/settings',
|
|
'/topic-tracker',
|
|
'/emotion',
|
|
'/map',
|
|
'/social',
|
|
'/analysis',
|
|
'/profile'
|
|
]
|
|
|
|
/**
|
|
* 检查路由是否需要认证
|
|
*/
|
|
const requiresAuth = (path: string): boolean => {
|
|
return authRequiredRoutes.some(route => path.startsWith(route))
|
|
}
|
|
|
|
/**
|
|
* 检查路由是否在白名单中
|
|
*/
|
|
const isInWhiteList = (path: string): boolean => {
|
|
return whiteList.includes(path) || whiteList.some(route => path.startsWith(route))
|
|
}
|
|
|
|
/**
|
|
* 权限检查守卫
|
|
*/
|
|
const authGuard = async (
|
|
to: RouteLocationNormalized,
|
|
from: RouteLocationNormalized,
|
|
next: NavigationGuardNext
|
|
) => {
|
|
const authStore = useAuthStore()
|
|
|
|
// 如果目标路由不需要认证,直接通过
|
|
if (!requiresAuth(to.path)) {
|
|
next()
|
|
return
|
|
}
|
|
|
|
// 检查是否已登录
|
|
if (!authStore.isLoggedIn) {
|
|
// 未登录,跳转到登录页
|
|
ElMessage.warning('请先登录')
|
|
next({
|
|
path: '/login',
|
|
query: { redirect: to.fullPath }
|
|
})
|
|
return
|
|
}
|
|
|
|
// 已登录,检查token是否有效
|
|
try {
|
|
// 这里可以添加token验证逻辑
|
|
// const isValid = await authStore.validateToken()
|
|
// if (!isValid) {
|
|
// throw new Error('Token无效')
|
|
// }
|
|
|
|
next()
|
|
} catch (error) {
|
|
console.error('Token验证失败:', error)
|
|
ElMessage.error('登录状态已过期,请重新登录')
|
|
|
|
// 清除认证状态
|
|
await authStore.logout()
|
|
|
|
// 跳转到登录页
|
|
next({
|
|
path: '/login',
|
|
query: { redirect: to.fullPath }
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 页面标题守卫
|
|
*/
|
|
const titleGuard = (
|
|
to: RouteLocationNormalized,
|
|
from: RouteLocationNormalized,
|
|
next: NavigationGuardNext
|
|
) => {
|
|
// 设置页面标题
|
|
const title = to.meta.title as string
|
|
if (title) {
|
|
document.title = `${title} - ${envConfig.appTitle}`
|
|
} else {
|
|
document.title = envConfig.appTitle
|
|
}
|
|
|
|
next()
|
|
}
|
|
|
|
/**
|
|
* 页面加载进度守卫
|
|
*/
|
|
const progressGuard = (
|
|
to: RouteLocationNormalized,
|
|
from: RouteLocationNormalized,
|
|
next: NavigationGuardNext
|
|
) => {
|
|
// 这里可以添加页面加载进度条逻辑
|
|
// NProgress.start()
|
|
next()
|
|
}
|
|
|
|
/**
|
|
* 页面加载完成守卫
|
|
*/
|
|
const progressDoneGuard = () => {
|
|
// 这里可以添加页面加载完成逻辑
|
|
// NProgress.done()
|
|
}
|
|
|
|
/**
|
|
* 登录重定向守卫
|
|
*/
|
|
const loginRedirectGuard = (
|
|
to: RouteLocationNormalized,
|
|
from: RouteLocationNormalized,
|
|
next: NavigationGuardNext
|
|
) => {
|
|
const authStore = useAuthStore()
|
|
|
|
// 如果已登录且访问登录页,重定向到首页
|
|
if (authStore.isLoggedIn && (to.path === '/login' || to.path === '/register')) {
|
|
const redirect = to.query.redirect as string || '/'
|
|
next(redirect)
|
|
return
|
|
}
|
|
|
|
next()
|
|
}
|
|
|
|
// 移除权限检查守卫,该功能不存在
|
|
|
|
/**
|
|
* 安装路由守卫
|
|
*/
|
|
export const setupRouterGuards = (router: Router) => {
|
|
// 全局前置守卫
|
|
router.beforeEach(async (to, from, next) => {
|
|
try {
|
|
// 页面加载进度
|
|
// NProgress.start()
|
|
|
|
const authStore = useAuthStore()
|
|
|
|
console.log('🔍 路由守卫检查:', {
|
|
to: to.path,
|
|
from: from.path,
|
|
isLoggedIn: authStore.isLoggedIn,
|
|
hasToken: !!authStore.accessToken,
|
|
hasUserInfo: !!authStore.userInfo
|
|
})
|
|
|
|
// 如果已登录且访问登录页,重定向到首页
|
|
if (authStore.isLoggedIn && (to.path === '/login' || to.path === '/register')) {
|
|
const redirect = to.query.redirect as string || '/'
|
|
console.log('🔍 已登录用户访问登录页,重定向到:', redirect)
|
|
next(redirect)
|
|
return
|
|
}
|
|
|
|
// 检查是否需要认证
|
|
if (requiresAuth(to.path)) {
|
|
console.log('🔍 页面需要认证:', to.path)
|
|
|
|
// 如果当前未登录,先尝试恢复本地存储的认证状态
|
|
if (!authStore.isLoggedIn) {
|
|
console.log('🔍 路由守卫:尝试恢复本地认证状态')
|
|
const restored = authStore.restoreLocalAuth()
|
|
console.log('🔍 路由守卫:恢复结果:', restored)
|
|
|
|
if (restored) {
|
|
console.log('🔍 认证状态已恢复:', {
|
|
isLoggedIn: authStore.isLoggedIn,
|
|
hasToken: !!authStore.accessToken,
|
|
hasUserInfo: !!authStore.userInfo
|
|
})
|
|
}
|
|
}
|
|
|
|
// 再次检查登录状态
|
|
if (!authStore.isLoggedIn) {
|
|
console.log('🔍 用户未登录,跳转到登录页')
|
|
// 未登录,跳转到登录页
|
|
ElMessage.warning('请先登录')
|
|
next({
|
|
path: '/login',
|
|
query: { redirect: to.fullPath }
|
|
})
|
|
return
|
|
}
|
|
|
|
console.log('🔍 用户已登录,允许访问:', to.path)
|
|
}
|
|
|
|
// 设置页面标题
|
|
const title = to.meta.title as string
|
|
if (title) {
|
|
document.title = `${title} - ${envConfig.appTitle}`
|
|
} else {
|
|
document.title = envConfig.appTitle
|
|
}
|
|
|
|
next()
|
|
} catch (error) {
|
|
console.error('路由守卫错误:', error)
|
|
next()
|
|
}
|
|
})
|
|
|
|
// 全局后置守卫
|
|
router.afterEach((to, from) => {
|
|
// 页面加载完成
|
|
progressDoneGuard()
|
|
|
|
// 页面访问统计
|
|
if (envConfig.debug) {
|
|
console.log(`路由跳转: ${from.path} -> ${to.path}`)
|
|
}
|
|
})
|
|
|
|
// 全局解析守卫
|
|
router.beforeResolve((to, from, next) => {
|
|
// 这里可以添加异步数据加载逻辑
|
|
next()
|
|
})
|
|
}
|
|
|
|
export {
|
|
authGuard,
|
|
titleGuard,
|
|
progressGuard,
|
|
progressDoneGuard,
|
|
loginRedirectGuard,
|
|
requiresAuth,
|
|
isInWhiteList
|
|
}
|