import { useState } from "react"; import { useLoaderData, useActionData, useNavigate, Form } from "@remix-run/react"; import { redirect, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction } from "@remix-run/node"; import { Card } from "~/components/ui/Card"; import { Button } from "~/components/ui/Button"; import documentEditStyles from "~/styles/pages/documents_edit.css?url"; export function links() { return [{ rel: "stylesheet", href: documentEditStyles }]; } export const meta: MetaFunction = () => { return [ { title: "修改文档 - 中国烟草AI合同及卷宗审核系统" }, { name: "description", content: "修改文档信息,包括文档类型、编号、状态和备注信息等" } ]; }; // 文档状态定义 enum DocumentStatus { PENDING = "pending", PROCESSING = "processing", PASS = "pass", WARNING = "warning", FAIL = "fail" } // 文档状态对应的中文标签 const STATUS_LABELS: Record = { [DocumentStatus.PENDING]: "待审核", [DocumentStatus.PROCESSING]: "审核中", [DocumentStatus.PASS]: "通过", [DocumentStatus.WARNING]: "警告", [DocumentStatus.FAIL]: "不通过" }; // 文档类型接口 interface DocumentType { id: string; name: string; } // 历史记录项接口 interface HistoryItem { time: string; user: string; action: string; details: string; } // 文档接口 interface Document { id: string; name: string; type_id: string; document_number: string | null; file_size: number; upload_time: string; is_test_document: boolean; status: DocumentStatus; remark: string | null; history: HistoryItem[]; file_url?: string; } // 模拟API获取文档类型列表 async function getDocumentTypes(): Promise { // 这里应该是实际API调用 return [ { id: "1", name: "销售合同" }, { id: "2", name: "采购合同" }, { id: "3", name: "专卖许可证" }, { id: "4", name: "行政处罚决定书" }, { id: "5", name: "承包协议" } ]; } // 模拟API获取文档详情 async function getDocument(id: string): Promise { // 这里应该是实际API调用 return { id, name: "2023年度烟草销售框架合同.pdf", type_id: "1", // 销售合同 document_number: "XS20230001", file_size: 2.5 * 1024 * 1024, // 2.5MB upload_time: "2023-10-15 15:30", is_test_document: false, status: DocumentStatus.PASS, remark: "此合同为2023年度与XX公司的销售框架协议,适用于全年的烟草销售业务。", history: [ { time: "2023-10-15 15:30", user: "系统", action: "创建了此文档", details: "首次上传文档,文档类型:销售合同,状态:待审核" }, { time: "2023-10-15 16:45", user: "张三", action: "启动了文档审核", details: "状态由'待审核'变更为'审核中'" }, { time: "2023-10-15 17:20", user: "系统", action: "完成了文档审核", details: "状态由'审核中'变更为'通过',未发现问题" }, { time: "2023-10-16 09:10", user: "李四", action: "修改了文档属性", details: "添加了备注信息,完善了文档编号" } ], file_url: "/mock/documents/sample.pdf" }; } // 模拟API更新文档信息 async function updateDocument(id: string, data: Partial): Promise { // 这里应该是实际API调用 console.log("更新文档:", id, data); // 模拟获取原始数据 const document = await getDocument(id); // 合并更新的数据 const updatedDocument = { ...document, ...data, // 添加新的历史记录 history: [ { time: new Date().toISOString().replace("T", " ").slice(0, 16), user: "当前用户", action: "修改了文档信息", details: `更新了文档类型、状态和备注信息` }, ...document.history ] }; return updatedDocument; } // 格式化文件大小 function formatFileSize(bytes: number): string { if (bytes === 0) return "0 Bytes"; const k = 1024; const sizes = ["Bytes", "KB", "MB", "GB", "TB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i]; } // Loader函数 export async function loader({ request }: LoaderFunctionArgs) { try { // 从URL查询参数获取文档ID const url = new URL(request.url); const id = url.searchParams.get("id"); if (!id) { throw new Response("缺少文档ID", { status: 400 }); } // 并行获取文档详情和文档类型列表 const [document, documentTypes] = await Promise.all([ getDocument(id), getDocumentTypes() ]); return Response.json({ document, documentTypes }); } catch (error) { console.error("加载文档数据失败:", error); throw new Response("加载文档数据失败", { status: 500 }); } } // Action函数处理表单提交 export async function action({ request }: ActionFunctionArgs) { // 从URL查询参数获取文档ID const url = new URL(request.url); const id = url.searchParams.get("id"); if (!id) { return Response.json({ error: "缺少文档ID" }, { status: 400 }); } try { const formData = await request.formData(); // 从表单数据中提取字段 const type_id = formData.get("type_id") as string; const document_number = formData.get("document_number") as string; const status = formData.get("status") as DocumentStatus; const is_test_document = formData.get("is_test_document") === "on"; const remark = formData.get("remark") as string; // 验证必填字段 if (!type_id || !status) { return Response.json( { error: "缺少必填字段", fieldErrors: { type_id: !type_id ? "文档类型不能为空" : null, status: !status ? "状态不能为空" : null } }, { status: 400 } ); } // 更新文档 await updateDocument(id, { type_id, document_number: document_number || null, status, is_test_document, remark: remark || null }); // 重定向回文档列表 return redirect("/documents"); } catch (error) { console.error("更新文档失败:", error); return Response.json({ error: "更新文档失败" }, { status: 500 }); } } // 文档编辑页面组件 export default function DocumentEdit() { const { document, documentTypes } = useLoaderData(); const actionData = useActionData(); const navigate = useNavigate(); // 状态 const [localStatus, setLocalStatus] = useState(document.status); // 处理状态变更 const handleStatusChange = (e: React.ChangeEvent) => { setLocalStatus(e.target.value as DocumentStatus); }; // 获取文档类型名称 const getDocumentTypeName = (typeId: string): string => { const docType = documentTypes.find((type: DocumentType) => type.id === typeId); return docType ? docType.name : "未知类型"; }; // 渲染状态徽章 const renderStatusBadge = (status: DocumentStatus) => { const statusClasses: Record = { [DocumentStatus.PENDING]: "status-badge status-pending", [DocumentStatus.PROCESSING]: "status-badge status-processing", [DocumentStatus.PASS]: "status-badge status-pass", [DocumentStatus.WARNING]: "status-badge status-warning", [DocumentStatus.FAIL]: "status-badge status-fail" }; return ( {STATUS_LABELS[status]} ); }; return (
{/* 页面头部 */}

修改文档信息

{/* 文档信息 */}
{document.name}
{getDocumentTypeName(document.type_id)}
{document.upload_time}
{formatFileSize(document.file_size)}
{renderStatusBadge(document.status)}
您可以修改此文档的基本信息,但不能更改文档内容。如需修改内容,请删除后重新上传新文档。
更改文档类型将重新应用对应的评查规则
{actionData?.fieldErrors?.type_id && (
{actionData.fieldErrors.type_id}
)}
如无编号可留空
更改状态可能会影响此文档在列表中的显示和排序
{actionData?.fieldErrors?.status && (
{actionData.fieldErrors.status}
)}
文档属性
标记为测试文档(不计入正式统计)
{/* 文档预览 */}
{document.name}

预览功能暂不可用

PDF文件需要外部查看器支持

{/* 修改历史 */}
{document.history.map((item: HistoryItem, index: number) => (
{item.time}
{item.user} {item.action}
{item.details}
))}
); } // 错误边界 export function ErrorBoundary() { return (

出错了

文档编辑页面加载失败。请检查文档ID是否正确,或稍后重试。

); }