123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- import { AxiosWrapper } from '@/utils/axios-wrapper'
- import { UserStore } from '@/store/user'
- import { cloneDeep, isArray, omit } from 'lodash-es'
- import NProgress from 'nprogress'
- import 'nprogress/nprogress.css'
- import { ElMessageBox } from 'element-plus'
- import i18n from '@/lang'
- const whiteList = ['/redirect', '/login', '/401', '/404']
- NProgress.configure({ showSpinner: false }) // 进度条
- // 检查路由是否存在
- const hasNecessaryRoute = (to, router) => {
- // 将默认注册的路由平铺成一维数组
- const routesOneDimensional = toOneDimensional(router.getRoutes())
- return routesOneDimensional.find((f) => f.path === to.path)
- }
- // 获取用户信息,返回菜单
- const getUserMeta = async (token) => {
- const userStore = UserStore()
- const axios = new AxiosWrapper()
- const result = await axios.$get(`/token/tokenView`, null, {
- headers: {
- token: token
- }
- })
- if (result.errcode === 0) {
- userStore.setUser(result.data)
- const resetMenusResult = resetMenus(result.data.menus)
- const storeMenus = toRaw(userStore.menus)
- if (storeMenus.length <= 0) {
- userStore.setMenus(resetMenusResult)
- }
- return { menus: result.data.menus, errcode: 0 }
- }
- return { errmsg: result.errmsg, errcode: result.errcode }
- }
- /**
- * 将路由数组一维化
- * @param {Array} routes 路由数组
- * @returns 一维路由数组
- */
- const toOneDimensional = (routes) => {
- const result = []
- for (const r of routes) {
- const { children = [], ...others } = r
- result.push(others)
- if (children.length > 0) result.push(...toOneDimensional(children))
- }
- return result
- }
- // 添加路由
- const addUserRoutes = async (menus, router) => {
- return new Promise((resolve, reject) => {
- // 将用户菜单转换成普通对象
- const menuArr = toRaw(menus)
- // 将用户菜单平铺成一维数组,并将目录过滤出去.目录不需要注册,不是组件
- const menuOneDimensional = toOneDimensional(menuArr)
- // 将默认注册的路由平铺成一维数组
- const routesOneDimensional = toOneDimensional(router.getRoutes())
- routesRegister(menuOneDimensional, routesOneDimensional, router)
- resolve()
- })
- }
- /**
- * 注册路由
- * @param {Array} menus 一维数组菜单
- * @param {Array} defaultRoutes 默认路由一维数组
- * @param {*} router 路由实例
- */
- const routesRegister = (menus, defaultRoutes, router) => {
- // 默认注册位置
- const __def = 'Layout'
- const loadComponent = import.meta.glob('../views/**/*.vue')
- for (const route of menus) {
- const { type, route_name, path, component, parent_id } = route
- if (!path) {
- console.log(route)
- }
- // 检查路由是否已存在,存在跳过
- const hasRoute = defaultRoutes.find((f) => f.path === path)
- if (hasRoute) continue
- if (type === '0') {
- // 目录, 默认使用 `/${路由名称}`
- const route = {
- path: `/${route_name}`,
- name: route_name,
- meta: { title: route_name, type }
- }
- router.addRoute(__def, route)
- } else if (type === '1' || type === '2') {
- // 菜单 或 子菜单
- const route = {
- path: path,
- name: route_name,
- meta: {
- title: route_name,
- type
- },
- component: loadComponent[`../views${component}.vue`]
- }
- if (parent_id) {
- const parent = menus.find((f) => f._id === parent_id)
- if (!parent) continue
- const pos = parent.route_name
- router.addRoute(pos, route)
- // try {
- // } catch (error) {
- // console.log(pos, route)
- // console.error(error)
- // }
- } else {
- router.addRoute(__def, route)
- }
- }
- }
- }
- const resetMenus = (menus) => {
- if (!isArray(menus) || menus.length <= 0) return []
- const cMenus = cloneDeep(menus)
- const result = []
- for (const m of cMenus) {
- const mid = omit(m, ['is_use', 'order_num', 'in_admin_frame'])
- const { children } = mid
- if (children) mid.children = resetMenus(children)
- result.push(mid)
- }
- return result
- }
- // 注册前置守卫
- export const registerBeforeRouter = async (router) => {
- router.beforeEach(async (to, from, next) => {
- NProgress.start() //开启进度条
- const token = localStorage.getItem('token')
- NProgress.inc()
- if (whiteList.includes(to.path)) {
- next()
- return
- }
- if (token) {
- NProgress.inc()
- if (to.path === '/login') next()
- NProgress.inc()
- const { menus, errcode, errmsg } = await getUserMeta(token)
- // 登录信息有问题
- if (errcode !== 0) {
- if (errcode.includes('FRAMEERROR_401')) {
- await ElMessageBox.alert(errmsg, i18n.global.t('common.user_confirm'), {
- confirmButtonText: i18n.global.t('common.re_login'),
- type: 'error'
- })
- next('/login')
- return
- } else {
- await ElMessageBox.alert(errmsg, i18n.global.t('common.user_confirm'), {
- confirmButtonText: i18n.global.t('common.re_login'),
- type: 'error'
- })
- location.reload()
- }
- }
- // 菜单格式不正确
- if (!menus) {
- next('/401')
- return
- }
- // 检查目的地路由是否注册
- const hasRoute = hasNecessaryRoute(to, router)
- NProgress.inc()
- if (hasRoute || to.meta.hidden) {
- // 注册了直接进入
- next()
- } else {
- // 没注册就先注册再重定向进入直到进入为止
- await addUserRoutes(menus, router)
- NProgress.inc()
- next({ ...to, replace: true })
- }
- } else {
- next('/login')
- }
- })
- }
- // 注册路由后置守卫
- export const registerAfterRouter = async (router) => {
- router.afterEach(async (to, form) => {
- NProgress.done() //完成进度条
- if (to.path === '/login') {
- return
- }
- // 请求该页面的权限
- })
- }
|