Files
mayfly-go/mayfly_go_web/src/router/index.ts

242 lines
7.8 KiB
TypeScript
Raw Normal View History

import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { clearSession, getToken } from '@/common/utils/storage';
import { templateResolve } from '@/common/utils/string';
2023-03-15 11:41:03 +08:00
import { NextLoading } from '@/common/utils/loading';
import { dynamicRoutes, staticRoutes, pathMatch } from './route';
import openApi from '@/common/openApi';
import syssocket from '@/common/syssocket';
2023-03-15 11:41:03 +08:00
import pinia from '@/store/index';
import { useThemeConfig } from '@/store/themeConfig';
import { useUserInfo } from '@/store/userInfo';
import { useRoutesList } from '@/store/routesList';
import { useKeepALiveNames } from '@/store/keepAliveNames';
/**
* .vue.tsx
* @method import.meta.glob
* @link https://cn.vitejs.dev/guide/features.html#json
*/
2023-12-27 19:55:36 +08:00
const viewsModules: Record<string, Function> = import.meta.glob(['../views/**/*.{vue,tsx}']);
2023-03-15 11:41:03 +08:00
const dynamicViewsModules: Record<string, Function> = Object.assign({}, { ...viewsModules });
// 添加静态路由
const router = createRouter({
history: createWebHashHistory(),
routes: staticRoutes,
});
// 前端控制路由:初始化方法,防止刷新时丢失
export function initAllFun() {
const token = getToken(); // 获取浏览器缓存 token 值
if (!token) {
// 无 token 停止执行下一步
return false;
}
2023-03-15 11:41:03 +08:00
useUserInfo().setUserInfo({});
router.addRoute(pathMatch); // 添加404界面
resetRoute(); // 删除/重置路由
2023-09-26 17:38:52 +08:00
router.addRoute(dynamicRoutes[0]);
// 过滤权限菜单
2023-09-26 17:38:52 +08:00
useRoutesList().setRoutesList(dynamicRoutes[0].children);
}
// 后端控制路由:执行路由数据初始化
export async function initBackEndControlRoutesFun() {
const token = getToken(); // 获取浏览器缓存 token 值
if (!token) {
// 无 token 停止执行下一步
return false;
}
2023-03-15 11:41:03 +08:00
useUserInfo().setUserInfo({});
// 获取路由
let menuRoute = await getBackEndControlRoutes();
2023-09-26 17:38:52 +08:00
const cacheList: Array<string> = [];
// 处理路由component
dynamicRoutes[0].children = backEndRouterConverter(menuRoute, (router: any) => {
// 可能为false时不存在isKeepAlive属性
if (!router.meta.isKeepAlive) {
router.meta.isKeepAlive = false;
}
if (router.meta.isKeepAlive) {
cacheList.push(router.name);
}
});
useKeepALiveNames().setCacheKeepAlive(cacheList);
// 添加404界面
router.addRoute(pathMatch);
resetRoute(); // 删除/重置路由
2023-09-26 17:38:52 +08:00
router.addRoute(dynamicRoutes[0] as unknown as RouteRecordRaw);
useRoutesList().setRoutesList(dynamicRoutes[0].children);
}
// 后端控制路由isRequestRoutes 为 true则开启后端控制路由
export async function getBackEndControlRoutes() {
try {
const menuAndPermission = await openApi.getPermissions();
// 赋值权限码,用于控制按钮等
useUserInfo().userInfo.permissions = menuAndPermission.permissions;
return menuAndPermission.menus;
} catch (e: any) {
console.error(e);
return [];
}
}
2023-09-26 17:38:52 +08:00
type RouterConvCallbackFunc = (router: any) => void;
// 后端控制路由,后端返回路由 转换为vue route
2023-09-26 17:38:52 +08:00
export function backEndRouterConverter(routes: any, callbackFunc: RouterConvCallbackFunc = null as any, parentPath: string = '/') {
if (!routes) return;
return routes.map((item: any) => {
if (!item.meta) {
return item;
}
// 将json字符串的meta转为对象
item.meta = JSON.parse(item.meta);
// 将meta.comoponet 解析为route.component
if (item.meta.component) {
item.component = dynamicImport(dynamicViewsModules, item.meta.component);
delete item.meta['component'];
}
2023-12-27 19:55:36 +08:00
let path = item.code;
// 如果不是以 / 开头,则路径需要拼接父路径
if (!path.startsWith('/')) {
path = parentPath + '/' + path;
}
item.path = path;
delete item['code'];
// route.meta.title == resource.name
item.meta.title = item.name;
delete item['name'];
// route.name == resource.meta.routeName
item.name = item.meta.routeName;
delete item.meta['routeName'];
// route.redirect == resource.meta.redirect
if (item.meta.redirect) {
item.redirect = item.meta.redirect;
delete item.meta['redirect'];
}
2023-09-26 17:38:52 +08:00
// 存在回调,则执行回调
callbackFunc && callbackFunc(item);
item.children && backEndRouterConverter(item.children, callbackFunc, item.path);
return item;
});
}
2023-03-15 11:41:03 +08:00
/**
* component
* @param dynamicViewsModules .vue.tsx
* @param component component
* @returns component
*/
export function dynamicImport(dynamicViewsModules: Record<string, Function>, component: string) {
const keys = Object.keys(dynamicViewsModules);
const matchKeys = keys.filter((key) => {
const k = key.replace(/..\/views|../, '');
return k.startsWith(`${component}`) || k.startsWith(`/${component}`);
});
2023-12-27 19:55:36 +08:00
if (matchKeys?.length === 1) {
2023-12-27 19:55:36 +08:00
return dynamicViewsModules[matchKeys[0]];
}
2023-12-27 19:55:36 +08:00
if (matchKeys?.length > 1) {
2023-12-27 19:55:36 +08:00
console.error('匹配到多个相似组件路径, 可添加后缀.vue或.tsx进行区分或者重命名组件名, 请调整...', matchKeys);
return null;
}
2023-12-27 19:55:36 +08:00
console.error(`未匹配到[${component}]组件名对应的组件文件`);
return null;
2023-03-15 11:41:03 +08:00
}
// 删除/重置路由
export function resetRoute() {
2023-03-15 11:41:03 +08:00
useRoutesList().routesList.forEach((route: any) => {
const { name } = route;
router.hasRoute(name) && router.removeRoute(name);
});
}
export async function initRouter() {
2023-09-23 22:52:05 +08:00
NextLoading.start(); // 界面 loading 动画开始执行
try {
// 初始化方法执行
const { isRequestRoutes } = useThemeConfig(pinia).themeConfig;
if (!isRequestRoutes) {
// 未开启后端控制路由
initAllFun();
} else if (isRequestRoutes) {
// 后端控制路由isRequestRoutes 为 true则开启后端控制路由
await initBackEndControlRoutesFun();
}
} finally {
NextLoading.done();
}
}
let loadRouter = false;
// 路由加载前
router.beforeEach(async (to, from, next) => {
NProgress.configure({ showSpinner: false });
if (to.meta.title) NProgress.start();
// 如果有标题参数,则再原标题后加上参数来区别
2023-09-26 17:38:52 +08:00
if (to.meta.titleRename && to.meta.title) {
to.meta.title = templateResolve(to.meta.title as string, to.query);
}
const token = getToken();
2023-07-24 22:36:07 +08:00
if ((to.path === '/login' || to.path == '/oauth2/callback') && !token) {
next();
NProgress.done();
2022-05-17 20:23:08 +08:00
return;
}
if (!token) {
next(`/login?redirect=${to.path}`);
clearSession();
resetRoute();
NProgress.done();
syssocket.destory();
2022-05-17 20:23:08 +08:00
return;
}
if (token && to.path === '/login') {
next('/');
NProgress.done();
return;
}
// 终端不需要连接系统websocket消息
if (to.path != '/machine/terminal') {
syssocket.init();
2022-05-17 20:23:08 +08:00
}
// 不存在路由避免刷新页面找不到路由并且未加载过避免token过期导致获取权限接口报权限不足无限获取则重新初始化路由
2023-12-27 19:55:36 +08:00
if (useRoutesList().routesList?.length == 0 && !loadRouter) {
await initRouter();
loadRouter = true;
next({ path: to.path, query: to.query });
} else {
2022-05-17 20:23:08 +08:00
next();
}
});
// 路由加载后
router.afterEach(() => {
NProgress.done();
});
// 导出路由
export default router;