diff --git a/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx b/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx index 451e1e1..daf28a1 100644 --- a/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx +++ b/frontend/src/pages/DataAnnotation/Create/components/CreateAnnotationTaskDialog.tsx @@ -6,6 +6,12 @@ import TextArea from "antd/es/input/TextArea"; import { useEffect, useMemo, useState } from "react"; import type { ReactNode } from "react"; import { Eye } from "lucide-react"; +import { + PREVIEW_TEXT_MAX_LENGTH, + resolvePreviewFileType, + truncatePreviewText, + type PreviewFileType, +} from "@/utils/filePreview"; import { createAnnotationTaskUsingPost, getAnnotationTaskByIdUsingGet, @@ -53,6 +59,7 @@ const isRecord = (value: unknown): value is Record => !!value && typeof value === "object" && !Array.isArray(value); const DEFAULT_SEGMENTATION_ENABLED = true; +const FILE_PREVIEW_MAX_HEIGHT = 500; const SEGMENTATION_OPTIONS = [ { label: "需要切片段", value: true }, { label: "不需要切片段", value: false }, @@ -116,7 +123,7 @@ export default function CreateAnnotationTask({ const [fileContent, setFileContent] = useState(""); const [fileContentLoading, setFileContentLoading] = useState(false); const [previewFileName, setPreviewFileName] = useState(""); - const [previewFileType, setPreviewFileType] = useState<"text" | "image" | "video" | "audio">("text"); + const [previewFileType, setPreviewFileType] = useState("text"); const [previewMediaUrl, setPreviewMediaUrl] = useState(""); // 任务详情加载状态(编辑模式) @@ -297,57 +304,32 @@ export default function CreateAnnotationTask({ // 预览文件内容 const handlePreviewFileContent = async (file: DatasetPreviewFile) => { - const fileName = file.fileName?.toLowerCase() || ''; - - // 文件类型扩展名映射 - const textExtensions = ['.json', '.jsonl', '.txt', '.csv', '.tsv', '.xml', '.md', '.yaml', '.yml']; - const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp', '.svg']; - const videoExtensions = ['.mp4', '.webm', '.ogg', '.mov', '.avi']; - const audioExtensions = ['.mp3', '.wav', '.ogg', '.aac', '.flac', '.m4a']; - - const isTextFile = textExtensions.some(ext => fileName.endsWith(ext)); - const isImageFile = imageExtensions.some(ext => fileName.endsWith(ext)); - const isVideoFile = videoExtensions.some(ext => fileName.endsWith(ext)); - const isAudioFile = audioExtensions.some(ext => fileName.endsWith(ext)); - - if (!isTextFile && !isImageFile && !isVideoFile && !isAudioFile) { + const fileType = resolvePreviewFileType(file.fileName); + if (!fileType) { message.warning("不支持预览该文件类型"); return; } setFileContentLoading(true); setPreviewFileName(file.fileName); + setPreviewFileType(fileType); + setFileContent(""); + setPreviewMediaUrl(""); - const fileUrl = `/api/data-management/datasets/${selectedDatasetId}/files/${file.id}/download`; + const previewUrl = `/api/data-management/datasets/${selectedDatasetId}/files/${file.id}/preview`; try { - if (isTextFile) { + if (fileType === "text") { // 文本文件:获取内容 - const response = await fetch(fileUrl); + const response = await fetch(previewUrl); 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); - } - setPreviewFileType("text"); - } else if (isImageFile) { - // 图片文件:直接使用 URL - setPreviewMediaUrl(fileUrl); - setPreviewFileType("image"); - } else if (isVideoFile) { - // 视频文件:使用 URL - setPreviewMediaUrl(fileUrl); - setPreviewFileType("video"); - } else if (isAudioFile) { - // 音频文件:使用 URL - setPreviewMediaUrl(fileUrl); - setPreviewFileType("audio"); + setFileContent(truncatePreviewText(text, PREVIEW_TEXT_MAX_LENGTH)); + } else { + // 媒体/PDF 文件:直接使用预览地址 + setPreviewMediaUrl(previewUrl); } setFileContentVisible(true); } catch (error) { @@ -878,7 +860,7 @@ export default function CreateAnnotationTask({ ]} > -
点击文件名可预览文件内容(支持文本、图片、音频、视频)
+
点击文件名可预览文件内容(支持文本、图片、音频、视频、PDF)
)} + {previewFileType === "pdf" && ( +