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

refactor: 简化路由守卫逻辑

This commit is contained in:
pany 2024-02-06 20:22:07 +08:00
parent 160f389c60
commit b92a1a24fc
5 changed files with 31 additions and 54 deletions

View File

@ -22,19 +22,13 @@ router.beforeEach(async (to, _from, next) => {
// 判断该用户是否已经登录
if (!token) {
// 如果在免登录的白名单中,则直接进入
if (isWhiteList(to)) {
next()
} else {
// 其他没有访问权限的页面将被重定向到登录页面
NProgress.done()
next("/login")
}
return
if (isWhiteList(to)) return next()
// 其他没有访问权限的页面将被重定向到登录页面
return next("/login")
}
// 如果已经登录,并准备进入 Login 页面,则重定向到主页
if (to.path === "/login") {
NProgress.done()
return next({ path: "/" })
}
@ -44,16 +38,11 @@ router.beforeEach(async (to, _from, next) => {
// 否则要重新获取权限角色
try {
await userStore.getInfo()
if (routeSettings.async) {
// 注意:角色必须是一个数组! 例如: ['admin'] 或 ['developer', 'editor']
const roles = userStore.roles
// 根据角色生成可访问的 Routes可访问路由 = 常驻路由 + 有访问权限的动态路由)
permissionStore.setRoutes(roles)
} else {
// 没有开启动态路由功能,则启用默认角色来生成
permissionStore.setRoutes(routeSettings.defaultRoles)
}
// 将'有访问权限的动态路由' 添加到 Router 中
// 注意:角色必须是一个数组! 例如: ["admin"] 或 ["developer", "editor"]
const roles = userStore.roles
// 生成可访问的 Routes
routeSettings.async ? permissionStore.setRoutes(roles) : permissionStore.setAllRoutes()
// 将 "有访问权限的动态路由" 添加到 Router 中
permissionStore.dynamicRoutes.forEach((route) => router.addRoute(route))
// 确保添加路由已完成
// 设置 replace: true, 因此导航将不会留下历史记录
@ -62,7 +51,6 @@ router.beforeEach(async (to, _from, next) => {
// 过程中发生任何错误,都直接重置 Token并重定向到登录页面
userStore.resetToken()
ElMessage.error(err.message || "路由守卫过程发生错误")
NProgress.done()
next("/login")
}
})

View File

@ -29,13 +29,23 @@ export const usePermissionStore = defineStore("permission", () => {
const routes = ref<RouteRecordRaw[]>([])
const dynamicRoutes = ref<RouteRecordRaw[]>([])
/** 根据角色生成可访问的 Routes可访问路由 = 常驻路由 + 有访问权限的动态路由) */
const setRoutes = (roles: string[]) => {
const accessedRoutes = routeSettings.async ? filterAsyncRoutes(asyncRoutes, roles) : asyncRoutes
const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
_set(accessedRoutes)
}
/** 所有路由 = 所有常驻路由 + 所有动态路由 */
const setAllRoutes = () => {
_set(asyncRoutes)
}
const _set = (accessedRoutes: RouteRecordRaw[]) => {
routes.value = constantRoutes.concat(accessedRoutes)
dynamicRoutes.value = routeSettings.thirdLevelRouteCache ? flatMultiLevelRoutes(accessedRoutes) : accessedRoutes
}
return { routes, dynamicRoutes, setRoutes }
return { routes, dynamicRoutes, setRoutes, setAllRoutes }
})
/** 在 setup 外使用 */

View File

@ -1,14 +1,12 @@
import { ref } from "vue"
import store from "@/store"
import { defineStore } from "pinia"
import { usePermissionStore } from "./permission"
import { useTagsViewStore } from "./tags-view"
import { useSettingsStore } from "./settings"
import { getToken, removeToken, setToken } from "@/utils/cache/cookies"
import router, { resetRouter } from "@/router"
import { resetRouter } from "@/router"
import { loginApi, getUserInfoApi } from "@/api/login"
import { type LoginRequestData } from "@/api/login/types/login"
import { type RouteRecordRaw } from "vue-router"
import routeSettings from "@/config/route"
export const useUserStore = defineStore("user", () => {
@ -16,7 +14,6 @@ export const useUserStore = defineStore("user", () => {
const roles = ref<string[]>([])
const username = ref<string>("")
const permissionStore = usePermissionStore()
const tagsViewStore = useTagsViewStore()
const settingsStore = useSettingsStore()
@ -33,18 +30,13 @@ export const useUserStore = defineStore("user", () => {
// 验证返回的 roles 是否为一个非空数组,否则塞入一个没有任何作用的默认角色,防止路由守卫逻辑进入无限循环
roles.value = data.roles?.length > 0 ? data.roles : routeSettings.defaultRoles
}
/** 切换角色 */
/** 模拟角色变化 */
const changeRoles = async (role: string) => {
const newToken = "token-" + role
token.value = newToken
setToken(newToken)
await getInfo()
permissionStore.setRoutes(roles.value)
resetRouter()
permissionStore.dynamicRoutes.forEach((item: RouteRecordRaw) => {
router.addRoute(item)
})
_resetTagsView()
// 用刷新页面代替重新登陆
window.location.reload()
}
/** 登出 */
const logout = () => {

View File

@ -2,16 +2,10 @@
import { ref, watch } from "vue"
import { useUserStore } from "@/store/modules/user"
/** Vue 3.3+ defineEmits 语法 */
const emit = defineEmits<{
change: []
}>()
const userStore = useUserStore()
const switchRoles = ref(userStore.roles[0])
watch(switchRoles, async (value) => {
await userStore.changeRoles(value)
emit("change")
watch(switchRoles, (value) => {
userStore.changeRoles(value)
})
</script>
@ -19,7 +13,7 @@ watch(switchRoles, async (value) => {
<div>
<div>你的权限{{ userStore.roles }}</div>
<div class="switch-roles">
<span>切换权限</span>
<span>切换权限模拟权限变化后重新登陆</span>
<el-radio-group v-model="switchRoles">
<el-radio-button label="editor" />
<el-radio-button label="admin" />

View File

@ -1,20 +1,13 @@
<script lang="ts" setup>
import { ref } from "vue"
import { checkPermission } from "@/utils/permission" // checkPermission
import { checkPermission } from "@/utils/permission"
import SwitchRoles from "./components/SwitchRoles.vue"
/** key 是为了能每次切换权限的时候重新初始化指令 */
const key = ref(1)
const handleRolesChange = () => {
key.value++
}
</script>
<template>
<div class="app-container">
<SwitchRoles @change="handleRolesChange" />
<SwitchRoles />
<!-- v-permission 示例 -->
<div :key="key" class="margin-top-30">
<div class="margin-top-30">
<div>
<el-tag v-permission="['admin']" type="success" size="large" effect="plain">
这里采用了 v-permission="['admin']" 所以只有 admin 可以看见这句话
@ -32,7 +25,7 @@ const handleRolesChange = () => {
</div>
</div>
<!-- checkPermission 示例 -->
<div :key="`checkPermission${key}`" class="margin-top-30">
<div class="margin-top-30">
<el-tag type="warning" size="large">
例如 Element Plus el-tab-pane el-table-column 以及其它动态渲染 Dom 的场景不适合使用
v-permission这种情况下你可以通过 v-if checkPermission 来实现