feat(knowledge): 添加知识条目文件预览和替换功能

- 后端实现知识条目文件预览接口,支持多种文件类型在线预览
- 后端实现知识条目文件替换功能,保留原有文件管理逻辑
- 前端新增文件预览模态框组件,支持文本、图片、音视频预览
- 前端知识条目编辑器添加文件替换上传功能
- 前端优化文件内容截断预览逻辑,统一使用工具函数处理
- 前端修复 PUT 请求中 FormData 处理问题,确保文件上传正常工作
- 新增文件预览相关工具函数和常量配置
This commit is contained in:
2026-01-29 11:37:36 +08:00
parent d0b5473068
commit ce98be5778
10 changed files with 467 additions and 46 deletions

View File

@@ -4,6 +4,7 @@ import type {
} from "@/pages/DataManagement/dataset.model";
import { App } from "antd";
import { useState } from "react";
import { PREVIEW_TEXT_MAX_LENGTH, resolvePreviewFileType, truncatePreviewText } from "@/utils/filePreview";
import {
deleteDatasetFileUsingDelete,
downloadFileByIdUsingGet,
@@ -15,11 +16,6 @@ import {
} from "../dataset.api";
import { useParams } from "react-router";
const MAX_PREVIEW_LENGTH = 50000;
const TEXT_FILE_EXTENSIONS = [".json", ".jsonl", ".txt", ".csv", ".tsv", ".xml", ".md", ".yaml", ".yml"];
const IMAGE_FILE_EXTENSIONS = [".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg"];
const VIDEO_FILE_EXTENSIONS = [".mp4", ".webm", ".ogg", ".mov", ".avi"];
const AUDIO_FILE_EXTENSIONS = [".mp3", ".wav", ".ogg", ".aac", ".flac", ".m4a"];
export function useFilesOperation(dataset: Dataset) {
const { message } = App.useApp();
@@ -99,23 +95,6 @@ export function useFilesOperation(dataset: Dataset) {
setSelectedFiles([]); // 清空选中状态
};
const resolvePreviewFileType = (fileName?: string) => {
const lowerName = (fileName || "").toLowerCase();
if (TEXT_FILE_EXTENSIONS.some((ext) => lowerName.endsWith(ext))) {
return "text";
}
if (IMAGE_FILE_EXTENSIONS.some((ext) => lowerName.endsWith(ext))) {
return "image";
}
if (VIDEO_FILE_EXTENSIONS.some((ext) => lowerName.endsWith(ext))) {
return "video";
}
if (AUDIO_FILE_EXTENSIONS.some((ext) => lowerName.endsWith(ext))) {
return "audio";
}
return null;
};
const handlePreviewFile = async (file: DatasetFile) => {
const datasetId = dataset?.id || id;
if (!datasetId) {
@@ -146,13 +125,7 @@ export function useFilesOperation(dataset: Dataset) {
throw new Error("下载失败");
}
const text = await response.text();
if (text.length > MAX_PREVIEW_LENGTH) {
setPreviewContent(
`${text.slice(0, MAX_PREVIEW_LENGTH)}\n\n... (内容过长,仅显示前 ${MAX_PREVIEW_LENGTH} 字符)`
);
} else {
setPreviewContent(text);
}
setPreviewContent(truncatePreviewText(text, PREVIEW_TEXT_MAX_LENGTH));
setPreviewVisible(true);
} catch (error) {
console.error("Preview file content error:", error);