From 1613e4e517ffd82bc11c1bd4ca18af8354cf3989 Mon Sep 17 00:00:00 2001 From: AI Clinical Dev Team Date: Sat, 11 Oct 2025 13:00:36 +0800 Subject: [PATCH] docs: Day 21 completed summary --- docs/05-每日进度/Day21-知识库管理前端完成.md | 708 +++++++++++++++++++ 1 file changed, 708 insertions(+) create mode 100644 docs/05-每日进度/Day21-知识库管理前端完成.md diff --git a/docs/05-每日进度/Day21-知识库管理前端完成.md b/docs/05-每日进度/Day21-知识库管理前端完成.md new file mode 100644 index 00000000..e0a464d2 --- /dev/null +++ b/docs/05-每日进度/Day21-知识库管理前端完成.md @@ -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; + fetchKnowledgeBaseById: (id: string) => Promise; + createKnowledgeBase: (name, description?) => Promise; + updateKnowledgeBase: (id, name?, description?) => Promise; + deleteKnowledgeBase: (id: string) => Promise; + + // 文档操作 + fetchDocuments: (kbId: string) => Promise; + uploadDocument: (kbId, file, onProgress?) => Promise; + deleteDocument: (id: string) => Promise; + reprocessDocument: (id: string) => Promise; +} +``` + +**特点**: +- ✅ 集中式状态管理 +- ✅ 自动错误处理 +- ✅ Loading状态管理 +- ✅ 操作后自动刷新 + +--- + +## 🧩 核心组件 + +### 1. KnowledgeBaseList(知识库列表) + +**功能**: +- ✅ 卡片式展示(3列网格布局) +- ✅ 配额显示(已使用 X/3 个) +- ✅ 文档数量、总大小、创建时间 +- ✅ 编辑/删除操作 +- ✅ 空状态提示 +- ✅ 配额上限禁用创建按钮 + +**UI特点**: +```typescript +// 卡片式布局 + + } + title={kb.name} + description={ + - 描述(省略显示) + - 文档数量 + - 总大小 + - 创建时间 + } + /> + + - 编辑按钮 + - 删除按钮(带确认) + + +``` + +### 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: , text: '上传中' }, + parsing: { color: 'processing', icon: , text: '解析中' }, + indexing: { color: 'processing', icon: , text: '索引中' }, + completed: { color: 'success', icon: , text: '已就绪' }, + error: { color: 'error', icon: , text: '失败' }, +}; +``` + +**进度显示**: +- 处理中:进度条(0-100%) +- 已完成:显示段落数和Token数 +- 失败:显示错误提示(Tooltip) + +### 6. KnowledgePage(主页面) + +**双视图架构**: + +#### 视图1:知识库列表 +```typescript + setCreateDialogOpen(true)} + onEditClick={handleEdit} + onDeleteClick={handleDelete} + onSelectClick={handleSelectKb} // 切换到详情视图 +/> + + + +``` + +#### 视图2:知识库详情 +```typescript +<返回按钮 onClick={handleBackToList} /> + + + <知识库名称和描述> + <编辑按钮> + + + + + + + + + + <统计卡片网格> + - 总文档数 + - 已就绪数 + - 处理中数 + - 失败数 + - 总Token数 + - 总段落数 + + + +``` + +**实时状态轮询**: +```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; + + + +// 后端验证 +if (user.kbUsed >= user.kbQuota) { + throw new Error('Knowledge base quota exceeded'); +} +``` + +**文档配额(50个/知识库)**: +```typescript +// 前端检查 +const isAtLimit = currentDocumentCount >= 50; + + { + 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 + + + +``` + +### 3. 状态可视化 + +**状态图标**: +- 🔵 上传中(Loading图标 + 蓝色) +- 🟡 解析中/索引中(Clock图标 + 黄色) +- 🟢 已就绪(CheckCircle图标 + 绿色) +- 🔴 失败(CloseCircle图标 + 红色) + +**进度显示**: +- 处理中:`` +- 已完成:`段落数 | Token数` +- 失败:`处理失败(带错误详情Tooltip)` + +--- + +## ✅ 测试验证 + +### 编译测试 +```bash +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行代码 + +--- + +## 🎯 功能清单 + +### 知识库管理 ✅ +- [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成功完成知识库管理的前端开发,所有组件功能完整,编译测试通过,为用户提供了流畅的知识库管理体验!🎉 +