docs: Day 21 completed summary

This commit is contained in:
AI Clinical Dev Team
2025-10-11 13:00:36 +08:00
parent 186ae55302
commit 1613e4e517

View File

@@ -0,0 +1,708 @@
# Day 21 - 知识库管理前端开发完成 ✅
**完成时间**: 2025年10月11日
**提交记录**: feat(frontend): Day 21 knowledge base management frontend completed
---
## 📋 任务概览
完成知识库管理的前端开发,包括:
1. ✅ 前端API服务封装
2. ✅ Zustand状态管理
3. ✅ 知识库列表组件
4. ✅ 创建/编辑知识库对话框
5. ✅ 文档上传组件
6. ✅ 文档列表组件
7. ✅ 主页面集成
8. ✅ 前端编译测试通过
---
## 🎨 前端架构
### 1. API服务层 (`knowledgeBaseApi.ts`)
**类型定义**
```typescript
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方法**
```typescript
// 知识库管理
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**
```typescript
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特点**
```typescript
// 卡片式布局
<Card hoverable onClick={onSelectClick}>
<Card.Meta
avatar={<FolderIcon />}
title={kb.name}
description={
-
-
-
-
}
/>
<Actions>
-
-
</Actions>
</Card>
```
### 2. CreateKBDialog创建对话框
**功能**
- ✅ 表单验证(名称必填、长度限制)
- ✅ 描述字段(可选、字数统计)
- ✅ 配额提示信息
- ✅ Loading状态
- ✅ 错误提示
**验证规则**
```typescript
- 50
- 200
```
**提示信息**
```
📌 提示
• 每个用户最多创建 3 个知识库
• 每个知识库最多上传 50 个文档
• 支持的文件格式PDF、DOC、DOCX、TXT、MD
• 单个文件最大10MB
```
### 3. EditKBDialog编辑对话框
**功能**
- ✅ 自动填充现有数据
- ✅ 表单验证
- ✅ 更新成功提示
- ✅ 错误处理
### 4. DocumentUpload文档上传
**功能**
- ✅ 拖拽上传
- ✅ 点击上传
- ✅ 文件类型验证(前端)
- ✅ 文件大小验证10MB
- ✅ 上传进度显示
- ✅ 配额检查50个/知识库)
- ✅ 实时进度条
**验证逻辑**
```typescript
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; // 手动上传
};
```
**上传流程**
```typescript
customRequest = async (options) => {
1. useKnowledgeBaseStore.uploadDocument()
2. 0-100%
3.
4. /
}
```
### 5. DocumentList文档列表
**功能**
- ✅ 表格展示
- ✅ 状态图标(上传中、解析中、索引中、已就绪、失败)
- ✅ 进度显示
- ✅ 文件大小格式化
- ✅ Token数、段落数显示
- ✅ 删除操作(带确认)
- ✅ 重试按钮(失败状态)
- ✅ 分页
- ✅ 空状态
**状态图标**
```typescript
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知识库列表
```typescript
<KnowledgeBaseList
knowledgeBases={knowledgeBases}
onCreateClick={() => setCreateDialogOpen(true)}
onEditClick={handleEdit}
onDeleteClick={handleDelete}
onSelectClick={handleSelectKb} // 切换到详情视图
/>
<CreateKBDialog />
<EditKBDialog />
```
#### 视图2知识库详情
```typescript
<返回按钮 onClick={handleBackToList} />
<Card>
<知识库名称和描述>
<编辑按钮>
</Card>
<Tabs>
<TabPane key="documents">
<DocumentUpload />
<DocumentList />
</TabPane>
<TabPane key="stats">
<统计卡片网格>
-
-
-
-
- Token数
-
</统计卡片网格>
</TabPane>
</Tabs>
```
**实时状态轮询**
```typescript
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个/用户)**
```typescript
// 前端检查
const canCreateMore = knowledgeBases.length < 3;
<Button
disabled={!canCreateMore}
onClick={onCreateClick}
>
</Button>
// 后端验证
if (user.kbUsed >= user.kbQuota) {
throw new Error('Knowledge base quota exceeded');
}
```
**文档配额50个/知识库)**
```typescript
// 前端检查
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. 文件验证
**前端验证**
```typescript
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;
}
```
**后端验证**
```typescript
// 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
```
**前端轮询**
```typescript
// 每5秒检查一次处理中的文档
const interval = setInterval(() => {
if (hasProcessingDocs) {
fetchDocuments(currentKb.id);
}
}, 5000);
```
**后端轮询**
```typescript
// 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. 错误处理
**统一错误处理**
```typescript
// 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. 响应式布局
**知识库列表**
```css
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 16px;
```
**统计信息**
```css
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
```
### 2. 交互反馈
**Loading状态**
- ✅ 按钮 `loading` 属性
- ✅ 列表 `loading` 属性
- ✅ 上传进度条
- ✅ Spin加载指示器
**成功/失败提示**
```typescript
message.success('操作成功');
message.error('操作失败');
message.warning('已达到上限');
```
**确认对话框**
```typescript
<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`
---
## ✅ 测试验证
### 编译测试
```bash
cd D:\MyCursor\AIclinicalresearch\frontend
npm run build
✅ TypeScript编译通过0错误
✅ Vite构建成功
✅ 产物大小1.98MBgzip: 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行代码
---
## 🎯 功能清单
### 知识库管理 ✅
- [x] 创建知识库(带表单验证)
- [x] 编辑知识库(名称、描述)
- [x] 删除知识库(带确认、级联删除)
- [x] 查看知识库列表(卡片式)
- [x] 查看知识库详情(文档列表、统计)
- [x] 配额管理3个/用户)
### 文档管理 ✅
- [x] 上传文档(拖拽/点击)
- [x] 删除文档(带确认)
- [x] 重新处理文档(失败时)
- [x] 查看文档列表(表格式)
- [x] 状态追踪5种状态
- [x] 进度显示(实时更新)
- [x] 配额管理50个/知识库)
### 文件验证 ✅
- [x] 类型验证PDF、DOC、DOCX、TXT、MD
- [x] 大小验证10MB上限
- [x] 数量验证50个上限
- [x] 前端预检查
- [x] 后端二次验证
### 实时更新 ✅
- [x] 状态轮询每5秒
- [x] 上传进度0-100%
- [x] 自动刷新(操作后)
- [x] 错误提示(实时)
### UI/UX ✅
- [x] 响应式布局
- [x] Loading状态
- [x] 成功/失败提示
- [x] 确认对话框
- [x] 空状态提示
- [x] 状态图标
- [x] 进度条
- [x] Tooltip提示
---
## 🚀 后续优化建议
### 1. 性能优化
- [ ] 虚拟滚动(大量文档时)
- [ ] 懒加载图片/文件预览
- [ ] 分页加载优化
- [ ] 代码分割(动态导入)
### 2. 功能增强
- [ ] 文件预览功能
- [ ] 批量上传
- [ ] 批量删除
- [ ] 导入/导出知识库
- [ ] 知识库搜索
- [ ] 文档内容搜索
- [ ] 标签管理
- [ ] 文档分类
### 3. 用户体验
- [ ] 上传队列管理
- [ ] 断点续传
- [ ] 拖拽排序
- [ ] 键盘快捷键
- [ ] 暗黑模式
- [ ] 移动端适配
---
## 💡 技术亮点
1. **组件化设计**8个独立组件职责清晰易于维护
2. **状态管理**Zustand集中管理操作简洁
3. **类型安全**完整的TypeScript类型定义
4. **错误处理**三层错误处理API → Store → Component
5. **实时更新**:智能轮询,只在需要时启动
6. **用户体验**:丰富的交互反馈,操作流畅
7. **配额管理**:前后端双重验证,防止滥用
8. **文件验证**:多重验证机制,保证数据质量
---
## 📝 提交信息
```bash
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成功完成知识库管理的前端开发所有组件功能完整编译测试通过为用户提供了流畅的知识库管理体验🎉