# API 契约：报告详情 / 列表中的「服务回顾短片」字段

> **本体对齐**：本文档与 [`ontology/objects.md#entity:report`](./ontology/objects.md) 的 `highlight_*` 字段对齐。冲突以本体为准。
>
> 与 `ReportController.putHighlightFields`、`ReportHighlightVideoService` 实现一致；前端 `getReportByToken`、`getReportList` 及 `utils/reportShare.js` 依赖本契约。

## 出现位置

以下接口的 `data`（单条报告对象或列表元素）均包含相同短片相关键名（camelCase）：

- `GET /api/report/get?token=...` 或 `?appointmentId=...`
- `GET /api/report/list`（分页与非分页）

## 字段说明

| 字段 | 类型 | 说明 |
|------|------|------|
| `highlightVideoUrl` | string \| null | 成片 MP4。成功时为可播放的**绝对 URL**（由服务端 `app.base-url` 拼接相对路径）；未生成 / 失败时多为 null。库内历史数据可能存绝对 URL，接口层会原样或补全后返回。 |
| `highlightShareCoverUrl` | string \| null | **分享卡片用封面**：成片导出后由 ffmpeg 截取的首帧 JPEG 的绝对 URL。仅 `highlightVideoStatus === 'done'` 且截帧成功时有值；失败或未生成时为 null。 |
| `highlightPosterUrl` | null | **预留**：画布海报等独立资源；当前接口**恒为 null**。前端分享封面应优先 `highlightShareCoverUrl`，再按业务降级（见 `frontend/src/utils/reportShare.js`）。 |
| `highlightVideoStatus` | string \| null | 如 `processing`、`done`、`failed`。 |
| `highlightVideoError` | string \| null | 失败时的用户可读简述（成功 / 处理中一般为 null）。 |
| `highlightFailReason` | string \| null | 机器可读归类：`material` / `service` / `network` / `unknown` 等。 |
| `highlightFailReasonLabel` | string \| null | 失败类中文短标签，供 UI 展示。 |
| `highlightDurationSec` | number \| null | 成片时长（秒，向上取整），done 时一般有值。 |
| `highlightComposeMode` | string \| null | `preset`（预设顺序）或 `interleave`（穿插成片）。 |

## 存储约定（后端）

- `t_report.highlight_share_cover_url`：相对路径 `/api/upload/image/{yyyy}/{MM}/{dd}/{stem}_cover.jpg`，与成片文件同目录。
- 新写入的 `highlight_video_url` 为相对路径 `/api/upload/image/.../highlight_{reportId}_{uuid}.mp4`（与上传接口返回形态一致）；历史全量 URL 仍兼容。

## 行为要点

1. 调用 `POST /api/report/highlight/start` 进入 `processing` 时，会**清空** `highlightShareCoverUrl`（旧封面不再与本次任务绑定）。
2. 成片合成成功后写回首帧路径；若 ffmpeg 截帧失败，**成片仍可成功**，`highlightShareCoverUrl` 为 null，分享侧降级为服务后首图等。
