/** * 评查选项卡组件 * 提供三个选项卡:评查结果、AI智能分析、文件信息 */ import { ReactNode, useState, useRef } from 'react'; import { useNavigate, useRevalidator } from 'react-router-dom'; import { loadingBarService } from '~/components/ui/LoadingBar'; import { Modal } from '~/components/ui/Modal'; import { UploadArea, type UploadAreaRef } from '~/components/ui/UploadArea'; import { Button } from '~/components/ui/Button'; import { toastService } from '~/components/ui/Toast'; // import { DOCUMENT_URL } from "~/api/axios-client"; import { uploadFileToBinary, uploadDocumentToServer } from '~/api/files/files-upload'; interface ReviewTabsProps { activeTab: string; onTabChange: (tabKey: string) => void; children: ReactNode; fileInfo: { id?: number; previousRoute?: string; path?: string; auditStatus?: number; type?: string; }; onConfirmResults: () => void; jwtToken?: string | null; } export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfirmResults, jwtToken }: ReviewTabsProps) { const [isNavigating, setIsNavigating] = useState(false); const [isReuploadModalOpen, setIsReuploadModalOpen] = useState(false); const [selectedTemplateFiles, setSelectedTemplateFiles] = useState([]); const [isUploading, setIsUploading] = useState(false); const uploadAreaRef = useRef(null); const navigate = useNavigate(); const revalidator = useRevalidator(); // 返回上一级 const handleBack = () => { // 防抖处理 - 如果已经在导航中,不重复触发 if (isNavigating) return; // 设置导航状态为true setIsNavigating(true); loadingBarService.show(); // 根据来源页面返回 const previousRoute = fileInfo.previousRoute || 'documents'; const returnTo = previousRoute === 'documents' ? "/documents" : previousRoute === 'filesUpload' ? "/files/upload" : "/rules-files"; // 立即导航返回 navigate(returnTo); // 触发上级页面数据重新加载 revalidator.revalidate(); }; // 下载原文件 const handleDownloadFile = async () => { try { // 使用 PDF 代理路由获取文件,自动添加 JWT 认证 const downloadUrl = `/api/pdf-proxy?path=${encodeURIComponent(fileInfo.path || '')}`; // 使用fetch获取文件内容 const response = await fetch(downloadUrl); if (!response.ok) { throw new Error(`下载失败: ${response.status} ${response.statusText}`); } // 将响应转换为Blob const blob = await response.blob(); // 创建Blob URL const blobUrl = URL.createObjectURL(blob); // 创建一个隐藏的a标签并点击它 const a = document.createElement('a'); a.style.display = 'none'; a.href = blobUrl; // 从路径中获取文件名 const fileName = fileInfo.path?.split('/').pop() || 'document'; a.download = decodeURIComponent(fileName); document.body.appendChild(a); a.click(); // 清理 setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(blobUrl); }, 100); } catch (error) { console.error('下载文件失败:', error); alert(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`); } }; // 打开重新上传模板模态框 const handleOpenReuploadModal = () => { setIsReuploadModalOpen(true); setSelectedTemplateFiles([]); }; // 关闭重新上传模板模态框 const handleCloseReuploadModal = () => { setIsReuploadModalOpen(false); setSelectedTemplateFiles([]); // 重置文件输入 if (uploadAreaRef.current) { uploadAreaRef.current.resetFileInput(); } }; // 处理模板文件选择 const handleTemplateFilesSelected = (files: FileList) => { try { if (files.length > 0) { // 验证文件类型,只允许PDF文件 const validFiles: File[] = []; let hasInvalidFiles = false; Array.from(files).forEach(file => { if (file.type === 'application/pdf' || file.name.toLowerCase().endsWith('.pdf')) { validFiles.push(file); } else { hasInvalidFiles = true; console.error(`无效的文件类型: ${file.name}, 类型: ${file.type}`); } }); if (hasInvalidFiles) { toastService.error('只能上传PDF格式的文件'); } if (validFiles.length > 0) { setSelectedTemplateFiles(validFiles); } } } catch (error) { console.error('处理模板文件选择时发生错误:', error); toastService.error('文件选择失败,请重试'); } }; // 确认上传模板文件 const handleConfirmUpload = async () => { if (selectedTemplateFiles.length === 0) { toastService.error('请先选择要上传的模板文件'); return; } try { setIsUploading(true); // 这里可以调用上传API let binaryData: ArrayBuffer; try { binaryData = await uploadFileToBinary(selectedTemplateFiles[0]); } catch (error) { console.error('上传文件失败:', error); throw new Error(`文件 ${selectedTemplateFiles[0].name} 转换失败: ${error instanceof Error ? error.message : '未知错误'}`); } // const uploadInfo = { // binaryData, // fileName: selectedTemplateFiles[0].name, // fileType: 'pdf', // documentType: '1', // priority: 'normal', // documentNumber: null, // remark: null, // isTestDocument: false, // documentId: fileInfo // }; // console.log('uploadInfo',uploadInfo); const uploadResult = await uploadDocumentToServer( binaryData, selectedTemplateFiles[0].name, 'pdf', //file_type 文件类型:pdf '1', //fileType(type_id) 合同id:1 'normal', //priority 优先级:normal null, //document_number 文档编号 null, //remark 备注 false, //is_test_document 是否为测试文档:false fileInfo.id, //document_id 主文档id true, //is_reupload 是否为重新上传:true jwtToken || undefined, //jwtToken ); // console.log('重新上传合同模板',uploadResult); if (uploadResult.error) { throw new Error(uploadResult.error); } toastService.success('模板文件上传成功,结构比对数据将会发生更新,即将返回上一页...'); await new Promise(resolve => setTimeout(resolve, 2000)); handleCloseReuploadModal(); handleBack(); } catch (error) { console.error('上传模板文件失败:', error); toastService.error(`上传失败: ${error instanceof Error ? error.message : '未知错误'}`); } finally { setIsUploading(false); } }; // 格式化文件大小 const formatFileSize = (bytes: number) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; return (
{/* 评查结果、AI智能分析、文件信息 */}
{/* */} {fileInfo.type === '1' && ( )}
{/* 操作按钮 */}
{/* 重新上传 */} {activeTab === 'filecompare' && ( )} {/* 返回上一级 */} {/* */}
{children}
{/* 重新上传模板模态框 */}
} >

请选择新的模板文件用于结构比对。

注意:只支持PDF格式的文件,上传后将替换当前的比对模板。

支持格式:PDF } disabled={isUploading} /> {/* 已选择的文件列表 */} {selectedTemplateFiles.length > 0 && (

已选择的文件:

{selectedTemplateFiles.map((file, index) => (
{file.name}
{formatFileSize(file.size)}
))}
)}
); }