Template
1
0
mirror of https://github.com/un-pany/v3-admin-vite.git synced 2025-04-21 11:29:20 +08:00

refactor: 调整 router 模块结构

This commit is contained in:
pany 2024-11-26 14:45:42 +08:00
parent c1290cdf28
commit 31b2a5ba82
8 changed files with 89 additions and 75 deletions

View File

@ -3,7 +3,6 @@ import App from "@/App.vue"
import { pinia } from "@/pinia"
import { router } from "@/router"
import { createApp } from "vue"
import "@/router/permission"
// load
import { loadDirectives } from "@/directives"
import { loadPlugins } from "@/plugins"

View File

@ -1,7 +1,7 @@
import type { RouteRecordRaw } from "vue-router"
import { routeSettings } from "@/config/route"
import { pinia } from "@/pinia"
import { constantRoutes, dynamicRoutes } from "@/router"
import { routerConfig } from "@/router/config"
import { flatMultiLevelRoutes } from "@/router/helper"
import { defineStore } from "pinia"
import { ref } from "vue"
@ -46,7 +46,7 @@ export const usePermissionStore = defineStore("permission", () => {
// 统一设置
const set = (accessedRoutes: RouteRecordRaw[]) => {
routes.value = constantRoutes.concat(accessedRoutes)
addRoutes.value = routeSettings.thirdLevelRouteCache ? flatMultiLevelRoutes(accessedRoutes) : accessedRoutes
addRoutes.value = routerConfig.thirdLevelRouteCache ? flatMultiLevelRoutes(accessedRoutes) : accessedRoutes
}
return { routes, addRoutes, setRoutes, setAllRoutes }

View File

@ -1,8 +1,8 @@
import type { LoginRequestData } from "@/http/apis/login/type"
import { routeSettings } from "@/config/route"
import { getUserInfoApi, loginApi } from "@/http/apis/login"
import { pinia } from "@/pinia"
import { resetRouter } from "@/router"
import { routerConfig } from "@/router/config"
import { getToken, removeToken, setToken } from "@/utils/cache/cookies"
import { defineStore } from "pinia"
import { ref } from "vue"
@ -29,7 +29,7 @@ export const useUserStore = defineStore("user", () => {
const { data } = await getUserInfoApi()
username.value = data.username
// 验证返回的 roles 是否为一个非空数组,否则塞入一个没有任何作用的默认角色,防止路由守卫逻辑进入无限循环
roles.value = data.roles?.length > 0 ? data.roles : routeSettings.defaultRoles
roles.value = data.roles?.length > 0 ? data.roles : routerConfig.defaultRoles
}
// 模拟角色变化

View File

@ -1,5 +1,13 @@
import type { RouterHistory } from "vue-router"
import { createWebHashHistory, createWebHistory } from "vue-router"
/** 路由配置 */
interface RouteSettings {
interface RouterConfig {
/**
* @name
* @description hash html5
*/
history: RouterHistory
/**
* @name
* @description 1. roles
@ -21,7 +29,12 @@ interface RouteSettings {
thirdLevelRouteCache: boolean
}
export const routeSettings: RouteSettings = {
const VITE_ROUTER_HISTORY = import.meta.env.VITE_ROUTER_HISTORY
const VITE_PUBLIC_PATH = import.meta.env.VITE_PUBLIC_PATH
export const routerConfig: RouterConfig = {
history: VITE_ROUTER_HISTORY === "hash" ? createWebHashHistory(VITE_PUBLIC_PATH) : createWebHistory(VITE_PUBLIC_PATH),
dynamic: true,
defaultRoles: ["DEFAULT_ROLE"],
thirdLevelRouteCache: false

58
src/router/guard.ts Normal file
View File

@ -0,0 +1,58 @@
import type { Router } from "vue-router"
import { setRouteChange } from "@/composables/useRouteListener"
import { useTitle } from "@/composables/useTitle"
import { isWhiteList } from "@/config/white-list"
import { usePermissionStore } from "@/pinia/stores/permission"
import { useUserStore } from "@/pinia/stores/user"
import { routerConfig } from "@/router/config"
import { getToken } from "@/utils/cache/cookies"
import { ElMessage } from "element-plus"
import NProgress from "nprogress"
import "nprogress/nprogress.css"
NProgress.configure({ showSpinner: false })
const { setTitle } = useTitle()
export function registerNavigationGuard(router: Router) {
// 全局前置守卫
router.beforeEach(async (to, _from, next) => {
NProgress.start()
const userStore = useUserStore()
const permissionStore = usePermissionStore()
// 如果没有登陆
if (!getToken()) {
// 如果在免登录的白名单中,则直接进入
if (isWhiteList(to)) return next()
// 其他没有访问权限的页面将被重定向到登录页面
return next("/login")
}
// 如果已经登录,并准备进入 Login 页面,则重定向到主页
if (to.path === "/login") return next({ path: "/" })
// 如果用户已经获得其权限角色
if (userStore.roles.length !== 0) return next()
// 否则要重新获取权限角色
try {
await userStore.getInfo()
// 注意:角色必须是一个数组! 例如: ["admin"] 或 ["developer", "editor"]
const roles = userStore.roles
// 生成可访问的 Routes
routerConfig.dynamic ? permissionStore.setRoutes(roles) : permissionStore.setAllRoutes()
// 将 "有访问权限的动态路由" 添加到 Router 中
permissionStore.addRoutes.forEach(route => router.addRoute(route))
// 设置 replace: true, 因此导航将不会留下历史记录
next({ ...to, replace: true })
} catch (error) {
// 过程中发生任何错误,都直接重置 Token并重定向到登录页面
userStore.resetToken()
ElMessage.error((error as Error).message || "路由守卫发生错误")
next("/login")
}
})
// 全局后置钩子
router.afterEach((to) => {
setRouteChange(to)
setTitle(to.meta.title)
NProgress.done()
})
}

View File

@ -1,11 +1,7 @@
import type { Router, RouteRecordNormalized, RouteRecordRaw } from "vue-router"
import { cloneDeep, omit } from "lodash-es"
import { createRouter, createWebHashHistory, createWebHistory } from "vue-router"
/** 路由模式 */
export const history = import.meta.env.VITE_ROUTER_HISTORY === "hash"
? createWebHashHistory(import.meta.env.VITE_PUBLIC_PATH)
: createWebHistory(import.meta.env.VITE_PUBLIC_PATH)
import { createRouter } from "vue-router"
import { routerConfig } from "./config"
/** 路由降级(把三级及其以上的路由转化为二级路由) */
export function flatMultiLevelRoutes(routes: RouteRecordRaw[]) {
@ -29,7 +25,7 @@ function isMultipleRoute(route: RouteRecordRaw) {
function promoteRouteLevel(route: RouteRecordRaw) {
// 创建 router 实例是为了获取到当前传入的 route 的所有路由信息
let router: Router | null = createRouter({
history,
history: routerConfig.history,
routes: [route]
})
const routes = router.getRoutes()

View File

@ -1,7 +1,8 @@
import type { RouteRecordRaw } from "vue-router"
import { routeSettings } from "@/config/route"
import { routerConfig } from "@/router/config"
import { registerNavigationGuard } from "@/router/guard"
import { createRouter } from "vue-router"
import { flatMultiLevelRoutes, history } from "./helper"
import { flatMultiLevelRoutes } from "./helper"
const Layouts = () => import("@/layouts/index.vue")
@ -290,9 +291,10 @@ export const dynamicRoutes: RouteRecordRaw[] = [
}
]
/** 路由实例 */
export const router = createRouter({
history,
routes: routeSettings.thirdLevelRouteCache ? flatMultiLevelRoutes(constantRoutes) : constantRoutes
history: routerConfig.history,
routes: routerConfig.thirdLevelRouteCache ? flatMultiLevelRoutes(constantRoutes) : constantRoutes
})
/** 重置路由 */
@ -310,3 +312,6 @@ export function resetRouter() {
window.location.reload()
}
}
// 注册路由导航守卫
registerNavigationGuard(router)

View File

@ -1,57 +0,0 @@
import { setRouteChange } from "@/composables/useRouteListener"
import { useTitle } from "@/composables/useTitle"
import { routeSettings } from "@/config/route"
import { isWhiteList } from "@/config/white-list"
import { usePermissionStore } from "@/pinia/stores/permission"
import { useUserStore } from "@/pinia/stores/user"
import { router } from "@/router"
import { getToken } from "@/utils/cache/cookies"
import { ElMessage } from "element-plus"
import NProgress from "nprogress"
import "nprogress/nprogress.css"
NProgress.configure({ showSpinner: false })
const { setTitle } = useTitle()
router.beforeEach(async (to, _from, next) => {
NProgress.start()
const userStore = useUserStore()
const permissionStore = usePermissionStore()
// 如果没有登陆
if (!getToken()) {
// 如果在免登录的白名单中,则直接进入
if (isWhiteList(to)) return next()
// 其他没有访问权限的页面将被重定向到登录页面
return next("/login")
}
// 如果已经登录,并准备进入 Login 页面,则重定向到主页
if (to.path === "/login") return next({ path: "/" })
// 如果用户已经获得其权限角色
if (userStore.roles.length !== 0) return next()
// 否则要重新获取权限角色
try {
await userStore.getInfo()
// 注意:角色必须是一个数组! 例如: ["admin"] 或 ["developer", "editor"]
const roles = userStore.roles
// 生成可访问的 Routes
routeSettings.dynamic ? permissionStore.setRoutes(roles) : permissionStore.setAllRoutes()
// 将 "有访问权限的动态路由" 添加到 Router 中
permissionStore.addRoutes.forEach(route => router.addRoute(route))
// 设置 replace: true, 因此导航将不会留下历史记录
next({ ...to, replace: true })
} catch (error) {
// 过程中发生任何错误,都直接重置 Token并重定向到登录页面
userStore.resetToken()
ElMessage.error((error as Error).message || "路由守卫发生错误")
next("/login")
}
})
router.afterEach((to) => {
setRouteChange(to)
setTitle(to.meta.title)
NProgress.done()
})