- Complete knowledge base list and detail pages - Complete document upload component - Fix CORS config (add PUT/DELETE method support) - Fix file upload issues (disabled state and beforeUpload return value) - Add detailed debug logs (cleaned up) - Create Day 21-22 completion summary document
16 KiB
16 KiB
Day 21 - 知识库管理前端开发完成 ✅
完成时间: 2025年10月11日
提交记录: feat(frontend): Day 21 knowledge base management frontend completed
📋 任务概览
完成知识库管理的前端开发,包括:
- ✅ 前端API服务封装
- ✅ Zustand状态管理
- ✅ 知识库列表组件
- ✅ 创建/编辑知识库对话框
- ✅ 文档上传组件
- ✅ 文档列表组件
- ✅ 主页面集成
- ✅ 前端编译测试通过
🎨 前端架构
1. API服务层 (knowledgeBaseApi.ts)
类型定义:
export interface KnowledgeBase {
id: string;
userId: string;
name: string;
description?: string;
difyDatasetId: string;
fileCount: number;
totalSizeBytes: number;
createdAt: string;
updatedAt: string;
_count?: { documents: number };
}
export interface Document {
id: string;
kbId: string;
filename: string;
fileType: string;
fileSizeBytes: number;
status: 'uploading' | 'parsing' | 'indexing' | 'completed' | 'error';
progress: number;
errorMessage?: string;
segmentsCount?: number;
tokensCount?: number;
uploadedAt: string;
processedAt?: string;
}
API方法:
// 知识库管理
knowledgeBaseApi.getList() // 获取列表
knowledgeBaseApi.getById(id) // 获取详情
knowledgeBaseApi.create(data) // 创建
knowledgeBaseApi.update(id, data) // 更新
knowledgeBaseApi.delete(id) // 删除
knowledgeBaseApi.getStats(id) // 统计信息
knowledgeBaseApi.search(id, query) // 检索(RAG)
// 文档管理
documentApi.getList(kbId) // 获取列表
documentApi.upload(kbId, file) // 上传
documentApi.delete(id) // 删除
documentApi.reprocess(id) // 重新处理
2. 状态管理 (useKnowledgeBaseStore.ts)
Zustand Store:
interface KnowledgeBaseState {
// 数据状态
knowledgeBases: KnowledgeBase[];
currentKb: KnowledgeBase | null;
documents: Document[];
loading: boolean;
error: string | null;
// 知识库操作
fetchKnowledgeBases: () => Promise<void>;
fetchKnowledgeBaseById: (id: string) => Promise<void>;
createKnowledgeBase: (name, description?) => Promise<KnowledgeBase>;
updateKnowledgeBase: (id, name?, description?) => Promise<void>;
deleteKnowledgeBase: (id: string) => Promise<void>;
// 文档操作
fetchDocuments: (kbId: string) => Promise<void>;
uploadDocument: (kbId, file, onProgress?) => Promise<Document>;
deleteDocument: (id: string) => Promise<void>;
reprocessDocument: (id: string) => Promise<void>;
}
特点:
- ✅ 集中式状态管理
- ✅ 自动错误处理
- ✅ Loading状态管理
- ✅ 操作后自动刷新
🧩 核心组件
1. KnowledgeBaseList(知识库列表)
功能:
- ✅ 卡片式展示(3列网格布局)
- ✅ 配额显示(已使用 X/3 个)
- ✅ 文档数量、总大小、创建时间
- ✅ 编辑/删除操作
- ✅ 空状态提示
- ✅ 配额上限禁用创建按钮
UI特点:
// 卡片式布局
<Card hoverable onClick={onSelectClick}>
<Card.Meta
avatar={<FolderIcon />}
title={kb.name}
description={
- 描述(省略显示)
- 文档数量
- 总大小
- 创建时间
}
/>
<Actions>
- 编辑按钮
- 删除按钮(带确认)
</Actions>
</Card>
2. CreateKBDialog(创建对话框)
功能:
- ✅ 表单验证(名称必填、长度限制)
- ✅ 描述字段(可选、字数统计)
- ✅ 配额提示信息
- ✅ Loading状态
- ✅ 错误提示
验证规则:
- 名称:必填、最多50字
- 描述:选填、最多200字
提示信息:
📌 提示
• 每个用户最多创建 3 个知识库
• 每个知识库最多上传 50 个文档
• 支持的文件格式:PDF、DOC、DOCX、TXT、MD
• 单个文件最大10MB
3. EditKBDialog(编辑对话框)
功能:
- ✅ 自动填充现有数据
- ✅ 表单验证
- ✅ 更新成功提示
- ✅ 错误处理
4. DocumentUpload(文档上传)
功能:
- ✅ 拖拽上传
- ✅ 点击上传
- ✅ 文件类型验证(前端)
- ✅ 文件大小验证(10MB)
- ✅ 上传进度显示
- ✅ 配额检查(50个/知识库)
- ✅ 实时进度条
验证逻辑:
const beforeUpload = (file: File) => {
// 检查数量限制
if (currentDocumentCount >= 50) {
message.error('已达到文档数量上限(50个)');
return Upload.LIST_IGNORE;
}
// 检查文件类型
const allowedTypes = ['application/pdf', 'application/msword', ...];
if (!allowedTypes.includes(file.type)) {
message.error('不支持的文件类型');
return Upload.LIST_IGNORE;
}
// 检查文件大小(10MB)
if (file.size > 10 * 1024 * 1024) {
message.error('文件大小不能超过 10MB');
return Upload.LIST_IGNORE;
}
return false; // 手动上传
};
上传流程:
customRequest = async (options) => {
1. 调用 useKnowledgeBaseStore.uploadDocument()
2. 显示上传进度(0-100%)
3. 上传完成后通知父组件刷新
4. 显示成功/失败消息
}
5. DocumentList(文档列表)
功能:
- ✅ 表格展示
- ✅ 状态图标(上传中、解析中、索引中、已就绪、失败)
- ✅ 进度显示
- ✅ 文件大小格式化
- ✅ Token数、段落数显示
- ✅ 删除操作(带确认)
- ✅ 重试按钮(失败状态)
- ✅ 分页
- ✅ 空状态
状态图标:
const statusConfig = {
uploading: { color: 'blue', icon: <LoadingOutlined />, text: '上传中' },
parsing: { color: 'processing', icon: <ClockCircleOutlined />, text: '解析中' },
indexing: { color: 'processing', icon: <ClockCircleOutlined />, text: '索引中' },
completed: { color: 'success', icon: <CheckCircleOutlined />, text: '已就绪' },
error: { color: 'error', icon: <CloseCircleOutlined />, text: '失败' },
};
进度显示:
- 处理中:进度条(0-100%)
- 已完成:显示段落数和Token数
- 失败:显示错误提示(Tooltip)
6. KnowledgePage(主页面)
双视图架构:
视图1:知识库列表
<KnowledgeBaseList
knowledgeBases={knowledgeBases}
onCreateClick={() => setCreateDialogOpen(true)}
onEditClick={handleEdit}
onDeleteClick={handleDelete}
onSelectClick={handleSelectKb} // 切换到详情视图
/>
<CreateKBDialog />
<EditKBDialog />
视图2:知识库详情
<返回按钮 onClick={handleBackToList} />
<Card>
<知识库名称和描述>
<编辑按钮>
</Card>
<Tabs>
<TabPane key="documents">
<DocumentUpload />
<DocumentList />
</TabPane>
<TabPane key="stats">
<统计卡片网格>
- 总文档数
- 已就绪数
- 处理中数
- 失败数
- 总Token数
- 总段落数
</统计卡片网格>
</TabPane>
</Tabs>
实时状态轮询:
useEffect(() => {
if (!currentKb) return;
// 检查是否有处理中的文档
const hasProcessing = documents.some(doc =>
['uploading', 'parsing', 'indexing'].includes(doc.status)
);
if (!hasProcessing) return;
// 每5秒轮询一次
const interval = setInterval(() => {
fetchDocuments(currentKb.id);
}, 5000);
return () => clearInterval(interval);
}, [currentKb, documents]);
🎯 核心功能实现
1. 配额管理
知识库配额(3个/用户):
// 前端检查
const canCreateMore = knowledgeBases.length < 3;
<Button
disabled={!canCreateMore}
onClick={onCreateClick}
>
创建知识库
</Button>
// 后端验证
if (user.kbUsed >= user.kbQuota) {
throw new Error('Knowledge base quota exceeded');
}
文档配额(50个/知识库):
// 前端检查
const isAtLimit = currentDocumentCount >= 50;
<Upload
disabled={isAtLimit}
beforeUpload={(file) => {
if (isAtLimit) {
message.error('已达到文档数量上限(50个)');
return Upload.LIST_IGNORE;
}
}}
/>
// 后端验证
const documentCount = await prisma.document.count({ where: { kbId } });
if (documentCount >= 50) {
throw new Error('Document limit exceeded');
}
2. 文件验证
前端验证:
const allowedTypes = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'text/plain',
'text/markdown',
];
const allowedExtensions = ['.pdf', '.doc', '.docx', '.txt', '.md'];
// 类型检查
if (!allowedTypes.includes(file.type) &&
!allowedExtensions.some(ext => file.name.endsWith(ext))) {
message.error('不支持的文件类型');
return Upload.LIST_IGNORE;
}
// 大小检查
if (file.size > 10 * 1024 * 1024) {
message.error('文件大小不能超过 10MB');
return Upload.LIST_IGNORE;
}
后端验证:
// Controller层
const allowedTypes = [
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'text/plain',
'text/markdown',
];
if (!allowedTypes.includes(fileType)) {
return reply.status(400).send({
success: false,
message: 'File type not supported',
});
}
if (fileSizeBytes > 10 * 1024 * 1024) {
return reply.status(400).send({
success: false,
message: 'File size exceeds 10MB limit',
});
}
3. 状态追踪
文档处理状态流:
uploading → parsing → indexing → completed
↘ error
前端轮询:
// 每5秒检查一次处理中的文档
const interval = setInterval(() => {
if (hasProcessingDocs) {
fetchDocuments(currentKb.id);
}
}, 5000);
后端轮询:
// Service层:上传后自动轮询Dify状态
async function pollDocumentStatus(userId, kbId, documentId, difyDocumentId) {
for (let i = 0; i < 30; i++) {
await new Promise(resolve => setTimeout(resolve, 2000));
const difyDocument = await difyClient.getDocument(
knowledgeBase.difyDatasetId,
difyDocumentId
);
await prisma.document.update({
where: { id: documentId },
data: {
status: difyDocument.indexing_status,
progress: calculateProgress(difyDocument),
segmentsCount: difyDocument.word_count,
tokensCount: difyDocument.tokens,
},
});
if (difyDocument.indexing_status === 'completed') break;
if (difyDocument.indexing_status === 'error') break;
}
}
4. 错误处理
统一错误处理:
// Store层
try {
await operation();
} catch (error: any) {
const errorMsg = error.response?.data?.message || '操作失败';
set({ error: errorMsg, loading: false });
throw new Error(errorMsg);
}
// 组件层
useEffect(() => {
if (error) {
message.error(error);
clearError();
}
}, [error]);
// 操作层
const handleDelete = async (kb: KnowledgeBase) => {
try {
await deleteKnowledgeBase(kb.id);
message.success('知识库删除成功');
} catch (error: any) {
message.error(error.message || '删除失败');
}
};
📊 UI/UX设计
1. 响应式布局
知识库列表:
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 16px;
统计信息:
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
2. 交互反馈
Loading状态:
- ✅ 按钮
loading属性 - ✅ 列表
loading属性 - ✅ 上传进度条
- ✅ Spin加载指示器
成功/失败提示:
message.success('操作成功');
message.error('操作失败');
message.warning('已达到上限');
确认对话框:
<Popconfirm
title="确认删除?"
description="删除知识库将同时删除其中的所有文档,此操作不可恢复。"
onConfirm={onDelete}
okText="确认"
cancelText="取消"
okButtonProps={{ danger: true }}
>
<Button danger>删除</Button>
</Popconfirm>
3. 状态可视化
状态图标:
- 🔵 上传中(Loading图标 + 蓝色)
- 🟡 解析中/索引中(Clock图标 + 黄色)
- 🟢 已就绪(CheckCircle图标 + 绿色)
- 🔴 失败(CloseCircle图标 + 红色)
进度显示:
- 处理中:
<Progress percent={progress} status="active" /> - 已完成:
段落数 | Token数 - 失败:
处理失败(带错误详情Tooltip)
✅ 测试验证
编译测试
cd D:\MyCursor\AIclinicalresearch\frontend
npm run build
✅ TypeScript编译通过(0错误)
✅ Vite构建成功
✅ 产物大小:1.98MB(gzip: 656.82KB)
代码质量
- ✅ TypeScript类型安全
- ✅ ESLint检查通过
- ✅ 组件化设计
- ✅ 状态管理规范
- ✅ 错误处理完善
📦 新增文件
frontend/src/
├── api/
│ └── knowledgeBaseApi.ts # API服务(270行)
├── stores/
│ └── useKnowledgeBaseStore.ts # 状态管理(180行)
├── components/knowledge/
│ ├── KnowledgeBaseList.tsx # 知识库列表(205行)
│ ├── CreateKBDialog.tsx # 创建对话框(95行)
│ ├── EditKBDialog.tsx # 编辑对话框(85行)
│ ├── DocumentUpload.tsx # 文档上传(145行)
│ └── DocumentList.tsx # 文档列表(220行)
└── pages/
└── KnowledgePage.tsx # 主页面(281行)
总计:8个文件,约1481行代码
🎯 功能清单
知识库管理 ✅
- 创建知识库(带表单验证)
- 编辑知识库(名称、描述)
- 删除知识库(带确认、级联删除)
- 查看知识库列表(卡片式)
- 查看知识库详情(文档列表、统计)
- 配额管理(3个/用户)
文档管理 ✅
- 上传文档(拖拽/点击)
- 删除文档(带确认)
- 重新处理文档(失败时)
- 查看文档列表(表格式)
- 状态追踪(5种状态)
- 进度显示(实时更新)
- 配额管理(50个/知识库)
文件验证 ✅
- 类型验证(PDF、DOC、DOCX、TXT、MD)
- 大小验证(10MB上限)
- 数量验证(50个上限)
- 前端预检查
- 后端二次验证
实时更新 ✅
- 状态轮询(每5秒)
- 上传进度(0-100%)
- 自动刷新(操作后)
- 错误提示(实时)
UI/UX ✅
- 响应式布局
- Loading状态
- 成功/失败提示
- 确认对话框
- 空状态提示
- 状态图标
- 进度条
- Tooltip提示
🚀 后续优化建议
1. 性能优化
- 虚拟滚动(大量文档时)
- 懒加载图片/文件预览
- 分页加载优化
- 代码分割(动态导入)
2. 功能增强
- 文件预览功能
- 批量上传
- 批量删除
- 导入/导出知识库
- 知识库搜索
- 文档内容搜索
- 标签管理
- 文档分类
3. 用户体验
- 上传队列管理
- 断点续传
- 拖拽排序
- 键盘快捷键
- 暗黑模式
- 移动端适配
💡 技术亮点
- 组件化设计:8个独立组件,职责清晰,易于维护
- 状态管理:Zustand集中管理,操作简洁
- 类型安全:完整的TypeScript类型定义
- 错误处理:三层错误处理(API → Store → Component)
- 实时更新:智能轮询,只在需要时启动
- 用户体验:丰富的交互反馈,操作流畅
- 配额管理:前后端双重验证,防止滥用
- 文件验证:多重验证机制,保证数据质量
📝 提交信息
git commit -m "feat(frontend): Day 21 knowledge base management frontend completed"
9 files changed, 1466 insertions(+)
create mode 100644 frontend/src/api/knowledgeBaseApi.ts
create mode 100644 frontend/src/components/knowledge/CreateKBDialog.tsx
create mode 100644 frontend/src/components/knowledge/DocumentList.tsx
create mode 100644 frontend/src/components/knowledge/DocumentUpload.tsx
create mode 100644 frontend/src/components/knowledge/EditKBDialog.tsx
create mode 100644 frontend/src/components/knowledge/KnowledgeBaseList.tsx
create mode 100644 frontend/src/stores/useKnowledgeBaseStore.ts
rewrite frontend/src/pages/AgentChatPage.tsx
rewrite frontend/src/pages/KnowledgePage.tsx
总结:Day 21成功完成知识库管理的前端开发,所有组件功能完整,编译测试通过,为用户提供了流畅的知识库管理体验!🎉