import { useEffect, useState } from "react"; import { Button, DatePicker, Form, Input, message, Modal, Select, Upload, UploadFile } from "antd"; import { UploadOutlined } from "@ant-design/icons"; import dayjs from "dayjs"; import { downloadKnowledgeItemFileUsingGet, replaceKnowledgeItemFileUsingPut, updateKnowledgeItemByIdUsingPut, uploadKnowledgeItemsUsingPost, } from "../knowledge-management.api"; import { knowledgeStatusOptions, } from "../knowledge-management.const"; import { KnowledgeContentType, KnowledgeItem, KnowledgeSourceType, KnowledgeStatusType, } from "../knowledge-management.model"; import { queryDatasetTagsUsingGet } from "@/pages/DataManagement/dataset.api"; const stripFileExtension = (fileName: string) => { const dotIndex = fileName.lastIndexOf("."); if (dotIndex <= 0) { return fileName; } return fileName.slice(0, dotIndex); }; export default function KnowledgeItemEditor({ open, setId, data, onCancel, onSuccess, readOnly, }: { open: boolean; setId: string; data?: Partial | null; readOnly?: boolean; onCancel: () => void; onSuccess: () => void; }) { const [form] = Form.useForm(); const [tagOptions, setTagOptions] = useState<{ label: string; value: string }[]>([]); const [fileList, setFileList] = useState([]); const [replaceFileList, setReplaceFileList] = useState([]); const [titleBeforeReplace, setTitleBeforeReplace] = useState(null); const isMultiFile = fileList.length > 1; const isFileItem = data?.contentType === KnowledgeContentType.FILE || data?.sourceType === KnowledgeSourceType.FILE_UPLOAD; const contentTypeLabel = !data?.id ? "文件" : data?.contentType === KnowledgeContentType.MARKDOWN ? "Markdown" : data?.contentType === KnowledgeContentType.TEXT ? "文本" : "文件"; const fetchTags = async () => { try { const { data: tagData } = await queryDatasetTagsUsingGet(); const options = Array.isArray(tagData) ? tagData.map((tag) => ({ label: tag.name, value: tag.name })) : []; setTagOptions(options); } catch (error) { console.error("获取标签失败", error); } }; useEffect(() => { if (open) { fetchTags(); } }, [open]); useEffect(() => { if (open) { if (data?.id) { form.setFieldsValue({ title: data.title, status: data.status ?? KnowledgeStatusType.DRAFT, domain: data.domain, businessLine: data.businessLine, owner: data.owner, sensitivity: data.sensitivity, validFrom: data.validFrom ? dayjs(data.validFrom) : null, validTo: data.validTo ? dayjs(data.validTo) : null, tags: data.tags?.map((tag) => tag.name) || [], metadata: data.metadata, }); setTitleBeforeReplace(null); } else { form.resetFields(); form.setFieldsValue({ status: KnowledgeStatusType.DRAFT, tags: [], }); setTitleBeforeReplace(null); } setFileList([]); setReplaceFileList([]); } else { setFileList([]); setReplaceFileList([]); setTitleBeforeReplace(null); } }, [open, data, form]); const handleFileBeforeUpload = (file: File) => { setFileList((prev) => { const nextList = [ ...prev, { uid: `${Date.now()}-${file.name}`, name: file.name, status: "done", originFileObj: file, }, ]; if (nextList.length === 1) { const currentTitle = form.getFieldValue("title"); if (!currentTitle) { form.setFieldsValue({ title: stripFileExtension(file.name), }); } } return nextList; }); message.success("文件已就绪,可提交创建条目"); return false; }; const handleFileRemove = (removedFile: UploadFile) => { setFileList((prev) => { const nextList = prev.filter((file) => file.uid !== removedFile.uid); if (!data?.id && nextList.length === 0) { form.setFieldsValue({ title: undefined }); } return nextList; }); return true; }; const handleReplaceFileBeforeUpload = (file: File) => { if (!titleBeforeReplace) { setTitleBeforeReplace(form.getFieldValue("title") || null); } setReplaceFileList([ { uid: `${Date.now()}-${file.name}`, name: file.name, status: "done", originFileObj: file, }, ]); form.setFieldsValue({ title: stripFileExtension(file.name) }); message.success("已选择替换文件,提交后生效"); return false; }; const handleReplaceFileRemove = (removedFile: UploadFile) => { setReplaceFileList((prev) => prev.filter((file) => file.uid !== removedFile.uid)); if (titleBeforeReplace !== null) { form.setFieldsValue({ title: titleBeforeReplace || undefined }); setTitleBeforeReplace(null); } return true; }; const handleDownloadFile = async () => { if (!data?.id) { return; } try { await downloadKnowledgeItemFileUsingGet(setId, data.id, data.sourceFileId); } catch (error) { console.error("下载文件失败", error); message.error("下载失败,请稍后重试"); } }; const handleSubmit = async () => { try { if (!data?.id && fileList.length === 0) { message.warning("请先选择文件"); return; } const values = await form.validateFields(); const validFrom = values.validFrom ? values.validFrom.format("YYYY-MM-DD") : undefined; const validTo = values.validTo ? values.validTo.format("YYYY-MM-DD") : undefined; if (validFrom && validTo && dayjs(validFrom).isAfter(dayjs(validTo))) { message.warning("有效期开始不能晚于结束时间"); return; } if (data?.id) { const payload: Record = { ...values, validFrom, validTo, tags: values.tags || [], }; if (replaceFileList.length > 0) { delete payload.title; } await updateKnowledgeItemByIdUsingPut(setId, data.id, payload); if (replaceFileList.length > 0) { const formData = new FormData(); const replaceFile = replaceFileList[0]?.originFileObj as File | undefined; if (!replaceFile) { message.warning("请先选择要替换的文件"); return; } formData.append("file", replaceFile); await replaceKnowledgeItemFileUsingPut(setId, data.id, formData); } message.success("知识条目更新成功"); } else { if (fileList.length === 0) { message.warning("请先选择文件"); return; } const formData = new FormData(); fileList.forEach((file) => { const origin = file.originFileObj as File | undefined; if (origin) { formData.append("files", origin); } }); if (fileList.length === 1 && values.title) { formData.append("title", values.title); } if (values.status) { formData.append("status", values.status); } if (values.tags && Array.isArray(values.tags)) { values.tags.forEach((tag) => formData.append("tags", tag)); } if (values.domain) { formData.append("domain", values.domain); } if (values.businessLine) { formData.append("businessLine", values.businessLine); } if (values.owner) { formData.append("owner", values.owner); } if (values.sensitivity) { formData.append("sensitivity", values.sensitivity); } if (validFrom) { formData.append("validFrom", validFrom); } if (validTo) { formData.append("validTo", validTo); } if (values.metadata) { formData.append("metadata", values.metadata); } await uploadKnowledgeItemsUsingPost(setId, formData); message.success(`已创建 ${fileList.length} 个知识条目`); } form.resetFields(); setFileList([]); setReplaceFileList([]); setTitleBeforeReplace(null); onSuccess(); } catch { message.error("操作失败,请重试"); } }; const title = data?.id ? "编辑知识条目" : "新建知识条目"; return (