manager 升级到vue3

This commit is contained in:
pikachu1995@126.com
2026-05-25 10:49:09 +08:00
parent e7350899bf
commit 615ee91511
239 changed files with 22907 additions and 30841 deletions

View File

@@ -1,10 +1,130 @@
import { getCurrentPermissionList } from "@/api/index";
import lazyLoading from "./lazyLoading.js";
import { router } from "@/router/index";
import Cookies from "js-cookie";
let util = {};
/** 动态菜单路由 name用于登出或重新注册时清理 */
util.dynamicRouteNames = [];
util.clearDynamicRoutes = function () {
util.dynamicRouteNames.forEach((name) => {
if (router.hasRoute(name)) {
router.removeRoute(name);
}
});
util.dynamicRouteNames = [];
};
util.collectLeafRoutes = function (routes, result = [], parentPath = "") {
routes.forEach((route) => {
let segment = route.path != null ? String(route.path) : "";
segment = segment.replace(/^\//, "");
const fullPath = [parentPath, segment].filter(Boolean).join("/");
const hasChildren = route.children && route.children.length > 0;
if (hasChildren) {
util.collectLeafRoutes(route.children, result, fullPath);
} else if (
route.name &&
route.component &&
!String(route.name).endsWith("__layout")
) {
result.push({
path: fullPath || segment || route.name,
name: route.name,
component: route.component,
meta: route.meta || {},
});
}
});
return result;
};
/** Vue Router 4动态路由必须挂到 otherRouter 下,且刷新/热更新后需重新注册 */
util.registerDynamicRoutes = function (menuData, options = {}) {
const { rematch = true } = options;
const pendingPath = router.currentRoute.value.fullPath;
const pendingUnmatched = router.currentRoute.value.matched.length === 0;
util.clearDynamicRoutes();
const constRoutes = [];
util.initAllMenuData(constRoutes, menuData);
const leaves = [];
constRoutes.forEach((top) => {
const base = (top.path || "").replace(/^\//, "");
if (top.children && top.children.length) {
util.collectLeafRoutes(top.children, leaves, base);
} else if (
top.name &&
top.component &&
!String(top.name).endsWith("__layout")
) {
leaves.push({
path: base || top.name,
name: top.name,
component: top.component,
meta: top.meta || {},
});
}
});
leaves.forEach((leaf) => {
const path = (leaf.path || leaf.name || "").replace(/^\//, "");
if (!router.hasRoute(leaf.name)) {
router.addRoute("otherRouter", {
path,
name: leaf.name,
component: leaf.component,
meta: leaf.meta,
});
util.dynamicRouteNames.push(leaf.name);
}
});
if (!router.hasRoute("error-404")) {
router.addRoute({
path: "/:pathMatch(.*)*",
name: "error-404",
component: lazyLoading("error-page/404"),
meta: { title: "404-页面不存在" },
});
util.dynamicRouteNames.push("error-404");
}
if (
rematch &&
pendingUnmatched &&
pendingPath &&
pendingPath !== "/login"
) {
const resolved = router.resolve(pendingPath);
if (resolved.matched.length > 0) {
router.replace(pendingPath).catch(() => {});
}
}
};
/** 从 localStorage 恢复动态路由(刷新深链前必须先注册,避免 /member/xxx 无匹配) */
util.bootstrapDynamicRoutesFromCache = function () {
if (!Cookies.get("userInfoManager")) {
return false;
}
try {
const raw = window.localStorage.getItem("menuData");
if (!raw) {
return false;
}
util.registerDynamicRoutes(JSON.parse(raw), { rematch: false });
return true;
} catch (e) {
console.warn("[router] menuData parse failed", e);
return false;
}
};
util.title = function(title) {
title = title || "运营后台";
window.document.title = title;
@@ -94,7 +214,7 @@ util.initRouter = function(vm) {
// 404路由需要和动态路由一起加载
const otherRouter = [
{
path: "/*",
path: "/:pathMatch(.*)*",
name: "error-404",
meta: {
title: "404-页面不存在"
@@ -132,15 +252,11 @@ util.initRouter = function(vm) {
return;
}
util.initAllMenuData(constRoutes, menuData);
util.initRouterNode(otherRoutes, otherRouter);
// 添加所有主界面路由
util.registerDynamicRoutes(menuData);
vm.$store.commit(
"updateAppRouter",
constRoutes.filter(item => item.children.length > 0)
constRoutes.filter((item) => item.children && item.children.length > 0)
);
// 添加全局路由
vm.$store.commit("updateDefaultRouter", otherRoutes);
// 添加菜单路由
util.initMenuData(vm, menuData);
// 缓存数据 修改加载标识
window.localStorage.setItem("menuData", JSON.stringify(menuData));
@@ -154,7 +270,7 @@ util.initRouter = function(vm) {
return;
}
let menuData = JSON.parse(data);
// 添加菜单路由
util.registerDynamicRoutes(menuData);
util.initMenuData(vm, menuData);
}
};
@@ -235,17 +351,27 @@ util.initRouterNode = function(routers, data) {
// data为所有子菜单数据
for (let item of data) {
let menu = Object.assign({}, item);
const menu = Object.assign({}, item);
const hasChildren = item.children && item.children.length > 0;
menu.component = lazyLoading(menu.frontRoute);
if (item.children && item.children.length > 0) {
if (hasChildren) {
menu.children = [];
// Vue Router 4父子路由 name 必须不同,后端菜单常出现同名父子节点
if (menu.name) {
menu.name = `${menu.name}__layout`;
}
util.initRouterNode(menu.children, item.children);
// 分组节点通常无页面,仅在有 frontRoute 时挂载组件
if (menu.frontRoute) {
menu.component = lazyLoading(menu.frontRoute);
} else {
delete menu.component;
}
} else if (menu.frontRoute) {
menu.component = lazyLoading(menu.frontRoute);
}
let meta = {};
// 给页面添加标题、父级菜单name方便左侧菜单选中
const meta = {};
meta.title = menu.title ? menu.title + " - 运营后台" : null;
meta.firstRouterName = item.firstRouterName;
menu.meta = meta;