赞
踩
一、路由全局前置守卫设置。
permission.ts:
1、先判断是否有token。
没有token: 可以访问白名单页面;但未登录如果要去的不是白名单页面,让他到登录页面,然后再重定向到要去的页面。
有token(即登录成功):如果要去登录页,直接跳转;如果要去其他页面,
2、要先判断是否有用户信息—有用户信息:如果没有从已有的所有路由中匹配到路由,有从上个路由过来的就直接跳到上个路由,否则就跳到401;没有用户信息:先通过store获取用户信息,根据用户角色来获取并添加动态路由
import { RouteRecordRaw } from "vue-router"; //这行代码是使用 vue-router 库在 Vue.js 应用程序中定义路由所必需的。 RouteRecordRaw 接口用于定义 Vue.js 应用程序中的路由。 import { defineStore } from "pinia"; import {constantRoutes} from '@/router'; //拿到路由文件里的静态路由 import {listRoutes} from '@/api/system/menu'; //拿到路由api import router from '@/router'; import NProgress from 'nprogress'; import useStore from '@/store'; import { RouteRecord } from 'vue-router'; NProgress.configure({ showSpinner: false }); //进度环显示/隐藏 // import.meta.glob 函数从文件系统导入多个模块 const modules = import.meta.glob('../../views/**/**.vue'); //白名单 const whiteList = ['/login', '/auth-redirect' ]; //路由全局前置守卫 router.beforeEach(async (to, from, next) => { NProgress.start();//进度条开始 const { user, permission, app } = useStore(); const hasToken = user.token; // 1.路由跳转前先判断是否有token if (hasToken) { // 1.1登录成功,跳转到首页 if (to.path === '/login') { next({path: '/'}); NProgress.done(); } else { // 1.2登录成功,去其他页面----要判断是否有用户信息 const hasGetUserInfo = user.roles.length > 0; //有用户信息 if (hasGetUserInfo) { // 1.2.1如果没有从已有的所有路由中匹配到路由,有从上个路由过来的就直接跳到上个路由,否则就跳到401 if (to.matched.length === 0) { // next({name: ''})----通过名称导航到特定路由。name: 是我要导航到的路由名称 from.name ? next({name: from.name as any }) : next('/401'); } else { next(); } } else { // 1.2.2 登录成功但 没有用户信息----先通过store获取用户信息,根据用户来获取并添加动态路由 try { await user.getUserInfo(); const roles = user.roles; //通过获取到的角色拿到相应角色的动态路由信息 const accessedRoutes: any = await permission.generateRoutes(roles); accessedRoutes.forEach((route:any) => { //将动态路由里的每个路由添加进去 router.addRoute(route); }); // 将当前路由信息与replace:true合并为一个新的对象,这个新的对象会被传入到next函数中。 // 表示要跳转到一个新的路由,并且使用replace模式进行跳转---会替换当前的路由记录,而不是添加一条新的记录。 next({...to, replace:true}); } catch (error) {//登录成功但获取用户信息失败----要移除token并跳转到登录页 await user.resetToken(); ElMessage.error((error as any) || 'Has Error'); next(`/login?redirect=${to.path}`); NProgress.done(); } } } } else { //2.没有token的话可以访问白名单页面(登录页面) // indexOf: 返回数组中第一次出现给定元素的下标,如果不存在就返回-1 if (whiteList.indexOf(to.path) !== -1) { next(); } else { // 未登录但要去的不是白名单页面-----让他到登录页面,然后再重定向到要去的页面 next(`/login?redirect=${to.path}`); NProgress.done(); } } })
二、根据用户角色来筛选获取并添加动态路由
store下的permission.ts:
const usePermissionStore = defineStore({ id:'permission', state: ():PermissionState => ({ routes: [], //总共的路由 addRoutes: [], //动态添加的路由 }), actions: { setRoutes(routes: RouteRecordRaw[]) { this.addRoutes = routes; this.routes = constantRoutes.concat(routes); }, // 根据角色筛选得到的动态路由 重要一步! generateRoutes(roles: string[]){ return new Promise((resolve, reject) => { //从接口获取路由列表 listRoutes().then((response) => { const asyncRoutes = response.data;//从接口获取的所有路由 const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);//根据角色筛选得到的动态路由 重要一步! this.setRoutes(accessedRoutes); //把获得的动态路由给store赋值 resolve(accessedRoutes); }).catch((error) => { reject(error) }) }) } } }) export default usePermissionStore; //根据角色过滤所有路由生成动态路由 export const filterAsyncRoutes = (routes:RouteRecordRaw[], roles: string[]) => { // 对每一个路由进行遍历 routes.forEach((route) => { //定义一个空数组----放过滤出来的动态路由 const res: RouteRecordRaw[] = []; //拿到每一个路由项并对里面的属性进行解构 const tmp = {...route} as any; //如果这个角色有这个路由权限就说明可以访问路由 if (hasPermission(roles, tmp)) {//此角色可以访问路由后就要配置路由信息了 if (tmp.component == 'Layout') { tmp.component = Layout; } else { //如果不是Layout组件,拿到其他组件名称 const component = modules[`../../views/${tmp.component}.vue`] as any; if (component) { tmp.component = modules[`../../views/${tmp.component}.vue`]; } else { //如果这个组件不存在 就跳到404页面 tmp.component = modules[`../../views/error-page/404.vue`] } } res.push(tmp); if(tmp.children) { tmp.children = filterAsyncRoutes(tmp.children, roles); } } }); return res; } //对某个角色是否对某个路由拥有权限进行判断------ 根据不同角色判断路由是否存在 const hasPermission = (roles: string[], route: RouteRecord) => { if(route.meta && route.meta.roles) { //如果是管理员--肯定有权限 if(roles.includes('ROOT')) { return true; } //如果不是管理员 return roles.some((role) => { if(route.meta?.roles !== undefined) { //实例路由里面的roles里包含实际登录的用户role--返回true,说明这个用户有路由权限 return (route.meta.roles as stirng[]).includes(role); } }) } return false; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。