feat(workbench): 接入工作台首页概览聚合接口

This commit is contained in:
yelan
2026-09-02 13:17:40 +08:00
parent e0e98ec74f
commit e52f203123
13 changed files with 398 additions and 358 deletions
+48 -120
View File
@@ -1,141 +1,69 @@
# 工作台首页后端接口需求
# 工作台首页接口核验与接入说明
## 1. 目标
> 事实基准:用户于 2026-09-02 导出的 default_OpenAPI.json,OpenAPI 3.1.0,MEDISIGN 患者电子签 API v1。
>
> 接入状态:当 VITE_USE_MOCK=false 时,首页已接入 GET /api/v1/workbench/overview。
工作台首页是只读的概览页,当前前端可以通过模板、院区和签署任务接口临时聚合数据,但任务量较大时会产生多次分页请求,而且现有任务列表主要按 `createdAt` 查询,无法准确支持“按签署时间统计”和“按超时时间统计”。
## 1. 核验结论
建议后端提供一个聚合接口,由后端在权限范围内一次性计算首页所需数据。
最新契约已提供工作台首页聚合接口。真实模式下,首页不再循环读取模板、签署任务和组织数据并在浏览器聚合,而是由后端在权限范围内一次性返回指标、趋势、待办和文档排名。
## 2. 推荐接口
```http
GET /api/v1/workbench/overview
```
请求头:
全局 `appStore` 在应用加载后调用 GET /api/v1/campuses(page=1、size=200),仅保留启用院区,并以 UUID 作为下拉选项值。首页将当前选中 UUID 直接传给概览接口;API 边界只在未传 UUID 的调用场景下按院区名称兜底解析。
## 2. 已接入的请求
```http
GET /api/v1/workbench/overview?campusId={UUID}&period={7|14|30}&todoLimit=8&rankingLimit=10
X-Token: {登录令牌}
```
请求参数:
| 参数 | 必填 | 前端传值 | 契约说明 |
| ------------ | ---- | ------------------------- | ------------------------------ |
| campusId | 是 | 当前工作台院区对应的 UUID | 必须在当前用户数据范围内 |
| period | 是 | 7、14 或 30 | 同时决定趋势和文档排名统计周期 |
| todoLimit | 否 | 8 | 待办返回数量,范围 1–20 |
| rankingLimit | 否 | 10 | 排名返回数量,范围 1–20 |
| 参数 | 类型 | 必填 | 说明 |
| -------------- | ------- | ---- | ---------------------------------------------- |
| `campusId` | UUID | 是 | 当前首页选择的院区 |
| `period` | integer | 是 | 签署趋势和文档排名周期,只允许 `7`、`14`、`30` |
| `todoLimit` | integer | 否 | 待办数量,默认 `8`,最大 `20` |
| `rankingLimit` | integer | 否 | 排名数量,默认 `10`,最大 `20` |
请求通过 utils/request.ts 的单例发送,实际浏览器路径为 /api/v1/workbench/overview,由 Vite 开发代理转发到后端。
日期计算建议统一使用服务端的医院业务时区(上海为 `Asia/Shanghai`),响应中的时间字段使用 ISO-8601 格式。
## 3. 接口字段与页面映射
## 3. 返回结构
| 页面区域 | 后端字段 | 前端展示 |
| ---------- | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| 四张指标卡 | summary.todaySigned、todaySignedChange、pendingPatientSigning、todayOverdue、availableTemplates、coveredDepartments | 今日签署、较昨日变化、待签署、今日超时、可用模板及覆盖科室 |
| 签署趋势 | trend[].label、trend[].signedCount | 按后端业务时区生成的近 7、14 或 30 天趋势 |
| 我的待办 | todos[].taskId、patientId、patientName、documentName、departmentName、status、signMethod、updatedAt | 待办列表;点击 taskId 跳转签署工作台 |
| 文档排名 | documentRanking[].templateId、documentName、departmentName、signedCount | Top10 文档签署排名 |
接口继续使用当前统一响应包装:
趋势和排名都直接使用后端按 signedAt、医院业务时区聚合的结果;前端不再用 createdAt 或浏览器时区重新计算。
```json
{
"code": 0,
"message": "OK",
"data": {
"campusId": "550e8400-e29b-41d4-a716-446655440000",
"timezone": "Asia/Shanghai",
"generatedAt": "2026-09-01T08:00:00Z",
"summary": {
"todaySigned": 36,
"todaySignedChange": 2,
"pendingPatientSigning": 18,
"todayOverdue": 2,
"availableTemplates": 128,
"coveredDepartments": 9
},
"trend": [
{
"date": "2026-08-26",
"label": "8/26",
"signedCount": 39
}
],
"todos": [
{
"taskId": "任务 UUID",
"patientId": "脱敏患者标识",
"patientName": "患者姓名",
"documentName": "知情同意书",
"departmentName": "消化内科",
"status": "WAITING_SIGN",
"signMethod": "PAD",
"updatedAt": "2026-09-01T07:50:00Z",
"expiredAt": "2026-09-01T09:00:00Z"
}
],
"documentRanking": [
{
"templateId": "模板 UUID",
"documentName": "住院患者知情同意书",
"departmentName": "全院通用",
"signedCount": 58
}
]
},
"traceId": "链路追踪 ID",
"timestamp": "2026-09-01T08:00:00Z"
}
```
## 4. 待办状态展示
## 4. 统计口径
后端 TodoItem.status 使用签署任务状态枚举。前端按下列方式展示,避免把生成中、失败或已作废任务误标为待签署:
### 4.1 指标卡
| 后端状态 | 页面状态 |
| ------------ | -------------------------- |
| CREATED | 待发送 |
| WAITING_SIGN | 待签署,并区分手写板或短信 |
| GENERATING | 文书生成中 |
| EXPIRED | 已超时 |
| SIGNED | 已签署 |
| VOIDED | 已作废 |
| FAILED | 处理失败 |
- `todaySigned`:`status=SIGNED` 且 `signedAt` 位于今天业务时区起止范围内的任务数。
- `todaySignedChange`:`todaySigned - yesterdaySigned`,正数表示上升,负数表示下降,`0` 表示持平。
- `pendingPatientSigning`:状态为 `CREATED`、`WAITING_SIGN` 或 `GENERATING` 的任务数;不按创建日期限制。
- `todayOverdue`:状态为 `EXPIRED` 且 `expiredAt` 位于今天业务时区起止范围内的任务数。
- `availableTemplates`:当前用户在指定院区有 `USE` 权限且已发布生效的模板数量,按 `templateId` 去重,不按版本行数重复计算。
- `coveredDepartments`:上述可用模板中非空 `departmentId` 的去重数量;全院通用模板不计入科室数。
pendingPatientSigning 的后端口径只统计 WAITING_SIGN;CREATED 和 GENERATING 不会被前端补入该指标。
### 4.2 签署趋势
## 5. 权限、错误与数据边界
返回最近 `period` 个自然日,包含今天,按日期升序排列。每天按 `signedAt` 统计 `SIGNED` 任务数,而不是按 `createdAt` 或 `updatedAt` 统计。
- 接口使用 X-Token 鉴权;任务数据范围和模板 ACL 由后端在 SQL 层执行。
- campusId 无权限或工作台无权限时,后端返回 403;参数错误返回 400;未登录返回 401。
- 患者标识为不可逆展示标识;前端不记录或补全身份证号、完整手机号和病历数据。
- 接口返回 timezone 和 generatedAt,统计日期以医院业务时区为准。
### 4.3 待办任务
## 6. 联调验收标准
待办包括 `CREATED`、`WAITING_SIGN`、`GENERATING` 和 `EXPIRED` 任务,按 `updatedAt` 倒序返回前 `todoLimit` 条。前端会将前三种状态展示为“等待患者签署”,将 `EXPIRED` 展示为“已超时”。
返回的患者标识必须遵守现有数据脱敏和权限规则,不返回明文证件号、明文手机号或其他不必要的敏感信息。
### 4.4 文档签署排名
仅统计 `signedAt` 位于最近 `period` 个自然日内的 `SIGNED` 任务,按 `templateId` 分组后倒序返回前 `rankingLimit` 条。分组键必须使用模板 ID,不能只使用文档名称,避免同名模板被错误合并。
## 5. 权限和错误响应
接口必须复用签署任务查询和模板 `USE` 权限的数据范围控制,只统计当前用户有权查看的院区、科室和任务。
建议至少返回以下状态:
| HTTP 状态 | 场景 |
| --------- | ------------------------------- |
| `200` | 查询成功 |
| `400` | `campusId` 或 `period` 参数错误 |
| `401` | 未登录或令牌失效 |
| `403` | 无权查看指定院区或工作台数据 |
| `500` | 服务端聚合失败 |
## 6. 暂时不增加聚合接口时的最小改造
如果暂时不能提供 `/workbench/overview`,现有接口至少需要补充或明确以下能力:
1. `GET /api/v1/templates/available-versions` 必须支持 `campusId`,并返回真实 `departmentId`;前端已可以使用该筛选参数。
2. `GET /api/v1/sign-tasks` 需要支持按 `signedAt` 和 `expiredAt` 查询,而不能只支持 `createdAt`。
3. 任务列表最好支持多状态查询,或者提供待签署任务汇总接口,否则待办数量需要分别请求多个状态。
4. 任务或模板响应需要提供稳定的 `templateId`、`templateName`、`departmentName`,避免历史模板不可用时只能显示模板版本号。
5. 如果继续使用分页聚合,接口需要保证 `total`、`page`、`size` 一致,并允许客户端按最大页大小安全拉取全部数据。
## 7. 前端对接验收标准
- 切换院区后,四个指标、趋势、待办和排名都只属于当前院区。
- 切换 `7/14/30` 天后,趋势和排名同时改变统计周期。
- 跨自然日、任务延迟签署和任务延迟超时场景下,指标仍按 `signedAt`、`expiredAt` 正确统计。
- 首页显示的昨日变化不再使用固定文案。
- 待办点击后可以根据 `taskId` 直接打开详情,即使任务不在签署工作台当前第一页。
- 切换院区后,请求携带新 campusId,四张指标卡、趋势、待办和排名同步更新。
- 切换 7、14、30 天后,趋势标题、趋势数据和文档排名同步变化。
- 返回空数组时,趋势、待办和排名显示各自空状态;指标卡显示 0。
- 服务端返回 GENERATING、FAILED、VOIDED 等状态时,页面标签与状态含义一致。
- Network 中不再出现首页为统计目的而循环拉取全部签署任务或模板的请求。