docs: reorganize by module
This commit is contained in:
@@ -0,0 +1,398 @@
|
||||
# 文档上传与列表 — 接口分析 & 接入方案
|
||||
|
||||
> 所有信息已逐文件验证。源代码位置均已标注。
|
||||
>
|
||||
> 说明:这份文档已经吸收旧的 `新系统版_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`):
|
||||
|
||||
```json
|
||||
{
|
||||
"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`):
|
||||
|
||||
```json
|
||||
{
|
||||
"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、统计字段
|
||||
- 新增 `documentNumber`、`remark`、`isTestDocument`、`auditStatus`、`pageCount`
|
||||
- 历史版本:`historyVersions` 返回同一 `version_group_key` 下除当前文档外的其它未删除版本
|
||||
|
||||
#### PUT /api/documents/{id}
|
||||
|
||||
- 用途:更新文档元数据
|
||||
- 请求体:`DocumentUpdateDTO`
|
||||
|
||||
```json
|
||||
{
|
||||
"documentNumber": "粤烟合同〔2026〕001号",
|
||||
"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.urgent` 或 `leaudit.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` 映射为 `fileType`、`ossUrl` 映射为 `path` 等
|
||||
2. **筛选项不全**:`documentNumber`、`auditStatus`、`dateFrom/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.ts` — `uploadDocumentToServer()` 重写
|
||||
- `new_doc_review/app/routes/files.upload.tsx` — `startUpload()` 适配新参数
|
||||
|
||||
### 第 2 步:列表字段精简
|
||||
|
||||
**前端字段直接对齐**,逐步去掉 `mapLeauditDocToAuditStatus`、`mapProcessingStatusToFileStatus` 等映射函数。`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
|
||||
|
||||
`deleteDocument`、`updateDocument` 从前端 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 |
|
||||
Reference in New Issue
Block a user