修改文档列表

This commit is contained in:
2025-04-13 18:49:43 +08:00
parent 60680cd4bf
commit cb52bf8179
10 changed files with 396 additions and 407 deletions
+70 -56
View File
@@ -19,22 +19,31 @@ export const meta: MetaFunction = () => {
];
};
// 文档状态定义
enum DocumentStatus {
WAITING = "waiting",
PROCESSING = "processing",
PASS = "pass",
WARNING = "warning",
FAIL = "fail"
// 文档审核状态定义
enum DocumentAuditStatus {
FAIL = -1,
WAITING = 0,
PASS = 1,
WARNING = 2,
PROCESSING = 3
}
// 文档状态对应的中文标签
const STATUS_LABELS: Record<DocumentStatus, string> = {
[DocumentStatus.WAITING]: "待审核",
[DocumentStatus.PROCESSING]: "审核",
[DocumentStatus.PASS]: "通过",
[DocumentStatus.WARNING]: "警告",
[DocumentStatus.FAIL]: "不通过"
const STATUS_LABELS: Record<DocumentAuditStatus, string> = {
[DocumentAuditStatus.FAIL]: "不通过",
[DocumentAuditStatus.WAITING]: "审核",
[DocumentAuditStatus.PASS]: "通过",
[DocumentAuditStatus.WARNING]: "警告",
[DocumentAuditStatus.PROCESSING]: "审核中"
};
// 文档状态样式配置
const STATUS_STYLES: Record<number, { color: string; icon: string }> = {
[-1]: { color: "red", icon: "ri-close-line" },
[0]: { color: "blue", icon: "ri-time-line" },
[1]: { color: "green", icon: "ri-check-line" },
[2]: { color: "yellow", icon: "ri-alert-line" },
[3]: { color: "purple", icon: "ri-search-line" }
};
// 格式化文件大小
@@ -99,31 +108,31 @@ export async function action({ request }: ActionFunctionArgs) {
// 从表单数据中提取字段
const type = formData.get("type_id") as string;
const documentNumber = formData.get("document_number") as string;
const status = formData.get("status") as DocumentStatus;
const auditStatus = parseInt(formData.get("audit_status") as string);
const isTest = formData.get("is_test_document") === "on";
const remark = formData.get("remark") as string;
// 验证必填字段
if (!type || !status) {
if (!type || auditStatus === undefined || isNaN(auditStatus)) {
return Response.json(
{
error: "缺少必填字段",
fieldErrors: {
type_id: !type ? "文档类型不能为空" : null,
status: !status ? "状态不能为空" : null
audit_status: (auditStatus === undefined || isNaN(auditStatus)) ? "审核状态不能为空" : null
}
},
{ status: 400 }
);
}
console.log('提交更新:', { type, documentNumber, status, isTest, remark });
console.log('提交更新:', { type, documentNumber, auditStatus, isTest, remark });
// 更新文档
const updateResponse = await updateDocument(id, {
type,
documentNumber,
status,
auditStatus,
isTest,
remark
});
@@ -160,43 +169,38 @@ export default function DocumentEdit() {
}
// 状态
const [localStatus, setLocalStatus] = useState<DocumentStatus>(document.status as DocumentStatus);
const [localStatus, setLocalStatus] = useState<number>(document.auditStatus);
// 处理状态变更
const handleStatusChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setLocalStatus(e.target.value as DocumentStatus);
setLocalStatus(parseInt(e.target.value));
};
// 获取文档类型名称
const getDocumentTypeName = (typeId: string): string => {
const docType = documentTypes.find((type) => (type as any).id.toString() === typeId);
return docType ? (docType as any).name : "未知类型";
const docType = documentTypes.find((type: DocType) => type.id.toString() === typeId);
return docType ? docType.name : "未知类型";
};
// 渲染状态徽章
const renderStatusBadge = (status: string) => {
const statusClasses: Record<string, string> = {
"waiting": "status-badge status-pending",
"processing": "status-badge status-processing",
"pass": "status-badge status-pass",
"warning": "status-badge status-warning",
"fail": "status-badge status-fail"
};
const statusLabel: Record<string, string> = {
"waiting": "待审核",
"processing": "审核中",
"pass": "通过",
"warning": "警告",
"fail": "不通过"
};
const renderStatusBadge = (status: number) => {
const style = STATUS_STYLES[status] || STATUS_STYLES[0];
const label = STATUS_LABELS[status as DocumentAuditStatus] || STATUS_LABELS[DocumentAuditStatus.WAITING];
return (
<span className={statusClasses[status] || "status-badge"}>
{statusLabel[status] || status}
<span className={`status-badge bg-${style.color}-100 text-${style.color}-800`}>
<i className={`${style.icon} mr-1`}></i>
{label}
</span>
);
};
// 在新窗口打开文档预览
const openPreview = () => {
// 假设有一个预览URL的格式,比如 /preview?path=xxx
const previewUrl = `/preview?path=${encodeURIComponent(document.path)}&name=${encodeURIComponent(document.name)}`;
window.open(previewUrl, '_blank');
};
return (
<div className="document-edit-page">
@@ -250,7 +254,7 @@ export default function DocumentEdit() {
<span>{formatFileSize(document.size)}</span>
</div>
<div className="meta-item">
{renderStatusBadge(document.status)}
{renderStatusBadge(document.auditStatus)}
</div>
</div>
</div>
@@ -271,7 +275,7 @@ export default function DocumentEdit() {
defaultValue={document.type}
required
>
{documentTypes.map(type => (
{documentTypes.map((type: DocType) => (
<option key={type.id} value={type.id}>{type.name}</option>
))}
</select>
@@ -295,24 +299,24 @@ export default function DocumentEdit() {
</div>
<div className="form-group">
<label htmlFor="status" className="form-label"> <span className="text-red-500">*</span></label>
<label htmlFor="audit-status" className="form-label"> <span className="text-red-500">*</span></label>
<select
id="status"
name="status"
id="audit-status"
name="audit_status"
className="form-select"
value={localStatus}
onChange={handleStatusChange}
required
>
<option value={DocumentStatus.WAITING}>{STATUS_LABELS[DocumentStatus.WAITING]}</option>
<option value={DocumentStatus.PROCESSING}>{STATUS_LABELS[DocumentStatus.PROCESSING]}</option>
<option value={DocumentStatus.PASS}>{STATUS_LABELS[DocumentStatus.PASS]}</option>
<option value={DocumentStatus.WARNING}>{STATUS_LABELS[DocumentStatus.WARNING]}</option>
<option value={DocumentStatus.FAIL}>{STATUS_LABELS[DocumentStatus.FAIL]}</option>
<option value={DocumentAuditStatus.WAITING}>{STATUS_LABELS[DocumentAuditStatus.WAITING]}</option>
<option value={DocumentAuditStatus.PROCESSING}>{STATUS_LABELS[DocumentAuditStatus.PROCESSING]}</option>
<option value={DocumentAuditStatus.PASS}>{STATUS_LABELS[DocumentAuditStatus.PASS]}</option>
<option value={DocumentAuditStatus.WARNING}>{STATUS_LABELS[DocumentAuditStatus.WARNING]}</option>
<option value={DocumentAuditStatus.FAIL}>{STATUS_LABELS[DocumentAuditStatus.FAIL]}</option>
</select>
<div className="text-sm text-secondary mt-1"></div>
{actionData?.fieldErrors?.status && (
<div className="text-red-500 text-sm mt-1">{actionData.fieldErrors.status}</div>
{actionData?.fieldErrors?.audit_status && (
<div className="text-red-500 text-sm mt-1">{actionData.fieldErrors.audit_status}</div>
)}
</div>
@@ -356,7 +360,7 @@ export default function DocumentEdit() {
<div className="document-preview">
<div className="preview-toolbar">
<div className="flex items-center">
<i className="ri-file-pdf-line text-red-500 mr-1"></i>
<i className={`ri-file-${document.fileType}-line text-${document.fileType === 'pdf' ? 'red' : 'blue'}-500 mr-1`}></i>
<span>{document.name}</span>
</div>
<div>
@@ -364,21 +368,31 @@ export default function DocumentEdit() {
type="default"
size="small"
icon="ri-download-line"
className="mr-2"
>
</Button>
<Button
type="primary"
size="small"
icon="ri-external-link-line"
onClick={openPreview}
>
</Button>
</div>
</div>
<div className="preview-content">
<div className="preview-placeholder">
<i className="ri-file-pdf-line"></i>
<i className={`ri-file-${document.fileType}-line`}></i>
<p></p>
<p className="text-xs mt-2">PDF文件需要外部查看器支持</p>
<p className="text-xs mt-2">&quot;&quot;</p>
<Button
type="primary"
size="small"
icon="ri-external-link-line"
className="mt-4"
onClick={openPreview}
>
</Button>
@@ -388,7 +402,7 @@ export default function DocumentEdit() {
</Card>
{/* 修改历史 */}
<Card title="修改历史">
<Card title="修改历史" className="hidden">
<div className="history-timeline">
{[
{