permission.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import router, { resetRouter } from './router'
  2. import Layout from '@/layout'
  3. import { checkToken, refreshToken } from '@/api/system'
  4. import {
  5. getToken,
  6. setToken
  7. } from './utils/auth'
  8. import progress from '@/utils/progress'
  9. import store from './store'
  10. import Vue from 'vue'
  11. // 刷新token状态
  12. let isRefreshToken = true
  13. let isRefreshTree = true
  14. // 路由拦截
  15. router.beforeEach(async (to, from, next) => {
  16. // debugger
  17. // 无需登录无需获取动态路由
  18. if (to?.meta?.noLogin) {
  19. next()
  20. return
  21. }
  22. // 前往登陆页面判断
  23. if (to.path === '/login-local') {
  24. if (!getToken()) {
  25. next()
  26. return
  27. }
  28. next('/')
  29. return
  30. }
  31. if (to.path === '/login') {
  32. next('/')
  33. return
  34. }
  35. progress.start()
  36. try {
  37. if (from.path !== '/login-local') {
  38. if (isRefreshToken) {
  39. isRefreshToken = false
  40. const { data } = await refreshToken()
  41. setToken(data)
  42. } else {
  43. await checkToken()
  44. }
  45. }
  46. // 判断是否已经存在机构信息
  47. if (isRefreshTree) {
  48. store.dispatch('system/getOrganizationTree').then(_ => {
  49. isRefreshTree = false
  50. }).catch(e => {
  51. Vue.prototype.$message.error('获取机构信息失败')
  52. }).finally(() => {
  53. onFilterRoutes(to, next)
  54. })
  55. return
  56. }
  57. onFilterRoutes(to, next)
  58. } catch (error) {
  59. Vue.prototype.$message.error(error)
  60. }
  61. })
  62. router.afterEach((to, from) => {
  63. progress.done()
  64. document.title = `${Vue.prototype.$DEFAULT_TITLE} ${to.meta.title ?? ''}`
  65. })
  66. // 路由过滤和跳转
  67. async function onFilterRoutes (to, _next) {
  68. // 无需更新路由
  69. if (!store.getters.refresh) {
  70. _next()
  71. return
  72. }
  73. const _route = store.getters.route
  74. // 监测是否需要更新路由
  75. if (_route && _route.length) {
  76. initRoutes(to, _next, _route)
  77. return
  78. }
  79. try {
  80. const res = await store.dispatch('menu/getMenu2')
  81. if (!res || !res.length) {
  82. // 无权限 返回登录页面
  83. Vue.prototype.$message.error('无权限账户,请联系管理员')
  84. store.dispatch('user/userLogout')
  85. return
  86. }
  87. initRoutes(to, _next, res)
  88. } catch (error) {
  89. store.dispatch('user/userLogout')
  90. Vue.prototype.$message.error(error)
  91. }
  92. }
  93. function initRoutes (to, _next, e) {
  94. store.commit('menu/SET_REFRESH', false) // 关闭路由刷新
  95. // 清除路由
  96. resetRouter()
  97. const routes = mapASyncRoutes(e) // 路由替换
  98. routes.forEach(item => {
  99. router.addRoute(item)
  100. })
  101. router.addRoute({ path: '/', redirect: chooseFirst(routes[0]) })
  102. router.addRoute({ path: '*', redirect: '/404', hidden: true })
  103. _next({ ...to, replace: true })
  104. }
  105. function chooseFirst (item) {
  106. if (item.children && item.children.length > 0 && item.component.name === 'layoutIndex') {
  107. return chooseFirst(item.children[0])
  108. }
  109. return item.path
  110. }
  111. // 递归路由 转换为组件对象和路径
  112. function mapASyncRoutes (data) {
  113. return data.map(item => {
  114. item.meta.title = item.label
  115. item.meta.type = item.type
  116. item.meta.hidden = item.hidden === 0
  117. item.component = item.component === 'Layout' ? Layout : loadView(item.component)
  118. if (item.children && item.children.length > 0) {
  119. item.children = mapASyncRoutes(item.children)
  120. }
  121. return item
  122. })
  123. }
  124. // 路由插件
  125. function loadView (view) {
  126. return !view ? { render: (c) => c('router-view') } : () => import(`@/views/${view}`)
  127. }