Files
leaudit-platform-frontend/app/components/cross-checking/DocumentListModal.tsx
T

325 lines
9.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Modal } from '../ui/Modal';
import { Table } from '../ui/Table';
import { Button } from '../ui/Button';
import { FileIcon } from '../ui/FileIcon';
import { FileTypeTag } from '../ui/FileTypeTag';
import { StatusBadge } from '../ui/StatusBadge';
import { Pagination } from '../ui/Pagination';
import { LoadingIndicator } from '../ui/SkeletonScreen';
import { updateDocumentAuditStatus, type TaskDocument } from '~/api/cross-checking/cross-files'; // 更新导入
import { toastService } from '../ui/Toast';
import { formatDate } from '~/utils';
// 导出样式链接
export const links = () => [];
interface DocumentListModalProps {
isOpen: boolean;
onClose: () => void;
title: string;
files: TaskDocument[]; // 更新类型
onViewFile?: (fileId: string) => void;
loading?: boolean;
// 分页相关属性
currentPage?: number;
pageSize?: number;
total?: number;
onPageChange?: (page: number) => void;
onPageSizeChange?: (size: number) => void;
}
export function DocumentListModal({
isOpen,
onClose,
title,
files,
onViewFile,
loading = false,
// 分页属性,使用默认值
currentPage = 1,
pageSize = 10,
total = 0,
onPageChange,
onPageSizeChange
}: DocumentListModalProps) {
// 查看评查文件
const handleReviewFileClick = async (fileId: string, auditStatus: number | null) => {
// 检查audit_status是否为0,如果是则更新为2
if (auditStatus === 0 || auditStatus === null) {
try {
// TODO: 不需要传递userId,直接使用fileId找到对应文档,然后更新文档状态
// 更新文档状态
const updatedFile = await updateDocumentAuditStatus(fileId, 2);
console.log('更新后的文档状态:', updatedFile);
} catch (error) {
console.error('更新文件审核状态时出错:', error);
toastService.error(`更新文件审核状态时出错:${error instanceof Error ? error.message : '未知错误'}`);
return;
}
}
// 如果有自定义的查看处理函数,则调用它
if (onViewFile) {
onViewFile(fileId);
}
};
// 渲染问题摘要
const renderIssues = (file: TaskDocument) => {
// 如果文件有问题信息
if (file.issues && file.issues.length > 0) {
// 最多显示2个问题
const displayIssues = file.issues.slice(0, 2);
return (
<div className="text-sm">
{displayIssues.map((issue, index) => (
<div key={index} className="mb-1">
<i className={`ri-circle-fill mr-1 ${
issue.severity === 'error' ? 'text-red-400' :
issue.severity === 'warning' ? 'text-yellow-400' :
'text-blue-400'
}`}></i>
{issue.message}
</div>
))}
{file.issues.length > 2 && (
<div className="text-secondary mt-1">
{file.issues.length - 2} ...
</div>
)}
</div>
);
}
// 如果没有问题信息,根据状态显示
if (file.evaluations_status === 1) {
return (
<div className="text-sm text-success">
<i className="ri-check-double-line mr-1"></i>
</div>
);
}
// 其他状态显示占位符
return <div className="text-sm text-secondary">-</div>;
};
// 获取文件大小的友好显示
const formatFileSize = (bytes: number) => {
if (bytes === 0) return '0 B';
const k = 1024;
const sizes = ['B', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
};
// 定义表格列配置
const columns = [
{
title: "文件名称",
key: "fileName",
width: "30%",
render: (_: unknown, file: TaskDocument) => (
<div className="flex">
<div className="flex-shrink-0 flex items-center self-center">
<FileIcon fileName={file.file_name} className="text-lg w-10 h-10" />
</div>
<div className="min-w-0 flex-1 flex flex-col py-2 ml-2">
<div className="font-normal text-base break-words whitespace-normal leading-normal" title={file.file_name}>{file.file_name}</div>
<div className="text-xs text-secondary mt-2">
{file.file_code}
</div>
<div className="text-xs text-secondary mt-1">
{formatFileSize(file.file_size)}
</div>
</div>
</div>
)
},
{
title: "文件类型",
key: "fileType",
width: "10%",
render: (_: unknown, file: TaskDocument) => (
<FileTypeTag
type="other"
typeName={file.file_type_name}
text={file.file_type_name}
size="sm"
showIcon={false}
colorMode="light"
/>
)
},
{
title: "上传时间",
key: "uploadTime",
width: "12%",
render: (_: unknown, file: TaskDocument) => {
const uploadTime = formatDate(file.upload_time).split(' ');
const date = uploadTime[0];
const time = uploadTime[1];
return (
<div>
<span className="text-base">{date}</span> {/* 2025-07-22 */}
<br />
<span className="text-xs text-secondary">{time}</span> {/* 10:00:00 */}
</div>
);
}
},
{
title: "评查统计",
key: "reviewStatus",
width: "12%",
render: (_: unknown, file: TaskDocument) =>
// 要文件切分处理完之后,再显示评查统计
file.status === 'Processed' ? (
<div>
{file.pass_count > 0 && (
<StatusBadge
status="pass"
text={`通过(${file.pass_count})`}
showIcon={true}
className="my-2"
/>
)}
{file.warning_count > 0 && (
<StatusBadge
status="warning"
text={`警告(${file.warning_count})`}
showIcon={true}
className="my-2"
/>
)}
{file.fail_count > 0 && (
<StatusBadge
status="fail"
text={`不通过(${file.fail_count})`}
showIcon={true}
className="my-2"
/>
)}
{/* {file.manual_count > 0 && (
<StatusBadge
status="pending"
text={`需人工(${file.manual_count})`}
showIcon={true}
className="my-2"
/>
)} */}
</div>
) : (
<div className="text-sm">
-
</div>
)
},
{
title: "评查分数",
key: "score",
width: "8%",
render: (_: unknown, file: TaskDocument) => (
<div className="text-center">
{file.final_score ? (
<span className={`font-medium ${
file.final_score >= 90 ? 'text-green-600' :
file.final_score >= 70 ? 'text-yellow-600' :
'text-red-600'
}`}>
{file.final_score}
</span>
) : (
<span className="text-gray-400">-</span>
)}
</div>
)
},
{
title: "问题摘要",
key: "issues",
width: "20%",
render: (_: unknown, file: TaskDocument) => renderIssues(file)
},
{
title: "操作",
key: "operation",
width: "auto",
render: (_: unknown, file: TaskDocument) => (
<>
<Button
type="default"
size="small"
icon="ri-eye-line"
onClick={() => handleReviewFileClick(file.document_id.toString(), file.audit_status)}
disabled={file.status !== 'Processed'}
className="mr-2"
>
</Button>
</>
)
}
];
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title={title}
size="full"
className="document-list-modal"
>
<div className="px-6 py-4">
{loading ? (
// 显示loading状态
<div className="py-8">
<LoadingIndicator text="正在加载文档列表..." />
</div>
) : files.length === 0 ? (
// 无数据状态
<div className="text-center py-8 text-gray-500">
</div>
) : (
// 有数据时显示表格和分页
<>
<div className="mb-4 flex items-center">
<i className="ri-file-list-3-line text-primary text-lg mr-2"></i>
<span className="text-sm text-secondary"></span>
<span className="text-base font-normal text-primary ml-1 mr-1">{total || files.length}</span>
<span className="text-sm text-secondary"></span>
</div>
<Table
columns={columns}
dataSource={files}
rowKey="document_id"
emptyText="暂无文件数据"
className="files-table table-auto-height"
/>
{/* 分页组件 - 只有在提供了分页回调函数且总数大于每页大小时才显示 */}
{onPageChange && total > 0 && (
<Pagination
currentPage={currentPage}
total={total}
pageSize={pageSize}
onChange={onPageChange || (() => {})}
onPageSizeChange={onPageSizeChange}
showTotal={true}
showPageSizeChanger={!!onPageSizeChange}
pageSizeOptions={[10, 20, 30, 50]}
/>
)}
</>
)}
</div>
</Modal>
);
}