@@ -21,11 +21,11 @@ export const setPageTitleTxt = (meta: RouteLocationNormalized['meta']): void =>
2121
2222/**
2323 * 设置路由守卫
24- * - 使用函数作用域的 flag 变量,确保每次应用初始化时状态独立
24+ * - isFirstNavigation 变量,函数作用域标识,标记是否为首次导航(每次应用初始化时重置为 true)
2525 * - 处理登录状态验证、动态路由加载、页面刷新等场景
2626 */
2727export function setupRouterHooks ( ) : void {
28- let flag = true // 函数作用域标识,记录路由是否已添加(每次调用独立)
28+ let isFirstNavigation = true // 标记是否为首次导航,用于判断是否需要添加动态路由
2929
3030 router . beforeEach ( async ( to , from , next ) => {
3131 Nprogress . start ( )
@@ -34,37 +34,46 @@ export function setupRouterHooks(): void {
3434 const userStore = useUserStore ( )
3535 const routes = routeStore . getRoutes
3636
37- // 未登录处理
37+ // 白名单优先处理:登录页、404页等直接放行,不再执行后续逻辑
38+ const whiteList = [ '/login' , '/404' , '/403' ]
39+ if ( whiteList . includes ( to . path ) ) {
40+ console . log ( `📋 白名单页面,直接放行: ${ to . path } ` )
41+ Nprogress . done ( )
42+ return next ( )
43+ }
44+
45+ // 未登录处理:跳转到登录页
3846 if ( ! userStore . getToken ) {
39- // 白名单:登录页直接放行
40- if ( to . path === '/login' ) {
41- Nprogress . done ( )
42- return next ( )
43- }
44- // 其他页面跳转到登录页
47+ console . log ( `🚫 未登录,跳转到登录页: ${ to . path } ` )
4548 Nprogress . done ( )
4649 return next ( '/login' )
4750 }
4851
49- // 已登录处理
52+ // 已登录处理:只有在非白名单页面才处理路由逻辑
5053 try {
51- // 首次加载:路由已存储但未添加到路由实例
52- if ( flag && routes . length > 0 ) {
53- await addRoutes ( routes )
54- console . log ( '动态路由已添加:' , routes )
55- flag = false
54+ console . log (
55+ `🔍 路由守卫检查: isFirstNavigation=${ isFirstNavigation } , routes.length=${ routes . length } , path=${ to . path } `
56+ )
57+
58+ // 场景1:路由数据为空(页面刷新或直接访问URL)
59+ if ( routes . length === 0 ) {
60+ console . log ( '📦 路由数据为空,重新加载...' )
61+ await routeStore . setRoutes ( ) // 获取路由数据
62+ await addRoutes ( routeStore . getRoutes ) // 添加到路由实例
63+ isFirstNavigation = false
5664 return next ( { path : to . path } )
5765 }
5866
59- // 页面刷新:路由存储为空,需要重新加载
60- if ( routes . length === 0 ) {
61- console . log ( '页面刷新,重新加载路由' )
62- await routeStore . setRoutes ( )
67+ // 场景2:路由数据存在但未添加到路由实例(首次登录或刷新后的首次导航)
68+ if ( isFirstNavigation ) {
69+ console . log ( '🚀 首次导航,添加动态路由...' )
70+ await addRoutes ( routes )
71+ isFirstNavigation = false
6372 return next ( { path : to . path } )
6473 }
6574
66- // 正常导航
67- console . log ( '正常路由跳转:' , to . path )
75+ // 场景3: 正常导航(路由已添加,isFirstNavigation=false)
76+ console . log ( '✅ 正常路由跳转:' , to . path )
6877 return next ( )
6978 } catch ( error ) {
7079 console . error ( '路由守卫错误:' , error )
@@ -96,8 +105,15 @@ export async function addRoutes(menu: RouteRecordRaw[]): Promise<void> {
96105
97106 // 只将叶子节点(页面)添加到路由中
98107 if ( ! children || children . length === 0 ) {
99- // 仅当 component 为字符串路径时拼接视图 key,避免对象被隐式字符串化
100- const viewKey = typeof component === 'string' ? `../views/${ component as string } .vue` : null
108+ // 检查路由是否已存在,避免重复添加
109+ const existingRoute = router . hasRoute ( name as string )
110+ if ( existingRoute ) {
111+ console . log ( `⚠️ 路由已存在,跳过: ${ name } ` )
112+ continue
113+ }
114+
115+ const cleanComponent = typeof component === 'string' ? component . replace ( / ^ \/ / , '' ) : null
116+ const viewKey = cleanComponent ? `../views/${ cleanComponent } .vue` : null
101117 const viewImporter = viewKey ? loadView [ viewKey ] : undefined
102118 // 保证组件始终为可用的异步导入函数,避免 TS 选择需要 redirect 的重载
103119 const componentImporter = ( viewImporter ?? loadView [ '../views/DefaultView.vue' ] ) !
0 commit comments