Browse Source

✨ feat: 修复侧边菜单监听失败的问题

Pchen. 6 days ago
parent
commit
59bd3d9d5c
1 changed files with 59 additions and 12 deletions
  1. 59 12
      src/utils/route-listener.js

+ 59 - 12
src/utils/route-listener.js

@@ -1,5 +1,56 @@
 import { ref, watch } from 'vue'
 import { useRoute } from 'vue-router'
+import { routes } from '@/router'
+
+const joinRoutePath = (parentPath, routePath) => {
+    const base = parentPath.endsWith('/') ? parentPath.slice(0, -1) : parentPath
+    const segment = routePath.startsWith('/') ? routePath : `/${routePath}`
+    return `${base}${segment}`.replace(/\/+/g, '/')
+}
+
+const buildRouteMenuKeyMap = (routeList, parentPath = '', map = {}) => {
+    routeList.forEach((route) => {
+        const fullPath = joinRoutePath(parentPath, route.path)
+
+        if (route.children?.length > 0) {
+            const childPrefix = fullPath.endsWith('/') ? fullPath : `${fullPath}/`
+            const visibleChildren = route.children.filter((child) => !child.meta?.hideInMenu)
+
+            if (route.meta?.flatMenu && visibleChildren.length === 1) {
+                const child = visibleChildren[0]
+                const menuKey = joinRoutePath(childPrefix, child.path)
+                if (route.name) map[route.name] = menuKey
+                if (child.name) map[child.name] = menuKey
+            }
+
+            buildRouteMenuKeyMap(route.children, childPrefix, map)
+        }
+
+        if (route.name && !route.meta?.hideInMenu && !map[route.name]) {
+            map[route.name] = fullPath
+        }
+    })
+
+    return map
+}
+
+const routeMenuKeyMap = buildRouteMenuKeyMap(routes)
+
+const getRouteHierarchy = (path) => {
+    const segments = path.split('/').filter(Boolean)
+    return segments.map((_, index) => '/' + segments.slice(0, index + 1).join('/'))
+}
+
+const resolveActiveMenuPath = (route) => {
+    const leaf = route.matched[route.matched.length - 1]
+    const routeName = leaf?.meta?.parent || route.name
+
+    if (routeName && routeMenuKeyMap[routeName]) {
+        return routeMenuKeyMap[routeName]
+    }
+
+    return route.path
+}
 
 /**
  * 路由监听器
@@ -7,19 +58,15 @@ import { useRoute } from 'vue-router'
  */
 export function useRouteListener() {
     const route = useRoute()
-    
-    // 计算当前路径及其所有父级路径
-    const getRouteHierarchy = (path) => {
-        const segments = path.split('/').filter(Boolean)
-        return segments.map((_, index) => '/' + segments.slice(0, index + 1).join('/'))
-    }
-    
-    const selectedKey = ref(getRouteHierarchy(route.path))
 
-    // 监听路径变化并更新选中项
-    watch(() => route.path, (newPath) => {
-        selectedKey.value = getRouteHierarchy(newPath)
-    })
+    const selectedKey = ref(getRouteHierarchy(resolveActiveMenuPath(route)))
+
+    watch(
+        () => [route.path, route.name, route.matched.length],
+        () => {
+            selectedKey.value = getRouteHierarchy(resolveActiveMenuPath(route))
+        }
+    )
 
     return { selectedKey }
 }