diff --git a/app/routes/documents._index.tsx b/app/routes/documents._index.tsx index 21960c9..a333760 100644 --- a/app/routes/documents._index.tsx +++ b/app/routes/documents._index.tsx @@ -13,6 +13,7 @@ import documentsIndexStyles from "~/styles/pages/documents_index.css?url"; import { getDocuments, deleteDocument, type DocumentUI } from "~/api/files/documents"; import { getDocumentTypes } from "~/api/document-types/document-types"; import { updateDocumentAuditStatus } from "~/api/evaluation_points/rules-files"; +import { appendContractAttachments, uploadContractTemplate } from "~/api/files/files-upload"; import { toastService } from "~/components/ui/Toast"; import { messageService } from "~/components/ui/MessageModal"; import { loadingBarService } from "~/components/ui/LoadingBar"; @@ -192,6 +193,17 @@ export default function DocumentsIndex() { // 添加一个状态来跟踪是否执行了删除操作 const [isDeleting, setIsDeleting] = useState(false); + // 附件追加和模板上传状态 + const [showAttachmentUpload, setShowAttachmentUpload] = useState(false); + const [showTemplateUpload, setShowTemplateUpload] = useState(false); + const [selectedDocumentId, setSelectedDocumentId] = useState(null); + const [attachmentFiles, setAttachmentFiles] = useState([]); + const [templateFile, setTemplateFile] = useState(null); + const [attachmentMergeMode, setAttachmentMergeMode] = useState<'overwrite' | 'new'>('overwrite'); + const [attachmentRemark, setAttachmentRemark] = useState(""); + const [attachmentUploading, setAttachmentUploading] = useState(false); + const [templateUploading, setTemplateUploading] = useState(false); + // 查询参数记忆 key 与保存/恢复方法 const SEARCH_PARAMS_STORAGE_KEY = 'documents.searchParams'; const persistSearchParams = (params: URLSearchParams) => { @@ -720,6 +732,166 @@ export default function DocumentsIndex() { navigate(`/reviews?id=${fileId}&previousRoute=documents`); }; + // 处理附件追加文件选择 + const handleAttachmentFilesSelected = (files: FileList) => { + try { + console.log('【附件追加】开始处理附件文件选择, 文件数量:', files.length); + + if (files.length > 0) { + // 验证文件类型,支持PDF、Word、ZIP、RAR + const validFiles: File[] = []; + let hasInvalidFiles = false; + + Array.from(files).forEach(file => { + const fileName = file.name.toLowerCase(); + const isValidType = + file.type === 'application/pdf' || fileName.endsWith('.pdf') || + file.type === 'application/msword' || fileName.endsWith('.doc') || + file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || fileName.endsWith('.docx') || + file.type === 'application/zip' || fileName.endsWith('.zip') || + file.type === 'application/x-rar-compressed' || fileName.endsWith('.rar'); + + if (isValidType) { + validFiles.push(file); + } else { + hasInvalidFiles = true; + console.error(`【附件追加】无效的文件类型: ${file.name}, 类型: ${file.type}`); + } + }); + + if (hasInvalidFiles) { + messageService.error('只支持PDF、Word、ZIP、RAR格式的文件', { + title: '文件类型错误', + confirmText: '确定', + cancelText: '', + }); + } + + if (validFiles.length > 0) { + setAttachmentFiles(validFiles); + console.log('【附件追加】有效文件数量:', validFiles.length); + } + } + } catch (error) { + console.error('【附件追加】处理文件选择时发生错误:', error); + } + }; + + // 处理附件追加上传 + const handleAttachmentUpload = async () => { + if (!selectedDocumentId || attachmentFiles.length === 0) { + toastService.error('请选择文档和附件文件'); + return; + } + + try { + setAttachmentUploading(true); + + const result = await appendContractAttachments( + selectedDocumentId, + attachmentFiles, + attachmentMergeMode, + true, // isReprocess + attachmentRemark || undefined, + loaderData.userInfo?.token as string | undefined + ); + + if (result.error) { + throw new Error(result.error); + } + + toastService.success('附件追加成功!'); + + // 重置状态 + setAttachmentFiles([]); + setAttachmentRemark(""); + setShowAttachmentUpload(false); + setSelectedDocumentId(null); + + // 刷新文档列表 + if (reviewType) { + fetchData(reviewType); + } + + } catch (error) { + console.error('【附件追加】上传失败:', error); + toastService.error(error instanceof Error ? error.message : '附件追加失败'); + } finally { + setAttachmentUploading(false); + } + }; + + // 处理合同模板文件选择 + const handleTemplateFileSelected = (files: FileList) => { + try { + console.log('【合同模板上传】开始处理模板文件选择, 文件数量:', files.length); + + if (files.length > 0) { + const file = files[0]; + // 验证文件类型,支持PDF和Word + const fileName = file.name.toLowerCase(); + const isValidType = + file.type === 'application/pdf' || fileName.endsWith('.pdf') || + file.type === 'application/msword' || fileName.endsWith('.doc') || + file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || fileName.endsWith('.docx'); + + if (isValidType) { + setTemplateFile(file); + console.log('【合同模板上传】有效文件:', file.name); + } else { + messageService.error('只支持PDF、Word格式的文件', { + title: '文件类型错误', + confirmText: '确定', + cancelText: '', + }); + } + } + } catch (error) { + console.error('【合同模板上传】处理文件选择时发生错误:', error); + } + }; + + // 处理合同模板上传 + const handleTemplateUpload = async () => { + if (!selectedDocumentId || !templateFile) { + toastService.error('请选择文档和模板文件'); + return; + } + + try { + setTemplateUploading(true); + + const result = await uploadContractTemplate( + templateFile, + selectedDocumentId, + undefined, // comparisonId + loaderData.userInfo?.token as string | undefined + ); + + if (result.error) { + throw new Error(result.error); + } + + toastService.success('合同模板上传成功!'); + + // 重置状态 + setTemplateFile(null); + setShowTemplateUpload(false); + setSelectedDocumentId(null); + + // 刷新文档列表 + if (reviewType) { + fetchData(reviewType); + } + + } catch (error) { + console.error('【合同模板上传】上传失败:', error); + toastService.error(error instanceof Error ? error.message : '合同模板上传失败'); + } finally { + setTemplateUploading(false); + } + }; + // 表格列定义 const columns = [ @@ -842,14 +1014,14 @@ export default function DocumentsIndex() { { title: "操作", key: "actions", - width: "20%", + width: "25%", render: (_: unknown, record: DocumentUI) => ( -
+
{(record.auditStatus === 0 || record.auditStatus == null) ? ( + {record.type === 1 && record.fileStatus === 'Processed' && ( + <> + + + + )}
+ + {/* 附件追加模态框 */} + {showAttachmentUpload && ( +
+
+
+

追加合同附件

+ +
+ +
+ {/* 文档信息 */} +
+

+ 目标文档ID: {selectedDocumentId} +

+

+ 支持PDF、Word、ZIP、RAR格式,ZIP/RAR内仅合并其中的PDF文件 +

+
+ + {/* 文件上传区域 */} +
+ +
+ e.target.files && handleAttachmentFilesSelected(e.target.files)} + className="hidden" + id="attachment-file-input" + /> + +
+ {attachmentFiles.length > 0 && ( +
+

+ 已选择 {attachmentFiles.length} 个文件 +

+
+ {attachmentFiles.map((file, index) => ( +
+ + {file.name} ({formatFileSize(file.size)}) +
+ ))} +
+
+ )} +
+ + {/* 合并模式选择 */} +
+ +
+ + +
+
+ + {/* 备注 */} +
+ +