From 996f86d3d07e91d0037c325f033c09f4702eb223 Mon Sep 17 00:00:00 2001 From: zxr <271055687@qq.com> Date: Sat, 21 Mar 2026 17:53:40 +0800 Subject: [PATCH] fix --- src/components/menu/index.vue | 29 +++++++++--- src/components/menu/use-menu-tree.ts | 16 ++----- src/router/routes/modules/remote.ts | 45 ++----------------- .../system-settings/license-center/index.vue | 1 - 4 files changed, 30 insertions(+), 61 deletions(-) diff --git a/src/components/menu/index.vue b/src/components/menu/index.vue index 77d97bb..64bc4fe 100644 --- a/src/components/menu/index.vue +++ b/src/components/menu/index.vue @@ -6,7 +6,13 @@ import { listenerRouteChange } from '@/utils/route-listener' import { compile, computed, defineComponent, h, ref } from 'vue' import { useI18n } from 'vue-i18n' import type { RouteMeta } from 'vue-router' -import { RouteRecordRaw, useRoute, useRouter } from 'vue-router' +import { + isNavigationFailure, + NavigationFailureType, + RouteRecordRaw, + useRoute, + useRouter, +} from 'vue-router' import useMenuTree from './use-menu-tree' import { COMMON_ICONS } from '@/views/ops/pages/system-settings/menu-management/menuIcons' @@ -45,10 +51,20 @@ export default defineComponent({ selectedKey.value = [item.name as string] return } - console.log('item', item) - // Trigger router change - router.push({ - name: item.name, + const name = item.name + if (name == null || name === '') { + console.warn('[Menu] 无法跳转:路由缺少 name', item.path, item.meta?.locale) + return + } + if (!router.hasRoute(name as string)) { + console.warn('[Menu] 无法跳转:未注册的路由 name', name, item.meta?.locale) + return + } + router.push({ name }).catch((err) => { + if (isNavigationFailure(err, NavigationFailureType.duplicated)) { + return + } + console.error('[Menu] 路由跳转失败', name, err) }) } const findMenuOpenKeys = (target: string) => { @@ -80,7 +96,8 @@ export default defineComponent({ const keySet = new Set([...menuOpenKeys, ...openKeys.value]) openKeys.value = [...keySet] - selectedKey.value = [activeMenu || menuOpenKeys[menuOpenKeys.length - 1]] + const leafKey = (activeMenu || menuOpenKeys[menuOpenKeys.length - 1]) as string | undefined + selectedKey.value = leafKey ? [leafKey] : [] } }, true) const setCollapse = (val: boolean) => { diff --git a/src/components/menu/use-menu-tree.ts b/src/components/menu/use-menu-tree.ts index 7f88f03..ef49203 100644 --- a/src/components/menu/use-menu-tree.ts +++ b/src/components/menu/use-menu-tree.ts @@ -15,12 +15,12 @@ export default function useMenuTree() { return appClientMenus }) const menuTree = computed(() => { - const copyRouter = cloneDeep(appRoute.value) as RouteRecordNormalized[] + const copyRouter = cloneDeep(appRoute.value || []) as RouteRecordNormalized[] copyRouter.sort((a: RouteRecordNormalized, b: RouteRecordNormalized) => { return (a.meta.order || 0) - (b.meta.order || 0) }) - function travel(_routes: RouteRecordRaw[], layer: number) { - if (!_routes) return null + function travel(_routes: RouteRecordRaw[], layer: number): RouteRecordRaw[] { + if (!_routes?.length) return [] const collector: any = _routes.map((element) => { // no access @@ -44,16 +44,8 @@ export default function useMenuTree() { element.children = subItem return element } - // the else logic - if (layer > 1) { - element.children = subItem - return element - } - - if (element.meta?.hideInMenu === false) { - return element - } + // 子级全部被权限/隐藏规则过滤时,不再把父级当成可点击叶子(避免 push 父级 name 无对应页面) return null }) return collector.filter(Boolean) diff --git a/src/router/routes/modules/remote.ts b/src/router/routes/modules/remote.ts index 70ca8d8..cb9d2f1 100644 --- a/src/router/routes/modules/remote.ts +++ b/src/router/routes/modules/remote.ts @@ -1,43 +1,4 @@ -import { DEFAULT_LAYOUT } from '../base' -import { AppRouteRecordRaw } from '../types' +import type { AppRouteRecordRaw } from '../types' -const REMOTE: AppRouteRecordRaw = { - // path: '/dc', - // name: 'DC', - // component: DEFAULT_LAYOUT, - // meta: { - // locale: 'menu.dc', - // requiresAuth: true, - // icon: 'icon-desktop', - // order: 99, - // hideInMenu: true, - // }, - // children: [ - // { - // path: 'detail', - // name: 'DCDetail', - // component: () => import('@/views/ops/pages/dc/detail/index.vue'), - // meta: { - // locale: 'menu.dc.detail', - // requiresAuth: true, - // roles: ['*'], - // // is_full: true, - // isNewTab: true, - // }, - // }, - // { - // path: 'remote', - // name: 'DCRemote', - // component: () => import('@/views/ops/pages/dc/remote/index.vue'), - // meta: { - // locale: 'menu.dc.remote', - // requiresAuth: true, - // roles: ['*'], - // // is_full: true, - // isNewTab: true, - // }, - // }, - // ], -} - -export default REMOTE +/** 占位:勿导出空对象 `{}`,否则会被当作一条无效路由加入 router,导致部分菜单匹配异常 */ +export default [] as AppRouteRecordRaw[] diff --git a/src/views/ops/pages/system-settings/license-center/index.vue b/src/views/ops/pages/system-settings/license-center/index.vue index 34bd380..4394882 100644 --- a/src/views/ops/pages/system-settings/license-center/index.vue +++ b/src/views/ops/pages/system-settings/license-center/index.vue @@ -6,7 +6,6 @@ 许可证信息 - {{ license?.company_name || '—' }}