官网参考:https://router.vuejs.org/zh/guide/advanced/dynamic-routing.html
router/index.ts 配置代码,导出的router在main.ts中use即可。SystemDataStore.menus是用户登录后从后端获得的菜单数据。
router/index.ts 配置代码,导出的router在main.ts中use即可。SystemDataStore.menus是用户登录后从后端获得的菜单数据。
import { defineAsyncComponent } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import { type route_data, type route_meta } from '@/common/interfaces'
import pinia from '@/stores/store'
import { useSystemDataStore } from '@/stores/index'
import { getCookie } from '@/common/cookie'
// SystemDataStore 可以在本文件中随意使用
const SystemDataStore = useSystemDataStore(pinia);
//创建路由
const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'home',
// 重定向到login 重定向和别名:https://router.vuejs.org/zh/guide/essentials/redirect-and-alias.html
redirect: { name: 'login' },
},
{
path: '/login',
name: 'login',
component: () => import('../views/Login.vue'),
},
// 嵌套路由:https://router.vuejs.org/zh/guide/essentials/nested-routes.html
{
path: '/main',
name: 'main',
component: () => import('../views/Main.vue'),
},
//注释掉原路由配置,改为动态路由。
// {
// path: '/SysSetting',
// name: 'SysSetting',
// meta: { title: "系统设置" },
// children: [
// {
// path: '/SysSetting/UserMgr',
// name: 'UserMgr',
// meta: { title: "用户管理" },
// children: [
// {
// path: '/SysSetting/UserMgr/UserAccountMgr',
// name: 'UserAccountMgr',
// component: () => import('../views/SysSetting/UserMgr/UserAccountMgr.vue'),
// meta: { title: "用户账户管理" },
// },
// {
// path: '/SysSetting/UserMgr/UserAddressMgr',
// name: 'UserAddressMgr',
// component: () => import('../views/SysSetting/UserMgr/UserAddressMgr.vue'),
// meta: { title: "用户地址管理" },
// },
// ],
// },
// {
// path: '/SysSetting/RoleMgr',
// name: 'RoleMgr',
// component: () => import('../views/SysSetting/RoleMgr.vue'),
// meta: { title: "角色管理" },
// },
// {
// path: '/SysSetting/MenuMgr',
// name: 'MenuMgr',
// component: () => import('../views/SysSetting/MenuMgr.vue'),
// meta: { title: "菜单管理" },
// },
// {
// path: '/SysSetting/ProductionMgr',
// name: 'ProductionMgr',
// component: () => import('../views/SysSetting/ProductionMgr.vue'),
// meta: { title: "商品管理" },
// },
// ]
// },
//注释掉,动态路由在刷新的时候尚未添加到routes中,会造成404.
// 将匹配所有内容并将其放在 `$route.params.pathMatch` 下。
// { path: '/:pathMatch(.*)*', name: 'NotFound', component: () => import('../views/NotFound.vue') },
]
})
//导航守卫
router.beforeEach(async (to, from, next) => {
//用户登录后的token
let token = getCookie('XSRF-TOKEN');
//标记是否已经添加过动态路由true/false
let isLoadRouters = SystemDataStore.isLoadRouters;
if (inWhiteList(to.path)) {
next()
} else {
//用户已登录,加载用户信息、菜单信息、权限信息。
SystemDataStore.initData();
if (token && JSON.stringify(SystemDataStore.menus) !== '[]') {
if (isLoadRouters) {
// console.log('路由已添加,直接跳转到目标页面', router.getRoutes());
next()
} else {
//解决刷新页面空白
//console.log('重新加载路由,并跳转到目标页');
SystemDataStore.setIsLoadRouters(true)
//添加动态路由
await generateRoutes();
// console.log('路由添加完毕,从新进入路由。', router.getRoutes());
next({ ...to, replace: true })
}
} else {
// console.log('无登录信息,跳转到登录页');
SystemDataStore.setIsLoadRouters(false)
next(`/login`)
}
}
})
//动态添加路由
const generateRoutes = () => {
SystemDataStore.initData();
let _asyncRoutes = SystemDataStore.menus;
if (_asyncRoutes == null) {
return;
}
_asyncRoutes.forEach((menu1: any) => {
if (menu1.children.length > 0) {
menu1.children.forEach((menu2: any) => {
if (menu2.children.length > 0) {
menu2.children.forEach((menu3: any) => {
let _asyncRoute3: any = menuToRoute(menu3);
if (_asyncRoute3) {
router.addRoute(_asyncRoute3)
}
});
} else {
//二级
let _asyncRoute2: any = menuToRoute(menu2);
if (_asyncRoute2) {
router.addRoute(_asyncRoute2)
}
}
})
} else {
//一级
let _asyncRoute1: any = menuToRoute(menu1);
if (_asyncRoute1) {
router.addRoute(_asyncRoute1)
}
}
})
}
//将菜单转换成router可以识别的路由
const menuToRoute = (menu: any) => {
if (!menu.url) {
return null;
} else {
let routeCur: route_data = {
name: menu.name,
path: menu.url,
meta: {
title: menu.meta.title, idx: menu.meta.idx
},
children: [],
component: null
}
//方式1 动态组件 /* @vite-ignore */ 忽略vite警告
//vite语法不识别动态导入,报错:The above dynamic import cannot be analyzed by Vite.
routeCur.component = () => import(/* @vite-ignore */'../views' + menu.url + '.vue');
//方式2 动态组件
// routeCur.component = defineAsyncComponent(() => import(/* @vite-ignore */'../views' + menu.url + '.vue'))
return routeCur;
}
}
// 检查是否存在于免登陆白名单
const inWhiteList = (toPath: any) => {
const whiteList = ['/login']
let str = toPath.toLowerCase();
if (whiteList.indexOf(str) > -1) {
return true;
}
return false;
}
export default router
interfaces.ts
export interface sys_user { userId: number; userAvatar: string, userName: string; role: string; mobile: string; email: string; token: string; authsTime: string; expiresTime: string; } export interface sys_user_props { sysUserId: number; dialogVisible: boolean; mode: string; } export interface SysUserRoleWithAllRolesDto { sysRoleId: number; sysRoleName: string; checked: boolean; } export interface sys_role { sysRoleId: number; sysRoleName: string; sysRoleStatus: string; dialogVisible: boolean; mode: string; } export interface Tree { id: string label: string children?: Tree[] } export interface TreeSelectDto { defaultCheckedKeys: string[] defaultExpandedKeys: string[] data: Tree[] } export interface data_props { key: number | string; dialogVisible: boolean; mode: string; } export interface route_data { path: string; name: string; meta: route_meta; component: any; children: route_data[] } export interface route_meta { title: string; idx: string; } export interface select_items { value: string; label: string; }
浙公网安备 33010602011771号