import { type MetaFunction, type LoaderFunctionArgs } from "@remix-run/node"; import { useLoaderData, useSearchParams } from "@remix-run/react"; import { Button } from "~/components/ui/Button"; import { Card } from "~/components/ui/Card"; import { FileIcon } from "~/components/ui/FileIcon"; import { FilterPanel, FilterSelect, SearchFilter } from "~/components/ui/FilterPanel"; import { Pagination } from "~/components/ui/Pagination"; import { Table } from "~/components/ui/Table"; import { Tag } from "~/components/ui/Tag"; import { StatusBadge } from "~/components/ui/StatusBadge"; import rulesFilesStyles from "~/styles/pages/rules-files.css?url"; import { getReviewFiles, updateReviewStatus, type ReviewFileUI } from "~/api/evaluation_points/rules-files"; import { getDocumentTypes } from "~/api/document-types/document-types"; export const links = () => [ { rel: "stylesheet", href: rulesFilesStyles } ]; export const handle = { breadcrumb: "评查文件列表" }; export const meta: MetaFunction = () => { return [ { title: "评查文件列表 - 中国烟草AI合同及卷宗审核系统" }, { name: "description", content: "管理系统中所有上传的评查文件,支持按文件类型、评查状态进行筛选" }, { name: "keywords", content: "评查文件,合同审核,中国烟草,文件管理" } ]; }; // 日期范围枚举 export enum DateRange { ALL = 'all', TODAY = 'today', WEEK = 'week', MONTH = 'month', CUSTOM = 'custom' } // 评查状态标签映射 export const REVIEW_STATUS_LABELS: Record = { 'pass': '通过', 'warning': '警告', 'fail': '不通过', 'pending': '待人工确认' }; export async function loader({ request }: LoaderFunctionArgs) { const url = new URL(request.url); const fileType = url.searchParams.get("fileType") || ""; const reviewStatus = url.searchParams.get("reviewStatus") || ""; const dateRange = url.searchParams.get("dateRange") || ""; const keyword = url.searchParams.get("keyword") || ""; const sortOrder = url.searchParams.get("sortOrder") || "upload_time_desc"; const currentPage = parseInt(url.searchParams.get("page") || "1", 10); const pageSize = parseInt(url.searchParams.get("pageSize") || "10", 10); try { // 获取文档类型列表 const typesResponse = await getDocumentTypes({pageSize:500}); const documentTypes = typesResponse.data?.types || []; // 获取文件列表 const searchParams = { fileType, reviewStatus, dateRange, keyword, sortOrder, page: currentPage, pageSize, }; console.log('rules-filessearchParams-----',searchParams); const filesResponse = await getReviewFiles(searchParams); if (filesResponse.error) { console.error('获取评查文件列表失败:', filesResponse.error); throw new Response('获取评查文件列表失败', { status: filesResponse.status || 500 }); } const files = filesResponse.data?.files || []; const totalCount = filesResponse.data?.total || 0; return Response.json({ files, documentTypes, totalCount, currentPage, pageSize, }); } catch (error) { console.error('加载评查文件列表失败:', error); throw new Response('加载评查文件列表失败', { status: 500 }); } } // 提取renderErrorBoundary函数作为命名导出 export function ErrorBoundary() { return (

出错了

加载评查文件列表时发生错误。请稍后再试,或联系管理员。

); } // 在文件中定义一个与路由文件名匹配的命名函数组件 export default function RulesFiles() { const { files, documentTypes, totalCount, currentPage, pageSize } = useLoaderData(); const [searchParams, setSearchParams] = useSearchParams(); // 处理筛选条件变更 const handleFilterChange = (e: React.ChangeEvent) => { const { name, value } = e.target; const newParams = new URLSearchParams(searchParams); if (value) { newParams.set(name, value); } else { newParams.delete(name); } // 切换筛选条件时,重置到第一页 newParams.set('page', '1'); setSearchParams(newParams); }; // 处理搜索操作 const handleSearch = (keyword: string) => { const newParams = new URLSearchParams(searchParams); if (keyword) { newParams.set('keyword', keyword); } else { newParams.delete('keyword'); } // 搜索时,重置到第一页 newParams.set('page', '1'); setSearchParams(newParams); }; // 处理页码变更 const handlePageChange = (page: number) => { const newParams = new URLSearchParams(searchParams); newParams.set('page', page.toString()); setSearchParams(newParams); }; // 处理每页条数变更 const handlePageSizeChange = (size: number) => { const newParams = new URLSearchParams(searchParams); newParams.set('pageSize', size.toString()); newParams.set('page', '1'); // 改变每页条数时重置为第一页 setSearchParams(newParams); }; // 渲染问题摘要 const renderIssues = (file: ReviewFileUI) => { // 如果评查状态为通过,显示"所有评查点均通过" if (file.reviewStatus === 'pass') { return (
所有评查点均通过
); } // 其他状态显示占位符 return
-
; }; // 文件类型选项 const fileTypeOptions = documentTypes.map((type: {id: number, name: string}) => ({ value: type.id.toString(), label: type.name })); // 评查状态选项 const reviewStatusOptions = [ { value: 'pass', label: '通过' }, { value: 'warning', label: '警告' }, { value: 'fail', label: '不通过' }, { value: 'pending', label: '待人工确认' } ]; // 时间范围选项 const dateRangeOptions = [ { value: DateRange.TODAY, label: '今天' }, { value: DateRange.WEEK, label: '本周' }, { value: DateRange.MONTH, label: '本月' }, { value: DateRange.CUSTOM, label: '自定义时间段' } ]; // 定义表格列配置 const columns = [ { title: "文件名称", key: "fileName", width: "30%", render: (_: unknown, file: ReviewFileUI) => (
{file.fileName}
文件编号:{file.fileCode}
) }, { title: "文件类型", key: "fileType", width: "12%", render: (_: unknown, file: ReviewFileUI) => ( {file.fileType} ) }, { title: "上传时间", key: "uploadTime", width: "12%", render: (_: unknown, file: ReviewFileUI) => { const [date, time] = file.uploadTime.split(' '); return (
{date}
{time}
); } }, { title: "评查状态", key: "reviewStatus", width: "12%", render: (_: unknown, file: ReviewFileUI) => ( ) }, { title: "问题摘要", key: "issues", width: "20%", render: (_: unknown, file: ReviewFileUI) => renderIssues(file) }, { title: "操作", key: "operation", width: "14%", render: (_: unknown, file: ReviewFileUI) => ( <> ) } ]; return (
{/* 页面头部 */}

评查文件列表

总文件数: {totalCount}
{/* 筛选区域 */} {/* 文件列表 */} {/* 分页组件 */} {totalCount > 0 && ( )} ); }