wip: 临时提交
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-menu
|
<el-menu
|
||||||
ref="menuRef"
|
ref="menuRef"
|
||||||
:default-active="currentRoute.path"
|
:default-active="activeMenuIndex"
|
||||||
:collapse="!appStore.sidebar.opened"
|
:collapse="!appStore.sidebar.opened"
|
||||||
:background-color="
|
:background-color="
|
||||||
theme === 'dark' || sidebarColorScheme === SidebarColor.CLASSIC_BLUE
|
theme === 'dark' || sidebarColorScheme === SidebarColor.CLASSIC_BLUE
|
||||||
@@ -78,6 +78,83 @@ const theme = computed(() => settingsStore.theme);
|
|||||||
// 获取浅色主题下的侧边栏配色方案
|
// 获取浅色主题下的侧边栏配色方案
|
||||||
const sidebarColorScheme = computed(() => settingsStore.sidebarColorScheme);
|
const sidebarColorScheme = computed(() => settingsStore.sidebarColorScheme);
|
||||||
|
|
||||||
|
// 计算当前激活的菜单项
|
||||||
|
const activeMenuIndex = computed(() => {
|
||||||
|
const currentPath = currentRoute.path;
|
||||||
|
|
||||||
|
// 如果路由设置了 activeMenu,优先使用
|
||||||
|
if (currentRoute.meta?.activeMenu) {
|
||||||
|
return currentRoute.meta.activeMenu as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在水平模式下(顶部布局),需要找到匹配的顶级菜单
|
||||||
|
if (props.menuMode === "horizontal") {
|
||||||
|
// 首先尝试简单的路径前缀匹配
|
||||||
|
const pathSegments = currentPath.split("/").filter(Boolean);
|
||||||
|
if (pathSegments.length > 0) {
|
||||||
|
const topLevelPath = `/${pathSegments[0]}`;
|
||||||
|
|
||||||
|
// 检查是否有菜单项匹配这个顶级路径
|
||||||
|
const matchingMenu = props.data.find((menu) => {
|
||||||
|
const menuPath = resolveFullPath(menu.path);
|
||||||
|
return menuPath === topLevelPath;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (matchingMenu) {
|
||||||
|
console.log("🎯 Top menu matched:", topLevelPath, "for route:", currentPath);
|
||||||
|
return topLevelPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果简单匹配失败,使用详细匹配
|
||||||
|
const findMatchingTopMenu = (menus: RouteRecordRaw[], targetPath: string): string | null => {
|
||||||
|
for (const menu of menus) {
|
||||||
|
const menuPath = resolveFullPath(menu.path);
|
||||||
|
|
||||||
|
// 精确匹配
|
||||||
|
if (targetPath === menuPath) {
|
||||||
|
return menuPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 路径前缀匹配(子路径匹配父菜单)
|
||||||
|
if (targetPath.startsWith(menuPath + "/")) {
|
||||||
|
return menuPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果有子菜单,检查子菜单是否匹配
|
||||||
|
if (menu.children && menu.children.length > 0) {
|
||||||
|
const hasMatchingChild = menu.children.some((child) => {
|
||||||
|
// 对于子菜单,需要正确解析路径
|
||||||
|
let childPath;
|
||||||
|
if (child.path.startsWith("/")) {
|
||||||
|
// 如果子路径是绝对路径,直接使用
|
||||||
|
childPath = child.path;
|
||||||
|
} else {
|
||||||
|
// 如果是相对路径,基于父菜单路径解析
|
||||||
|
childPath = path.resolve(menuPath, child.path);
|
||||||
|
}
|
||||||
|
return targetPath === childPath || targetPath.startsWith(childPath + "/");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasMatchingChild) {
|
||||||
|
return menuPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const matchedMenu = findMatchingTopMenu(props.data, currentPath);
|
||||||
|
if (matchedMenu) {
|
||||||
|
console.log("🎯 Detailed menu matched:", matchedMenu, "for route:", currentPath);
|
||||||
|
return matchedMenu;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回当前路径
|
||||||
|
return currentPath;
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取完整路径
|
* 获取完整路径
|
||||||
*
|
*
|
||||||
@@ -92,6 +169,11 @@ function resolveFullPath(routePath: string) {
|
|||||||
return props.basePath;
|
return props.basePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果 basePath 为空(顶部布局),直接返回 routePath
|
||||||
|
if (!props.basePath || props.basePath === "") {
|
||||||
|
return routePath;
|
||||||
|
}
|
||||||
|
|
||||||
// 解析路径,生成完整的绝对路径
|
// 解析路径,生成完整的绝对路径
|
||||||
return path.resolve(props.basePath, routePath);
|
return path.resolve(props.basePath, routePath);
|
||||||
}
|
}
|
||||||
@@ -126,4 +208,54 @@ watch(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听激活菜单变化,为包含激活子菜单的父菜单添加样式类
|
||||||
|
*/
|
||||||
|
watch(
|
||||||
|
() => activeMenuIndex.value,
|
||||||
|
() => {
|
||||||
|
nextTick(() => {
|
||||||
|
updateParentMenuStyles();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新父菜单样式 - 为包含激活子菜单的父菜单添加 has-active-child 类
|
||||||
|
*/
|
||||||
|
function updateParentMenuStyles() {
|
||||||
|
if (!menuRef.value?.$el) return;
|
||||||
|
|
||||||
|
const menuEl = menuRef.value.$el as HTMLElement;
|
||||||
|
|
||||||
|
// 移除所有现有的 has-active-child 类
|
||||||
|
const allSubMenus = menuEl.querySelectorAll(".el-sub-menu");
|
||||||
|
allSubMenus.forEach((subMenu) => {
|
||||||
|
subMenu.classList.remove("has-active-child");
|
||||||
|
});
|
||||||
|
|
||||||
|
// 查找当前激活的菜单项
|
||||||
|
const activeMenuItem = menuEl.querySelector(".el-menu-item.is-active");
|
||||||
|
if (activeMenuItem) {
|
||||||
|
// 向上查找父级 el-sub-menu 元素
|
||||||
|
let parent = activeMenuItem.parentElement;
|
||||||
|
while (parent && parent !== menuEl) {
|
||||||
|
if (parent.classList.contains("el-sub-menu")) {
|
||||||
|
parent.classList.add("has-active-child");
|
||||||
|
}
|
||||||
|
parent = parent.parentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组件挂载后立即更新父菜单样式
|
||||||
|
*/
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
updateParentMenuStyles();
|
||||||
|
});
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -190,4 +190,41 @@ html.sidebar-color-blue {
|
|||||||
background-color: $menu-hover;
|
background-color: $menu-hover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 父菜单激活状态样式 - 当子菜单激活时,父菜单显示激活状态
|
||||||
|
.el-sub-menu {
|
||||||
|
// 当父菜单包含激活子菜单时的样式
|
||||||
|
&.has-active-child .el-sub-menu__title {
|
||||||
|
color: var(--el-color-primary) !important;
|
||||||
|
background-color: var(--el-color-primary-light-9) !important;
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
color: var(--el-color-primary) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 深色主题下的父菜单激活状态
|
||||||
|
html.dark & {
|
||||||
|
&.has-active-child .el-sub-menu__title {
|
||||||
|
color: var(--el-color-primary-light-3) !important;
|
||||||
|
background-color: rgba(64, 128, 255, 0.15) !important;
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
color: var(--el-color-primary-light-3) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 深蓝色侧边栏配色下的父菜单激活状态
|
||||||
|
html.sidebar-color-blue & {
|
||||||
|
&.has-active-child .el-sub-menu__title {
|
||||||
|
color: var(--el-color-primary-light-3) !important;
|
||||||
|
background-color: rgba(64, 128, 255, 0.2) !important;
|
||||||
|
|
||||||
|
.menu-icon {
|
||||||
|
color: var(--el-color-primary-light-3) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user