# 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成功完成知识库管理的前端开发,所有组件功能完整,编译测试通过,为用户提供了流畅的知识库管理体验!🎉