添加合同和卷宗数据隔离

This commit is contained in:
2025-06-03 12:16:31 +08:00
parent b02978508d
commit 0397139ad8
20 changed files with 1190 additions and 437 deletions
+176 -73
View File
@@ -71,6 +71,7 @@ export const PRIORITY_LABELS: Record<Priority, string> = {
};
// 优先级中文映射
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const PRIORITY_TO_CHINESE: Record<Priority, string> = {
[Priority.NORMAL]: "普通",
[Priority.HIGH]: "优先",
@@ -109,60 +110,74 @@ export interface UploadedFile {
};
}
// 模拟上传文件到服务器的API
async function uploadFileToServer(
binaryData: ArrayBuffer,
fileName: string,
fileType: string,
documentType: FileType,
// 修改文件上传函数部分,解决类型问题
async function handleFileUpload(
binaryData: ArrayBuffer,
fileName: string,
fileType: string,
documentType: FileType,
priority: Priority,
documentNumber: string | null,
remark: string | null,
isTestDocument: boolean
): Promise<FileUploadResponse> {
// 在实际应用中,这里会使用fetch或axios发送请求到后端API
// console.log(`[API] 上传文件: ${fileName}, 大小: ${binaryData.byteLength} 字节`);
// 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 : '上传失败'
// };
// }
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,
fileType,
documentType,
priority,
documentNumber,
remark,
isTestDocument
);
if (response.error || !response.data) {
throw new Error(response.error || '上传失败');
}
return response.data;
}
// 定义action返回数据的类型
@@ -242,6 +257,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
// console.log('loader: 开始加载数据...');
const url = new URL(request.url);
const mode = url.searchParams.get("mode") || "create";
// 我们不能在服务器端访问 sessionStorage,所以在客户端组件中处理 reviewType 过滤
// 并行加载文档和文档类型
const [documentsResponse, typesResponse] = await Promise.all([
getTodayDocuments(),
@@ -271,8 +288,12 @@ export async function loader({ request }: LoaderFunctionArgs) {
// 文件上传页面组件
export default function FilesUpload() {
// 获取 sessionStorage 中的 reviewType 值
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [reviewType, setReviewType] = useState<string | null>(null);
// 使用 useLoaderData 获取初始数据
const { documents, documentTypes } = useLoaderData<LoaderData>();
const loaderData = useLoaderData<LoaderData>();
// 状态管理
// 高级上传设置
@@ -285,9 +306,10 @@ export default function FilesUpload() {
const [currentFiles, setCurrentFiles] = useState<File[]>([]);
// 合同文件上传状态
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");
@@ -302,8 +324,76 @@ export default function FilesUpload() {
const navigate = useNavigate();
// 队列文件状态
const [queueFiles, setQueueFiles] = useState<Document[]>(documents);
const [documentTypesState] = useState<DocumentType[]>(documentTypes);
const [queueFiles, setQueueFiles] = useState<Document[]>([]);
const [documentTypesState, setDocumentTypesState] = useState<DocumentType[]>([]);
// 在组件挂载时从 sessionStorage 获取 reviewType
useEffect(() => {
try {
// 在客户端环境中执行
if (typeof window !== 'undefined') {
const storedReviewType = sessionStorage.getItem('reviewType');
setReviewType(storedReviewType);
// 根据 reviewType 过滤文档类型和文档列表
filterDocumentTypes(storedReviewType, loaderData.documentTypes);
filterDocuments(storedReviewType);
}
} catch (error) {
console.error('获取 sessionStorage 中的 reviewType 失败:', error);
}
}, [loaderData]);
// 过滤文档类型列表
const filterDocumentTypes = (reviewType: string | null, types: DocumentType[]) => {
if (!reviewType) {
// 如果没有特定的 reviewType,使用原始数据
setDocumentTypesState(types);
return;
}
let filteredTypes: DocumentType[] = [];
if (reviewType === 'contract') {
// 只保留 id=1 的选项
filteredTypes = types.filter(type => type.id === 1);
} else if (reviewType === 'record') {
// 只保留 id=2 和 id=3 的选项
filteredTypes = types.filter(type => type.id === 2 || type.id === 3);
} else {
// 如果reviewType不匹配任何条件,使用原始数据
filteredTypes = types;
}
setDocumentTypesState(filteredTypes);
};
// 过滤文档列表
const filterDocuments = async (reviewType: string | null) => {
if (!reviewType) {
// 如果没有特定的 reviewType,使用原始数据
setQueueFiles(loaderData.documents);
return;
}
try {
// 使用 reviewType 获取过滤后的文档列表
const response = await getTodayDocuments(reviewType);
if (response.error) {
console.error('过滤文档列表失败:', response.error);
// 失败时使用原始数据
setQueueFiles(loaderData.documents);
return;
}
setQueueFiles(response.data || []);
} catch (error) {
console.error('过滤文档列表失败:', error);
// 出错时使用原始数据
setQueueFiles(loaderData.documents);
}
};
// 构建文件类型标签映射
useEffect(() => {
@@ -312,11 +402,11 @@ export default function FilesUpload() {
delete FILE_TYPE_LABELS[key];
});
// 使用从API获取的文档类型构建新的映射
documentTypes.forEach(type => {
// 使用过滤后的文档类型构建新的映射
documentTypesState.forEach(type => {
FILE_TYPE_LABELS[type.id.toString()] = type.name;
});
}, [documentTypes]);
}, [documentTypesState]);
// 上传完成后的文件信息列表
const [completedFiles, setCompletedFiles] = useState<UploadedFile[]>([]);
@@ -462,7 +552,7 @@ export default function FilesUpload() {
setFileTypeError(null);
// 检查是否选择了合同类型
const selectedType = documentTypes.find(t => t.id.toString() === value);
const selectedType = loaderData.documentTypes.find(t => t.id.toString() === value);
const isContract = !!(selectedType && selectedType.name.includes('合同'));
// console.log('【调试-handleFileTypeChange】文件类型检查:', {
// selectedType,
@@ -471,11 +561,11 @@ export default function FilesUpload() {
// currentFiles: currentFiles.length
// });
setIsContractType(isContract);
// setIsContractType(isContract);
// 重置文件状态
setContractMainFiles([]);
setContractAttachmentFiles([]);
// setContractMainFiles([]);
// setContractAttachmentFiles([]);
setCurrentFiles([]);
// 如果已经有选中的文件,且选择了文件类型,且不是合同类型,则开始上传
@@ -490,20 +580,21 @@ export default function FilesUpload() {
} else {
setFileType("");
setIsContractType(false);
// setIsContractType(false);
// 如果用户选择了空选项,显示错误信息
setFileTypeError("上传文件之前请选择文件类型");
}
};
// 处理合同主文件选择
// 处理合同主文件选择 - 暂时未使用,保留以备将来扩展
/*
const handleContractMainFilesSelected = (files: FileList) => {
try {
// console.log('【调试-handleContractMainFilesSelected】开始处理合同主文件选择, 文件数量:', files.length);
// 检查组件是否已卸载
if (!isMountedRef.current) {
// console.error('【调试-handleContractMainFilesSelected】组件已卸载,取消处理');
console.error('【调试-handleContractMainFilesSelected】组件已卸载,取消处理');
return;
}
@@ -535,7 +626,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文件或组件已卸载');
}
@@ -546,8 +637,10 @@ export default function FilesUpload() {
console.error('【调试-handleContractMainFilesSelected】处理合同主文件选择时发生错误:', error);
}
};
*/
// 处理合同附件选择
// 处理合同附件选择 - 暂时未使用,保留以备将来扩展
/*
const handleContractAttachmentFilesSelected = (files: FileList) => {
try {
// console.log('【调试-handleContractAttachmentFilesSelected】开始处理合同附件选择, 文件数量:', files.length);
@@ -586,7 +679,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文件或组件已卸载');
}
@@ -597,8 +690,10 @@ export default function FilesUpload() {
console.error('【调试-handleContractAttachmentFilesSelected】处理合同附件选择时发生错误:', error);
}
};
*/
// 检查并准备上传
// 检查并准备上传 - 暂时未使用,保留以备将来扩展
/*
const checkAndPrepareUpload = (mainFiles: File[], attachmentFiles: File[]) => {
try {
// console.log('【调试-checkAndPrepareUpload】开始检查并准备上传文件', {
@@ -621,7 +716,7 @@ export default function FilesUpload() {
}
// 检查是否为合同类型
const selectedType = documentTypes.find(t => t.id.toString() === fileType);
const selectedType = loaderData.documentTypes.find(t => t.id.toString() === fileType);
const isContract = !!(selectedType && selectedType.name.includes('合同'));
// console.log('【调试-checkAndPrepareUpload】文件类型检查', {
@@ -721,6 +816,7 @@ export default function FilesUpload() {
}
}
};
*/
// 开始上传文件
const startUpload = async (files: File[]) => {
@@ -822,7 +918,7 @@ export default function FilesUpload() {
// console.log(`【调试-startUpload】准备上传文件 ${file.name} 到服务器`);
// 使用Promise.race添加超时处理
const uploadPromise = uploadFileToServer(
const uploadPromise = handleFileUpload(
binaryData,
file.name,
file.type,
@@ -840,7 +936,7 @@ export default function FilesUpload() {
});
// 使用Promise.race处理超时
response = await Promise.race([uploadPromise, timeoutPromise]);
const uploadResult = await Promise.race([uploadPromise, timeoutPromise]);
// 再次检查组件是否已卸载
if (!isMountedRef.current) {
@@ -848,6 +944,13 @@ export default function FilesUpload() {
return;
}
// 检查上传结果
if (!uploadResult.success || !uploadResult.result) {
throw new Error(uploadResult.error || '上传失败');
}
response = uploadResult;
// console.log(`【调试-startUpload】文件 ${file.name} 上传响应:`, response);
} catch (error) {
// 检查组件是否已卸载
@@ -1215,8 +1318,8 @@ export default function FilesUpload() {
setCompletedFiles([]);
// 重置合同文件状态
setContractMainFiles([]);
setContractAttachmentFiles([]);
// setContractMainFiles([]);
// setContractAttachmentFiles([]);
// 重置步骤状态
setProcessingSteps([
@@ -1493,7 +1596,7 @@ export default function FilesUpload() {
disabled={uploadStage !== "idle"}
>
<option value=""></option>
{documentTypes.map(type => (
{documentTypesState.map(type => (
<option key={type.id} value={type.id}>{type.name}</option>
))}
</select>