添加登录内容,尚未完善,先创建分支

This commit is contained in:
2025-07-14 12:31:43 +08:00
parent e3109423d4
commit fff474f46b
25 changed files with 2693 additions and 1102 deletions
+229 -221
View File
@@ -1,6 +1,6 @@
import { useState, useEffect, useRef } from "react";
import { MetaFunction, ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
import { Form, useActionData, useLoaderData, useNavigate, useBlocker } from "@remix-run/react";
import { Form, useActionData, useLoaderData, useNavigate } from "@remix-run/react";
import { Card } from "~/components/ui/Card";
import { Button } from "~/components/ui/Button";
import { Table } from "~/components/ui/Table";
@@ -121,49 +121,10 @@ async function handleFileUpload(
priority: Priority,
documentNumber: string | null,
remark: string | null,
isTestDocument: boolean
isTestDocument: boolean,
documentId?: number | null,
isReupload: boolean = false
): Promise<FileUploadResponse> {
// try {
// // 使用封装的上传函数
// const response = await uploadDocumentToServer(
// binaryData,
// fileName,
// fileType,
// documentType,
// PRIORITY_TO_CHINESE[priority],
// documentNumber,
// remark,
// isTestDocument
// );
// if (response.error) {
// console.error('[API] 上传错误:', response.error);
// return {
// success: false,
// error: response.error
// };
// }
// // 确保返回有效的FileUploadResponse对象
// // console.log('上传成功:', response.data);
// if (response.data) {
// return response.data;
// }
// // 如果没有数据,则返回错误
// // console.log('上传失败:', response.error);
// return {
// success: false,
// error: '上传失败,未获取到响应数据'
// };
// } catch (error) {
// console.error('[API] 上传错误:', error);
// return {
// success: false,
// error: error instanceof Error ? error.message : '上传失败'
// };
// }
const response = await uploadDocumentToServer(
binaryData,
fileName,
@@ -172,7 +133,9 @@ async function handleFileUpload(
priority,
documentNumber,
remark,
isTestDocument
isTestDocument,
documentId,
isReupload
);
if (response.error || !response.data) {
@@ -309,9 +272,9 @@ export default function FilesUpload() {
// 合同文件上传状态
// 这些变量暂时未使用,但保留以备将来扩展
// const [isContractType, setIsContractType] = useState<boolean>(false);
// const [contractMainFiles, setContractMainFiles] = useState<File[]>([]);
// const [contractAttachmentFiles, setContractAttachmentFiles] = useState<File[]>([]);
const [isContractType, setIsContractType] = useState<boolean>(false);
const [contractMainFiles, setContractMainFiles] = useState<File[]>([]);
const [contractAttachmentFiles, setContractAttachmentFiles] = useState<File[]>([]);
const [uploadProgress, setUploadProgress] = useState(0);
const [uploadSpeed, setUploadSpeed] = useState("0KB/s");
@@ -336,13 +299,13 @@ export default function FilesUpload() {
if (typeof window !== 'undefined') {
const storedReviewType = sessionStorage.getItem('reviewType');
setReviewType(storedReviewType);
// 根据 reviewType 过滤文档类型和文档列表
filterDocumentTypes(storedReviewType, loaderData.documentTypes);
filterDocuments(storedReviewType);
// 如果reviewType是contract,自动选择合同文档类型
if (storedReviewType === 'contract') {
setIsContractType(true);
// 查找ID为1的合同文档类型
const contractType = loaderData.documentTypes.find(type => type.id === 1);
if (contractType) {
@@ -385,7 +348,11 @@ export default function FilesUpload() {
const filterDocuments = async (reviewType: string | null) => {
if (!reviewType) {
// 如果没有特定的 reviewType,使用原始数据
setQueueFiles(loaderData.documents);
const documents = loaderData.documents;
setQueueFiles(documents);
// 启动状态检查定时器
startStatusChecker(documents);
return;
}
@@ -399,12 +366,20 @@ export default function FilesUpload() {
setQueueFiles(loaderData.documents);
return;
}
const documents = response.data || [];
console.log('过滤文档列表成功:', documents);
setQueueFiles(documents);
setQueueFiles(response.data || []);
// 数据加载完成后立即启动状态检查定时器
startStatusChecker(documents);
} catch (error) {
console.error('过滤文档列表失败:', error);
// 出错时使用原始数据
setQueueFiles(loaderData.documents);
const documents = loaderData.documents;
setQueueFiles(documents);
// 即使出错也启动状态检查定时器
startStatusChecker(documents);
}
};
@@ -424,8 +399,10 @@ export default function FilesUpload() {
// 上传完成后的文件信息列表
const [completedFiles, setCompletedFiles] = useState<UploadedFile[]>([]);
// 计时器引用
const progressIntervalRef = useRef<NodeJS.Timeout | null>(null);
// 计时器引用 - 分离为三个独立的定时器
const uploadProgressIntervalRef = useRef<NodeJS.Timeout | null>(null);
const processingStatusIntervalRef = useRef<NodeJS.Timeout | null>(null);
const queueStatusIntervalRef = useRef<NodeJS.Timeout | null>(null); // 原 statusCheckIntervalRef
// UploadArea组件引用
const uploadAreaRef = useRef<UploadAreaRef>(null);
@@ -451,69 +428,122 @@ export default function FilesUpload() {
}
}, [actionData]);
// 状态检查定时器引用
const statusCheckIntervalRef = useRef<NodeJS.Timeout | null>(null);
// 添加组件挂载状态引用
const isMountedRef = useRef<boolean>(true);
// useEffect 处理上传队列状态检查定时器 - 只在组件卸载时清除
useEffect(() => {
// console.log('设置上传队列状态检查定时器');
console.log('设置上传队列状态检查定时器');
// 标记组件已挂载
isMountedRef.current = true;
// 设置定时器检查队列中文件的状态,初始先加载一次查询
checkQueueStatus();
statusCheckIntervalRef.current = setInterval(checkQueueStatus, 10000);
// 只在组件卸载时清除
return () => {
// console.log('组件卸载,清除上传队列状态检查定时器');
// 标记组件已卸载
isMountedRef.current = false;
if (statusCheckIntervalRef.current) {
clearInterval(statusCheckIntervalRef.current);
statusCheckIntervalRef.current = null;
if (queueStatusIntervalRef.current) {
clearInterval(queueStatusIntervalRef.current);
queueStatusIntervalRef.current = null;
}
};
}, []);
// 检查队列中未完成文档的状态
const checkQueueStatus = async () => {
// 启动状态检查定时器的函数
const startStatusChecker = (files: Document[]) => {
console.log('启动状态检查定时器,队列文件数量:', files.length);
// 清除之前的定时器
if (queueStatusIntervalRef.current) {
clearInterval(queueStatusIntervalRef.current);
}
// 只有当有文件时才启动定时器
if (files.length > 0) {
// 立即检查一次
checkQueueStatusWithFiles(files);
// 启动定时器
queueStatusIntervalRef.current = setInterval(() => {
if (isMountedRef.current) {
// 获取最新的queueFiles状态
setQueueFiles(currentFiles => {
checkQueueStatusWithFiles(currentFiles);
return currentFiles; // 不改变状态,只是为了获取最新值
});
}
}, 10000);
}
};
// 检查指定文件列表的状态
const checkQueueStatusWithFiles = async (files: Document[]) => {
try {
// console.log('开始检查队列状态,当前队列文件:', queueFiles);
// console.log('开始检查队列状态,当前队列文件:', files);
// 获取所有未完成的文档ID
const incompleteIds = queueFiles
.filter(file => file.status !== DocumentStatus.PROCESSED && file.id)
.map(file => file.id);
// 直接从sessionStorage读取reviewType,避免异步状态更新问题
const currentReviewType = typeof window !== 'undefined' ? sessionStorage.getItem('reviewType') : null;
// console.log('从sessionStorage读取的reviewType:', currentReviewType);
// console.log('未完成的文档ID:', incompleteIds);
// 获取所有未完成的文档
const incompleteFiles = files.filter(file =>
file.status !== DocumentStatus.PROCESSED && file.id
);
if (incompleteIds.length === 0) {
// console.log('没有未完成的文档,跳过状态检查');
if (incompleteFiles.length === 0) {
console.log('没有未完成的文档,跳过状态检查');
return;
}
// 获取这些文档的最新状态
const statusResponse = await getDocumentsStatus(incompleteIds);
let statusResponse;
// 如果是合同类型,需要分类处理
console.log('当前reviewType:', currentReviewType);
if (currentReviewType === 'contract') {
// 分类文档ID
const mainDocumentIds: number[] = [];
const attachmentIds: number[] = [];
incompleteFiles.forEach(file => {
// 检查是否存在template_contract_path属性来判断是否为合同附件
if ('template_contract_path' in file && file.template_contract_path) {
attachmentIds.push(file.id);
} else {
mainDocumentIds.push(file.id);
}
});
console.log('合同主文件ID:', mainDocumentIds);
console.log('合同附件ID:', attachmentIds);
// 分别查询状态
statusResponse = await getDocumentsStatus(mainDocumentIds, attachmentIds);
} else {
// 非合同类型,使用原有逻辑
const incompleteIds = incompleteFiles.map(file => file.id);
// console.log('未完成的文档ID:', incompleteIds);
statusResponse = await getDocumentsStatus(incompleteIds);
}
// console.log('状态检查响应:', statusResponse);
if (statusResponse.data) {
// 更新队列中的文档状态
// 更新队列中的文档状态,使用批量更新避免频繁渲染
setQueueFiles(prevFiles => {
let hasChanges = false;
const updatedFiles = prevFiles.map(file => {
const updatedStatus = statusResponse.data.find(doc => doc.id === file.id);
if (updatedStatus) {
// console.log(`文档 ${file.id} 状态更新: ${file.status} -> ${updatedStatus.status}`);
if (updatedStatus && updatedStatus.status !== file.status) {
console.log(`文档 ${file.id} 状态更新: ${file.status} -> ${updatedStatus.status}`);
hasChanges = true;
return { ...file, status: updatedStatus.status };
}
return file;
});
// console.log('更新后的队列文件:', updatedFiles);
return updatedFiles;
// 只有在确实有变化时才返回新数组
return hasChanges ? updatedFiles : prevFiles;
});
}
} catch (error) {
@@ -574,11 +604,11 @@ export default function FilesUpload() {
// currentFiles: currentFiles.length
// });
// setIsContractType(isContract);
setIsContractType(isContract);
// 重置文件状态
// setContractMainFiles([]);
// setContractAttachmentFiles([]);
setContractMainFiles([]);
setContractAttachmentFiles([]);
setCurrentFiles([]);
// 如果已经有选中的文件,且选择了文件类型,且不是合同类型,则开始上传
@@ -593,14 +623,13 @@ export default function FilesUpload() {
} else {
setFileType("");
// setIsContractType(false);
setIsContractType(false);
// 如果用户选择了空选项,显示错误信息
setFileTypeError("上传文件之前请选择文件类型");
}
};
// 处理合同主文件选择 - 暂时未使用,保留以备将来扩展
/*
// 处理合同主文件选择
const handleContractMainFilesSelected = (files: FileList) => {
try {
// console.log('【调试-handleContractMainFilesSelected】开始处理合同主文件选择, 文件数量:', files.length);
@@ -639,7 +668,7 @@ export default function FilesUpload() {
// console.log('【调试-handleContractMainFilesSelected】有效文件数量:', validFiles.length);
// console.log('【调试-handleContractMainFilesSelected】有效文件:', validFiles.map(f => ({ name: f.name, size: f.size, type: f.type })));
// setContractMainFiles(validFiles);
setContractMainFiles(validFiles);
} else {
console.error('【调试-handleContractMainFilesSelected】没有有效的PDF文件或组件已卸载');
}
@@ -650,10 +679,8 @@ export default function FilesUpload() {
console.error('【调试-handleContractMainFilesSelected】处理合同主文件选择时发生错误:', error);
}
};
*/
// 处理合同附件选择 - 暂时未使用,保留以备将来扩展
/*
// 处理合同附件选择
const handleContractAttachmentFilesSelected = (files: FileList) => {
try {
// console.log('【调试-handleContractAttachmentFilesSelected】开始处理合同附件选择, 文件数量:', files.length);
@@ -692,7 +719,7 @@ export default function FilesUpload() {
// console.log('【调试-handleContractAttachmentFilesSelected】有效文件数量:', validFiles.length);
// console.log('【调试-handleContractAttachmentFilesSelected】有效文件:', validFiles.map(f => ({ name: f.name, size: f.size, type: f.type })));
// setContractAttachmentFiles(validFiles);
setContractAttachmentFiles(validFiles);
} else {
console.error('【调试-handleContractAttachmentFilesSelected】没有有效的PDF文件或组件已卸载');
}
@@ -703,17 +730,15 @@ export default function FilesUpload() {
console.error('【调试-handleContractAttachmentFilesSelected】处理合同附件选择时发生错误:', error);
}
};
*/
// 检查并准备上传 - 暂时未使用,保留以备将来扩展
/*
// 检查并准备上传
const checkAndPrepareUpload = (mainFiles: File[], attachmentFiles: File[]) => {
try {
// console.log('【调试-checkAndPrepareUpload】开始检查并准备上传文件', {
// mainFilesCount: mainFiles.length,
// attachmentFilesCount: attachmentFiles.length,
// fileType
// });
console.log('【调试-checkAndPrepareUpload】开始检查并准备上传文件', {
mainFilesCount: mainFiles.length,
attachmentFilesCount: attachmentFiles.length,
fileType
});
// 检查组件是否已卸载
if (!isMountedRef.current) {
@@ -749,11 +774,11 @@ export default function FilesUpload() {
}
// 记录主文件和附件文件信息
// console.log('【调试-checkAndPrepareUpload】合同主文件:', mainFiles.map(f => ({ name: f.name, size: f.size, type: f.type })));
console.log('【调试-checkAndPrepareUpload】合同主文件:', mainFiles.map(f => ({ name: f.name, size: f.size, type: f.type })));
if (attachmentFiles.length > 0) {
// console.log('【调试-checkAndPrepareUpload】合同附件文件:', attachmentFiles.map(f => ({ name: f.name, size: f.size, type: f.type })));
console.log('【调试-checkAndPrepareUpload】合同附件文件:', attachmentFiles.map(f => ({ name: f.name, size: f.size, type: f.type })));
} else {
// console.log('【调试-checkAndPrepareUpload】无合同附件文件');
console.log('【调试-checkAndPrepareUpload】无合同附件文件');
}
}
@@ -778,7 +803,7 @@ export default function FilesUpload() {
setCurrentFiles(allFiles);
// 将准备上传的操作移到这里,暂时不执行
// console.log('【调试-checkAndPrepareUpload】准备上传', allFiles.length, '个文件');
console.log('【调试-checkAndPrepareUpload】准备上传', allFiles.length, '个文件');
if (fileType) {
try {
@@ -829,12 +854,11 @@ export default function FilesUpload() {
}
}
};
*/
// 开始上传文件
const startUpload = async (files: File[]) => {
try {
// console.log('【调试-startUpload】开始上传过程,文件数量:', files.length);
console.log('【调试-startUpload】开始上传过程,文件数量:', files.length);
// 检查组件是否已卸载
if (!isMountedRef.current) {
@@ -878,14 +902,14 @@ export default function FilesUpload() {
// console.log("【调试-startUpload】开始转换文件到二进制格式...");
// 模拟上传进度
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
if (uploadProgressIntervalRef.current) {
clearInterval(uploadProgressIntervalRef.current);
}
const startTime = Date.now();
let lastUploadedSize = 0;
progressIntervalRef.current = setInterval(() => {
uploadProgressIntervalRef.current = setInterval(() => {
const currentTime = Date.now();
const timeElapsed = (currentTime - startTime) / 1000; // 转换为秒
const currentSpeed = (uploadedSize - lastUploadedSize) / timeElapsed; // 字节/秒
@@ -902,7 +926,12 @@ export default function FilesUpload() {
// 上传所有文件
const uploadedFiles: UploadedFile[] = [];
let temp_n = 0;
let firstFileDocumentId: number | null = null; // 保存第一个文件的document_id
for (const file of files) {
temp_n++;
console.log('【调试-startUpload】上传文件:','第', temp_n, '个文件', file.name);
try {
// console.log(`【调试-startUpload】准备上传文件: ${file.name}, 大小: ${formatFileSize(file.size)}`);
@@ -939,7 +968,9 @@ export default function FilesUpload() {
priority,
documentNumber || null,
remark || null,
isTestDocument
isTestDocument,
temp_n > 1 ? firstFileDocumentId : null, // 第二个文件及以后使用第一个文件的document_id
false
);
const timeoutPromise = new Promise<FileUploadResponse>((_, reject) => {
@@ -964,6 +995,12 @@ export default function FilesUpload() {
response = uploadResult;
// 保存第一个文件的document_id,用于后续附件上传
if (temp_n === 1 && response.result?.id) {
firstFileDocumentId = response.result.id;
console.log('【调试-startUpload】保存第一个文件的document_id:', firstFileDocumentId);
}
// console.log(`【调试-startUpload】文件 ${file.name} 上传响应:`, response);
} catch (error) {
// 检查组件是否已卸载
@@ -1010,8 +1047,8 @@ export default function FilesUpload() {
}
// 清除进度定时器
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
if (uploadProgressIntervalRef.current) {
clearInterval(uploadProgressIntervalRef.current);
}
// 更新上传状态
@@ -1052,8 +1089,8 @@ export default function FilesUpload() {
setProcessingSteps(errorSteps);
// 清除进度定时器
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
if (uploadProgressIntervalRef.current) {
clearInterval(uploadProgressIntervalRef.current);
}
// 显示错误提示
@@ -1107,8 +1144,8 @@ export default function FilesUpload() {
// console.log('【调试-startProcessing】开始处理文件,设置文件处理进度定时器');
// 清除之前的进度定时器(如果存在)
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
if (processingStatusIntervalRef.current) {
clearInterval(processingStatusIntervalRef.current);
}
// 立即开始检查状态
@@ -1120,7 +1157,7 @@ export default function FilesUpload() {
}
// 设置文件处理进度定时器,每10秒检查一次状态
progressIntervalRef.current = setInterval(() => {
processingStatusIntervalRef.current = setInterval(() => {
// console.log('【调试-startProcessing】文件处理进度定时器触发,检查文件状态');
try {
checkProcessingStatus(fileIds);
@@ -1133,9 +1170,9 @@ export default function FilesUpload() {
console.error('【调试-startProcessing】处理文件过程中发生错误:', error);
// 清除进度定时器
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
progressIntervalRef.current = null;
if (processingStatusIntervalRef.current) {
clearInterval(processingStatusIntervalRef.current);
processingStatusIntervalRef.current = null;
}
// 更新步骤状态为错误
@@ -1205,9 +1242,9 @@ export default function FilesUpload() {
// console.log('【调试-checkProcessingStatus】所有文件处理完成,更新步骤状态为完成');
// 清除文件处理进度定时器
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
progressIntervalRef.current = null;
if (processingStatusIntervalRef.current) {
clearInterval(processingStatusIntervalRef.current);
processingStatusIntervalRef.current = null;
// console.log('【调试-checkProcessingStatus】文件处理完成,清除文件处理进度定时器');
}
@@ -1316,10 +1353,15 @@ export default function FilesUpload() {
// 重置上传状态 - 不清除队列状态检查定时器
const resetUpload = () => {
// 清除文件处理进度定时器
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
progressIntervalRef.current = null;
// 清除上传和处理相关的定时器
if (uploadProgressIntervalRef.current) {
clearInterval(uploadProgressIntervalRef.current);
uploadProgressIntervalRef.current = null;
}
if (processingStatusIntervalRef.current) {
clearInterval(processingStatusIntervalRef.current);
processingStatusIntervalRef.current = null;
}
// 重置状态
@@ -1331,8 +1373,8 @@ export default function FilesUpload() {
setCompletedFiles([]);
// 重置合同文件状态
// setContractMainFiles([]);
// setContractAttachmentFiles([]);
setContractMainFiles([]);
setContractAttachmentFiles([]);
// 重置步骤状态
setProcessingSteps([
@@ -1390,6 +1432,9 @@ export default function FilesUpload() {
const handleViewFile = async (record: Document) => {
try {
// console.log('【调试-handleViewFile】开始处理查看文件,文件ID:', record.id);
// console.log('【调试-handleViewFile】开始处理查看文件,文件:', record);
// 点击查看
// 检查audit_status是否为0,如果是则更新为2
if (record.audit_status === 0 || record.audit_status === null) {
@@ -1448,8 +1493,8 @@ export default function FilesUpload() {
width: "40%",
render: (_: unknown, record: Document) => (
<div className="flex items-center">
<i className={`${record.name.includes('.pdf') ? 'ri-file-pdf-line text-red-500' : 'ri-file-word-2-line text-blue-500'} mr-2 text-lg`}></i>
<span className="truncate">{record.name}</span>
<i className={`${record.name?.includes('.pdf') ? 'ri-file-pdf-line text-red-500' : 'ri-file-word-2-line text-blue-500'} mr-2 text-lg`}></i>
<span className="truncate">{record.name || '未知文件'}</span>
</div>
)
},
@@ -1559,45 +1604,6 @@ export default function FilesUpload() {
}
];
// 添加路由阻止器
// const shouldBlock = uploadStage === "uploading" || uploadStage === "processing";
// 使用useBlocker来阻止页面导航
// const blocker = useBlocker(
// ({ nextLocation }) => {
// return shouldBlock && window.location.pathname !== nextLocation.pathname;
// }
// );
// // 处理阻止导航的逻辑
// useEffect(() => {
// if (blocker.state === "blocked") {
// const confirmed = window.confirm(
// "文件正在上传或处理中,离开页面将中断操作。确定要离开吗?"
// );
// if (confirmed) {
// blocker.proceed();
// } else {
// blocker.reset();
// }
// }
// }, [blocker]);
// 添加页面刷新/关闭提示
// useEffect(() => {
// const handleBeforeUnload = (e: BeforeUnloadEvent) => {
// if (shouldBlock) {
// e.preventDefault();
// e.returnValue = "文件正在上传或处理中,离开页面将中断操作。确定要离开吗?";
// return e.returnValue;
// }
// };
// window.addEventListener("beforeunload", handleBeforeUnload);
// return () => {
// window.removeEventListener("beforeunload", handleBeforeUnload);
// };
// }, [shouldBlock]);
return (
<div className="file-upload-page">
@@ -1688,7 +1694,7 @@ export default function FilesUpload() {
{/* 自定义标题栏 */}
<div className="w-full flex justify-between items-center mb-4">
<h3 className="text-lg font-medium"></h3>
{/* {isContractType && uploadStage === "idle" && (
{isContractType && uploadStage === "idle" && (
<Button
type="primary"
icon="ri-upload-cloud-line"
@@ -1696,15 +1702,14 @@ export default function FilesUpload() {
>
</Button>
)} */}
)}
</div>
{/* 初始上传区域 */}
{uploadStage === "idle" && (
<>
{/* {!isContractType ? ( */}
{/* {true ? ( */}
{/* // 标准上传区域 - 非合同类型 */}
{!isContractType ? (
// 标准上传区域 - 非合同类型
<UploadArea
ref={uploadAreaRef}
onFilesSelected={handleFilesSelected}
@@ -1713,53 +1718,53 @@ export default function FilesUpload() {
tipText="支持单个或多个pdf文件上传,文件格式:PDF"
shouldPreventFileSelect={!fileType}
/>
{/* ) : ( */}
{/* 合同文件上传区域 - 双区域并排 */}
{/* <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
) : (
// 合同文件上传区域 - 双区域并排
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h4 className="font-medium mb-2"></h4>
<UploadArea
// onFilesSelected={handleContractMainFilesSelected}
// ref={contractMainFileRef}
// multiple={false}
// accept=".pdf"
// tipText="请上传合同主文件,格式:PDF"
// mainText="上传合同主文件"
// buttonText="选择主文件"
// icon="ri-file-text-line"
// shouldPreventFileSelect={!fileType}
// />
// {contractMainFiles.length > 0 && (
// <div className="mt-2 text-sm text-green-600">
// <i className="ri-checkbox-circle-line"></i>
// 已选择主文件: <span className="font-medium">{contractMainFiles[0].name}</span>
// </div>
// )}
// </div>
// <div>
// <h4 className="font-medium mb-2">合同附件</h4>
// <UploadArea
// onFilesSelected={handleContractAttachmentFilesSelected}
// ref={contractAttachmentFileRef}
// multiple={false}
// accept=".pdf"
// tipText="请上传合同附件,格式:PDF"
// mainText="上传合同附件"
// buttonText="选择附件"
// icon="ri-file-copy-line"
// shouldPreventFileSelect={!fileType}
// />
// {contractAttachmentFiles.length > 0 && (
// <div className="mt-2 text-sm text-green-600">
// <i className="ri-checkbox-circle-line"></i>
// 已选择附件: {contractAttachmentFiles.map((file, index) => (
// <span key={index} className="font-medium">{file.name}</span>
// ))}
// </div>
// )}
// </div>
// </div>
// )}
onFilesSelected={handleContractMainFilesSelected}
ref={contractMainFileRef}
multiple={false}
accept=".pdf"
tipText="请上传合同主文件,格式:PDF"
mainText="上传合同主文件"
buttonText="选择主文件"
icon="ri-file-text-line"
shouldPreventFileSelect={!fileType}
/>
{contractMainFiles.length > 0 && (
<div className="mt-2 text-sm text-green-600">
<i className="ri-checkbox-circle-line"></i>
: <span className="font-medium">{contractMainFiles[0].name}</span>
</div>
)}
</div>
<div>
<h4 className="font-medium mb-2"></h4>
<UploadArea
onFilesSelected={handleContractAttachmentFilesSelected}
ref={contractAttachmentFileRef}
multiple={false}
accept=".pdf"
tipText="请上传合同附件,格式:PDF"
mainText="上传合同附件"
buttonText="选择附件"
icon="ri-file-copy-line"
shouldPreventFileSelect={!fileType}
/>
{contractAttachmentFiles.length > 0 && (
<div className="mt-2 text-sm text-green-600">
<i className="ri-checkbox-circle-line"></i>
: {contractAttachmentFiles.map((file, index) => (
<span key={index} className="font-medium">{file.name}</span>
))}
</div>
)}
</div>
</div>
)}
{/* 测试文档标记 */}
<div className="switch-container mb-4">
@@ -1915,8 +1920,11 @@ export default function FilesUpload() {
icon="ri-refresh-line"
onClick={() => {
// 清除所有定时器
if (progressIntervalRef.current) {
clearInterval(progressIntervalRef.current);
if (uploadProgressIntervalRef.current) {
clearInterval(uploadProgressIntervalRef.current);
}
if (processingStatusIntervalRef.current) {
clearInterval(processingStatusIntervalRef.current);
}
// 重置状态
resetUpload();