refactor: 重构backMenuToVbenMenu

This commit is contained in:
dap
2024-10-20 12:39:00 +08:00
parent 86950953ff
commit 29ec264dcd

View File

@@ -19,6 +19,170 @@ import { localMenuList } from './routes/local';
const forbiddenComponent = () => import('#/views/_core/fallback/forbidden.vue');
const NotFoundComponent = () => import('#/views/_core/fallback/not-found.vue');
/**
* 后台路由转vben路由
* @param menuList 后台菜单
* @param parentPath 上级目录
* @returns vben路由
*/
function backMenuToVbenMenu(
menuList: Menu[],
parentPath = '',
): RouteRecordStringComponent[] {
const resultList: RouteRecordStringComponent[] = [];
menuList.forEach((menu) => {
// 根目录为菜单形式
// 固定有一个children children为当前菜单
if (menu.path === '/' && menu.children && menu.children.length === 1) {
if (!menu.children || !menu.children[0]) {
return;
}
// 需要处理根目录为内嵌的情况 不会带InnerLink
if (/^https?:\/\//.test(menu.children[0].path)) {
menu.children[0].component = 'InnerLink';
menu.children[0].path = menu.children[0].path
.replaceAll(/^https?:\/\//g, '')
.replaceAll('/#/', '')
.replaceAll('#', '')
.replaceAll(/[?&]/g, '');
}
// 取子路径作为父级路径
const path = menu.children[0].path;
// 取子菜单的meta作为当前菜单的meta
menu.meta = menu.children[0].meta;
// 由于在一级路由 父级路径需要加上/
menu.path = `/${path}`;
menu.component = 'RootMenu';
// 将子路径设置为''
menu.children[0].path = '';
}
// 外链: http开头 & 组件为Layout || ParentView
// 正则判断是否为http://或者https://开头
if (
/^https?:\/\//.test(menu.path) &&
(menu.component === 'Layout' || menu.component === 'ParentView')
) {
menu.component = 'Link';
}
// 内嵌iframe 组件为InnerLink
if (menu.meta?.link && menu.component === 'InnerLink') {
menu.component = 'IFrameView';
}
/**
* 拼接path
* menu.path为''(根目录路由) 则不拼接
*/
if (parentPath && menu.path) {
menu.path = `${parentPath}/${menu.path}`;
}
// 创建vben路由对象
const vbenRoute: RouteRecordStringComponent = {
component: menu.component,
meta: {
// 当前路由不在菜单显示 但是可以通过链接访问
// 不可访问的路由由后端控制隐藏(不返回对应路由)
hideInMenu: menu.hidden,
icon: menu.meta?.icon,
keepAlive: !menu.meta?.noCache,
title: menu.meta?.title,
},
name: menu.name,
path: menu.path,
};
// 添加路由参数信息
if (menu.query) {
try {
const query = JSON.parse(menu.query);
vbenRoute.meta && (vbenRoute.meta.query = query);
} catch {
console.error('错误的路由参数类型, 必须为[json]格式');
}
}
/**
* 处理不同组件
*/
switch (menu.component) {
/**
* iframe内嵌
*/
case 'IFrameView': {
vbenRoute.component = 'IFrameView';
if (vbenRoute.meta) {
vbenRoute.meta.iframeSrc = menu.meta.link;
}
/**
* 需要判断特殊情况 比如vue的hash是带#的
* 比如链接 aaa.com/#/bbb path会转换为 aaa/com/#/bbb
* 比如链接 aaa.com/?bbb=xxx
* 需要去除# 否则无法被添加到路由
*/
vbenRoute.path = vbenRoute.path
// 替换https:// 或者 http://
.replaceAll(/^https?:\/\//g, '')
.replaceAll('/#/', '')
.replaceAll('#', '')
.replaceAll(/[?&]/g, '');
break;
}
case 'Layout': {
vbenRoute.component = 'BasicLayout';
break;
}
/**
* 外链 新窗口打开
*/
case 'Link': {
if (vbenRoute.meta) {
vbenRoute.meta.link = menu.meta.link;
}
vbenRoute.component = 'BasicLayout';
break;
}
/**
* 三级以上菜单 父级component为ParentView
* 不能为layout 会套两层BasicLayout
*/
case 'ParentView': {
vbenRoute.component = '';
break;
}
/**
* 根目录菜单
*/
case 'RootMenu': {
if (vbenRoute.meta) {
vbenRoute.meta.hideChildrenInMenu = true;
}
vbenRoute.component = 'BasicLayout';
break;
}
/**
* 其他自定义组件 如system/user/index 拼接/
*/
default: {
vbenRoute.component = `/${menu.component}`;
break;
}
}
// children处理
if (menu.children && menu.children.length > 0) {
vbenRoute.children = backMenuToVbenMenu(menu.children, menu.path);
}
// 添加
resultList.push(vbenRoute);
});
return resultList;
}
async function generateAccess(options: GenerateMenuAndRoutesOptions) {
const pageMap: ComponentRecordType = import.meta.glob('../views/**/*.vue');
@@ -28,156 +192,6 @@ async function generateAccess(options: GenerateMenuAndRoutesOptions) {
NotFoundComponent,
};
/**
* 后台路由转vben路由
*
* todo 需要重构
* @param menuList 后台菜单
* @param parentPath 上级目录
* @returns vben路由
*/
function backMenuToVbenMenu(
menuList: Menu[],
parentPath = '',
): RouteRecordStringComponent[] {
const resultList: RouteRecordStringComponent[] = [];
menuList.forEach((menu) => {
// 根目录为菜单形式
// 固定有一个children children为当前菜单
if (menu.path === '/' && menu.children && menu.children.length === 1) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
menu.meta = menu.children[0]!.meta;
/**
* todo 先写死 后续再优化
*/
menu.path = '/root_menu';
menu.component = 'RootMenu';
}
// 外链: http开头 & 组件为Layout || ParentView
// 正则判断是否为http://或者https://开头
if (
/^https?:\/\//.test(menu.path) &&
(menu.component === 'Layout' || menu.component === 'ParentView')
) {
menu.component = 'Link';
}
// 内嵌iframe 组件为InnerLink
if (menu.meta?.link && menu.component === 'InnerLink') {
menu.component = 'IFrameView';
}
// path
if (parentPath) {
menu.path = `${parentPath}/${menu.path}`;
}
const vbenRoute: RouteRecordStringComponent = {
component: menu.component,
meta: {
// 当前路由不在菜单显示 但是可以通过链接访问
// 不可访问的路由由后端控制隐藏(不返回对应路由)
hideInMenu: menu.hidden,
icon: menu.meta?.icon,
keepAlive: !menu.meta?.noCache,
title: menu.meta?.title,
},
name: menu.name,
path: menu.path,
};
// 添加路由参数信息
if (menu.query) {
try {
const query = JSON.parse(menu.query);
vbenRoute.meta && (vbenRoute.meta.query = query);
} catch {
console.error('错误的路由参数类型, 必须为[json]格式');
}
}
/**
* 处理不同组件
*/
switch (menu.component) {
case 'Layout': {
vbenRoute.component = 'BasicLayout';
break;
}
/**
* iframe内嵌
*/
case 'IFrameView': {
vbenRoute.component = 'IFrameView';
if (vbenRoute.meta) {
vbenRoute.meta.iframeSrc = menu.meta.link;
}
/**
* 需要判断特殊情况 比如vue的hash是带#的
* 比如链接 aaa.com/#/bbb path会转换为 aaa/com/#/bbb
* 比如链接 aaa.com/?bbb=xxx
* 需要去除# 否则无法被添加到路由
*/
/**
* todo 不优雅 考虑别的方案
*/
if (vbenRoute.path.includes('/#/')) {
vbenRoute.path = vbenRoute.path.replace('/#/', '');
}
if (vbenRoute.path.includes('#')) {
vbenRoute.path = vbenRoute.path.replace('#', '');
}
if (vbenRoute.path.includes('?') || vbenRoute.path.includes('&')) {
vbenRoute.path = vbenRoute.path.replace('?', '');
vbenRoute.path = vbenRoute.path.replace('&', '');
}
break;
}
/**
* 外链 新窗口打开
*/
case 'Link': {
if (vbenRoute.meta) {
vbenRoute.meta.link = menu.meta.link;
}
vbenRoute.component = 'BasicLayout';
break;
}
/**
* 根目录菜单
*/
case 'RootMenu': {
if (vbenRoute.meta) {
vbenRoute.meta.hideChildrenInMenu = true;
}
vbenRoute.component = 'BasicLayout';
break;
}
/**
* 不能为layout 会套两层BasicLayout
*/
case 'ParentView': {
vbenRoute.component = '';
break;
}
/**
* 其他自定义组件 如system/user/index 拼接/
*/
default: {
vbenRoute.component = `/${menu.component}`;
break;
}
}
// children处理
if (menu.children && menu.children.length > 0) {
vbenRoute.children = backMenuToVbenMenu(menu.children, menu.path);
}
resultList.push(vbenRoute);
});
return resultList;
}
return await generateAccessible(preferences.app.accessMode, {
...options,
fetchMenuListAsync: async () => {