完善评查详情

This commit is contained in:
2025-04-18 15:41:43 +08:00
parent 119f9197b2
commit 01d93522b8
25 changed files with 1731 additions and 511 deletions
+159 -30
View File
@@ -1,5 +1,5 @@
import { useState } from "react";
import { useSearchParams, Link, useLoaderData, useFetcher } from "@remix-run/react";
import { useSearchParams, useLoaderData, useFetcher, useNavigate,Link } from "@remix-run/react";
import { type MetaFunction, type ActionFunctionArgs, type LoaderFunctionArgs } from "@remix-run/node";
import { Card } from "~/components/ui/Card";
import { Button } from "~/components/ui/Button";
@@ -11,6 +11,7 @@ import { FilterPanel, FilterSelect, SearchFilter, DateRangeFilter } from "~/comp
import documentsIndexStyles from "~/styles/pages/documents_index.css?url";
import { getDocuments, deleteDocument, type DocumentUI } from "~/api/files/documents";
import { getDocumentTypes } from "~/api/document-types/document-types";
import { updateDocumentAuditStatus } from "~/api/evaluation_points/rules-files";
// 导入样式
export function links() {
@@ -119,11 +120,11 @@ export const action = async ({ request }: ActionFunctionArgs) => {
// 审核状态筛选选项
const auditStatusOptions = [
// { value: "", label: "全部" },
{ value: "-2", label: "警告" },
{ value: "-1", label: "不通过" },
{ value: "0", label: "待审核" },
{ value: "1", label: "通过" },
{ value: "2", label: "警告" },
{ value: "3", label: "审核中" },
{ value: "2", label: "审核中" },
];
// 文件处理状态选项
@@ -148,10 +149,10 @@ const fileStatusOptions = [
// 审核状态选项及样式
const auditStatusMapping: Record<string, { label: string; color: string; icon: string }> = {
"-1": { label: "不通过", color: "red", icon: "ri-close-line" },
"-2": { label: "警告", color: "yellow", icon: "ri-alert-line" },
"0": { label: "待审核", color: "blue", icon: "ri-time-line" },
"1": { label: "通过", color: "green", icon: "ri-check-line" },
"2": { label: "警告", color: "yellow", icon: "ri-alert-line" },
"3": { label: "审核中", color: "purple", icon: "ri-search-line" },
"2": { label: "审核中", color: "purple", icon: "ri-search-line" },
};
// 格式化文件大小
@@ -182,6 +183,7 @@ export default function DocumentsIndex() {
const [selectedRowKeys, setSelectedRowKeys] = useState<string[]>([]);
const loaderData = useLoaderData<typeof loader>();
const fetcher = useFetcher();
const navigate = useNavigate();
// 从URL获取当前筛选条件
const search = searchParams.get("search") || "";
@@ -321,29 +323,41 @@ export default function DocumentsIndex() {
};
// 下载文档
const handleDownload = async (path: string, fileName: string) => {
console.log('handleDownload',path,fileName)
const handleDownload = async (path: string) => {
try {
// 使用API获取授权的下载链接
// const { data, error } = await getFileDownloadUrl(path);
const urlBefore = 'http://172.18.0.100:9000/docauditai/';
const downloadUrl = `${urlBefore}${path}`;
// if (error || !data?.downloadUrl) {
// console.error('获取下载链接失败:', error);
// alert('获取下载链接失败: ' + (error || '未知错误'));
// return;
// }
// 使用fetch获取文件内容
const response = await fetch(downloadUrl);
if (!response.ok) {
throw new Error(`下载失败: ${response.status} ${response.statusText}`);
}
// 将响应转换为Blob
const blob = await response.blob();
// 创建Blob URL
const blobUrl = URL.createObjectURL(blob);
// 创建一个隐藏的a标签并点击它
const a = document.createElement('a');
// a.href = data.downloadUrl;
a.href = path;
a.download = fileName; // 设置下载的文件名
a.style.display = 'none';
a.href = blobUrl;
// 从路径中获取文件名
const fileName = path.split('/').pop() || 'document';
a.download = decodeURIComponent(fileName);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
} catch (err) {
console.error('下载文件失败:', err);
alert('下载文件失败: ' + (err instanceof Error ? err.message : '未知错误'));
// 清理
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(blobUrl);
}, 100);
} catch (error) {
console.error('下载文件失败:', error);
alert(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
};
@@ -412,6 +426,114 @@ export default function DocumentsIndex() {
setSearchParams(params);
};
// 导出列表
const handleExport = async () => {
// 如果没有文档,显示提示信息
if (documents.length === 0) {
alert('当前页面没有文档可供导出');
return;
}
try {
// 创建一个ZIP文件
const JSZip = await import('jszip').then(module => module.default);
const zip = new JSZip();
// 准备所有下载任务
const downloadTasks = documents.map(async (doc: DocumentUI) => {
try {
if (!doc.path) {
console.warn(`文档 ${doc.name} 没有有效的路径`);
return;
}
const urlBefore = 'http://172.18.0.100:9000/docauditai/';
const downloadUrl = `${urlBefore}${doc.path}`;
// 获取文件内容
const response = await fetch(downloadUrl);
if (!response.ok) {
throw new Error(`下载失败: ${response.status} ${response.statusText}`);
}
// 将响应转换为Blob
const blob = await response.blob();
// 从路径中获取文件名
const fileName = doc.path.split('/').pop() || doc.name;
// 添加到ZIP文件
zip.file(decodeURIComponent(fileName), blob);
return { success: true, name: fileName };
} catch (error) {
console.error(`下载文件 ${doc.name} 失败:`, error);
return { success: false, name: doc.name, error };
}
});
// 等待所有下载任务完成
const results = await Promise.all(downloadTasks);
// 计算成功和失败的数量
const succeeded = results.filter(r => r && r.success).length;
const failed = results.filter(r => r && !r.success).length;
if (succeeded === 0) {
alert('所有文件下载失败');
return;
}
// 生成ZIP文件
const zipBlob = await zip.generateAsync({ type: 'blob' });
// 创建下载链接
const url = URL.createObjectURL(zipBlob);
const a = document.createElement('a');
a.href = url;
a.download = `文档导出_${new Date().toISOString().slice(0, 10)}.zip`;
document.body.appendChild(a);
a.click();
// 清理
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
}, 100);
// 显示结果消息
if (failed > 0) {
alert(`成功导出 ${succeeded} 个文件,${failed} 个文件失败`);
} else {
alert(`成功导出 ${succeeded} 个文件`);
}
} catch (error) {
console.error('导出文件失败:', error);
alert(`导出文件失败: ${error instanceof Error ? error.message : '未知错误'}`);
}
};
// 开始审核
const handleReviewFileClick = async (fileId: number, auditStatus: number | null) => {
// 检查audit_status是否为0,如果是则更新为2
if (auditStatus === 0) {
try {
const response = await updateDocumentAuditStatus(fileId.toString(), 2);
if (response.error) {
console.error('更新文件审核状态失败:', response.error);
alert('更新文件审核状态失败:' + (response.error || '未知错误'));
}
} catch (error) {
console.error('更新文件审核状态时出错:', error);
alert('更新文件审核状态时出错:' + (error instanceof Error ? error.message : '未知错误'));
}
}
// 导航到评查详情页
navigate(`/reviews?id=${fileId}`);
};
// 表格列定义
const columns = [
{
@@ -517,7 +639,7 @@ export default function DocumentsIndex() {
{
title: "问题数量",
key: "issues",
width:"5%",
width:"7%",
render: (_: unknown, record: DocumentUI) => (
record.issues === null ? "-" : record.issues
)
@@ -535,14 +657,20 @@ export default function DocumentsIndex() {
render: (_: unknown, record: DocumentUI) => (
<div className="operations-cell">
{(record.auditStatus === 0 || record.auditStatus == null) ? (
<Link
to={`/reviews?id=${record.id}`}
className="mr-1 hover:underline"
<button
onClick={() => handleReviewFileClick(record.id, record.auditStatus)}
disabled={record.fileStatus !== 'Processed'}
className={`mr-1 ${
record.fileStatus === 'Processed'
? 'hover:underline hover:cursor-pointer text-primary'
: 'text-gray-400 cursor-not-allowed opacity-60'
}`}
>
<i className="ri-play-circle-line"></i>
<i className="ri-play-circle-line"></i>
</Link>
) : record.auditStatus === 3 ? (
</button>
) : record.auditStatus === 3 ? (
//record.auditStatus === 3 目前这个状态不存在,所以除了待审核(0)-开始审核,其他都是审核中(2)-查看
<Link
to={`/documents/${record.id}/progress`}
className="mr-1 hover:underline"
@@ -552,7 +680,7 @@ export default function DocumentsIndex() {
</Link>
) : (
<Link
to={`/documents/${record.id}`}
to={`/reviews?id=${record.id}`}
className="mr-1 hover:underline"
>
<i className="ri-eye-line"></i>
@@ -569,7 +697,7 @@ export default function DocumentsIndex() {
<button
type="button"
className="mr-1 text-gray-500 hover:underline hover:text-gray-700"
onClick={() => handleDownload(record.path, record.name)}
onClick={() => handleDownload(record.path)}
>
<i className="ri-download-line"></i>
@@ -699,6 +827,7 @@ export default function DocumentsIndex() {
<Button
type="default"
icon="ri-download-line"
onClick={handleExport}
>
</Button>