You've already forked DataMate
feat(data-annotation): 扩展文件预览功能支持多媒体格式
- 添加对图片、视频、音频文件的预览支持 - 新增文件类型检测逻辑,支持多种媒体格式扩展名 - 实现不同文件类型的预览界面适配 - 更新预览弹窗以支持文本、图像、音视频内容展示 - 调整预览窗口尺寸以优化不同媒体类型显示效果 - 完善预览组件卸载时的状态清理机制
This commit is contained in:
@@ -48,6 +48,8 @@ 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 [previewMediaUrl, setPreviewMediaUrl] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
@@ -121,30 +123,57 @@ 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 等)");
|
||||
// 文件类型扩展名映射
|
||||
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) {
|
||||
message.warning("不支持预览该文件类型");
|
||||
return;
|
||||
}
|
||||
|
||||
setFileContentLoading(true);
|
||||
setPreviewFileName(file.fileName);
|
||||
|
||||
const fileUrl = `/api/data-management/datasets/${selectedDatasetId}/files/${file.id}/download`;
|
||||
|
||||
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);
|
||||
if (isTextFile) {
|
||||
// 文本文件:获取内容
|
||||
const response = await fetch(fileUrl);
|
||||
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");
|
||||
}
|
||||
setFileContentVisible(true);
|
||||
} catch (error) {
|
||||
@@ -574,7 +603,7 @@ export default function CreateAnnotationTask({
|
||||
</Button>
|
||||
]}
|
||||
>
|
||||
<div className="mb-2 text-xs text-gray-500">点击文件名可预览文本类文件内容</div>
|
||||
<div className="mb-2 text-xs text-gray-500">点击文件名可预览文件内容(支持文本、图片、音频、视频)</div>
|
||||
<Table
|
||||
dataSource={datasetPreviewData}
|
||||
columns={[
|
||||
@@ -618,29 +647,66 @@ export default function CreateAnnotationTask({
|
||||
{/* 文件内容预览弹窗 */}
|
||||
<Modal
|
||||
open={fileContentVisible}
|
||||
onCancel={() => setFileContentVisible(false)}
|
||||
onCancel={() => {
|
||||
setFileContentVisible(false);
|
||||
setPreviewMediaUrl("");
|
||||
setFileContent("");
|
||||
}}
|
||||
title={`文件预览:${previewFileName}`}
|
||||
width={800}
|
||||
width={previewFileType === "text" ? 800 : 700}
|
||||
footer={[
|
||||
<Button key="close" onClick={() => setFileContentVisible(false)}>
|
||||
<Button key="close" onClick={() => {
|
||||
setFileContentVisible(false);
|
||||
setPreviewMediaUrl("");
|
||||
setFileContent("");
|
||||
}}>
|
||||
关闭
|
||||
</Button>
|
||||
]}
|
||||
>
|
||||
<pre
|
||||
style={{
|
||||
maxHeight: '500px',
|
||||
overflow: 'auto',
|
||||
backgroundColor: '#f5f5f5',
|
||||
padding: '12px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-all',
|
||||
}}
|
||||
>
|
||||
{fileContent}
|
||||
</pre>
|
||||
{previewFileType === "text" && (
|
||||
<pre
|
||||
style={{
|
||||
maxHeight: '500px',
|
||||
overflow: 'auto',
|
||||
backgroundColor: '#f5f5f5',
|
||||
padding: '12px',
|
||||
borderRadius: '4px',
|
||||
fontSize: '12px',
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-all',
|
||||
}}
|
||||
>
|
||||
{fileContent}
|
||||
</pre>
|
||||
)}
|
||||
{previewFileType === "image" && (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<img
|
||||
src={previewMediaUrl}
|
||||
alt={previewFileName}
|
||||
style={{ maxWidth: '100%', maxHeight: '500px', objectFit: 'contain' }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{previewFileType === "video" && (
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<video
|
||||
src={previewMediaUrl}
|
||||
controls
|
||||
style={{ maxWidth: '100%', maxHeight: '500px' }}
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
</div>
|
||||
)}
|
||||
{previewFileType === "audio" && (
|
||||
<div style={{ textAlign: 'center', padding: '40px 0' }}>
|
||||
<audio src={previewMediaUrl} controls style={{ width: '100%' }}>
|
||||
您的浏览器不支持音频播放
|
||||
</audio>
|
||||
</div>
|
||||
)}
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user