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

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
+242 -8
View File
@@ -2,16 +2,22 @@
* 评查选项卡组件
* 提供三个选项卡:评查结果、AI智能分析、文件信息
*/
import { ReactNode, useState } from 'react';
import { useNavigate } from 'react-router-dom';
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;
@@ -22,7 +28,12 @@ interface ReviewTabsProps {
export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfirmResults }: ReviewTabsProps) {
const [isNavigating, setIsNavigating] = useState(false);
const [isReuploadModalOpen, setIsReuploadModalOpen] = useState(false);
const [selectedTemplateFiles, setSelectedTemplateFiles] = useState<File[]>([]);
const [isUploading, setIsUploading] = useState(false);
const uploadAreaRef = useRef<UploadAreaRef>(null);
const navigate = useNavigate();
const revalidator = useRevalidator();
// 返回上一级
const handleBack = () => {
@@ -40,9 +51,10 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
: previousRoute === 'filesUpload'
? "/files/upload"
: "/rules-files";
// 立即导航返回
navigate(returnTo);
// 立即导航返回
navigate(returnTo);
// 触发上级页面数据重新加载
revalidator.revalidate();
};
// 下载原文件
@@ -83,6 +95,127 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
}
};
// 打开重新上传模板模态框
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) 合同id1
'normal', //priority 优先级:normal
null, //document_number 文档编号
null, //remark 备注
false, //is_test_document 是否为测试文档:false
fileInfo.id, //document_id 主文档id
true //is_reupload 是否为重新上传:true
);
// 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 (
<div className="tab-container w-full flex-1">
@@ -105,9 +238,7 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
>
<i className="ri-lightbulb-line"></i> AI智能分析
</button> */}
{/* {fileInfo.type === '1' && ( */}
{/* 隐藏结构比对 */}
{fileInfo.type === '999999' && (
{fileInfo.type === '1' && (
<button
className={`tab-nav-item ${activeTab === 'filecompare' ? 'active' : ''}`}
onClick={() => onTabChange('filecompare')}
@@ -128,6 +259,15 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
</div>
{/* 操作按钮 */}
<div className="flex space-x-3">
{/* 重新上传 */}
{activeTab === 'filecompare' && (
<button
className="ant-btn ant-btn-default flex items-center my-2 mr-4"
onClick={handleOpenReuploadModal}
>
<i className="ri-refresh-line mr-1"></i>
</button>
)}
{/* 返回上一级 */}
<button
className="ant-btn ant-btn-default flex items-center my-2"
@@ -160,6 +300,100 @@ export function ReviewTabs({ activeTab, onTabChange, children, fileInfo, onConfi
<div className="tab-content w-full">
{children}
</div>
{/* 重新上传模板模态框 */}
<Modal
isOpen={isReuploadModalOpen}
onClose={handleCloseReuploadModal}
title="重新上传模板"
size="medium"
footer={
<div className="flex justify-end space-x-3">
<Button
type="default"
onClick={handleCloseReuploadModal}
disabled={isUploading}
>
</Button>
<Button
type="primary"
onClick={handleConfirmUpload}
disabled={selectedTemplateFiles.length === 0 || isUploading}
icon={isUploading ? 'ri-loader-4-line animate-spin' : undefined}
>
{isUploading ? '上传中...' : '确定上传'}
</Button>
</div>
}
>
<div className="space-y-4">
<div className="text-sm text-gray-600 mb-4">
<p></p>
<p className="mt-2 text-orange-600">
<i className="ri-information-line mr-1"></i>
PDF格式的文件
</p>
</div>
<UploadArea
ref={uploadAreaRef}
onFilesSelected={handleTemplateFilesSelected}
accept=".pdf,application/pdf"
multiple={false}
icon="ri-file-pdf-line"
buttonText="选择模板文件"
mainText="点击或拖拽PDF文件到此区域"
tipText={
<span className="text-xs text-gray-500">
PDF
</span>
}
disabled={isUploading}
/>
{/* 已选择的文件列表 */}
{selectedTemplateFiles.length > 0 && (
<div className="mt-4">
<h4 className="text-sm font-medium text-gray-900 mb-2"></h4>
<div className="space-y-2">
{selectedTemplateFiles.map((file, index) => (
<div
key={index}
className="flex items-center justify-between p-3 bg-gray-50 rounded-lg border"
>
<div className="flex items-center">
<i className="ri-file-pdf-line text-red-500 mr-2"></i>
<div>
<div className="text-sm font-medium text-gray-900">
{file.name}
</div>
<div className="text-xs text-gray-500">
{formatFileSize(file.size)}
</div>
</div>
</div>
<button
className="text-gray-400 hover:text-red-500 transition-colors"
onClick={() => {
setSelectedTemplateFiles(prev =>
prev.filter((_, i) => i !== index)
);
if (uploadAreaRef.current) {
uploadAreaRef.current.resetFileInput();
}
}}
disabled={isUploading}
>
<i className="ri-close-line"></i>
</button>
</div>
))}
</div>
</div>
)}
</div>
</Modal>
</div>
);
}