import { useState } from "react"; import { messageService } from "./MessageModal"; // 格式化文件大小 const formatFileSize = (bytes: number) => { if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; }; export interface AttachmentUploadModalProps { /** 是否显示 */ isOpen: boolean; /** 关闭回调 */ onClose: () => void; /** 目标文档ID */ documentId: number | null; /** 目标文档名称 */ documentName: string | null; /** 目标文档版本号(可选) */ documentVersion?: number | null; /** 主文件路径(用于判断是否为docx) */ mainFilePath?: string; /** 上传回调 */ onUpload: (files: File[], mergeMode: 'overwrite' | 'new', remark: string) => Promise; /** 是否正在上传 */ uploading?: boolean; /** 标题(可选,默认"追加合同附件") */ title?: string; /** 支持的文件格式描述(可选) */ supportedFormatsDesc?: string; /** 是否显示合并模式选择(可选,默认false,仅显示新建模式) */ showMergeMode?: boolean; } export function AttachmentUploadModal({ isOpen, onClose, documentId, documentName, documentVersion, mainFilePath, onUpload, uploading = false, title = "追加合同附件", supportedFormatsDesc = "支持.pdf、.docx、ZIP、RAR格式。ZIP/RAR内需要保证文件格式一致,否则报错", showMergeMode = false }: AttachmentUploadModalProps) { // 附件文件列表 const [attachmentFiles, setAttachmentFiles] = useState([]); // 合并模式 const [attachmentMergeMode, setAttachmentMergeMode] = useState<'overwrite' | 'new'>('new'); // 备注 const [attachmentRemark, setAttachmentRemark] = useState(""); // 拖拽状态 const [isDragging, setIsDragging] = useState(false); // 重置状态 const resetState = () => { setAttachmentFiles([]); setAttachmentRemark(""); setIsDragging(false); }; // 关闭处理 const handleClose = () => { resetState(); onClose(); }; // 处理文件选择 const handleFilesSelected = (files: FileList) => { try { if (files.length > 0) { // 检查主文件类型 const isMainFileDocx = mainFilePath?.toLowerCase().endsWith('.docx'); // 验证文件类型 const validFiles: File[] = []; let hasInvalidFiles = false; let hasPdfForDocx = false; Array.from(files).forEach(file => { const fileName = file.name.toLowerCase(); const isPdf = file.type === 'application/pdf' || fileName.endsWith('.pdf'); const isValidType = isPdf || 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'); // 如果主文件是docx,不允许上传pdf附件 if (isMainFileDocx && isPdf) { hasPdfForDocx = true; return; } if (isValidType) { validFiles.push(file); } else { hasInvalidFiles = true; } }); if (hasPdfForDocx) { messageService.error('主文件为DOCX格式时,附件不可以是PDF格式', { title: '文件类型限制', confirmText: '确定', cancelText: '', }); } else if (hasInvalidFiles) { messageService.error('只支持PDF、Word、ZIP、RAR格式的文件', { title: '文件类型错误', confirmText: '确定', cancelText: '', }); } if (validFiles.length > 0) { setAttachmentFiles(validFiles); } } } catch (error) { console.error('处理文件选择时发生错误:', error); } }; // 处理上传 const handleUpload = async () => { if (!documentId || attachmentFiles.length === 0) { return; } await onUpload(attachmentFiles, attachmentMergeMode, attachmentRemark); resetState(); }; // 拖拽事件处理 const handleDragEnter = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(true); }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); }; const handleDragLeave = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setIsDragging(false); const files = e.dataTransfer.files; if (files && files.length > 0) { handleFilesSelected(files); } }; if (!isOpen) return null; return (
e.stopPropagation()} >

{title}

{/* 文档信息 */}

目标文档名称: {documentName} {documentVersion && ( v{documentVersion} )}

{supportedFormatsDesc}

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

已选择 {attachmentFiles.length} 个文件

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