From ab2aaef3f5797c99252962ce1840bef50ec7ae4f Mon Sep 17 00:00:00 2001 From: yaosutu <770858045@qq.com> Date: Thu, 21 May 2026 15:52:46 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20=E5=8F=B8=E6=9C=BA?= =?UTF-8?q?=E8=AF=A6=E6=83=85=20attachments=20=E5=AD=97=E6=AE=B5=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=20Map=20->=20=E5=BC=BA=E7=B1=BB=E5=9E=8B=20DriverAtta?= =?UTF-8?q?chmentsVO=20(#2812=20/=20PR=20#2818)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 前序 21_2791_司机档案 changelog §3.2 描述的 Map> 已废,以本文档为准。 前端需要把 data.attachments['id_card'] 改成 data.attachments.idCard。 --- ...详情attachments强类型化-修改接口-管理后台.md | 197 ++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 changelogs-v2/2026-05/21_2812_司机详情attachments强类型化-修改接口-管理后台.md diff --git a/changelogs-v2/2026-05/21_2812_司机详情attachments强类型化-修改接口-管理后台.md b/changelogs-v2/2026-05/21_2812_司机详情attachments强类型化-修改接口-管理后台.md new file mode 100644 index 0000000..1c8c2d3 --- /dev/null +++ b/changelogs-v2/2026-05/21_2812_司机详情attachments强类型化-修改接口-管理后台.md @@ -0,0 +1,197 @@ +# 【修改接口·管理后台】司机详情 attachments 弱类型 Map 改强类型 DriverAttachmentsVO (#2812) + +> **PR**: #2818 | **服务**: hl-fleet-service | **更新时间**: 2026-05-21 15:30 +> +> **存放目录**: `changelogs-v2/2026-05/` +> **关联前序**: [`21_2791_司机档案-修改接口-管理后台.md`](./21_2791_司机档案-修改接口-管理后台.md)(commit `761ca07`) + +--- + +## ⚠️ 关键变化(30 秒速读) + +**`GET /admin/fleet/drivers/{driverId}` 的响应字段 `attachments` 类型变了**: + +| 项 | 改前 | 改后 | +|---|---|---| +| 类型 | `Map`(动态 key) | `DriverAttachmentsVO`(8 个固定字段) | +| 前端用法 | `data.attachments['id_card']` 字符串访问 | `data.attachments.idCard` 字段访问 | +| TypeScript 类型 | 没有具体字段名 | 8 个具体字段(含类型提示) | + +**前序 changelog 废止内容**:[`21_2791_司机档案-修改接口-管理后台.md`](./21_2791_司机档案-修改接口-管理后台.md) **§3.2 详情接口** + **§9 业务边界** 中所有把 attachments 描述为 `Map>` 的部分**已废**,以本文档为准。 + +**前端必须改动**(不是兼容的):所有 `data.attachments[key]` 形式的访问要改成 `data.attachments.xxx` 字段访问。 + +--- + +## 1. 接口背景 + +`attachments` 当前用 `Map>` 返回违反 HL 项目规则 [禁止弱类型返回值]: +- Swagger / TypeScript 生成的类型是 `{ [key: string]: DriverAttachmentRespVO[] }`,**没有具体字段名** +- 前端 IDE 不能自动补全 +- 拼错 key 编译期不报错 +- 文档无法自包含描述每个类目出参 + +改为强类型 `DriverAttachmentsVO`,8 个 List 字段对应 8 个固定类目(与 `DriverAttachmentCategoryEnum` 严格对齐)。 + +--- + +## 2. 变更清单 + +| # | 方法 | 路径 | 变更类型 | 说明 | +|---|------|------|----------|------| +| 1 | GET | `/admin/fleet/drivers/{driverId}` | **修改** | 响应字段 `attachments` 类型变化(详见 §3.1) | + +仅 1 个端点受影响。其余 5 个司机档案接口(page / create / update / delete / import)**不受影响**。 + +--- + +## 3. 接口详情 + +### 3.1 司机详情 — `attachments` 字段类型变化 + +**GET** `/admin/fleet/drivers/{driverId}` + +#### 改后的 `attachments` 字段结构 + +字段:`DriverAttachmentsVO` 对象(**不再是 Map**)。 + +| 字段 | 类型 | 默认 | 张数上限(来自 DriverAttachmentCategoryEnum) | +|---|---|---|---| +| `idCard` | `DriverAttachmentRespVO[]` | `[]` | 2("换证留历史":支持正反 2 张或新旧 2 套) | +| `driverLicense` | `DriverAttachmentRespVO[]` | `[]` | 2(换证留历史) | +| `portrait` | `DriverAttachmentRespVO[]` | `[]` | 2(换证留历史) | +| `healthCert` | `DriverAttachmentRespVO[]` | `[]` | 2 | +| `trainingCert` | `DriverAttachmentRespVO[]` | `[]` | 5 | +| `award` | `DriverAttachmentRespVO[]` | `[]` | 5 | +| `qualification` | `DriverAttachmentRespVO[]` | `[]` | 3 | +| `other` | `DriverAttachmentRespVO[]` | `[]` | 5 | + +> **每个字段默认空数组**(不为 null),前端**无需判空**,直接 `.map()` 渲染即可。 + +`DriverAttachmentRespVO[]` 单条项字段(**不变**): + +| 字段 | 类型 | 说明 | +|---|---|---| +| `id` | string | 附件 ID(Long 序列化为 String) | +| `driverId` | string | 所属司机 ID | +| `category` | string | 类目 | +| `sortNo` | int | 同类目排序(0-based) | +| `url` | string | OSS URL | +| `mimeType` | string | 例 `image/jpeg` | + +#### 改后响应示例(节选) + +```json +{ + "code": 200, + "data": { + "id": "1234567890123456789", + "name": "张三", + "...其他字段保持不变...": "...", + "attachments": { + "idCard": [ + { "id": "...", "driverId": "...", "category": "id_card", "sortNo": 0, "url": "https://oss/.../id-front.jpg", "mimeType": "image/jpeg" }, + { "id": "...", "driverId": "...", "category": "id_card", "sortNo": 1, "url": "https://oss/.../id-back.jpg", "mimeType": "image/jpeg" } + ], + "driverLicense": [ + { "id": "...", "driverId": "...", "category": "driver_license", "sortNo": 0, "url": "https://oss/.../license.jpg", "mimeType": "image/jpeg" } + ], + "portrait": [], + "healthCert": [], + "trainingCert": [], + "award": [], + "qualification": [], + "other": [] + }, + "relatedOrders": [...] + }, + "msg": "成功" +} +``` + +--- + +## 6. 枚举 / 数据字典 + +无新增枚举。`category` 字段语义和取值与前序 changelog [`21_2791_司机档案-修改接口-管理后台.md`](./21_2791_司机档案-修改接口-管理后台.md) §6.1 一致(8 个值),唯一差异是 **API 响应不再以 category 字符串作为 key**,而是用 VO 字段名(驼峰)。 + +类目 ↔ VO 字段对应关系: + +| DB / category 字段值 | VO 字段(驼峰) | +|---|---| +| `id_card` | `idCard` | +| `driver_license` | `driverLicense` | +| `portrait` | `portrait` | +| `health_cert` | `healthCert` | +| `training_cert` | `trainingCert` | +| `award` | `award` | +| `qualification` | `qualification` | +| `other` | `other` | + +注意单条 `DriverAttachmentRespVO.category` 仍然是 `id_card` / `driver_license` 等下划线值(不变)。改的是**外层分组的 key 形式**。 + +--- + +## 7. 错误码 + +无变化。 + +--- + +## 10. 修改前后对比 + +### 10.1 字段级对比 + +| 字段 | 改前 | 改后 | +|---|---|---| +| `attachments` 类型 | `Map` | `DriverAttachmentsVO`(8 个固定 List 字段) | +| `attachments` key 形式 | DB 下划线值(`id_card` / `driver_license` / `portrait` / ...) | VO 驼峰字段(`idCard` / `driverLicense` / `portrait` / ...) | +| 类目缺失 | 该 key 不在 Map 里 | 该字段是空数组 `[]` | + +### 10.2 前端代码对照 + +```typescript +// 改前 +const idCardAttachments = data.attachments['id_card'] ?? []; +const licenseAttachments = data.attachments['driver_license'] ?? []; + +// 改后 +const idCardAttachments = data.attachments.idCard; // 不用判空 +const licenseAttachments = data.attachments.driverLicense; +``` + +--- + +## 11. 影响评估 + +- **是否破坏向后兼容**:⚠️ **是**(字段类型变了,前端必须改) +- **前端是否必须同步上线**:**是**(老前端按 Map 解析会拿到 undefined) +- **影响其他后端服务**:无(DriverDetailRespVO 仅 admin 接口返回,不走 Feign) +- **影响已有数据**:无(仅 API 序列化形式变化,DB 无变) + +--- + +## 12. 注意事项 + +- **前端 workaround 清理点**: + - 改前如果前端有 `const map = data.attachments; const idCard = map['id_card'] ?? [];` 之类 workaround,**改成 `data.attachments.idCard`** 即可 + - 改前如果前端硬编码遍历类目(如 `for (const key of ['id_card', 'driver_license'])`),**改成直接读 VO 字段** + - 改前如果前端有 `if (map['portrait'])` 判空逻辑,**直接删** —— 强类型 VO 字段必非 null(默认空数组) +- **前序 changelog 描述废止**:[`21_2791_司机档案-修改接口-管理后台.md`](./21_2791_司机档案-修改接口-管理后台.md) 已发出的 attachments Map 描述以本文档为准,前序 changelog **不会修改**(changelog 只追加不回写历史) + +--- + +## 13. 关联 / 联系人 + +### 13.1 链接 + +- **Issue**: [#2812](https://git.1814.love:8443/wx/HL/issues/2812) +- **PR**: [#2818](https://git.1814.love:8443/wx/HL/pulls/2818) +- **Merge commit**: [`8c340550`](https://git.1814.love:8443/wx/HL/commit/8c340550656bdee3ee2243b98d694b818474aeba) +- **前序 changelog(attachments Map 描述废)**: [`21_2791_司机档案-修改接口-管理后台.md`](./21_2791_司机档案-修改接口-管理后台.md) +- **规则**: HL `MEMORY.md` → `feedback_no-map-return-type.md` (禁止弱类型返回值) + +### 13.2 联系人 + +- **后端负责人**: @yst(腰苏图) +- **前端对接(管理后台)**: 待指派