feat(annotation): 添加数据集文件内容预览功能

- 添加文件内容预览相关状态管理
- 实现支持多种文本格式文件的预览功能(JSON、JSONL、TXT、CSV等)
- 添加文件内容长度限制以避免页面卡顿
- 在数据集预览表格中添加文件名点击预览功能
- 创建文件内容预览弹窗界面
- 添加文件预览加载状态和错误处理
This commit is contained in:
2026-01-19 19:24:42 +08:00
parent fe5c0fd0a3
commit 7a73322858

View File

@@ -43,6 +43,12 @@ export default function CreateAnnotationTask({
const [datasetPreviewLoading, setDatasetPreviewLoading] = useState(false);
const [selectedDatasetId, setSelectedDatasetId] = useState<string | null>(null);
// 文件内容预览相关状态
const [fileContentVisible, setFileContentVisible] = useState(false);
const [fileContent, setFileContent] = useState("");
const [fileContentLoading, setFileContentLoading] = useState(false);
const [previewFileName, setPreviewFileName] = useState("");
useEffect(() => {
if (!open) return;
const fetchData = async () => {
@@ -113,6 +119,42 @@ export default function CreateAnnotationTask({
}
};
// 预览文件内容
const handlePreviewFileContent = async (file: any) => {
// 支持预览的文本文件类型
const textExtensions = ['.json', '.jsonl', '.txt', '.csv', '.tsv', '.xml', '.md', '.yaml', '.yml'];
const fileName = file.fileName?.toLowerCase() || '';
const isTextFile = textExtensions.some(ext => fileName.endsWith(ext));
if (!isTextFile) {
message.warning("仅支持预览文本类文件(JSON、JSONL、TXT、CSV 等)");
return;
}
setFileContentLoading(true);
setPreviewFileName(file.fileName);
try {
const response = await fetch(`/api/data-management/datasets/${selectedDatasetId}/files/${file.id}/download`);
if (!response.ok) {
throw new Error('下载失败');
}
const text = await response.text();
// 限制预览内容长度,避免大文件导致页面卡顿
const maxLength = 50000;
if (text.length > maxLength) {
setFileContent(text.substring(0, maxLength) + '\n\n... (内容过长,仅显示前 50000 字符)');
} else {
setFileContent(text);
}
setFileContentVisible(true);
} catch (error) {
console.error("Preview file content error:", error);
message.error("获取文件内容失败");
} finally {
setFileContentLoading(false);
}
};
const generateXmlFromConfig = (objects: any[], labels: any[]) => {
let xml = '<View>\n';
@@ -532,6 +574,7 @@ export default function CreateAnnotationTask({
</Button>
]}
>
<div className="mb-2 text-xs text-gray-500"></div>
<Table
dataSource={datasetPreviewData}
columns={[
@@ -540,6 +583,17 @@ export default function CreateAnnotationTask({
dataIndex: "fileName",
key: "fileName",
ellipsis: true,
render: (text: string, record: any) => (
<Button
type="link"
size="small"
className="p-0 h-auto text-left"
loading={fileContentLoading && previewFileName === text}
onClick={() => handlePreviewFileContent(record)}
>
{text}
</Button>
),
},
{
title: "大小",
@@ -560,6 +614,34 @@ export default function CreateAnnotationTask({
size="small"
/>
</Modal>
{/* 文件内容预览弹窗 */}
<Modal
open={fileContentVisible}
onCancel={() => setFileContentVisible(false)}
title={`文件预览:${previewFileName}`}
width={800}
footer={[
<Button key="close" onClick={() => setFileContentVisible(false)}>
</Button>
]}
>
<pre
style={{
maxHeight: '500px',
overflow: 'auto',
backgroundColor: '#f5f5f5',
padding: '12px',
borderRadius: '4px',
fontSize: '12px',
whiteSpace: 'pre-wrap',
wordBreak: 'break-all',
}}
>
{fileContent}
</pre>
</Modal>
</>
);
}