Files
pc-10588/app/components/Breadcrumbs.vue

70 lines
1.8 KiB
Vue

<template>
<nav v-if="items.length > 1" class="breadcrumbs" aria-label="面包屑导航">
<a-breadcrumb>
<a-breadcrumb-item v-for="(it, idx) in items" :key="`${it.key}::${idx}`">
<NuxtLink v-if="it.to && idx < items.length - 1" :to="it.to">
{{ it.label }}
</NuxtLink>
<span v-else>{{ it.label }}</span>
</a-breadcrumb-item>
</a-breadcrumb>
</nav>
</template>
<script setup lang="ts">
import { mainNav, type NavItem } from '@/config/nav'
type Crumb = { key: string; label: string; to?: string }
const route = useRoute()
const currentPath = computed(() => route.path || '/')
function bestTrail(items: NavItem[], path: string): NavItem[] {
let best: NavItem[] = []
const walk = (list: NavItem[], ancestors: NavItem[]) => {
for (const item of list) {
const nextAncestors = [...ancestors, item]
const to = item.to || ''
const isPrefix = to && to !== '/' && (path === to || path.startsWith(`${to}/`))
const isExact = to && path === to
if (isExact || isPrefix) {
if (nextAncestors.length > best.length) best = nextAncestors
}
if (item.children?.length) walk(item.children, nextAncestors)
}
}
walk(items, [])
return best
}
const items = computed<Crumb[]>(() => {
const home: Crumb = { key: 'home', label: '首页', to: '/' }
if (currentPath.value === '/') return [home]
const trail = bestTrail(mainNav, currentPath.value)
if (!trail.length) {
return [home, { key: currentPath.value, label: currentPath.value.replace(/^\//, '') || '当前页面' }]
}
return [
home,
...trail.map((it) => ({ key: it.key, label: it.label, to: it.to }))
]
})
</script>
<style scoped>
.breadcrumbs {
padding: 10px 0;
color: var(--text-secondary);
}
.breadcrumbs :deep(.ant-breadcrumb) {
font-size: 13px;
}
</style>