当前位置:   article > 正文

02---vue+element+admin将本地路由修改为权限路由_vue3 静态路由 权限

vue3 静态路由 权限

1.修改路由导航守卫,判断何时获取路由数据,并处理获取数据的js,阻止通过网址想直接进入后台进行权限管理

路由导航守卫文件在scr/permission.js中,下面是修改好之后的代码

  1. import router from './router'
  2. import store from './store'
  3. import { Message } from 'element-ui'
  4. import NProgress from 'nprogress' // progress bar
  5. import 'nprogress/nprogress.css' // progress bar style
  6. import { getToken, getNickName } from '@/utils/auth' // get token from cookie
  7. import { resetRouter } from '@/router'
  8. import getPageTitle from '@/utils/get-page-title'
  9. NProgress.configure({ showSpinner: false }) // NProgress Configuration
  10. const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
  11. router.beforeEach(async(to, from, next) => {
  12. // start progress bar
  13. NProgress.start()
  14. // set page title
  15. document.title = getPageTitle(to.meta.title)
  16. // determine whether the user has logged in
  17. const hasToken = getToken() //获取登录token
  18. const nickName = getNickName(); //获取刚才在模块页使用cookie保存的模块名称
  19. // 判断是否有token
  20. if (hasToken) {
  21. // 判断当前路径是否为登录页
  22. if (to.path === '/login') {
  23. // 进入模块页
  24. next({ path: '/cache' })
  25. NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
  26. // 判断当前是否为根路径
  27. } else if (to.path === '/') {
  28. //进入模块页
  29. next({ path: '/cache' })
  30. // 判断当前是否为模块页
  31. } else if (to.path === '/cache') {
  32. // 清除cookie保存的模块名称
  33. await store.dispatch("user/cache");
  34. next();
  35. // 判断当前是否为重定项页,首页
  36. } else if (to.path === '/dashboard') {
  37. resetRouter() //重置路由
  38. if (nickName == undefined) { //判断名称是否为空
  39. //为空直接跳回模块页
  40. next({ path: '/cache' });
  41. NProgress.done()
  42. } else {
  43. // 获取路由
  44. const { roles } = await store.dispatch('user/getInfo')
  45. const accessRoutes = await store.dispatch('permission/generateRoutes', { roles, nickName });
  46. //动态添加
  47. router.addRoutes(accessRoutes);
  48. next();
  49. }
  50. // 解决动态页面,强制刷新,路径丢失,和退出登录,重新登录,路径丢失问题
  51. } else if (to.path != '/dashboard') {
  52. // 先放行
  53. next();
  54. // 判断动态路由是否有数据,没有重新动态添加
  55. if (store.getters.permission_routes.length == 0) {
  56. const { roles } = await store.dispatch('user/getInfo')
  57. const accessRoutes = await store.dispatch('permission/generateRoutes', { roles, nickName });
  58. router.addRoutes(accessRoutes)
  59. next();
  60. // 名称为空,直接跳转到模块页面
  61. } else if (nickName == undefined) {
  62. next({ path: '/cache' });
  63. NProgress.done()
  64. }
  65. } else {
  66. const hasRoles = store.getters.roles && store.getters.roles.length > 0
  67. if (hasRoles) {
  68. next()
  69. } else {
  70. try {
  71. // get user info
  72. // 注意:角色必须是对象数组!例如:['admin']或,['developer','editor']
  73. const { roles } = await store.dispatch('user/getInfo')
  74. const accessRoutes = await store.dispatch('permission/generateRoutes', { roles, nickName })
  75. router.addRoutes(accessRoutes);
  76. // 黑客方法,以确保addRoutes是完整的
  77. // 设置replace:true,这样导航就不会留下历史记录
  78. next({...to, replace: true })
  79. } catch (error) { // 获取用户信息失败,进入以下一级
  80. await store.dispatch('user/resetToken') // 获取用户信息失败后,就删除token
  81. Message.error(error || 'Has Error') // 提示相应的错误
  82. //next(`/login?redirect=${to.path}`) // 并跳转回登录界面,重新登录
  83. next('login')
  84. NProgress.done()
  85. }
  86. }
  87. }
  88. } else {
  89. /* 没有令牌*/
  90. if (whiteList.indexOf(to.path) !== -1) {
  91. // 在免费登录白名单中,直接进入
  92. next()
  93. } else {
  94. // 其他没有访问权限的页面将被重定向到登录页面。
  95. // next(`/login?redirect=${to.path}`)
  96. next('/login')
  97. NProgress.done()
  98. }
  99. }
  100. })
  101. router.afterEach(() => {
  102. // 完成进度条
  103. NProgress.done()
  104. })

判断当前路径为/cache时删除cookie中保存的模块名称,不然通过网址进入后台管理页面时就会出现导航守卫死循环bug,其中await store.dispatch(‘user/cache’);是使用vuex中的方法,这个方法在上一篇博客01---vue+element+admin将本地路由修改为动态路由_天尘不打野的博客-CSDN博客中的src/store/modules/user.js文件中已经定义了,这里就不贴代码了

判断当前路径为/dashboard,并且模块名称不能为空时,获取路由数据,并动态添加进去。其中await store.dispatch(‘permission/generateRoutes’, nickName);是使用vuex中的方法,给permission.js中的generateRoutes,传递一个模块名称。

2.在src/store/modules/permission.js文件中定义generateRoutes方法

定义方法之前先将scr/router/modules中的四个路由文件里面的路由数据改为数组对象形式,因为动态路由需要数组对象形式,否则报错

 修改src/store/modules/permission.js文件

  1. import { asyncRoutes, constantRoutes } from '@/router'
  2. import Layout from '@/layout'
  3. // 引入刚才改好的四个路由文件
  4. import componentsRouter from '@/router/modules/components'
  5. import chartsRouter from '@/router/modules/charts'
  6. import tableRouter from '@/router/modules/table'
  7. import nestedRouter from '@/router/modules/nested'
  8. /**
  9. * Use meta.role to determine if the current user has permission
  10. * @param roles
  11. * @param route
  12. */
  13. function hasPermission(roles, route) {
  14. if (route.meta && route.meta.roles) {
  15. return roles.some(role => route.meta.roles.includes(role))
  16. } else {
  17. return true
  18. }
  19. }
  20. /**
  21. * Filter asynchronous routing tables by recursion
  22. * @param routes asyncRoutes
  23. * @param roles
  24. */
  25. export function filterAsyncRoutes(routes, roles) {
  26. const res = []
  27. routes.forEach(route => {
  28. const tmp = {...route }
  29. if (hasPermission(roles, tmp)) {
  30. if (tmp.children) {
  31. tmp.children = filterAsyncRoutes(tmp.children, roles)
  32. }
  33. res.push(tmp)
  34. }
  35. })
  36. return res
  37. }
  38. const state = {
  39. routes: [],
  40. addRoutes: []
  41. }
  42. const mutations = {
  43. SET_ROUTES: (state, routes) => {
  44. state.addRoutes = routes
  45. state.routes = constantRoutes.concat(routes)
  46. }
  47. }
  48. // 懒加载
  49. export const loadView = (view) => {
  50. return (resolve) => require([`@/views${view}`], resolve)
  51. }
  52. /**
  53. *
  54. * @param { * 后台查询的菜单数据拼装成路由格式的数据
  55. * @param routes} routes
  56. * @param {*} data
  57. */
  58. export function generaMenu(routes, data) {
  59. data.forEach(item => {
  60. const menu = {
  61. path: item.path === '#' ? item.menuId + '_key' : item.path,
  62. // component: item.component === '#' ? Layout : loadView(item.component),
  63. /**
  64. * 因为引入的路由文件里已经做了路由懒加载,这里就直接赋值就行
  65. * 如果是调用后台接口获取的数组对象,把下面的代码注释,上面的代码解开就可以了
  66. */
  67. component: item.component,
  68. hidden: item.hidden,
  69. children: [],
  70. //在4.4.0中路由父节点允许name属性存在值否则出现VUE之Router命令行警告:Named Route 'Home' has a default child route 警告
  71. name: item.component === '#' ? "" : item.name,
  72. meta: item.meta
  73. }
  74. if (item.children) {
  75. generaMenu(menu.children, item.children)
  76. }
  77. // 当存在单路由时要将children为空的属性删除否则无法在左侧菜单中展示独立的路由菜单
  78. if (menu.children.length <= 0) delete menu.children
  79. routes.push(menu)
  80. })
  81. }
  82. /**
  83. * 删除子节点children 为空数组
  84. * @param {*} data
  85. */
  86. export function deleteChildren(data) {
  87. let childs = data
  88. for (let i = childs.length; i--; i > 0) {
  89. //if(childs[i].meta != null){
  90. // childs[i].meta = (childs[i].meta).replace("\"","").replace("\"","");
  91. //}
  92. if (childs[i].children) {
  93. if (childs[i].children.length) {
  94. deleteChildren(childs[i].children)
  95. } else {
  96. delete childs[i].children
  97. }
  98. }
  99. }
  100. return data
  101. }
  102. const actions = {
  103. // 自己封装一个js
  104. //这个就为刚才在导航守卫,条件判断通过后,调用的获取数据的方法
  105. generateRoutes({ commit }, obj) {
  106. return new Promise(resolve => {
  107. const loadMenuData = [];
  108. let response = [];
  109. // 在这里可以调取后端接口,获取动态路由数组对象并把数据添加到路由
  110. if (obj.nickName === "组件系统") {
  111. response = deleteChildren(componentsRouter);
  112. } else if (obj.nickName === "图表系统") {
  113. response = deleteChildren(chartsRouter);
  114. } else if (obj.nickName === "表格系统") {
  115. response = deleteChildren(tableRouter);
  116. } else if (obj.nickName === "多级路由") {
  117. response = deleteChildren(nestedRouter);
  118. }
  119. Object.assign(loadMenuData, response)
  120. const tempAsyncRoutes = Object.assign([], asyncRoutes)
  121. generaMenu(tempAsyncRoutes, loadMenuData)
  122. let accessedRoutes
  123. if (obj.roles.includes('admin')) {
  124. accessedRoutes = tempAsyncRoutes || []
  125. } else {
  126. accessedRoutes = filterAsyncRoutes(tempAsyncRoutes, obj.roles)
  127. }
  128. commit('SET_ROUTES', accessedRoutes);
  129. //抛出路由,导航守卫获取数据要使用
  130. resolve(accessedRoutes)
  131. })
  132. }
  133. }
  134. export default {
  135. namespaced: true,
  136. state,
  137. mutations,
  138. actions
  139. }

 注:因为内容太多,后面的内容在我另外的几个博客里:

01---vue+element+admin将本地路由修改为动态路由_天尘不打野的博客-CSDN博客

03---vue+element+admin将本地路由修改为动态路由_天尘不打野的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/58880
推荐阅读
相关标签
  

闽ICP备14008679号