auto-generate breadcrumb navigation for tool pages
This commit is contained in:
parent
0a23ee2587
commit
66036da8e9
@ -79,9 +79,75 @@ const appName = computed(() => localStorage.getItem('appName') || 'Jingrow')
|
||||
|
||||
const isSystemUser = computed(() => authStore.user?.user_type === 'System User')
|
||||
|
||||
// 将路径段转换为可读标签
|
||||
function pathSegmentToLabel(segment: string): string {
|
||||
// 将 kebab-case 或 snake_case 转换为标题格式
|
||||
return segment
|
||||
.split(/[-_]/)
|
||||
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
|
||||
.join(' ')
|
||||
}
|
||||
|
||||
// 从路由路径自动生成面包屑
|
||||
function generateBreadcrumbFromPath(path: string): Array<{ label: string; href?: string }> {
|
||||
const items: Array<{ label: string; href?: string }> = []
|
||||
const segments = path.split('/').filter(Boolean)
|
||||
|
||||
// 构建路径前缀,用于生成 href
|
||||
let currentPath = ''
|
||||
|
||||
segments.forEach((segment, index) => {
|
||||
currentPath += `/${segment}`
|
||||
const isLast = index === segments.length - 1
|
||||
|
||||
// 特殊处理:tools 路径
|
||||
if (segment === 'tools') {
|
||||
items.push({
|
||||
label: t('Tools'),
|
||||
href: isLast ? undefined : currentPath
|
||||
})
|
||||
} else {
|
||||
// 对于最后一项,不添加链接
|
||||
items.push({
|
||||
label: pathSegmentToLabel(segment),
|
||||
href: isLast ? undefined : currentPath
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
const breadcrumbItems = computed(() => {
|
||||
const items: Array<{ label: string; href?: string }> = []
|
||||
|
||||
// 优先检查路由 meta 中的 toolName(工具路由)
|
||||
if (route.meta?.toolName) {
|
||||
// 工具路由:显示 Tools / 工具名称
|
||||
// 自动解析 Tools 路由的路径(用于面包屑链接)
|
||||
let toolsPath = '/app/tools' // 默认值
|
||||
try {
|
||||
const resolved = router.resolve({ name: 'Tools' })
|
||||
if (resolved.matched.length > 0) {
|
||||
toolsPath = resolved.path
|
||||
}
|
||||
} catch {
|
||||
// 解析失败,使用默认值
|
||||
}
|
||||
items.push({
|
||||
label: t('Tools'),
|
||||
href: toolsPath
|
||||
})
|
||||
// 使用 meta.toolName(工具的显示名称)
|
||||
const toolLabel = route.meta.toolName as string
|
||||
if (toolLabel) {
|
||||
items.push({
|
||||
label: toolLabel
|
||||
})
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
// 根据路由名称和参数生成面包屑
|
||||
if (route.name === 'PageTypeList') {
|
||||
const entity = route.params.entity as string
|
||||
@ -105,8 +171,15 @@ const breadcrumbItems = computed(() => {
|
||||
label: id === 'new' ? t('Create') : id
|
||||
})
|
||||
}
|
||||
} else if (route.name === 'WorkspacePage') {
|
||||
const name = route.params.name as string
|
||||
if (name) {
|
||||
items.push({
|
||||
label: pathSegmentToLabel(name)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// 其他页面的标题映射
|
||||
// 其他页面的标题映射(保留向后兼容)
|
||||
const map: Record<string, string> = {
|
||||
Dashboard: t('Dashboard'),
|
||||
AgentList: t('Agents'),
|
||||
@ -123,8 +196,24 @@ const breadcrumbItems = computed(() => {
|
||||
SearchResults: t('Search Results')
|
||||
}
|
||||
const title = map[route.name as string]
|
||||
|
||||
if (title) {
|
||||
items.push({ label: title })
|
||||
} else {
|
||||
// 如果没有匹配的标题,尝试从路径自动生成
|
||||
// 排除根路径和已知的特殊路径
|
||||
if (route.path !== '/' && !route.path.startsWith('/app/') && !route.path.startsWith('/page/')) {
|
||||
const pathItems = generateBreadcrumbFromPath(route.path)
|
||||
if (pathItems.length > 0) {
|
||||
items.push(...pathItems)
|
||||
} else {
|
||||
// 最后的后备方案:使用路由名称
|
||||
const routeName = route.name as string
|
||||
if (routeName) {
|
||||
items.push({ label: pathSegmentToLabel(routeName) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -256,7 +256,7 @@ router.beforeEach(async (to, _from, next) => {
|
||||
return
|
||||
} else {
|
||||
// 路由不存在,重定向到工具列表页
|
||||
next('/tools')
|
||||
next({ name: 'Tools' })
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user