import React, { useState, useEffect, useCallback } from 'react'; import { useDropzone } from 'react-dropzone'; import { FileText, Upload, Search, RefreshCcw, Trash2, Clock, ChevronDown, ChevronUp, Database, FileSpreadsheet, File } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Card } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { backendApi } from '@/db/backend-api'; import { format } from 'date-fns'; import { toast } from 'sonner'; import { cn } from '@/lib/utils'; import { Skeleton } from '@/components/ui/skeleton'; type DocumentItem = { doc_id: string; filename: string; original_filename: string; doc_type: string; file_size: number; created_at: string; metadata?: { row_count?: number; column_count?: number; columns?: string[]; }; }; const Documents: React.FC = () => { const [documents, setDocuments] = useState([]); const [loading, setLoading] = useState(true); const [search, setSearch] = useState(''); const [expandedDoc, setExpandedDoc] = useState(null); const [uploading, setUploading] = useState(false); const loadDocuments = useCallback(async () => { setLoading(true); try { const result = await backendApi.getDocuments(undefined, 100); if (result.success) { setDocuments(result.documents || []); } } catch (err: any) { toast.error('加载文档失败: ' + (err.message || '未知错误')); } finally { setLoading(false); } }, []); useEffect(() => { loadDocuments(); }, [loadDocuments]); const onDrop = async (acceptedFiles: File[]) => { setUploading(true); const uploaded: string[] = []; try { for (const file of acceptedFiles) { try { const result = await backendApi.uploadDocument(file); if (result.task_id) { uploaded.push(file.name); // 轮询任务状态 const checkStatus = async () => { let attempts = 0; while (attempts < 30) { try { const status = await backendApi.getTaskStatus(result.task_id); if (status.status === 'success') { toast.success(`文件 ${file.name} 处理完成`); loadDocuments(); return; } else if (status.status === 'failure') { toast.error(`文件 ${file.name} 处理失败: ${status.error}`); return; } } catch (e) { console.error('检查状态失败', e); } await new Promise(resolve => setTimeout(resolve, 2000)); attempts++; } toast.error(`文件 ${file.name} 处理超时`); }; checkStatus(); } } catch (err: any) { toast.error(`上传失败: ${file.name} - ${err.message}`); } } if (uploaded.length > 0) { toast.success(`已提交 ${uploaded.length} 个文件进行处理`); } } finally { setUploading(false); } }; const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop, accept: { 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'], 'text/markdown': ['.md'], 'text/plain': ['.txt'] } }); const handleDelete = async (docId: string) => { try { const result = await backendApi.deleteDocument(docId); if (result.success) { setDocuments(prev => prev.filter(d => d.doc_id !== docId)); toast.success('文档已删除'); } } catch (err: any) { toast.error('删除失败: ' + (err.message || '未知错误')); } }; const filteredDocs = documents.filter(doc => doc.original_filename.toLowerCase().includes(search.toLowerCase()) ); const getDocIcon = (docType: string) => { switch (docType) { case 'xlsx': case 'xls': return ; case 'docx': case 'doc': return ; default: return ; } }; return (

文档中心

上传并管理您的非结构化文档(docx/md/txt),系统将自动进行深度理解与信息提取。

{/* Upload Zone - For non-Excel documents */}
{uploading ? : }

{isDragActive ? '释放以开始上传' : '点击或拖拽文件到这里'}

支持 docx, md, txt 格式文档,系统将自动识别关键信息并存入 MongoDB

Word 文档 Markdown 文本文件
{/* Filter & Search */}
setSearch(e.target.value)} />
{documents.length} 个文档
{/* Document List */}
{loading ? ( Array.from({ length: 3 }).map((_, i) => ( )) ) : filteredDocs.length > 0 ? ( filteredDocs.map((doc) => (
{getDocIcon(doc.doc_type)}

{doc.original_filename}

{doc.doc_type} {doc.metadata?.columns && ( {doc.metadata.columns.length} 列 )}
{format(new Date(doc.created_at), 'yyyy-MM-dd HH:mm')} {(doc.file_size / 1024).toFixed(1)} KB
{/* Expanded Details */} {expandedDoc === doc.doc_id && (

文件信息

文件名 {doc.original_filename}
文件大小 {(doc.file_size / 1024).toFixed(2)} KB
文档类型 {doc.doc_type.toUpperCase()}
创建时间 {format(new Date(doc.created_at), 'yyyy-MM-dd HH:mm:ss')}
{doc.metadata?.columns && doc.metadata.columns.length > 0 && (

表格结构

{doc.metadata.columns.map((col: string, idx: number) => ( {col} ))}
{doc.metadata.row_count && (

共 {doc.metadata.row_count} 行数据

)}
)}

存储位置

{doc.doc_type === 'xlsx' ? 'MySQL 数据库(结构化数据)' : 'MongoDB 数据库(非结构化文档)'}
)}
)) ) : (

空空如也

快去上传一份文档,体验 AI 的智能解析能力吧!

)}
); }; export default Documents;