# OCR Platform API v1

## 通用响应

```json
{
  "code": "OK",
  "message": "success",
  "data": {},
  "timestamp": "2026-05-09T23:30:00+08:00"
}
```

## 健康检查

```http
GET /api/v1/health
```

用于业务系统、运维监控或容器健康检查确认 API 服务存活。

## OCR 引擎列表

```http
GET /api/v1/engines
```

返回中台已知的 OCR 引擎描述。当前只是静态描述，后续会接入引擎注册、健康检查、限流和版本治理。

## 创建 OCR 任务

```http
POST /api/v1/ocr/tasks
Content-Type: multipart/form-data
```

表单字段：

- `sourceSystem`：来源系统编码，必填。
- `businessType`：业务类型，必填。
- `templateCode`：表单模板编码，可选。
- `priority`：任务优先级，可选，默认 `5`。
- `file`：待识别文件，必填。

当前行为：

- 生成平台统一 `taskId`。
- 保存任务记录到 `ocr_task`。
- 保存原始文件到本地文件目录。
- 保存文件元数据到 `ocr_document`。
- 任务状态进入 `QUEUED`。

## 查询 OCR 任务

```http
GET /api/v1/ocr/tasks
GET /api/v1/ocr/tasks/{taskId}
GET /api/v1/ocr/tasks/{taskId}/detail
GET /api/v1/ocr/tasks/{taskId}/events
POST /api/v1/ocr/tasks/{taskId}/cancel
```

当前列表接口返回最近 50 条任务。

`OcrTaskSummary` 中包含：

- `taskId`
- `status`
- `sourceSystem`
- `businessType`
- `templateCode`
- `originalFilename`
- `fileSize`
- `sha256`
- `attemptCount`
- `createdAt`
- `updatedAt`

`/api/v1/ocr/tasks/{taskId}/detail` 返回单个任务的聚合信息：

- 任务元数据（状态、来源、业务类型、模板、优先级）
- 文件元数据
- 全文文本块
- 键值对结果
- 原始引擎结果
- 错误码/错误信息
- 失败重试次数（`attemptCount`）
- 耗时统计（处理时长、从提交到结束耗时）
- 汇总信息中的 latest-run 指标（`latestRunNo`、`latestRunRawResultCount`、`latestRunTextBlockCount`、`latestRunKeyValueCount`）
- 字段抽取质量：`extractionQuality`（`expectedFieldCount`、`extractedFieldCount`、`emptyValueCount`、`averageConfidence`、`hitRate`、`manualCorrectionRate`）
- 任务事件时间线
- 注意：`detail` 默认不再返回完整 `rawJson`、`bboxJson` 或全部文本块，避免大样张响应过大。完整识别产物请按下面的结果接口分页或单条读取。

```http
POST /api/v1/ocr/tasks/{taskId}/cancel
```

任务取消语义：

- 只允许在未完成状态下取消（`CREATED/QUEUED/PREPROCESSING/RECOGNIZING/NORMALIZING/EXTRACTING/REVIEW_REQUIRED`）
- 任务会记录 `TASK_CANCELLED` 事件

任务执行恢复语义（当前默认实现）：

- `WORKER_ERROR` 会触发重试（默认最多 2 次失败重试，配置项见 `ocr-platform.worker.max-retry-attempts`）
- `RECOGNIZING` 状态超过超时阈值（`ocr-platform.worker.recognizing-timeout-ms`）会自动回收到队列并重试

配置参数（可通过环境变量覆盖）：

- `OCR_WORKER_MAX_RETRY_ATTEMPTS`（默认 `2`）：最多重试次数
- `OCR_TASK_RECOGNIZING_TIMEOUT_MS`（默认 `120000`）：识别状态超时阈值（ms）

## 查询键值对结果

```http
GET /api/v1/ocr/tasks/{taskId}/key-values
```

返回任务已经抽取出的标准键值对。返回值新增 `runNo` 字段，可按批次追溯同一任务的重试历史，默认按 `runNo` 正序展示。

## 查询全文 OCR 结果

```http
GET /api/v1/ocr/tasks/{taskId}/text-blocks
```

返回任务识别出的文本块，默认分页：

```http
GET /api/v1/ocr/tasks/{taskId}/text-blocks?page=0&size=100
```

默认不返回 `bboxJson`，避免坐标数组拖大响应。返回值包含 `runNo` 字段，可按批次追溯同一任务的重试历史。

## 查询原始引擎结果

```http
GET /api/v1/ocr/tasks/{taskId}/raw-results
GET /api/v1/ocr/tasks/{taskId}/raw-results/{rawResultId}
```

`/raw-results` 默认只返回 OCR 引擎原始结果元信息，不带完整 `rawJson`。返回值包含以下字段，支持列表展示与复盘定位：

- `runNo`：识别批次号。
- `elapsedMs`：引擎调用耗时（毫秒）。
- `errorCode`：失败时错误码。
- `errorMessage`：失败时错误信息。
- `rawJsonLength`：完整原始结果字符数。
- `requestPayloadJsonLength`：完整请求快照字符数。

需要查看完整 `rawJson` / `requestPayloadJson` 时，调用 `/raw-results/{rawResultId}` 单条读取。

中台后续所有标准化结果都应能回溯到这里。多个 `runNo` 代表同任务多次识别历史，可用于效果对比。

## 表单模板管理

```http
GET /api/v1/form-templates
GET /api/v1/form-templates/{templateCode}
GET /api/v1/form-templates/{templateCode}/versions
GET /api/v1/form-templates/{templateCode}?versionNo=2
POST /api/v1/form-templates
GET /api/v1/form-templates/{templateCode}/mappings
POST /api/v1/form-templates/{templateCode}/mappings
GET /api/v1/form-templates/{templateCode}/preview
```

路径说明：

- `GET /api/v1/form-templates`
  - 列出每个模板编码的最新版本。
- `GET /api/v1/form-templates/{templateCode}`
  - 读取指定模板。
  - `versionNo` 可选，传入则返回指定版本；不传返回最新版本。
- `GET /api/v1/form-templates/{templateCode}/versions`
  - 列出模板所有版本。
- `POST /api/v1/form-templates`
  - 创建 / 覆盖模板版本（业务层会根据 `templateCode` 和 `versionNo` 做幂等保存）。
- `GET /api/v1/form-templates/{templateCode}/mappings`
  - 查询该模板的抽取映射配置。
- `POST /api/v1/form-templates/{templateCode}/mappings`
  - 覆盖保存该模板映射。
- `GET /api/v1/form-templates/{templateCode}/preview`
  - 与按需读取模板一致，语义偏向回填页面预览。

`FormTemplateUpsertRequest`：

```json
{
  "templateCode": "FORM_001",
  "templateName": "工商登记表单",
  "businessType": "BUSINESS_REGISTRATION",
  "versionNo": 1,
  "formJson": "...",
  "enabled": true
}
```

`FormFieldMappingUpsertRequest`：

```json
[
  {
    "formFieldKey": "enterpriseName",
    "formInputName": "basic.enterpriseName[2]",
    "ocrFieldKey": "经营者名称",
    "fieldLabel": "经营者名称",
    "valueType": "TEXT",
    "required": true,
    "transformRuleJson": null
  }
]
```

注意：`formInputName` 字段已新增用于回填时的字段名归一化和兼容。

## form3 回填接口

```http
GET /api/fill-data/{taskId}/form3
GET /api/v1/plugins/fill/tasks/{taskId}/form3
```

通用参数：

- `templateCode`（可选）：
  - 不传：按任务绑定模板生成回填。
  - 传入：按指定模板进行回填。

响应格式：

- `/api/fill-data/**` 与 `/api/v1/plugins/fill/**` 的返回是统一契约：

```json
{
  "code": 0,
  "msg": "success",
  "data": {
    "taskId": "T20260510001",
    "taskNo": "T20260510001",
    "formTemplateCode": "FORM_001",
    "status": "DONE",
    "nameModal": {
      "basic.enterpriseName[2]": "示例企业"
    },
    "fieldIdModal": {
      "enterpriseName": "示例企业"
    },
    "canonicalModal": {
      "basic.enterpriseName": "示例企业"
    },
    "fields": [
      {
        "fieldId": "enterpriseName",
        "inputName": "basic.enterpriseName[2]",
        "canonicalKey": "basic.enterpriseName",
        "title": "经营者名称",
        "value": "示例企业",
        "valueType": "TEXT",
        "pageNo": 1,
        "confidence": "0.9876",
        "reviewStatus": "CONFIRMED",
        "ocrFieldKey": "经营者名称"
      }
    ],
    "warnings": []
  }
}
```

当某些 OCR 字段未命中时，`warnings` 会返回 `未命中抽取字段: ...`。字段值为空时 `value` 为空字符串，`confidence` 可能为空。

## 系统配置

```http
GET /api/v1/settings
PUT /api/v1/settings
POST /api/v1/settings/reset
```

系统配置用于后台运行参数维护，配置会持久化到数据库 `app_setting`，不是前端本地状态。

`PUT /api/v1/settings` 请求体：

```json
{
  "items": [
    {
      "key": "ocr.task.auto_poll_seconds",
      "value": "6"
    }
  ]
}
```

当前内置配置包括任务轮询间隔、结果最大展示行数、默认 OCR Provider、外部 Provider 启用开关和严格模式开关。

## 插件式调用鉴权与限流

所有以下路径由鉴权拦截器处理：

- `/api/fill-data/**`
- `/api/v1/plugins/**`

请求头：

- `X-API-CLIENT-CODE`
- `X-API-CLIENT-SECRET`

鉴权失败响应：

- `401` + `code: PLUGIN_AUTH_FAILED`
- 场景：缺失凭证 / 凭证错误 / 客户端不存在 / 被禁用

限流响应：

- `429` + `code: RATE_LIMIT_EXCEEDED`
- 说明：按分钟窗口计数，区分「已鉴权客户端」和「未鉴权请求」。

业务配置（环境变量）：

- `OCR_PLUGIN_API_ENABLED`（默认 `true`）
- `OCR_PLUGIN_CLIENT_CODE_HEADER`（默认 `X-API-CLIENT-CODE`）
- `OCR_PLUGIN_CLIENT_SECRET_HEADER`（默认 `X-API-CLIENT-SECRET`）
- `OCR_PLUGIN_RATE_LIMIT_PER_MINUTE`（默认 `60`）
- `OCR_PLUGIN_UNAUTH_RATE_LIMIT_PER_MINUTE`（默认 `20`）
- `OCR_PLUGIN_AUDIT_ENABLED`（默认 `true`）

失败与异常输出将写入 `api_access_audit_log`（成功调用也会记录）。

## 常见业务 API code（本阶段）

- `TASK_NOT_FOUND`
- `FORM_TEMPLATE_NOT_FOUND`
- `TASK_STATE_CONFLICT`
- `PLUGIN_AUTH_FAILED`
- `RATE_LIMIT_EXCEEDED`
- `BAD_REQUEST`
- `OCR_ENGINE_NOT_AVAILABLE`
- `OK`
