vue-vben-admin/src/router/helper/routeHelper.ts

108 lines
3.2 KiB
TypeScript
Raw Normal View History

2020-12-03 21:49:32 +08:00
import type { AppRouteModule, AppRouteRecordRaw } from '/@/router/types';
import type { RouteLocationNormalized, RouteRecordNormalized } from 'vue-router';
import { getParentLayout, LAYOUT } from '/@/router/constant';
import { cloneDeep } from 'lodash-es';
2021-01-09 23:28:52 +08:00
import { warn } from '/@/utils/log';
2020-12-03 21:49:32 +08:00
2020-12-15 14:59:22 +08:00
export type LayoutMapKey = 'LAYOUT';
const LayoutMap = new Map<LayoutMapKey, () => Promise<typeof import('*.vue')>>();
let dynamicViewsModules: Record<
string,
() => Promise<{
[key: string]: any;
}>
>;
2021-01-10 20:44:39 +08:00
2020-12-03 21:49:32 +08:00
// 动态引入
function asyncImportRoute(routes: AppRouteRecordRaw[] | undefined) {
// TODO It may be a bug in Vite. When the conditions are not established, the dynamically imported files will still be packaged in.
if (!__DYNAMIC_IMPORT__) {
dynamicViewsModules = {};
} else {
dynamicViewsModules = dynamicViewsModules || import.meta.glob('../../views/**/*.{vue,tsx}');
}
2020-12-03 21:49:32 +08:00
if (!routes) return;
routes.forEach((item) => {
const { component, name } = item;
const { children } = item;
if (component) {
2021-01-09 23:28:52 +08:00
item.component = dynamicImport(dynamicViewsModules, component as string);
2020-12-03 21:49:32 +08:00
} else if (name) {
item.component = getParentLayout(name);
}
children && asyncImportRoute(children);
});
}
2021-01-10 20:44:39 +08:00
function dynamicImport(
dynamicViewsModules: Record<
string,
() => Promise<{
[key: string]: any;
}>
>,
component: string
) {
const keys = Object.keys(dynamicViewsModules);
2021-01-09 23:28:52 +08:00
const matchKeys = keys.filter((key) => {
let k = key.replace('../../views', '');
const lastIndex = k.lastIndexOf('.');
k = k.substring(0, lastIndex);
return k === component;
2021-01-09 23:28:52 +08:00
});
if (matchKeys?.length === 1) {
const matchKey = matchKeys[0];
2021-01-10 20:44:39 +08:00
return dynamicViewsModules[matchKey];
2021-01-09 23:28:52 +08:00
}
if (matchKeys?.length > 1) {
warn(
'Please do not create `.vue` and `.TSX` files with the same file name in the same hierarchical directory under the views folder. This will cause dynamic introduction failure'
);
return;
}
}
2020-12-03 21:49:32 +08:00
// Turn background objects into routing objects
export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModule[]): T[] {
2020-12-15 14:59:22 +08:00
LayoutMap.set('LAYOUT', LAYOUT);
2020-12-03 21:49:32 +08:00
routeList.forEach((route) => {
if (route.component) {
if ((route.component as string).toUpperCase() === 'LAYOUT') {
route.component = LayoutMap.get(route.component as LayoutMapKey);
2020-12-03 21:49:32 +08:00
} else {
route.children = [cloneDeep(route)];
route.component = LAYOUT;
route.name = `${route.name}Parent`;
route.path = '';
const meta = route.meta || {};
meta.single = true;
meta.affix = false;
route.meta = meta;
}
}
route.children && asyncImportRoute(route.children);
});
return (routeList as unknown) as T[];
}
// Return to the new routing structure, not affected by the original example
export function getRoute(route: RouteLocationNormalized): RouteLocationNormalized {
if (!route) return route;
const { matched, ...opt } = route;
return {
...opt,
matched: (matched
? matched.map((item) => ({
meta: item.meta,
name: item.name,
path: item.path,
}))
: undefined) as RouteRecordNormalized[],
};
}