|
|
@@ -15,33 +15,36 @@ const routes = systemRouter
|
|
|
|
|
|
// 系统特殊路由
|
|
|
const routes_404 = {
|
|
|
- path: "/:pathMatch(.*)*",
|
|
|
hidden: true,
|
|
|
- component: () => import(/* webpackChunkName: "404" */ "@/layout/other/404"),
|
|
|
+ path: "/:pathMatch(.*)*",
|
|
|
+ component: () => import("@/layout/other/404")
|
|
|
}
|
|
|
|
|
|
const routes_empty = {
|
|
|
- path: "/:pathMatch(.*)*",
|
|
|
hidden: true,
|
|
|
- component: () => import(/* webpackChunkName: "404" */ "@/layout/other/empty"),
|
|
|
+ path: "/:pathMatch(.*)*",
|
|
|
+ component: () => import("@/layout/other/empty")
|
|
|
}
|
|
|
|
|
|
-let routes_404_r = () => {}
|
|
|
-
|
|
|
const router = createRouter({
|
|
|
history: createWebHashHistory(),
|
|
|
routes: routes
|
|
|
})
|
|
|
|
|
|
// 判断是否已加载过动态/静态路由
|
|
|
-let isGetRouter = false;
|
|
|
+let isGetRouter = false
|
|
|
// FIX 多个API同时401时疯狂弹窗BUG
|
|
|
let MessageBox_401_show = false
|
|
|
+// 存储删除404路由的方法
|
|
|
+let removeNotFoundRoute = () => {}
|
|
|
+// 标记是否正在加载路由
|
|
|
+let isLoadingRouter = false
|
|
|
+let index = 0
|
|
|
|
|
|
router.beforeEach(async (to, from, next) => {
|
|
|
NProgress.start()
|
|
|
// 动态标题
|
|
|
- document.title = to.meta.title ? `${to.meta.title} - ${config.APP_NAME}` : `${config.APP_NAME}`
|
|
|
+ document.title = to.meta.title ? `${to.meta.title} - ${config.APP_NAME}` : config.APP_NAME
|
|
|
|
|
|
let token = tool.cookie.get("MES_TOKEN")
|
|
|
|
|
|
@@ -49,7 +52,7 @@ router.beforeEach(async (to, from, next) => {
|
|
|
// 删除路由(替换当前layout路由)
|
|
|
router.addRoute(routes[0])
|
|
|
// 删除路由(404)
|
|
|
- routes_404_r()
|
|
|
+ removeNotFoundRoute()
|
|
|
isGetRouter = false
|
|
|
if (token) next(from.fullPath)
|
|
|
else {
|
|
|
@@ -69,77 +72,102 @@ router.beforeEach(async (to, from, next) => {
|
|
|
|
|
|
// 加载动态/静态路由
|
|
|
if (!isGetRouter) {
|
|
|
- const apiMenu = await api.system.menu.build()
|
|
|
- if (!apiMenu.length) {
|
|
|
- if (!MessageBox_401_show) {
|
|
|
- MessageBox_401_show = true;
|
|
|
- ElMessageBox.confirm("当前用户无任何菜单权限,请联系系统管理员", "无权限访问", {
|
|
|
- type: "error",
|
|
|
- showClose: false,
|
|
|
- closeOnPressEscape: false,
|
|
|
- closeOnClickModal: false,
|
|
|
- center: true,
|
|
|
- showCancelButton: false,
|
|
|
- beforeClose: (action, instance, done) => {
|
|
|
- MessageBox_401_show = false
|
|
|
- done()
|
|
|
- }
|
|
|
- }).then(() => {
|
|
|
- tool.cookie.remove("MES_TOKEN")
|
|
|
- location.reload() // 为了重新实例化vue-router对象 避免bug
|
|
|
- }).catch(() => {})
|
|
|
+ const response = await loadDynamicRoutes()
|
|
|
+
|
|
|
+ if (response !== "success") {
|
|
|
+ if (response === "NoPermission") {
|
|
|
+ removeNotFoundRoute = router.addRoute(routes_empty)
|
|
|
+ await handleNoPermission()
|
|
|
}
|
|
|
-
|
|
|
- routes_404_r = router.addRoute(routes_empty);
|
|
|
- } else {
|
|
|
- const zeroMenu = XEUtils.filter(mapAsyncMenu(apiMenu), item => item.type == 0)
|
|
|
- tool.data.set("MENU", [...userRoutes, ...zeroMenu])
|
|
|
-
|
|
|
- const menuRouter = XEUtils.mapTree([...userRoutes, ...zeroMenu], item => {
|
|
|
- return {
|
|
|
- ...XEUtils.omit(item, "component"),
|
|
|
- [item.component ? "component" : "redirect"]: item.component ? loadComponent(item.component) : XEUtils.get(XEUtils.first(item.children), "path", "")
|
|
|
- }
|
|
|
- })
|
|
|
- XEUtils.arrayEach(XEUtils.toTreeArray(menuRouter), item => router.addRoute("layout", item))
|
|
|
- routes_404_r = router.addRoute(routes_404)
|
|
|
- !to.matched.length && router.push(to.fullPath);
|
|
|
+ next()
|
|
|
+ return
|
|
|
}
|
|
|
|
|
|
- isGetRouter = true;
|
|
|
+ isGetRouter = true
|
|
|
+ if (!to.matched.length) router.push(to.fullPath)
|
|
|
+ else next()
|
|
|
}
|
|
|
|
|
|
beforeEach(to, from)
|
|
|
- next();
|
|
|
-});
|
|
|
+ next()
|
|
|
+})
|
|
|
|
|
|
router.afterEach((to, from) => {
|
|
|
- afterEach(to, from);
|
|
|
- NProgress.done();
|
|
|
-});
|
|
|
+ afterEach(to, from)
|
|
|
+ NProgress.done()
|
|
|
+})
|
|
|
|
|
|
router.onError(error => {
|
|
|
- NProgress.done();
|
|
|
- ElNotification.error({
|
|
|
- title: "路由错误",
|
|
|
- message: error.message
|
|
|
- });
|
|
|
-
|
|
|
- // const pattern = /Loading chunk (\d)+ failed/g;
|
|
|
- // const isChunkLoadFailed = error.message.match(pattern);
|
|
|
- // const targetPath = router.history.pending.fullPath;
|
|
|
+ NProgress.done()
|
|
|
+ ElNotification.error({ title: "路由错误", message: error.message })
|
|
|
+
|
|
|
+ // const pattern = /Loading chunk (\d)+ failed/g
|
|
|
+ // const isChunkLoadFailed = error.message.match(pattern)
|
|
|
+ // const targetPath = router.history.pending.fullPath
|
|
|
// if (isChunkLoadFailed) {
|
|
|
- // router.replace(targetPath);
|
|
|
+ // router.replace(targetPath)
|
|
|
// }
|
|
|
-});
|
|
|
+})
|
|
|
+
|
|
|
+// 封装加载动态路由
|
|
|
+async function loadDynamicRoutes() {
|
|
|
+ if (isLoadingRouter) return "loading"
|
|
|
+ isLoadingRouter = true
|
|
|
+
|
|
|
+ try {
|
|
|
+ const apiMenu = await api.system.menu.build()
|
|
|
+ if (!XEUtils.isArray(apiMenu) || apiMenu.length === 0) return "NoPermission"
|
|
|
+
|
|
|
+ const zeroMenu = XEUtils.filter(mapAsyncMenu(apiMenu), item => item.type == 0)
|
|
|
+ tool.data.set("MENU", [...userRoutes, ...zeroMenu])
|
|
|
+
|
|
|
+ const menuRouter = XEUtils.mapTree([...userRoutes, ...zeroMenu], item => {
|
|
|
+ return {
|
|
|
+ ...XEUtils.omit(item, "component"),
|
|
|
+ [item.component ? "component" : "redirect"]: item.component ? loadComponent(item.component) : XEUtils.get(XEUtils.first(item.children), "path", "")
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ XEUtils.arrayEach(XEUtils.toTreeArray(menuRouter), item => router.addRoute("layout", item))
|
|
|
+ removeNotFoundRoute = router.addRoute(routes_404)
|
|
|
+ return "success"
|
|
|
+ } catch (error) {
|
|
|
+ return "error"
|
|
|
+ } finally {
|
|
|
+ isLoadingRouter = false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 处理401无权限
|
|
|
+async function handleNoPermission() {
|
|
|
+ if (MessageBox_401_show) return
|
|
|
+ MessageBox_401_show = true
|
|
|
+
|
|
|
+ try {
|
|
|
+ await ElMessageBox.confirm("当前用户无任何菜单权限,请联系系统管理员", "无权限访问", {
|
|
|
+ type: "error",
|
|
|
+ center: true,
|
|
|
+ showClose: false,
|
|
|
+ closeOnPressEscape: false,
|
|
|
+ closeOnClickModal: false,
|
|
|
+ showCancelButton: false
|
|
|
+ })
|
|
|
+
|
|
|
+ tool.cookie.remove("MES_TOKEN")
|
|
|
+ await router.push({ path: "/login", replace: true })
|
|
|
+ } catch (error) {
|
|
|
+ } finally {
|
|
|
+ MessageBox_401_show = false
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
function mapPath(path) {
|
|
|
- return XEUtils.startsWith(path, "/") ? path : `/${path}`;
|
|
|
+ return XEUtils.startsWith(path, "/") ? path : `/${path}`
|
|
|
}
|
|
|
|
|
|
// 转换
|
|
|
function mapAsyncMenu(menus) {
|
|
|
- XEUtils.arrayEach(menus, item => item.path = mapPath(item.path));
|
|
|
+ XEUtils.arrayEach(menus, item => item.path = mapPath(item.path))
|
|
|
return XEUtils.mapTree(XEUtils.toArrayTree(menus, { parentKey: "pid", sortKey: "menuSort" }), item => {
|
|
|
return {
|
|
|
name: item.title,
|
|
|
@@ -153,11 +181,8 @@ function mapAsyncMenu(menus) {
|
|
|
}
|
|
|
|
|
|
function loadComponent(component) {
|
|
|
- if (component) {
|
|
|
- return () => import(/* webpackChunkName: "[request]" */ `@/views/${component}`)
|
|
|
- } else {
|
|
|
- return () => import(`@/layout/other/empty`)
|
|
|
- }
|
|
|
+ if (component) return () => import(`@/views/${component}`)
|
|
|
+ else return () => import(`@/layout/other/empty`)
|
|
|
}
|
|
|
|
|
|
export default router
|