import { createRouter, createWebHashHistory } from "vue-router"; import { ElNotification } from "element-plus"; import config from "@/config"; import NProgress from "nprogress"; import "nprogress/nprogress.css"; import tool from "@/utils/tool"; import systemRouter from "./systemRouter"; import { beforeEach, afterEach } from "./scrollBehavior"; import { t2 } from "@/utils/index"; // 匹配views里面所有的.vue文件 const modules = import.meta.glob("./../views/**/*.vue"); const otherModules = { 404: () => import("../layout/other/404.vue"), empty: () => import("../layout/other/empty.vue"), }; //系统路由 const routes = systemRouter; //系统特殊路由 const routes_404 = { path: "/:pathMatch(.*)*", hidden: true, component: otherModules["404"], }; let routes_404_r = () => {}; const router = createRouter({ history: createWebHashHistory(), routes, }); //设置标题 document.title = tool.data.get("APP_NAME"); //判断是否已加载过动态/静态路由 var isGetRouter = false; router.beforeEach(async (to, from, next) => { NProgress.start(); //动态标题 document.title = to.meta.title ? `${t2(to.meta.code) || to.meta.title} - ` + (tool.data.get("APP_NAME") || config.APP_NAME) : tool.data.get("APP_NAME") || config.APP_NAME; let token = tool.data.get(config.TOKEN); if (to.path === "/login") { //删除路由(替换当前layout路由) router.addRoute(routes[0]); //删除路由(404) routes_404_r(); isGetRouter = false; next(); return false; } if (!token) { next({ path: "/login", }); return false; } //整页路由处理 if (to.meta.fullpage) { to.matched = [to.matched[to.matched.length - 1]]; } //加载动态/静态路由 if (!isGetRouter) { let apiMenu = tool.data.get("MENU") || []; var menuRouter = filterAsyncRouter(apiMenu); menuRouter = flatAsyncRoutes(menuRouter); menuRouter.forEach((item) => { router.addRoute("layout", item); }); routes_404_r = router.addRoute(routes_404); if (to.matched.length == 0) { router.push(to.fullPath); } isGetRouter = true; } beforeEach(to, from); next(); }); router.afterEach((to, from) => { afterEach(to, from); NProgress.done(); }); router.onError((error) => { NProgress.done(); ElNotification.error({ title: "路由错误", message: error.message, }); }); //入侵追加自定义方法、对象 router.getMenu = () => { var apiMenu = tool.data.get("MENU") || []; return apiMenu; }; //转换 function filterAsyncRouter(routerMap) { const accessedRouters = []; routerMap.forEach((item) => { item.meta = item.meta ? item.meta : {}; //处理外部链接特殊路由 if (item.meta.target == "iframe") { item.meta.url = item.path; item.path = `/i/${item.meta.id}`; item.component = undefined; } else { item.component = item.path; } if (item.path == undefined) { item.path = ""; } //MAP转路由对象 var route = { path: item.path, name: item.path .replace(/^\//g, "") .replace(/[/]/g, "-") .replace(/[?]/g, "-") .replace(/&/g, "-") .replace(/=/g, "-") + item.meta.id, meta: item.meta, redirect: item.redirect, children: item.children ? filterAsyncRouter(item.children) : null, component: loadComponent(item.component), }; accessedRouters.push(route); }); return accessedRouters; } function loadComponent(component) { if (component) { for (const path in modules) { const dir = path.split("views")[1].split(".vue")[0]; if (dir === component || dir === component + "/index") { return () => modules[path](); } } } return otherModules["empty"]; } // function loadComponent(component) { // if (component) { // return () => modules[`./../views${component}.vue`](); // } else { // return otherModules["empty"]; // } // } //路由扁平化 function flatAsyncRoutes(routes, breadcrumb = []) { let res = []; routes.forEach((route) => { const tmp = { ...route }; if (tmp.children && tmp.children.length > 0) { let childrenBreadcrumb = [...breadcrumb]; childrenBreadcrumb.push(route); let tmpRoute = { ...route }; tmpRoute.meta.breadcrumb = childrenBreadcrumb; delete tmpRoute.children; if (tmpRoute.path) { res.push(tmpRoute); } let childrenRoutes = flatAsyncRoutes( tmp.children, childrenBreadcrumb ); childrenRoutes.map((item) => { if (item.path) { res.push(item); } }); } else { let tmpBreadcrumb = [...breadcrumb]; tmpBreadcrumb.push(tmp); tmp.meta.breadcrumb = tmpBreadcrumb; if (tmp.path) { res.push(tmp); } } }); return res; } export default router;