|
@@ -1,5 +1,56 @@
|
|
|
import { ref, watch } from 'vue'
|
|
import { ref, watch } from 'vue'
|
|
|
import { useRoute } from 'vue-router'
|
|
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() {
|
|
export function useRouteListener() {
|
|
|
const route = useRoute()
|
|
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 }
|
|
return { selectedKey }
|
|
|
}
|
|
}
|