fix(F006-W18): 面包屑显示完整路径(工作台>一级目录>...>末级菜单)

根因: AppLayout.vue 面包屑写死两级(工作台 + route.meta.title),
省略了中间的父级目录层级。

修法: 加 breadcrumbItems computed, 从当前 route.path 在菜单树
(menuStore.list) DFS 追溯父级链, 返回完整路径标题数组。
- 列表页: 工作台 > 父目录 > ... > 末级菜单
- 详情页: 工作台 > 父目录 > ... > meta.title
- 首页/未命中: 仅工作台

部署: dist rsync + docker rebuild + scp src + curl 200 验证
This commit is contained in:
Sisyphus 2026-07-10 10:27:36 +08:00
parent 15294f5c1c
commit 978058c543

View File

@ -60,6 +60,46 @@ function isActive(path: string): boolean {
return path === '/' ? route.path === '/' : route.path.startsWith(path) return path === '/' ? route.path === '/' : route.path.startsWith(path)
} }
/**
* 面包屑: 从当前 route.path 在菜单树里 DFS 追溯完整父级链
* 返回 [一级目录, ..., 末级菜单], 不含"工作台"前缀(template 里单独拼)
* 找不到时 fallback 到 route.meta.title
*/
const breadcrumbItems = computed<string[]>(() => {
const currentPath = route.path
// 工作台首页不显示中间层级
if (currentPath === '/' || currentPath === '/dashboard') return []
// DFS 找父级链
function findChain(items: MenuItem[], target: string, chain: MenuItem[]): boolean {
for (const item of items) {
if (item.path === target || (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
}
const chain: MenuItem[] = []
findChain(menuList.value, currentPath, chain)
const metaTitle = route.meta?.title as string | undefined
if (chain.length) {
const titles: string[] = chain.map(i => i.title)
const last = chain[chain.length - 1]
if (last.path !== currentPath) {
// 详情页: 命中的是父前缀, 追加 meta.title
return metaTitle ? [...titles, metaTitle] : titles
}
return titles
}
// 菜单树没命中 (如 /inquiry/:id 详情页), 用 meta.title 兜底
return metaTitle ? [metaTitle] : []
})
const PARENT_GROUP: Record<string, string> = { const PARENT_GROUP: Record<string, string> = {
'概览': '概览', '概览': '概览',
'业务': '业务', '业务': '业务',
@ -329,7 +369,7 @@ onMounted(loadBadges)
</div> </div>
<el-breadcrumb separator=">" class="rr-topbar-breadcrumb"> <el-breadcrumb separator=">" class="rr-topbar-breadcrumb">
<el-breadcrumb-item :to="{ path: '/' }">工作台</el-breadcrumb-item> <el-breadcrumb-item :to="{ path: '/' }">工作台</el-breadcrumb-item>
<el-breadcrumb-item>{{ route.meta?.title || '' }}</el-breadcrumb-item> <el-breadcrumb-item v-for="item in breadcrumbItems" :key="item">{{ item }}</el-breadcrumb-item>
</el-breadcrumb> </el-breadcrumb>
</div> </div>
<div class="rr-topbar-right"> <div class="rr-topbar-right">