import { useState } from 'react'; import { Button, Input, Table, Tag, Space, Tooltip, Popconfirm, Switch, message, Empty, Spin, } from 'antd'; import { SearchOutlined, ReloadOutlined, DeleteOutlined, FileTextOutlined, CloudUploadOutlined, EyeOutlined, ClockCircleOutlined, CheckCircleOutlined, SyncOutlined, ExclamationCircleOutlined, PauseCircleOutlined, } from '@ant-design/icons'; import type { ColumnsType } from 'antd/es/table'; import type { Document, IndexingStatus } from '~/api/dify-dataset/type/documentTypes'; import { deleteDocument, toggleDocumentStatus } from '~/api/dify-dataset/api/documentApi'; import DocumentUpload from './document-upload'; import '../../styles/components/dify-dataset-manager/index.css'; interface DocumentListProps { datasetId: string; datasetName: string; documents: Document[]; loading: boolean; total: number; page: number; pageSize: number; onPageChange: (page: number) => void; onDocumentDeleted: (documentId: string) => void; onDocumentStatusChanged: (documentId: string, enabled: boolean) => void; onRefresh: () => void; onViewDocument?: (document: Document) => void; } /** * 文档列表组件 */ export default function DocumentList({ datasetId, documents, loading, total, page, pageSize, onPageChange, onDocumentDeleted, onDocumentStatusChanged, onRefresh, onViewDocument, }: DocumentListProps) { const [searchValue, setSearchValue] = useState(''); const [deletingId, setDeletingId] = useState(null); // 显示上传页面的状态 const [showUploadPage, setShowUploadPage] = useState(false); /** * 获取状态标签配置 */ const getStatusConfig = (status: IndexingStatus) => { const configs: Record = { completed: { color: 'success', icon: , text: '已完成' }, indexing: { color: 'processing', icon: , text: '索引中' }, waiting: { color: 'warning', icon: , text: '等待中' }, parsing: { color: 'processing', icon: , text: '解析中' }, cleaning: { color: 'processing', icon: , text: '清洗中' }, splitting: { color: 'processing', icon: , text: '分段中' }, paused: { color: 'default', icon: , text: '已暂停' }, error: { color: 'error', icon: , text: '错误' }, }; return configs[status] || { color: 'default', icon: null, text: status }; }; /** * 格式化日期 */ const formatDate = (timestamp: number) => { return new Date(timestamp * 1000).toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }); }; /** * 格式化数字 */ const formatNumber = (num: number) => { if (num >= 10000) { return (num / 10000).toFixed(1) + 'w'; } if (num >= 1000) { return (num / 1000).toFixed(1) + 'k'; } return num.toString(); }; /** * 处理删除文档 */ const handleDelete = async (documentId: string) => { setDeletingId(documentId); try { await deleteDocument(datasetId, documentId); message.success('删除成功'); onDocumentDeleted(documentId); } catch (err: any) { console.error('删除文档失败:', err); message.error(err.message || '删除失败'); } finally { setDeletingId(null); } }; /** * 处理启用/禁用文档 */ const handleToggleStatus = async (documentId: string, enabled: boolean) => { try { await toggleDocumentStatus(datasetId, documentId, enabled); message.success(enabled ? '已启用' : '已禁用'); onDocumentStatusChanged(documentId, enabled); } catch (err: any) { console.error('切换文档状态失败:', err); message.error(err.message || '操作失败'); } }; /** * 点击上传按钮,显示上传页面 */ const handleUploadClick = () => { if (!datasetId) { message.error('请先选择知识库'); return; } setShowUploadPage(true); }; /** * 关闭上传页面 */ const handleUploadClose = () => { setShowUploadPage(false); }; /** * 上传成功回调 */ const handleUploadSuccess = () => { setShowUploadPage(false); onRefresh(); }; // 过滤文档 const filteredDocuments = documents.filter((doc) => doc.name.toLowerCase().includes(searchValue.toLowerCase()) ); // 表格列定义 const columns: ColumnsType = [ { title: '文档名称', dataIndex: 'name', key: 'name', ellipsis: true, render: (name: string) => (
{name}
), }, { title: '状态', dataIndex: 'indexing_status', key: 'indexing_status', width: 120, render: (status: IndexingStatus) => { const config = getStatusConfig(status); return ( {config.text} ); }, }, { title: '字数', dataIndex: 'word_count', key: 'word_count', width: 100, render: (count: number) => formatNumber(count), }, { title: '命中次数', dataIndex: 'hit_count', key: 'hit_count', width: 100, render: (count: number) => formatNumber(count), }, { title: '启用', dataIndex: 'enabled', key: 'enabled', width: 80, render: (enabled: boolean, record) => ( handleToggleStatus(record.id, checked)} /> ), }, { title: '创建时间', dataIndex: 'created_at', key: 'created_at', width: 160, render: (timestamp: number) => formatDate(timestamp), }, { title: '操作', key: 'action', width: 120, render: (_, record) => ( {/* 搜索栏 */}
} value={searchValue} onChange={(e) => setSearchValue(e.target.value)} allowClear style={{ width: 280 }} />
{/* 文档表格 */}
{loading && documents.length === 0 ? (
加载中...
) : filteredDocuments.length === 0 ? (
{!searchValue && ( )}
) : ( )} {/* 底部分页器 */} {filteredDocuments.length > 0 && (
共 {total} 条
第 {page} 页 / 共 {Math.ceil(total / pageSize)} 页
)} )} ); }