index.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. import { createRouter, createWebHistory } from 'vue-router'
  2. import { notification } from 'ant-design-vue'
  3. import NProgress from 'nprogress'
  4. import 'nprogress/nprogress.css'
  5. import systemRouter from './systemRouter'
  6. import { afterEach, beforeEach } from './scrollBehavior'
  7. import whiteListRouters from './whiteList'
  8. import portal from './portal'
  9. import forum from './forum'
  10. import student from './student'
  11. import userRoutes from '@/config/route'
  12. import tool from '@/utils/tool'
  13. import fullPageTool from './fullPageTool'
  14. import { cloneDeep } from 'lodash-es'
  15. const modules = import.meta.glob('/src/views/**/**.vue')
  16. import { globalStore, searchStore } from '@/store'
  17. // 进度条配置
  18. NProgress.configure({ showSpinner: false, speed: 500 })
  19. // 系统特殊路由
  20. const routes_404 = [
  21. {
  22. path: '/:pathMatch(.*)*',
  23. hidden: true,
  24. component: () => import('@/layout/other/404.vue')
  25. }
  26. ]
  27. // 系统路由
  28. const routes = [...systemRouter, ...whiteListRouters, ...routes_404,...forum,...student]
  29. const router = createRouter({
  30. history: createWebHistory(),
  31. routes
  32. })
  33. // 设置标题
  34. // document.title = sysBaseConfig.SNOWY_SYS_NAME
  35. // 判断是否已加载过动态/静态路由
  36. const isGetRouter = ref(false)
  37. // 白名单校验
  38. const exportWhiteListFromRouter = (router) => {
  39. const res = []
  40. for (const item of router) res.push(item.path)
  41. return res
  42. }
  43. const whiteList = exportWhiteListFromRouter(whiteListRouters)
  44. router.beforeEach(async (to, from, next) => {
  45. NProgress.start()
  46. const store = globalStore()
  47. const sysBaseConfig = tool.data.get('SNOWY_SYS_BASE_CONFIG') || store.sysBaseConfig
  48. // 动态标题
  49. document.title = to.meta.title
  50. ? `${to.meta.title} - ${sysBaseConfig.SNOWY_SYS_NAME}`
  51. : `${sysBaseConfig.SNOWY_SYS_NAME}`
  52. // 过滤白名单
  53. if (whiteList.includes(to.path)) {
  54. next()
  55. // NProgress.done()
  56. return false
  57. }
  58. const token = tool.data.get('TOKEN')
  59. if (to.path === '/slogin') {
  60. // 当用户输入了login路由,将其跳转首页即可
  61. if (token) {
  62. next({
  63. path: '/'
  64. })
  65. return false
  66. }
  67. // 删除路由(替换当前layout路由)
  68. router.addRoute(routes[0])
  69. isGetRouter.value = false
  70. next()
  71. return false
  72. } else {
  73. if (token) {
  74. // 有token的时候才保存登录之前要访问的页面
  75. tool.data.set('LAST_VIEWS_PATH', to.fullPath)
  76. }
  77. fullPageTool.check(to)
  78. }
  79. if (!token) {
  80. next({
  81. path: '/slogin'
  82. })
  83. return false
  84. }
  85. // 整页路由处理
  86. if (to.meta.fullpage) {
  87. to.matched = [to.matched[to.matched.length - 1]]
  88. }
  89. // 加载动态/静态路由
  90. if (!isGetRouter.value) {
  91. const apiMenu = tool.data.get('MENU') || []
  92. if (apiMenu.length === 0) {
  93. // 创建默认模块,显示默认菜单
  94. apiMenu[0] = cloneDeep(userRoutes.module[0])
  95. }
  96. const childrenApiMenu = apiMenu[0].children
  97. apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
  98. let menuRouter = filterAsyncRouter(apiMenu)
  99. menuRouter = flatAsyncRoutes(menuRouter)
  100. menuRouter.forEach((item) => {
  101. router.addRoute('layout', item)
  102. })
  103. const search_store = searchStore()
  104. search_store.init(menuRouter)
  105. isGetRouter.value = true
  106. next({ ...to, replace: true })
  107. return false
  108. }
  109. beforeEach(to, from)
  110. next()
  111. })
  112. router.afterEach((to, from) => {
  113. afterEach(to, from)
  114. NProgress.done()
  115. })
  116. router.onError((error) => {
  117. NProgress.done()
  118. notification.error({
  119. message: '路由错误',
  120. description: error.message
  121. })
  122. })
  123. // 入侵追加自定义方法、对象
  124. router.getMenu = () => {
  125. let apiMenu = tool.data.get('MENU') || []
  126. // 增加固定路由
  127. if (apiMenu.length === 0) {
  128. // 创建默认模块,显示默认菜单
  129. apiMenu[0] = cloneDeep(userRoutes.module[0])
  130. }
  131. const childrenApiMenu = apiMenu[0].children
  132. apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
  133. return filterUrl(apiMenu)
  134. }
  135. const filterUrl = (map) => {
  136. const newMap = []
  137. const traverse = (maps) => {
  138. maps &&
  139. maps.forEach((item) => {
  140. item.meta = item.meta ? item.meta : {}
  141. // 处理iframe
  142. if (item.meta.type === 'iframe') {
  143. item.path = `/${item.name}`
  144. }
  145. // 递归循环
  146. if (item.children && item.children.length > 0) {
  147. item.children = filterUrl(item.children)
  148. }
  149. newMap.push(item)
  150. })
  151. }
  152. traverse(map)
  153. return newMap
  154. }
  155. // 转换
  156. const filterAsyncRouter = (routerMap) => {
  157. const accessedRouters = []
  158. routerMap.forEach((item) => {
  159. item.meta = item.meta ? item.meta : {}
  160. // 处理外部链接特殊路由
  161. if (item.meta.type === 'iframe') {
  162. item.meta.url = item.path
  163. item.path = `/${item.name}`
  164. }
  165. // MAP转路由对象
  166. const route = {
  167. path: item.path,
  168. name: item.name,
  169. meta: item.meta,
  170. redirect: item.redirect,
  171. children: item.children ? filterAsyncRouter(item.children) : null,
  172. component: loadComponent(item.component)
  173. }
  174. // console.log('看看', route)
  175. accessedRouters.push(route)
  176. })
  177. return accessedRouters
  178. }
  179. const loadComponent = (component) => {
  180. if (component) {
  181. if (component.includes('/')) {
  182. return modules[`/src/views/${component}.vue`]
  183. }
  184. return modules[`/src/views/${component}/index.vue`]
  185. } else {
  186. return () => import(/* @vite-ignore */ `/src/layout/other/empty.vue`)
  187. }
  188. }
  189. // 路由扁平化
  190. const flatAsyncRoutes = (routes, breadcrumb = []) => {
  191. const res = []
  192. routes.forEach((route) => {
  193. const tmp = { ...route }
  194. if (tmp.children) {
  195. const childrenBreadcrumb = [...breadcrumb]
  196. childrenBreadcrumb.push(route)
  197. const tmpRoute = { ...route }
  198. tmpRoute.meta.breadcrumb = childrenBreadcrumb
  199. delete tmpRoute.children
  200. res.push(tmpRoute)
  201. const childrenRoutes = flatAsyncRoutes(tmp.children, childrenBreadcrumb)
  202. childrenRoutes.map((item) => {
  203. res.push(item)
  204. })
  205. } else {
  206. const tmpBreadcrumb = [...breadcrumb]
  207. tmpBreadcrumb.push(tmp)
  208. tmp.meta.breadcrumb = tmpBreadcrumb
  209. res.push(tmp)
  210. }
  211. })
  212. return res
  213. }
  214. export default router