import React, { useState, useEffect } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import { Box, Typography, Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow, Chip, IconButton, Button, TextField, InputAdornment, LinearProgress, Alert, Dialog, DialogTitle, DialogContent, DialogActions, Menu, MenuItem, Tooltip, Stack, Card, CardContent, Grid, Breadcrumbs, Link, } from '@mui/material'; import { Search as SearchIcon, Upload as UploadIcon, Delete as DeleteIcon, Refresh as RefreshIcon, MoreVert as MoreVertIcon, InsertDriveFile as FileIcon, PictureAsPdf as PdfIcon, Description as DocIcon, Image as ImageIcon, VideoFile as VideoIcon, AudioFile as AudioIcon, CloudUpload as CloudUploadIcon, Settings as SettingsIcon, } from '@mui/icons-material'; import knowledgeService from '@/services/knowledge_service'; import type { IKnowledge, IKnowledgeFile } from '@/interfaces/database/knowledge'; import { RUNNING_STATUS_KEYS, type RunningStatus } from '@/constants/knowledge'; // 文件类型图标映射 const getFileIcon = (type: string) => { const lowerType = type.toLowerCase(); if (lowerType.includes('pdf')) return ; if (lowerType.includes('doc') || lowerType.includes('txt') || lowerType.includes('md')) return ; if (lowerType.includes('jpg') || lowerType.includes('png') || lowerType.includes('jpeg')) return ; if (lowerType.includes('mp4') || lowerType.includes('avi') || lowerType.includes('mov')) return ; if (lowerType.includes('mp3') || lowerType.includes('wav') || lowerType.includes('m4a')) return ; return ; }; // 文件大小格式化 const formatFileSize = (bytes: number): string => { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; // 解析状态映射 const getStatusChip = (status: string, progress: number) => { switch (status) { case '1': return ; case '0': return ; default: return ; } }; // 运行状态映射 const getRunStatusChip = (run: RunningStatus, progress: number) => { switch (run) { case RUNNING_STATUS_KEYS.UNSTART: return ; case RUNNING_STATUS_KEYS.RUNNING: return ( {progress}% ); case RUNNING_STATUS_KEYS.CANCEL: return ; case RUNNING_STATUS_KEYS.DONE: return ; case RUNNING_STATUS_KEYS.FAIL: return ; default: return ; } }; function KnowledgeBaseDetail() { const { id } = useParams<{ id: string }>(); const navigate = useNavigate(); // 状态管理 const [knowledgeBase, setKnowledgeBase] = useState(null); const [files, setFiles] = useState([]); const [loading, setLoading] = useState(true); const [filesLoading, setFilesLoading] = useState(false); const [error, setError] = useState(null); const [searchKeyword, setSearchKeyword] = useState(''); const [selectedFiles, setSelectedFiles] = useState([]); const [anchorEl, setAnchorEl] = useState(null); const [uploadDialogOpen, setUploadDialogOpen] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); // 获取知识库详情 const fetchKnowledgeDetail = async () => { if (!id) return; try { setLoading(true); const response = await knowledgeService.getKnowledgeDetail({ kb_id: id }); if (response.data.code === 0) { setKnowledgeBase(response.data.data); } else { setError(response.data.message || '获取知识库详情失败'); } } catch (err: any) { setError(err.response?.data?.message || err.message || '获取知识库详情失败'); } finally { setLoading(false); } }; // 获取文件列表 const fetchFileList = async () => { if (!id) return; try { setFilesLoading(true); // const response = await knowledgeService.getDocumentList( // { kb_id: id }, // { keywords: searchKeyword } // ); // if (response.data.code === 0) { // setFiles(response.data.data.docs || []); // } else { // setError(response.data.message || '获取文件列表失败'); // } } catch (err: any) { setError(err.response?.data?.message || err.message || '获取文件列表失败'); } finally { setFilesLoading(false); } }; // 删除文件 const handleDeleteFiles = async () => { if (selectedFiles.length === 0) return; try { await knowledgeService.removeDocument({ doc_ids: selectedFiles }); setSelectedFiles([]); setDeleteDialogOpen(false); fetchFileList(); // 刷新列表 } catch (err: any) { setError(err.response?.data?.message || err.message || '删除文件失败'); } }; // 重新解析文件 const handleReparse = async (docIds: string[]) => { try { await knowledgeService.runDocument({ doc_ids: docIds }); fetchFileList(); // 刷新列表 } catch (err: any) { setError(err.response?.data?.message || err.message || '重新解析失败'); } }; // 初始化数据 useEffect(() => { fetchKnowledgeDetail(); // fetchFileList(); }, [id]); // 搜索文件 useEffect(() => { const timer = setTimeout(() => { fetchFileList(); }, 500); return () => clearTimeout(timer); }, [searchKeyword]); // 过滤文件 const filteredFiles = files.filter(file => file.name.toLowerCase().includes(searchKeyword.toLowerCase()) ); if (loading) { return ( 加载中... ); } if (error) { return ( {error} ); } if (!knowledgeBase) { return ( 知识库不存在 ); } return ( {/* 面包屑导航 */} navigate('/knowledge')} sx={{ textDecoration: 'none' }} > 知识库 {knowledgeBase.name} {/* 知识库信息卡片 */} {knowledgeBase.name} {knowledgeBase.description || '暂无描述'} 创建时间: {knowledgeBase.create_date} 更新时间: {knowledgeBase.update_date} 语言: {knowledgeBase.language} {/* 文件操作栏 */} setSearchKeyword(e.target.value)} InputProps={{ startAdornment: ( ), }} sx={{ minWidth: 300 }} size="small" /> {selectedFiles.length > 0 && ( <> )} fetchFileList()}> {/* 文件列表 */} {/* 全选复选框可以在这里添加 */} 文件名 类型 大小 分块数 状态 解析状态 上传时间 操作 {filesLoading ? ( 加载文件列表... ) : filteredFiles.length === 0 ? ( {searchKeyword ? '没有找到匹配的文件' : '暂无文件'} ) : ( filteredFiles.map((file) => ( {/* 文件选择复选框 */} {getFileIcon(file.type)} {file.name} {formatFileSize(file.size)} {file.chunk_num} {getStatusChip(file.status, file.progress)} {getRunStatusChip(file.run, file.progress)} {file.create_date} setAnchorEl(e.currentTarget)} > )) )}
{/* 文件操作菜单 */} setAnchorEl(null)} > setAnchorEl(null)}> 重新解析 setAnchorEl(null)}> 解析设置 setAnchorEl(null)} sx={{ color: 'error.main' }}> 删除 {/* 上传文件对话框 */} setUploadDialogOpen(false)} maxWidth="sm" fullWidth> 上传文件 拖拽文件到此处或点击上传 支持 PDF, DOCX, TXT, MD, PNG, JPG, MP4, WAV 等格式 {/* 删除确认对话框 */} setDeleteDialogOpen(false)}> 确认删除 确定要删除选中的 {selectedFiles.length} 个文件吗?此操作不可撤销。
); } export default KnowledgeBaseDetail;