From a59c934fd7074ac361707dbe4200cd57a58e36b4 Mon Sep 17 00:00:00 2001 From: Sisyphus Date: Fri, 10 Jul 2026 10:31:38 +0800 Subject: [PATCH] =?UTF-8?q?fix(F006-W18):=20=E9=9D=A2=E5=8C=85=E5=B1=91DFS?= =?UTF-8?q?=E4=BF=AE=E7=88=B6=E8=8F=9C=E5=8D=95=E7=9F=AD=E8=B7=AFbug(?= =?UTF-8?q?=E9=9B=86=E6=88=90=E7=AE=A1=E7=90=86>=E5=BA=94=E7=94=A8?= =?UTF-8?q?=E5=88=97=E8=A1=A8=E7=BC=BA=E6=9C=AB=E7=BA=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: resolveMenuItem 给父菜单 path = 第一个子菜单 path(如 集成管理.path = /openapi/app)。旧 DFS 用 path 前缀匹配短路命中父菜单, 不再递归子树, 导致 末级菜单标题丢失(只显示 工作台 > 集成管理, 缺 应用列表)。 修法: 父节点(有 children)优先递归子树, 子树没命中才考虑父节点 path 前缀 匹配(详情页场景)。叶子节点走 path 精确匹配。 --- src/components/AppLayout/AppLayout.vue | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/components/AppLayout/AppLayout.vue b/src/components/AppLayout/AppLayout.vue index 17e2771..7a2cea3 100644 --- a/src/components/AppLayout/AppLayout.vue +++ b/src/components/AppLayout/AppLayout.vue @@ -69,18 +69,28 @@ const breadcrumbItems = computed(() => { const currentPath = route.path // 工作台首页不显示中间层级 if (currentPath === '/' || currentPath === '/dashboard') return [] - // DFS 找父级链 + // DFS 找父级链: 父菜单(有 children)的 path 是第一个子菜单的 path(见 + // resolveMenuItem), 不能用 path 前缀短路命中父菜单, 必须先递归子树, + // 子树没命中才考虑父菜单自身。 function findChain(items: MenuItem[], target: string, chain: MenuItem[]): boolean { for (const item of items) { - if (item.path === target || (item.path !== '/' && target.startsWith(item.path))) { + // 叶子节点: path 精确匹配 + if (!item.children?.length) { + if (item.path === target) { + chain.push(item) + return true + } + continue + } + // 父节点: 先递归子树 + chain.push(item) + if (findChain(item.children, target, chain)) return true + chain.pop() + // 子树没命中, 看父节点自身 path 是否是 target 的前缀(详情页场景) + if (item.path !== '/' && target.startsWith(item.path)) { chain.push(item) return true } - if (item.children?.length) { - chain.push(item) - if (findChain(item.children, target, chain)) return true - chain.pop() - } } return false }