68 lines
1.6 KiB
TypeScript
68 lines
1.6 KiB
TypeScript
import './assets/main.css'
|
||
import 'ant-design-vue/dist/reset.css'
|
||
|
||
import { createApp } from 'vue'
|
||
import { createPinia } from 'pinia'
|
||
import { createRouter, createWebHistory } from 'vue-router'
|
||
import { routes } from 'vue-router/auto-routes'
|
||
|
||
import App from './App.vue'
|
||
import { setTokenGetter } from './utils/request'
|
||
import { isAdminOnlyPath } from '@/constants/permissions'
|
||
|
||
const router = createRouter({
|
||
history: createWebHistory(import.meta.env.BASE_URL),
|
||
routes,
|
||
})
|
||
|
||
const pinia = createPinia()
|
||
const app = createApp(App)
|
||
|
||
app.use(pinia)
|
||
app.use(router)
|
||
|
||
// 注入 token 获取函数,使 request.ts 能读取内存中的 token(remember=false 场景)
|
||
import { useUserStore } from './stores/user'
|
||
setTokenGetter(() => useUserStore().token)
|
||
|
||
// 路由守卫
|
||
const authWhitelist = ['/login', '/register']
|
||
|
||
router.beforeEach(async (to) => {
|
||
const { useUserStore } = await import('./stores/user')
|
||
const userStore = useUserStore()
|
||
|
||
// 白名单页面(登录/注册)
|
||
if (authWhitelist.includes(to.path)) {
|
||
if (userStore.isLoggedIn) {
|
||
return '/'
|
||
}
|
||
return true
|
||
}
|
||
|
||
// 未登录跳转登录页
|
||
if (!userStore.isLoggedIn) {
|
||
return `/login?redirect=${to.fullPath}`
|
||
}
|
||
|
||
// 已登录但未获取用户信息
|
||
if (!userStore.user) {
|
||
try {
|
||
await userStore.fetchCurrentUser()
|
||
} catch {
|
||
userStore.logout()
|
||
return '/login'
|
||
}
|
||
}
|
||
|
||
// 角色权限检查:非 admin 不能访问受限路由(前缀匹配)
|
||
if (isAdminOnlyPath(to.path) && !userStore.isAdmin) {
|
||
message.error('无权访问')
|
||
return '/'
|
||
}
|
||
|
||
return true
|
||
})
|
||
|
||
app.mount('#app')
|