Files
leaudit-platform-backend/docs/文档管理/文档上传与列表接口分析.md
2026-05-09 20:04:08 +08:00

13 KiB
Raw Permalink Blame History

文档上传与列表 — 接口分析 & 接入方案

所有信息已逐文件验证。源代码位置均已标注。

说明:这份文档已经吸收旧的 新系统版_documents_list接口.md文档上传与评查接口.md,后续以本文件作为文档上传、列表、详情、更新、删除、评查触发与状态查询的统一说明。


一、后端接口(已验证)

1.1 POST /api/upload — 文档上传

源码: fastapi_modules/fastapi_leaudit/controllers/documentController.py:20-45
实现: fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py:44-246

URL:    POST /api/upload
格式:   multipart/form-data (扁平字段)
字段 类型 必填 默认值 说明
file UploadFile 文件二进制
typeId int typeId/typeCode 二选一 None 文档类型 ID
typeCode str typeId/typeCode 二选一 None 文档类型编码,如 contract.construction
region str "default" 地区标识
fileRole str "primary" 文件角色:primary/attachment/template
createdBy int None 前端可传,但后端当前以 JWT 中的 user_id 为准
autoRun bool false 是否上传后自动触发评查
speed str "normal" urgent / normal

内部流程:

  1. 校验文件名/内容非空 → 解析文档类型(查 leaudit_document_types
  2. SHA-256 去重(仅 primary 文件):同名+同类型+同区域+同 hash → 复用已有记录,duplicateUpload=true
  3. 非重复:生成 internalDocumentNo,匹配前一版本,递增 versionNo,写 leaudit_documents
  4. 存 MinIO OSS,路径 bdocs/{Region}/{TypeCode}/{Year}/...
  5. leaudit_document_files
  6. autoRun=true → 调 AuditService.Run() 触发评查

响应 Result[DocumentUploadVO] (domian/vo/documentVo.py:8-27):

{
  "code": 200,
  "message": "ok",
  "data": {
    "documentId": 1,
    "internalDocumentNo": 1712345678000000001,
    "versionGroupKey": "abc123...",
    "versionNo": 2,
    "previousVersionId": 1,
    "rootVersionId": 1,
    "duplicateUpload": false,
    "fileId": 5,
    "typeId": 1,
    "typeCode": "contract.construction",
    "region": "meizhou",
    "fileName": "建设工程合同.pdf",
    "ossUrl": "http://minio/bdocs/...",
    "speed": "normal",
    "processingStatus": "waiting",
    "autoRunTriggered": true,
    "run": { "runId": 10, "status": "pending", ... }
  }
}

1.2 GET /api/documents/list — 文档列表

源码: controllers/documentController.py:47-67
实现: documentServiceImpl.py:248-443

URL:    GET /api/documents/list
格式:   query params
参数 类型 必填 说明
page int 否 (1) 页码
pageSize int 否 (20, max 100) 每页条数
keyword str 搜索文件名或归一化名
typeCode str 文档类型编码过滤
region str 地区过滤
processingStatus str waiting/processing/completed/failed
resultStatus str pass/fail/partial/review/error

内部流程:

  1. leaudit_documents d JOIN leaudit_document_files f ON f.document_id = d.id
  2. 条件: d.is_latest_version=true, d.deleted_at IS NULL, f.is_active=true, f.file_role='primary'
  3. LEFT JOIN leaudit_document_types dt, leaudit_audit_runs ar
  4. 子查询统计 total_versions(按 version_group_key 分组)
  5. 批量加载历史版本(is_latest_version=false 的同组文档)

响应 Result[DocumentListPageVO] (domian/vo/documentVo.py:77-84):

{
  "code": 200, "message": "ok",
  "data": {
    "total": 100, "page": 1, "pageSize": 20, "totalPages": 5,
    "documents": [
      {
        "documentId": 1, "internalDocumentNo": 1712345678000000001,
        "versionGroupKey": "abc123", "versionNo": 2,
        "typeId": 1, "typeCode": "contract.construction",
        "region": "meizhou", "normalizedName": "建设工程合同",
        "fileId": 5, "fileName": "建设工程合同.pdf",
        "fileExt": ".pdf", "mimeType": "application/pdf",
        "fileSize": 1048576, "ossUrl": "http://minio/...",
        "processingStatus": "completed",
        "runStatus": "completed", "resultStatus": "pass",
        "totalScore": 85, "passedCount": 10,
        "failedCount": 2, "skippedCount": 0,
        "hasHistory": true, "totalVersions": 2,
        "historyVersions": [
          { "documentId": 1, "versionNo": 1, "fileName": "...", ... }
        ]
      }
    ]
  }
}

1.3 文档详情 / 更新 / 删除(现已实现)

GET /api/documents/{id}

  • 用途:获取单个文档详情
  • 返回:Result[DocumentDetailVO]
  • 关键字段:
    • 继承列表接口的版本链、文件、run、统计字段
    • 新增 documentNumberremarkisTestDocumentauditStatuspageCount
  • 历史版本:historyVersions 返回同一 version_group_key 下除当前文档外的其它未删除版本

PUT /api/documents/{id}

  • 用途:更新文档元数据
  • 请求体:DocumentUpdateDTO
{
  "documentNumber": "粤烟合同〔2026001号",
  "remark": "地市管理员修订备注",
  "isTestDocument": false,
  "auditStatus": 1
}
  • 字段说明:
    • documentNumber:若 leaudit_documents.document_number 列存在则写入
    • remark:若 leaudit_documents.remark 列存在则写入
    • isTestDocument:若 leaudit_documents.is_test_document 列存在则写入
    • auditStatus:若 leaudit_documents.audit_status 列存在则写入;若当前环境未加该列,则接口忽略该字段但不报错

DELETE /api/documents/{id}

  • 用途:软删除文档
  • 行为:
    • leaudit_documents.deleted_at = now()
    • 当前文档的 active file 置为 is_active = false
    • 若删除的是当前最新版本,则自动把同版本链中剩余的最高版本提升为 is_latest_version = true

数据隔离规则(已在后端强制执行)

角色 范围
super_admin / provincial_admin 全量文档
admin 仅本地市 region = user.area
common 仅自己上传的文档 created_by = current_user_id

额外约束:

  • admin 若在列表接口传入其他地市 region,后端直接返回空结果
  • common 若试图访问、修改、删除他人文档,后端返回“文档不存在或无权访问”

尚未完成

操作 当前 需要
附件追加 POST /api/documents/{id}/attachments — fileRole=attachment

1.4 自动评查 / 手动评查 / 状态结果查询

POST /api/upload

  • 上传成功且 autoRun=true 时,后端会直接调用 AuditService.Run() 创建 run
  • 队列档位当前只保留:
    • urgent
    • normal

POST /api/audit/run

  • 用途:对已存在文档手动触发评查
  • 典型参数:
    • documentId
    • speed=normal|urgent
  • 当前收口:
    • 若同一文档已有活动 run,后端优先复用,不重复创建

GET /api/audit/run/{runId}

  • 用途:查询评查任务状态
  • 关键状态:
    • queued
    • running
    • completed
    • failed
  • 关键阶段:
    • dispatch
    • prepare
    • ocr / extraction / evaluation / rescue / persist

GET /api/audit/result/{runId}

  • 用途:查询评查结果
  • 返回来源:
    • leaudit_rule_results
    • leaudit_field_results
    • leaudit_run_metrics
    • leaudit_run_errors

当前评查链路口径

  1. 上传文档
  2. 建立 leaudit_documents / leaudit_document_files
  3. 创建 leaudit_audit_runs
  4. speed 投递 leaudit.urgentleaudit.normal
  5. worker 按 runId 查库
  6. bridge 下载文档与规则 YAML 到本地临时文件
  7. NativeRunner 构建原生 AuditCtx
  8. AuditService.audit(ctx) 执行
  9. StorageAdapter 结果写回 leaudit_*

二、前端调用现状(已验证)

2.1 上传 — uploadDocumentToServer()

源码: new_doc_review/app/api/files/files-upload.ts:374-443

URL:    ${UPLOAD_URL}/upload    (例: http://172.16.0.59:8096/upload)
格式:   FormData { file: Blob, upload_info: JSON字符串 }

前端实际发送的 FormData:

file:           Blob (文件二进制)
upload_info:    '{"type_id":1,"evaluation_level":"normal","document_number":null,"remark":null,"is_test_document":false,"document_id":null,"is_reupload":false,"attribute_type":null}'

与后端完全不兼容。 后端期望扁平字段 typeId/typeCode/region/fileRole/autoRun/speed,不接受嵌套的 upload_info JSON。

2.2 附件追加 — appendContractAttachments()

源码: files-upload.ts:320-336

URL:    ${UPLOAD_URL}/contracts/{documentId}/append_attachments
格式:   FormData { attachments: File[] }

后端没有对应接口,需要补。

2.3 合同模板上传 — uploadContractTemplate()

源码: files-upload.ts:244-259

URL:    ${UPLOAD_URL}/upload_contract_template
格式:   FormData { file: Blob }

后端没有对应接口。

2.4 列表 — getDocumentsListFromAPI()

源码: new_doc_review/app/api/files/documents.ts:627-784

URL:    ${API_BASE_URL}/api/documents/list   ✅ 正确

列表已接入新后端,但存在两个问题:

  1. 字段映射层太厚LeauditListItem → DocumentUI 转换 50+ 行,且把 fileExt 映射为 fileTypeossUrl 映射为 path
  2. 筛选项不全documentNumberauditStatusdateFrom/dateTo 在后端列表接口未支持,前端写了 void 占位

2.5 删除 — deleteDocument()

源码: documents.ts:540-560

URL:    /api/postgrest/proxy/documents?id=eq.{id}&user_id=eq.{userId}
方法:   DELETE

走 PostgREST 直删,未接入新后端。

2.6 编辑 — updateDocument()

源码: documents.ts:485-510

URL:    /api/postgrest/proxy/documents?id=eq.{id}
方法:   PATCH

走 PostgREST,未接入新后端。


三、接入方案

第 1 步:上传接口对齐 最高优先级

前端改造 uploadDocumentToServer()

改前:  FormData { file, upload_info: JSON.stringify({ type_id, evaluation_level, ... }) }
       POST ${UPLOAD_URL}/upload

改后:  FormData { file, typeId, typeCode, region, fileRole, createdBy, autoRun, speed }
       POST ${API_BASE_URL}/api/upload

字段映射:

前端旧参数 新后端参数 说明
upload_info.type_id typeId 直接传
typeCode 补充,从 document types 查
region 从 sessionStorage / user info 取当前用户地区
fileRole "primary"
createdBy 从 JWT payload 取 user_id
evaluation_level speed urgent/normal 映射
autoRun 默认 true(参考前端现有流程:上传后自动 treatment)

附件和模板上传合并方案:

  • 主文件:POST /api/upload + fileRole=primary
  • 附件:POST /api/upload + fileRole=attachment(或批量复用主上传)
  • 模板:POST /api/upload + fileRole=template

影响文件:

  • new_doc_review/app/api/files/files-upload.tsuploadDocumentToServer() 重写
  • new_doc_review/app/routes/files.upload.tsxstartUpload() 适配新参数

第 2 步:列表字段精简

前端字段直接对齐,逐步去掉 mapLeauditDocToAuditStatusmapProcessingStatusToFileStatus 等映射函数。DocumentUI 接口增加新字段,旧字段保留兼容。

影响文件:

  • new_doc_review/app/api/files/documents.ts — 简化 LeauditListItem → DocumentUI 转换

第 3 步:补后端 CRUD

后端新增:

DELETE  /api/documents/{id}       → 软删除 (deleted_at = now())
PUT     /api/documents/{id}       → 更新元数据 (备注、测试标记)
GET     /api/documents/{id}       → 文档详情(含所有版本)
POST    /api/documents/{id}/attachments  → 追加附件

影响文件:

  • fastapi_modules/fastapi_leaudit/controllers/documentController.py
  • fastapi_modules/fastapi_leaudit/services/impl/documentServiceImpl.py

第 4 步:前端切割 PostgREST

deleteDocumentupdateDocument 从前端 PostgREST 调用改为走新后端 /api/documents/...

第 5 步:清理旧依赖

确认无其他 PostgREST 调用后,移除旧 RPC 函数。


四、涉及文件清单

文件 改动类型
后端 documentController.py 新增 3 个端点
后端 documentServiceImpl.py 新增 Delete/Update/GetById/AppendAttachments
后端 documentVo.py 可能新增 VO
前端 files-upload.ts 重写 uploadDocumentToServer
前端 files.upload.tsx 适配新上传参数
前端 documents.ts 简化列表映射 + 切割删除/编辑到新后端
前端 documents.list.tsx 小改适配新字段
前端 documents.edit.tsx 切割到新后端 PUT