/** * 评查选项卡组件 * 提供三个选项卡:评查结果、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 { uploadContractTemplate } from '~/api/files/files-upload'; import axios from 'axios'; interface ReviewTabsProps { activeTab: string; onTabChange: (tabKey: string) => void; children: ReactNode; fileInfo: { id?: number; previousRoute?: string; path?: string; auditStatus?: number; type?: string; comparisonId?: number; }; 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/list" : 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 || '')}`; // 使用axios获取文件内容 const response = await axios.get(downloadUrl, { responseType: 'blob' }); // axios已经返回Blob const blob = response.data; // 创建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和Word文件 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' || file.type === 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || fileName.endsWith('.doc') || fileName.endsWith('.docx'); if (isValidType) { validFiles.push(file); } else { hasInvalidFiles = true; console.error(`无效的文件类型: ${file.name}, 类型: ${file.type}`); } }); if (hasInvalidFiles) { toastService.error('只能上传PDF或Word格式的文件'); } if (validFiles.length > 0) { setSelectedTemplateFiles(validFiles); } } } catch (error) { console.error('处理模板文件选择时发生错误:', error); toastService.error('文件选择失败,请重试'); } }; // 确认上传模板文件 const handleConfirmUpload = async () => { if (selectedTemplateFiles.length === 0) { toastService.error('请先选择要上传的模板文件'); return; } // 验证必需的参数 if (!fileInfo.id) { toastService.error('文档ID不能为空'); return; } try { setIsUploading(true); console.log('【重新上传模板】开始上传:', { fileName: selectedTemplateFiles[0].name, documentId: fileInfo.id, comparisonId: fileInfo.comparisonId }); // 调用专门的合同模板上传接口 const uploadResult = await uploadContractTemplate( selectedTemplateFiles[0], // file: File 对象 fileInfo.id, // documentId: 合同文件的id fileInfo.comparisonId, // comparisonId: 模板预览文件的id (可选) 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和Word格式的文件,上传后将替换当前的比对模板。

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

已选择的文件:

{selectedTemplateFiles.map((file, index) => { // 根据文件类型确定图标和颜色 const fileName = file.name.toLowerCase(); let fileIcon = 'ri-file-pdf-line'; let iconColor = 'text-red-500'; if (fileName.endsWith('.doc') || fileName.endsWith('.docx')) { fileIcon = 'ri-file-word-2-line'; iconColor = 'text-blue-600'; } return (
{file.name}
{formatFileSize(file.size)}
); })}
)}
); }