docs(changelog-v2): 车务审计修复批次 PR#3818/#3819 (新错误码+H5入职校验加固+编辑误拦修复)
这个提交包含在:
父节点
618a6fa5bc
当前提交
68afb81766
@ -0,0 +1,144 @@
|
||||
# 【行为变更·错误码·管理后台 + 司机H5】车务审计修复批次(PR #3818 / #3819)
|
||||
|
||||
> **PR**: #3818(审计修复)、#3819(分层重构 + 唯一键并发锁)
|
||||
> **服务**: hl-fleet-service | **更新时间**: 2026-06-15
|
||||
>
|
||||
> **存放目录**: `changelogs-v2/2026-06/`
|
||||
> **影响范围**: 管理后台「司机审核 / 司机档案编辑 / 价格日历」 + 司机自助 H5 入职(免登录端)
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 关键说明
|
||||
|
||||
本批是车务服务一次**全量代码质量审计修复**,绝大部分是**内部重构**(分层归位 / 并发锁 / 事务合并 / N+1 查询优化 / 注释口径),**对前端无契约变化**——**无新增/删除端点,无字段结构变化,无字段改名**。
|
||||
|
||||
本 changelog **只列前端可感知的变化**,分三类:
|
||||
1. **新增 3 个错误码** + 既有错误码的**新触发场景** —— 前端需补提示文案。
|
||||
2. **司机 H5 入职端点输入校验加固** —— 前端 H5 需补客户端校验 + 限流后重试提示。
|
||||
3. **个别编辑/删除的行为修复** —— 修掉前端原本会踩到的误拦/误清。
|
||||
|
||||
⚠️ 不需要前端改字段映射,只需按下表补错误码文案 + H5 端补几处校验。
|
||||
|
||||
---
|
||||
|
||||
## 1. 新增错误码(前端需补提示文案)
|
||||
|
||||
| code | 名称 | 触发端点 | 触发场景 | 建议前端文案 |
|
||||
|---|---|---|---|---|
|
||||
| **600404** | RENEW_TARGET_SEASON_ILLEGAL | `POST /admin/fleet/drivers/pending/{pendingId}/approve` | 审核**续签**记录时,目标司机当前处于**黑名单**状态(防止通过续签审核绕过授权静默解封黑名单司机) | 「该司机已被拉黑,不能通过续签审核解封,请走解除黑名单流程」 |
|
||||
| **600310** | APPROVED_CANNOT_VOID | `POST /admin/fleet/h5/tokens/{pendingId}/void` | 对**已通过审核**的入职链接点「作废」 | 「该链接对应的司机已审核通过,不可作废」 |
|
||||
| **600311** | ONBOARD_MODE_MISMATCH | `POST /app/h5/driver-onboard/submit/new`、`POST /app/h5/driver-onboard/submit/renew` | 用**新招** token 打到「续签提交」端点,或用**续签** token 打到「新招提交」端点 | 「入职链接类型不匹配,请使用正确的链接重新进入」 |
|
||||
|
||||
**既有错误码的新触发场景**(前端文案可能已有,确认覆盖即可):
|
||||
|
||||
| code | 名称 | 端点 | 新增触发 |
|
||||
|---|---|---|---|
|
||||
| 600203 | PHONE_DUPLICATED | `…/pending/{pendingId}/approve` | 续签审核里司机改了手机号,且新手机号与另一在册司机重复 |
|
||||
| 600503 | MODEL_NOT_FOUND | `DELETE /admin/fleet/pricing-calendar`(清除价格) | 传入不存在的车型 ID(之前静默成功删 0 行,现在明确报错) |
|
||||
| 600501 | DATE_RANGE_INVALID | `DELETE /admin/fleet/pricing-calendar`(清除价格) | startDate 晚于 endDate(区间反转,之前静默无效,现在明确报错) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 错误码语义修正(管理后台)
|
||||
|
||||
**端点**:`POST /admin/fleet/h5/tokens/{pendingId}/void`(作废入职链接)
|
||||
|
||||
- **旧行为**:对「已审核通过」的链接作废,返回 `600304`,消息「链接已作废」——与事实矛盾(该链接并未作废)。
|
||||
- **新行为**:返回 **`600310`「已通过的链接不可作废」**。
|
||||
- `600304`(LINK_VOIDED「链接已作废」)现在**只**用于校验真正已作废的链接。
|
||||
|
||||
> 前端:把「已通过不可作废」场景的错误码判断由 `600304` 改为 `600310`。
|
||||
|
||||
---
|
||||
|
||||
## 3. 司机 H5 入职端点输入校验加固(司机H5)
|
||||
|
||||
免登录 H5 端新增以下后端校验,前端最好同步补客户端校验提升体验:
|
||||
|
||||
### 3.1 证件 OCR 端点加文件校验 + 限流
|
||||
|
||||
**端点**:`POST /app/h5/driver-onboard/ocr/{step}`(multipart 上传证件照识别)
|
||||
|
||||
- **新增文件校验**:文件**非空** + **仅图片**(contentType `image/*`) + **≤ 10 MB**,不满足返 `100001`「参数非法: …」。
|
||||
- **新增限流**:`@RateLimiter` **30 次 / 60 秒**(与短链端点一致),超限返限流提示。
|
||||
|
||||
```
|
||||
# 反例:上传非图片或超大文件
|
||||
POST /app/h5/driver-onboard/ocr/idcard (multipart, file=xxx.pdf)
|
||||
→ { "code": 100001, "message": "参数非法: 仅支持图片格式(jpg/png/webp)" }
|
||||
```
|
||||
|
||||
> 前端:上传前先校验类型/大小;遇限流(短时间多次点)给「操作过于频繁,请稍后再试」提示。
|
||||
|
||||
### 3.2 提交端点加 mode 守卫
|
||||
|
||||
- `POST /app/h5/driver-onboard/submit/new` 现要求 token 是**新招**类型,否则返 `600311`。
|
||||
- `POST /app/h5/driver-onboard/submit/renew` 现要求 token 是**续签**类型,否则返 `600311`。
|
||||
|
||||
> 防止链接被错用到另一端点造成档案污染/数据丢弃。正常流程前端按 init 返回的 `mode` 走对应页面即不会触发。
|
||||
|
||||
### 3.3 新招提交「自带车」跨字段必填
|
||||
|
||||
**端点**:`POST /app/h5/driver-onboard/submit/new`
|
||||
|
||||
- `hasOwnVehicle = true` 时,`vehicle` 对象必须非空,且车牌 `plate`、车型 `model` 关键项非空,否则返 `100001`。
|
||||
- 之前 `hasOwnVehicle=true` 而 `vehicle` 为空会落库为空白车辆字段,审核侧拿到矛盾数据需人工驳回。
|
||||
|
||||
### 3.4 续签提交 `continueSeason` 必填
|
||||
|
||||
**端点**:`POST /app/h5/driver-onboard/submit/renew`
|
||||
|
||||
- `continueSeason`(是否继续合作)现为 **`@NotNull` 必填**,缺失返 `400`「是否继续合作不能为空」。
|
||||
- 之前缺失会被后端兜底当「归档」处理,可能误归档司机。
|
||||
|
||||
### 3.5 入职链接 URL 为路径参数(仅文档订正,无行为变化)
|
||||
|
||||
- 后端产出的入职链接一直是**路径参数**形式 `…/driver-intake/{token}`(对齐前端路由 `/driver-intake/:token`)。
|
||||
- 本次仅把 Swagger 文档/示例里残留的旧 query 形式 `?t={token}` 订正为 `/{token}`,**实际行为未变**。前端按现有路由即可。
|
||||
|
||||
---
|
||||
|
||||
## 4. 行为修复(管理后台)
|
||||
|
||||
### 4.1 编辑「单次投保」司机不再被误拦
|
||||
|
||||
**端点**:`PUT /admin/fleet/drivers/{driverId}`
|
||||
|
||||
- **旧问题**:编辑一个 `insuranceType=perTrip` 的司机时,若只回传 `insuranceType` 而**未重发** `insurancePlanId`,会被 `100001` 误拦(即便库里已有合法 planId)。
|
||||
- **新行为**:库里已有 planId 时,编辑不重发 planId **放行**;仅当库里也没有、入参也没有时才报必填。
|
||||
|
||||
### 4.2 编辑司机驾照不再误清有效期
|
||||
|
||||
**端点**:`PUT /admin/fleet/drivers/{driverId}`
|
||||
|
||||
- 编辑 license 块时,`licenseExpire`(驾照有效期)改为**入参非空才覆盖**(对齐同块其它字段),不再因前端缺省 `expire` 而把库里的有效期清成 NULL。
|
||||
|
||||
### 4.3 gender 字段口径统一
|
||||
|
||||
- 列表 / 详情的 `gender` 取值统一为 **`0=未知` `1=男` `2=女`**(之前列表文档漏了 `0`)。司机性别可能返回 `0`,前端按「未知」渲染。
|
||||
|
||||
---
|
||||
|
||||
## 5. 投保 / 退保幂等加固(管理后台)
|
||||
|
||||
**端点**:
|
||||
- `POST /admin/fleet/drivers/{driverId}/insurance/purchase`(投保,真实出单扣费)
|
||||
- `POST /admin/fleet/drivers/{driverId}/insurance/policies/{insuranceOrderId}/cancel`(退保)
|
||||
|
||||
- 这两个端点现已加**幂等 + 分布式锁**:短时间内**重复提交**(双击 / 弱网重试)会被拦截,返回「投保处理中,请勿重复提交」/「退保处理中,请勿重复提交」。
|
||||
- 前端**无需改动**,但可借此移除自己的临时防双击逻辑(后端已兜底,不会再重复扣费)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 内部变更(无前端影响,仅备查)
|
||||
|
||||
以下为本批的内部重构,**不影响任何接口契约**,列出仅供排查时参考:
|
||||
|
||||
- **分层重构(C5-B)**:司机/车辆/车型三子域的跨域数据访问改为 Port/Service 收口(消除循环依赖),读路径返回数据不变。
|
||||
- **常驻车唯一键(C8)**:车辆 `uk_primary_driver` 单列唯一键改复合 `(primary_driver_id, deleted_at)` + 并发锁,修掉「软删车残留常驻导致新绑定报 500」的潜在问题。绑定/解绑接口行为不变。
|
||||
- **价格日历并发**:四个价格写端点统一全局写锁,修掉并发「单改+批改」落重复记录致整页 500 的竞态。
|
||||
- **司机列表标签查询 N+1 优化**:列表返回结构不变。
|
||||
|
||||
---
|
||||
|
||||
> 有疑问或需要补具体 curl 示例的端点,随时找后端(wx)。
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户