123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /**
- * Copyright [2022] [https://www.xiaonuo.vip]
- * Snowy采用APACHE LICENSE 2.0开源协议,您在使用过程中,需要注意以下几点:
- * 1.请不要删除和修改根目录下的LICENSE文件。
- * 2.请不要删除和修改Snowy源码头部的版权声明。
- * 3.本项目代码可免费商业使用,商业使用请保留源码和相关描述文件的项目出处,作者声明等。
- * 4.分发源码时候,请注明软件出处 https://www.xiaonuo.vip
- * 5.不可二次分发开源参与同类竞品,如有想法可联系团队xiaonuobase@qq.com商议合作。
- * 6.若您的项目无法满足以上几点,需要更多功能代码,获取Snowy商业授权许可,请在官网购买授权,地址为 https://www.xiaonuo.vip
- */
- import { createRouter, createWebHistory } from 'vue-router'
- import { notification } from 'ant-design-vue'
- import NProgress from 'nprogress'
- import 'nprogress/nprogress.css'
- import systemRouter from './systemRouter'
- import { afterEach, beforeEach } from './scrollBehavior'
- import whiteListRouters from './whiteList'
- import userRoutes from '@/config/route'
- import tool from '@/utils/tool'
- import { cloneDeep } from 'lodash-es'
- const modules = import.meta.glob('/src/views/**/**.vue')
- import { globalStore, searchStore } from '@/store'
- // 进度条配置
- NProgress.configure({ showSpinner: false, speed: 500 })
- // 系统特殊路由
- const routes_404 = [
- {
- path: '/:pathMatch(.*)*',
- hidden: true,
- component: () => import('@/layout/other/404.vue')
- }
- ]
- // 系统路由
- const routes = [...systemRouter, ...whiteListRouters, ...routes_404]
- const router = createRouter({
- history: createWebHistory(import.meta.env.BASE_URL),
- routes
- })
- // 设置标题
- // document.title = sysBaseConfig.SNOWY_SYS_NAME
- // 判断是否已加载过动态/静态路由
- const isGetRouter = ref(false)
- // 白名单校验
- const exportWhiteListFromRouter = (router) => {
- const res = []
- for (const item of router) res.push(item.path)
- return res
- }
- const whiteList = exportWhiteListFromRouter(whiteListRouters)
- router.beforeEach(async (to, from, next) => {
- NProgress.start()
- const store = globalStore()
- const sysBaseConfig = tool.data.get('SNOWY_SYS_BASE_CONFIG') || store.sysBaseConfig
- // 动态标题
- document.title = to.meta.title
- ? `${to.meta.title} - ${sysBaseConfig.SNOWY_SYS_NAME}`
- : `${sysBaseConfig.SNOWY_SYS_NAME}`
- // 过滤白名单
- if (whiteList.includes(to.path)) {
- next()
- // NProgress.done()
- return false
- }
- const token = tool.data.get('TOKEN')
- if (to.path === '/login') {
- // 当用户输入了login路由,将其跳转首页即可
- if (token) {
- next({
- path: '/'
- })
- return false
- }
- // 删除路由(替换当前layout路由)
- router.addRoute(routes[0])
- isGetRouter.value = false
- next()
- return false
- } else {
- if (token) {
- // 有token的时候才保存登录之前要访问的页面
- tool.data.set('LAST_VIEWS_PATH', to.fullPath)
- }
- }
- if (!token) {
- next({
- path: '/login'
- })
- return false
- }
- // 整页路由处理
- if (to.meta.fullpage) {
- to.matched = [to.matched[to.matched.length - 1]]
- }
- // 加载动态/静态路由
- if (!isGetRouter.value) {
- const apiMenu = tool.data.get('MENU') || []
- if (apiMenu.length === 0) {
- // 创建默认模块,显示默认菜单
- apiMenu[0] = cloneDeep(userRoutes.module[0])
- }
- const childrenApiMenu = apiMenu[0].children
- // apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
- apiMenu.push(...userRoutes.menu)
- let menuRouter = filterAsyncRouter(apiMenu)
- menuRouter = flatAsyncRoutes(menuRouter)
- menuRouter.forEach((item) => {
- router.addRoute('layout', item)
- })
- const search_store = searchStore()
- search_store.init(menuRouter)
- isGetRouter.value = true
- next({ ...to, replace: true })
- return false
- }
- beforeEach(to, from)
- next()
- })
- router.afterEach((to, from) => {
- afterEach(to, from)
- NProgress.done()
- })
- router.onError((error) => {
- NProgress.done()
- notification.error({
- message: '路由错误',
- description: error.message
- })
- })
- // 入侵追加自定义方法、对象
- router.getMenu = () => {
- let apiMenu = tool.data.get('MENU') || []
- // 增加固定路由
- if (apiMenu.length === 0) {
- // 创建默认模块,显示默认菜单
- apiMenu[0] = cloneDeep(userRoutes.module[0])
- }
- const childrenApiMenu = apiMenu[0].children
- apiMenu[0].children = [...(childrenApiMenu ? childrenApiMenu : []), ...userRoutes.menu]
- return filterUrl(apiMenu)
- }
- const filterUrl = (map) => {
- const newMap = []
- const traverse = (maps) => {
- maps &&
- maps.forEach((item) => {
- item.meta = item.meta ? item.meta : {}
- // 处理iframe
- if (item.meta.type === 'iframe') {
- item.path = `/${item.name}`
- }
- // 递归循环
- if (item.children && item.children.length > 0) {
- item.children = filterUrl(item.children)
- }
- newMap.push(item)
- })
- }
- traverse(map)
- return newMap
- }
- // 转换
- const filterAsyncRouter = (routerMap) => {
- const accessedRouters = []
- routerMap.forEach((item) => {
- item.meta = item.meta ? item.meta : {}
- // 处理外部链接特殊路由
- if (item.meta.type === 'iframe') {
- item.meta.url = item.path
- item.path = `/${item.name}`
- }
- // MAP转路由对象
- const route = {
- path: item.path,
- name: item.id,
- meta: item.meta,
- redirect: item.redirect,
- children: item.children ? filterAsyncRouter(item.children) : null,
- component: loadComponent(item.component)
- }
- accessedRouters.push(route)
- })
- return accessedRouters
- }
- const loadComponent = (component) => {
- if (component) {
- if (component.includes('/')) {
- return modules[`/src/views/${component}.vue`]
- }
- return modules[`/src/views/${component}/index.vue`]
- } else {
- return () => import(/* @vite-ignore */ `/src/layout/other/empty.vue`)
- }
- }
- // 路由扁平化
- const flatAsyncRoutes = (routes, breadcrumb = []) => {
- const res = []
- routes.forEach((route) => {
- const tmp = { ...route }
- if (tmp.children) {
- const childrenBreadcrumb = [...breadcrumb]
- childrenBreadcrumb.push(route)
- const tmpRoute = { ...route }
- tmpRoute.meta.breadcrumb = childrenBreadcrumb
- delete tmpRoute.children
- res.push(tmpRoute)
- const childrenRoutes = flatAsyncRoutes(tmp.children, childrenBreadcrumb)
- childrenRoutes.map((item) => {
- res.push(item)
- })
- } else {
- const tmpBreadcrumb = [...breadcrumb]
- tmpBreadcrumb.push(tmp)
- tmp.meta.breadcrumb = tmpBreadcrumb
- res.push(tmp)
- }
- })
- return res
- }
- export default router
|