PixelAI-admin/src/router/index.ts
2021-02-24 00:27:24 +08:00

646 lines
23 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { defineAsyncComponent } from 'vue'
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { store } from "/@/store/index.ts"
import { getSession, clearSession } from "/@/utils/storage.ts"
import { getMenuAdmin, getMenuTest } from '/@/api/menu/index.ts'
// 定义动态路由
export const dynamicRoutes = [
{
path: '/',
name: '/',
component: () => import('/@/views/layout/index.vue'),
redirect: '/home',
meta: {
isKeepAlive: true
},
children: [{
path: '/home',
name: 'home',
component: () => import('/@/views/home/index.vue'),
meta: {
title: '首页',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-shouye'
}
},
{
path: '/system',
name: 'system',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/system/menu',
meta: {
title: '系统设置',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-xitongshezhi'
},
children: [
{
path: '/system/menu',
name: "systemMenu",
component: () => import('/@/views/system/menu/index.vue'),
meta: {
title: '菜单管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-caidan'
}
},
{
path: '/system/user',
name: "systemUser",
component: () => import('/@/views/system/user/index.vue'),
meta: {
title: '用户管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-icon-',
}
}
]
},
{
path: '/limits',
name: 'limits',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/limits/frontEnd',
meta: {
title: '权限管理',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-quanxian'
},
children: [
{
path: '/limits/frontEnd',
name: 'limitsFrontEnd',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/limits/frontEnd/page',
meta: {
title: '前端控制',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test']
},
children: [
{
path: '/limits/frontEnd/page',
name: 'limitsFrontEndPage',
component: () => import('/@/views/limits/frontEnd/page/index.vue'),
meta: {
title: '页面权限',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test']
}
},
{
path: '/limits/frontEnd/btn',
name: 'limitsFrontEndBtn',
component: () => import('/@/views/limits/frontEnd/btn/index.vue'),
meta: {
title: '按钮权限',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test']
}
}
]
},
{
path: '/limits/backEnd',
name: 'limitsBackEnd',
component: () => import('/@/views/layout/routerView/parent.vue'),
meta: {
title: '后端控制',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test']
},
children: [
{
path: '/limits/backEnd/page',
name: 'limitsBackEndEndPage',
component: () => import('/@/views/limits/backEnd/page/index.vue'),
meta: {
title: '页面权限',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test']
}
}
]
}
]
},
{
path: '/menu',
name: 'menu',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/menu/menu1',
meta: {
title: '菜单嵌套',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
},
children: [
{
path: '/menu/menu1',
name: 'menu1',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/menu/menu1/menu11',
meta: {
title: '菜单1',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
},
children: [
{
path: '/menu/menu1/menu11',
name: 'menu11',
component: () => import('/@/views/menu/menu1/menu11/index.vue'),
meta: {
title: '菜单11',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
}
},
{
path: '/menu/menu1/menu12',
name: 'menu12',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/menu/menu1/menu12/menu121',
meta: {
title: '菜单12',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
},
children: [
{
path: '/menu/menu1/menu12/menu121',
name: 'menu121',
component: () => import('/@/views/menu/menu1/menu12/menu121/index.vue'),
meta: {
title: '菜单121',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
}
},
{
path: '/menu/menu1/menu12/menu122',
name: 'menu122',
component: () => import('/@/views/menu/menu1/menu12/menu122/index.vue'),
meta: {
title: '菜单122',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
}
}
]
},
{
path: '/menu/menu1/menu13',
name: 'menu13',
component: () => import('/@/views/menu/menu1/menu13/index.vue'),
meta: {
title: '菜单13',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
}
}
]
},
{
path: '/menu/menu2',
name: 'menu2',
component: () => import('/@/views/menu/menu2/index.vue'),
meta: {
title: '菜单2',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-caidan'
}
}
]
},
{
path: '/fun',
name: 'funIndex',
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/fun/tagsView',
meta: {
title: '功能',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-crew_feature'
},
children: [
{
path: '/fun/tagsView',
name: 'funTagsView',
component: () => import('/@/views/fun/tagsView/index.vue'),
meta: {
title: 'tagsView 操作',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'el-icon-thumb'
}
}
]
},
{
path: '/pages',
name: 'pagesIndex',
component: () => import('/@/views/pages/index.vue'),
meta: {
title: '页面',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-fuzhiyemian'
}
},
{
path: '/chart',
name: 'chartIndex',
component: () => import('/@/views/chart/index.vue'),
meta: {
title: '大数据图表',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-ico_shuju'
}
},
{
path: '/personal',
name: 'personal',
component: () => import('/@/views/personal/index.vue'),
meta: {
title: '个人中心',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-gerenzhongxin'
}
},
{
path: '/tools',
name: 'tools',
component: () => import('/@/views/tools/index.vue'),
meta: {
title: '工具类集合',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test'],
icon: 'iconfont icon-gongju'
}
},
{
path: '/link',
name: 'layoutLinkView',
component: () => import('/@/views/layout/routerView/parent.vue'),
meta: {
title: '外链',
isLink: 'https://element-plus.gitee.io/#/zh-CN/component/installation',
isHide: false,
isKeepAlive: false,
isAffix: false,
isIframe: false,
auth: ['admin'],
icon: 'iconfont icon-caozuo-wailian'
}
},
{
path: '/iframes',
name: 'layoutIfameView',
component: () => import('/@/views/layout/routerView/parent.vue'),
meta: {
title: '内嵌 iframe',
isLink: 'https://gitee.com/lyt-top/vue-admin-wonderful',
isHide: false,
isKeepAlive: true,
isAffix: true,
isIframe: true,
auth: ['admin'],
icon: 'iconfont icon-neiqianshujuchucun'
}
}]
}
]
// 定义静态路由
const staticRoutes: Array<RouteRecordRaw> = [
{
path: '/login',
name: 'login',
component: () => import('/@/views/login/index.vue'),
meta: {
title: '登陆'
}
},
{
path: '/404',
name: '404',
component: () => import('/@/views/error/404.vue'),
meta: {
title: '找不到此页面'
}
},
{
path: '/401',
name: '401',
component: () => import('/@/views/error/401.vue'),
meta: {
title: '没有权限'
}
},
{
path: '/:pathMatch(.*)',
name: 'pathMatch',
redirect: '/404',
meta: {
title: '页面找不到重定向'
}
}
]
// 添加静态路由
const router = createRouter({
history: createWebHashHistory(),
routes: staticRoutes
})
// 后端控制路由isRequestRoutes 为 true则开启后端控制路由
// console.log(store)
// console.log(dynamicRoutes)
// store.dispatch('setBackEndControlRoutes', 'admin')
export function getBackEndControlRoutes() {
getMenuTest().then((res: any) => {
console.log(JSON.parse(JSON.stringify(res)));
console.log(backEndRouter(res.data))
dynamicRoutes[0].children = backEndRouter(res.data)
console.log(dynamicRoutes)
// initAllFun()
store.dispatch('setUserInfos')
setAddRoute() // 添加动态路由
setFilterMenu() // 过滤权限菜单
setCacheTagsViewRoutes() // 添加 keepAlive 缓存
console.log(router.getRoutes())
});
}
// 后端控制路由,递归处理每一项 `component` 中的路径
export function backEndRouter(routes: any) {
if (!routes) return false
return routes.map((v: any) => {
// if (v.component) v.component = () => import(`/@/views/${v.component}.vue`)
if (v.component) v.component = () => import(v.component)
if (v.children) v.children = backEndRouter(v.children)
return v
})
}
// 多级嵌套数组处理成一维数组
export function formatFlatteningRoutes(arr: any) {
if (arr.length < 0) return false
for (let i = 0; i < arr.length; i++) {
if (arr[i].children) {
arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1))
}
}
return arr
}
// 多级嵌套数组处理后的一维数组,再处理成 `定义动态路由` 的格式
// 只保留二级也就是二级以上全部处理成只有二级keep-alive 支持二级缓存
// isKeepAlive 处理 `name` 值,进行缓存。顶级关闭,全部不缓存
export function formatTwoStageRoutes(arr: any) {
if (arr.length < 0) return false
const newArr: any = []
const cacheList: Array<string> = []
arr.map((v: any) => {
if (v.path === '/') {
newArr.push({ component: v.component, name: v.name, path: v.path, redirect: v.redirect, meta: v.meta, children: [] })
} else {
newArr[0].children.push({ ...v })
if (newArr[0].meta.isKeepAlive && v.meta.isKeepAlive) {
cacheList.push(v.name)
store.dispatch('setCacheKeepAlive', cacheList)
}
}
})
return newArr
}
// 缓存多级嵌套数组处理后的一维数组(tagsView、菜单搜索中使用未过滤隐藏的(isHide))
export function setCacheTagsViewRoutes() {
// 先处理有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
let authsRoutes = setFilterMenuFun(dynamicRoutes, store.state.userInfos.authPageList)
// 添加到 vuex setTagsViewRoutes 中
store.dispatch('setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(authsRoutes))[0].children)
}
// 获取当前用户的权限去比对路由表,用于左侧菜单/横向菜单的显示
export function setFilterMenu() {
store.dispatch("setRoutes", setFilterMenuFun(dynamicRoutes[0].children, store.state.userInfos.authPageList))
}
// 判断路由 auth 中是否包含当前登录用户权限字段
export function hasAuth(auths: any, route: any) {
if (route.meta && route.meta.auth) return auths.some((auth: any) => route.meta.auth.includes(auth))
else return true
}
// 递归过滤有权限的路由
export function setFilterMenuFun(routes: any, auth: any) {
const menu: any = []
routes.map((route: any) => {
const item = { ...route }
if (hasAuth(auth, item)) {
if (item.children) item.children = setFilterMenuFun(item.children, auth)
menu.push(item)
}
})
return menu
}
// 获取当前用户的权限去比对路由表,用于动态路由的添加
export function setFilterRoute() {
let filterRoute: any = []
formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children.map((route: any) => {
route.meta.auth.map((metaAuth: any) => {
store.state.userInfos.authPageList.map((auth: any) => {
if (metaAuth === auth) filterRoute.push({ ...route })
})
})
})
return filterRoute
}
// 比对后的路由表,进行重新赋值
export function setFilterRouteEnd() {
let filterRouteEnd: any = formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))
filterRouteEnd[0].children = setFilterRoute()
return filterRouteEnd
}
// 添加动态路由
export function setAddRoute() {
setFilterRouteEnd().map((route: any) => {
router.addRoute(route as RouteRecordRaw)
})
}
// 删除/重置路由
export function resetRoute() {
setFilterRouteEnd().map((route: any) => {
const { name } = route
router.hasRoute(name) && router.removeRoute(name)
})
}
// 初始化方法,防止刷新时丢失
export function initAllFun() {
const token = getSession('token')
if (!token) return false
store.dispatch('setUserInfos')
setAddRoute() // 添加动态路由
setFilterMenu() // 过滤权限菜单
setCacheTagsViewRoutes() // 添加 keepAlive 缓存
}
// 初始化方法执行
if (!store.state.themeConfig.isRequestRoutes) initAllFun()
// 后端控制路由isRequestRoutes 为 true则开启后端控制路由
if (store.state.themeConfig.isRequestRoutes) getBackEndControlRoutes()
// 路由加载前
router.beforeEach((to, from, next) => {
document.title = `${to.meta.title} - vue-admin-wonderful-next` || 'vue-admin-wonderful-next'
NProgress.configure({ showSpinner: false })
NProgress.start()
const token = getSession('token')
if (to.path === '/login' && !token) {
next()
NProgress.done()
} else {
if (!token) {
next('/login')
clearSession()
resetRoute()
NProgress.done()
} else if (token && to.path === '/login') {
next('/home')
NProgress.done()
} else {
next();
}
}
})
// 路由加载后
router.afterEach(() => {
NProgress.done()
})
// 导出路由
export default router