diff --git a/frontend/src/pages/DataManagement/Detail/components/ImportConfiguration.tsx b/frontend/src/pages/DataManagement/Detail/components/ImportConfiguration.tsx index b18274b..aa6607b 100644 --- a/frontend/src/pages/DataManagement/Detail/components/ImportConfiguration.tsx +++ b/frontend/src/pages/DataManagement/Detail/components/ImportConfiguration.tsx @@ -1,13 +1,51 @@ -import { Select, Input, Form, Radio, Modal, Button, UploadFile, Switch } from "antd"; -import { InboxOutlined } from "@ant-design/icons"; +import { Select, Input, Form, Radio, Modal, Button, UploadFile, Switch, Tooltip } from "antd"; +import { InboxOutlined, QuestionCircleOutlined } from "@ant-design/icons"; import { dataSourceOptions } from "../../dataset.const"; import { Dataset, DataSource } from "../../dataset.model"; -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useState } from "react"; import { queryTasksUsingGet } from "@/pages/DataCollection/collection.apis"; import { updateDatasetByIdUsingPut } from "../../dataset.api"; import { sliceFile } from "@/utils/file.util"; import Dragger from "antd/es/upload/Dragger"; +/** + * 按行分割文件 + * @param file 原始文件 + * @returns 分割后的文件列表,每行一个文件 + */ +async function splitFileByLines(file: UploadFile): Promise { + const originFile = (file as any).originFileObj || file; + if (!originFile || typeof originFile.text !== "function") { + return [file]; + } + + const text = await originFile.text(); + if (!text) return [file]; + + // 按行分割并过滤空行 + const lines = text.split(/\r?\n/).filter((line: string) => line.trim() !== ""); + if (lines.length === 0) return []; + + // 生成文件名:原文件名_序号.扩展名 + const nameParts = file.name.split("."); + const ext = nameParts.length > 1 ? "." + nameParts.pop() : ""; + const baseName = nameParts.join("."); + const padLength = String(lines.length).length; + + return lines.map((line: string, index: number) => { + const newFileName = `${baseName}_${String(index + 1).padStart(padLength, "0")}${ext}`; + const blob = new Blob([line], { type: "text/plain" }); + const newFile = new File([blob], newFileName, { type: "text/plain" }); + return { + uid: `${file.uid}-${index}`, + name: newFileName, + size: newFile.size, + type: "text/plain", + originFileObj: newFile as any, + } as UploadFile; + }); +} + export default function ImportConfiguration({ data, open, @@ -29,13 +67,6 @@ export default function ImportConfiguration({ const [currentPrefix, setCurrentPrefix] = useState(""); const [fileList, setFileList] = useState([]); - const fileSliceList = useMemo(() => { - const sliceList = fileList.map((file) => { - const slices = sliceFile(file); - return { originFile: file, slices, name: file.name, size: file.size }; - }); - return sliceList; - }, [fileList]); // 本地上传文件相关逻辑 @@ -44,16 +75,34 @@ export default function ImportConfiguration({ }; const handleUpload = async (dataset: Dataset) => { - const formData = new FormData(); - fileList.forEach((file) => { - formData.append("file", file); + let filesToUpload = fileList; + + // 如果启用分行分割,处理文件 + if (importConfig.splitByLine) { + const splitResults = await Promise.all( + fileList.map((file) => splitFileByLines(file)) + ); + filesToUpload = splitResults.flat(); + } + + // 计算分片列表 + const sliceList = filesToUpload.map((file) => { + const originFile = (file as any).originFileObj || file; + const slices = sliceFile(originFile); + return { + originFile: file, + slices, + name: file.name, + size: (file as any).size || originFile.size || 0, + }; }); - console.log('[ImportConfiguration] Uploading with currentPrefix:', currentPrefix); + + console.log("[ImportConfiguration] Uploading with currentPrefix:", currentPrefix); window.dispatchEvent( new CustomEvent("upload:dataset", { detail: { dataset, - files: fileSliceList, + files: sliceList, updateEvent, hasArchive: importConfig.hasArchive, prefix: currentPrefix, @@ -222,6 +271,21 @@ export default function ImportConfiguration({ > + + 按分行分割{" "} + + + + + } + name="splitByLine" + valuePropName="checked" + initialValue={false} + > + +