permission.ts
2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import router from '@/router'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { ElMessage } from 'element-plus'
import { usePermissionStore, useUserStore } from '@/store'
import { getAccessToken } from '@/utils/auth'
import { APP_TITLE, HOME_PATH, LOGIN_PATH } from '@/config'
/**
* 路由守卫
*
* 流程:
* 1. 无 token → 白名单放行,其余跳登录页并带 redirect
* 2. 有 token 但还没拉过用户信息 → 调 getPermissionInfo,动态注册路由后原地重定向
* 3. 拉取失败(token 失效/后端不可用)→ 清状态回登录页
*/
NProgress.configure({ showSpinner: false, trickleSpeed: 120 })
// 无需登录即可访问
const whiteList = [LOGIN_PATH, '/404']
router.beforeEach(async (to, _from, next) => {
NProgress.start()
document.title = to.meta?.title ? `${to.meta.title} - ${APP_TITLE}` : APP_TITLE
const token = getAccessToken()
if (!token) {
if (whiteList.includes(to.path)) {
next()
} else {
next({ path: LOGIN_PATH, query: { redirect: to.fullPath } })
}
NProgress.done()
return
}
// 已登录还去登录页 → 回首页
if (to.path === LOGIN_PATH) {
next({ path: '/' })
NProgress.done()
return
}
const userStore = useUserStore()
if (!userStore.isUserInfoLoaded) {
try {
await userStore.getInfo()
const permissionStore = usePermissionStore()
// 落点修正:`/` 与 HOME_PATH('/dashboard') 都是「有首页菜单时」的默认落点,
// 而 /dashboard 是动态路由,账号没被授权「首页」菜单时它并不存在,
// 直接放行会命中 404 兜底。此时改送该账号实际可用的第一个页面。
const isLanding = to.path === '/' || to.path === HOME_PATH
const fallback = permissionStore.getDefaultPath()
if (isLanding && !permissionStore.canReach(to.fullPath) && fallback !== to.path) {
next({ path: fallback, replace: true })
return
}
// 路由是刚注册的,必须用 replace 重新解析一次目标地址
next({ ...to, replace: true })
} catch (e: any) {
userStore.resetState()
ElMessage.error(e?.message || '获取用户信息失败,请重新登录')
next({ path: LOGIN_PATH, query: { redirect: to.fullPath } })
NProgress.done()
}
return
}
next()
})
router.afterEach(() => {
NProgress.done()
})
router.onError(() => {
NProgress.done()
})