import { adminMenus } from '@/api/system/menu'; import { constantRouterIcon } from './router-icons'; import { RouteRecordRaw } from 'vue-router'; import { Layout, ParentLayout } from '@/router/constant'; import type { AppRouteRecordRaw } from '@/router/types'; import { DashboardOutlined, TableOutlined } from '@vicons/antd'; import { renderIcon } from '@/utils/index'; const Iframe = () => import('@/views/iframe/index.vue'); const LayoutMap = new Map Promise>(); LayoutMap.set('LAYOUT', Layout); LayoutMap.set('IFRAME', Iframe); /** * 格式化 后端 结构信息并递归生成层级路由表 * @param routerMap * @param parent * @returns {*} */ export const routerGenerator = (routerMap, parent?): any[] => { return routerMap.map((item) => { const names = item.target==2?item.component:item.path.replaceAll('/','') item.meta = { title:item.parentId==0 && item.children.length==0?'':item.name, icon:item.icon, sort:item.sort, permissions:item.permission, hidden: item.hide?true:false, isRoot:item.parentId==0 && item.children.length==0?true:false, alwaysShow: item.parentId==0 && item.children.length==0?true:false, frameSrc: item.target==1?item.component:'', } let components = '' if(item.parentId==0 && item.children.length==0) { components ='LAYOUT' } else if(item.target==0) { components = item.component } else if(item.target==1) { components ='IFRAME' } const currentRouter: any = { // 路由地址 动态拼接生成如 /dashboard/workplace path: item.target!=2?item.path:'', // 路由名称,建议唯一 name: names, // 该路由对应页面的 组件 component: components, // meta: 页面标题, 菜单图标, 页面权限(供指令权限用,可去掉) meta: { ...item.meta, label: item.meta.title, icon: item.meta.icon || null, permissions: item.meta.permissions || null, }, }; // 为了防止出现后端返回结果不规范,处理有可能出现拼接出两个 反斜杠 // currentRouter.path = currentRouter.path.replace('//', '/'); // 重定向 item.redirect && (currentRouter.redirect = item.redirect); // 是否有子菜单,并递归处理 if (item.children && item.children.length > 0) { //如果未定义 redirect 默认第一个子路由为 redirect !item.redirect && (currentRouter.redirect = `${item.children[0].path}`); // Recursion currentRouter.children = routerGenerator(item.children, currentRouter); } else { if(item.parentId==0 && item.children.length==0) { currentRouter.children =[] if(item.target==1 && (/http(s)?:/.test(item.component))){ currentRouter.children.push({ path: item.path, name: names, meta: { title: item.name, frameSrc: item.component, }, component: 'IFRAME', }) } else { currentRouter.children.push({ path: item.path, name: names, meta: { title: item.name, activeMenu: names, }, component: item.component, }) } } } return currentRouter; }); }; /** * 动态生成菜单 * @returns {Promise} */ export const generatorDynamicRouter = (): Promise => { return new Promise((resolve, reject) => { adminMenus() .then((result) => { const routeList = routerGenerator(result); asyncImportRoute(routeList); resolve(routeList); }) .catch((err) => { reject(err); }); }); }; /** * 查找views中对应的组件文件 * */ let viewsModules: Record Promise>; export const asyncImportRoute = (routes: AppRouteRecordRaw[] | undefined): void => { viewsModules = viewsModules || import.meta.glob('../views/**/*.{vue,tsx}'); if (!routes) return; routes.forEach((item) => { if (!item.component && item.meta?.frameSrc) { item.component = 'IFRAME'; } const { component, name } = item; const { children } = item; if (component) { const layoutFound = LayoutMap.get(component as string); if (layoutFound) { item.component = layoutFound; } else { item.component = dynamicImport(viewsModules, component as string); } } else if (name) { item.component = Layout; } children && asyncImportRoute(children); }); }; /** * 动态导入 * */ export const dynamicImport = ( viewsModules: Record Promise>, component: string, ) => { const keys = Object.keys(viewsModules); const matchKeys = keys.filter((key) => { let k = key.replace('../views', ''); const lastIndex = k.lastIndexOf('.'); k = k.substring(0, lastIndex); return k === component; }); if (matchKeys?.length === 1) { const matchKey = matchKeys[0]; return viewsModules[matchKey]; } if (matchKeys?.length > 1) { console.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; } }; /** * 查找第一个路由 * */ export const findFirstRoutePath = (routes)=>{ return routes.length > 0?(routes[0].redirect?routes[0].redirect:routes[0].path):'' }