feat(breadcrumbs): implement reusable breadcrumbs component and update usage

refactor(chunk): enhance chunk list with bulk operations and improved UI
This commit is contained in:
2025-10-17 11:11:48 +08:00
parent 50628816e3
commit de3d196e11
12 changed files with 519 additions and 285 deletions

View File

@@ -1,88 +1,35 @@
import React from 'react';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { Breadcrumbs, Link, Typography } from '@mui/material';
import type { IKnowledge } from '@/interfaces/database/knowledge';
import type { SxProps, Theme } from '@mui/material';
import { BaseBreadcrumbs, type BreadcrumbItem } from '@/components/Breadcrumbs';
interface KnowledgeBreadcrumbsProps {
knowledge?: IKnowledge | null;
sx?: object;
sx?: SxProps<Theme>;
/** 知识库相关的面包屑项目,可以完全自定义 */
kbItems?: BreadcrumbItem[];
/** 额外的面包屑项目会添加到kbItems之后 */
extraItems?: BreadcrumbItem[];
}
const KnowledgeBreadcrumbs: React.FC<KnowledgeBreadcrumbsProps> = ({ knowledge, sx }) => {
const location = useLocation();
const navigate = useNavigate();
const { id } = useParams<{ id: string }>();
// 解析当前路径
const pathSegments = location.pathname.split('/').filter(Boolean);
const KnowledgeBreadcrumbs: React.FC<KnowledgeBreadcrumbsProps> = ({
sx,
kbItems = [],
extraItems = []
}) => {
// 合并所有面包屑项目
const allItems = [...kbItems, ...extraItems];
// 生成面包屑
const breadcrumbItems = [];
// 第一层:知识库列表
breadcrumbItems.push({
label: '知识库',
path: '/knowledge',
isLast: false
});
// 第二层知识库详情如果有id
if (id && knowledge) {
const isDetailPage = pathSegments.length === 2; // /knowledge/:id
breadcrumbItems.push({
label: knowledge.name,
path: `/knowledge/${id}`,
isLast: isDetailPage
});
// 第三层:设置或测试页面
if (pathSegments.length === 3) {
const lastSegment = pathSegments[2];
let label = '';
switch (lastSegment) {
case 'setting':
label = '设置';
break;
case 'testing':
label = '测试';
break;
default:
label = lastSegment;
}
breadcrumbItems.push({
label,
path: location.pathname,
isLast: true
});
}
}
// 确保最后一个项目被标记为最后一
const breadcrumbItems = allItems.map((item, index) => ({
...item,
isLast: index === allItems.length - 1
}));
return (
<Breadcrumbs sx={{ mb: 2, ...sx }}>
{breadcrumbItems.map((item, index) => {
if (item.isLast) {
return (
<Typography key={index} color="text.primary">
{item.label}
</Typography>
);
}
return (
<Link
key={index}
component="button"
variant="body1"
onClick={() => navigate(item.path)}
sx={{ textDecoration: 'none' }}
>
{item.label}
</Link>
);
})}
</Breadcrumbs>
<BaseBreadcrumbs
items={breadcrumbItems}
sx={sx}
linkVariant="body1"
/>
);
};

View File

@@ -212,7 +212,7 @@ function KnowledgeBaseCreate() {
<Divider sx={{ my: 3 }} />
{/* 操作按钮 */}
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
<Box sx={{ display: 'flex', gap: 2 }}>
{activeStep === 0 && (
<Button

View File

@@ -275,7 +275,18 @@ function KnowledgeBaseDetail() {
return (
<Box sx={{ p: 3 }}>
{/* 面包屑导航 */}
<KnowledgeBreadcrumbs knowledge={knowledgeBase} />
<KnowledgeBreadcrumbs
kbItems={[
{
label: '知识库',
path: '/knowledge'
},
{
label: knowledgeBase?.name || '知识库详情',
path: `/knowledge/${id}`
}
]}
/>
{/* 知识库信息卡片 */}
<KnowledgeInfoCard knowledgeBase={knowledgeBase} />

View File

@@ -157,7 +157,21 @@ function KnowledgeBaseSetting() {
return (
<MainContainer>
{/* 面包屑导航 */}
<KnowledgeBreadcrumbs knowledge={knowledge} />
<KnowledgeBreadcrumbs
kbItems={[
{
label: '知识库',
path: '/knowledge'
},
{
label: knowledge?.name || '知识库详情',
path: `/knowledge/${id}`
},
{
label: '设置'
}
]}
/>
<Box sx={{ mb: 3 }}>
<Typography variant="h4" gutterBottom>

View File

@@ -236,7 +236,21 @@ function KnowledgeBaseTesting() {
<Container maxWidth="lg" sx={{ py: 4 }}>
{/* 面包屑导航 */}
<KnowledgeBreadcrumbs knowledge={knowledgeDetail} />
<KnowledgeBreadcrumbs
kbItems={[
{
label: '知识库',
path: '/knowledge'
},
{
label: knowledgeDetail?.name || '知识库详情',
path: `/knowledge/${id}`
},
{
label: '测试'
}
]}
/>
<Box sx={{ mb: 3 }}>
<Typography variant="h4" gutterBottom>