hl-api-changelog/changelogs-v2/2026-08/11_5855_出行人保存校验至少一成人填手机号-修改接口-管理后台.md
yaosutu 627c4c8721
一些检查失败了
changelog-filename-gate / validate (push) Failing after 2s
changelog(#5867): 出行人智能批量导入纳入"至少一名成人填手机号"硬校验(581136,PR #5868)
补充 #5855 changelog:smart-parse(dryRun=false 正式落库)与 5 个保存入口复用同一
成人手机门禁;dryRun=true 预览不校验。部署测试服网关实调通过:无成人手机导入被
581136 阻断且 DB 零写入,含 1 成人手机导入 200 放行落库。
2026-08-11 18:15:46 +08:00

164 行
9.0 KiB
Markdown

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

---
schema: "hl-changelog/v2"
ticket: "5855"
title: "出行人保存新增「至少一名成人必须填手机号」服务端硬校验(新增错误码 581136"
consumer: "admin"
change_type: "修改接口"
author: "yst"
backend_status: "deployed"
gateway_status: "not_required"
frontend_status: "implemented"
frontend_owner: "mmg"
frontend_ref: "24f31813"
target_release: ""
verified_at: "2026-08-11"
status_note: "前端已实现(2026-08-11,mmg,24f31813)。实证保存链路天然兼容——persistTravelerInfo(order-v2/detail/index.vue:1005)走统一拦截器,581136 由后端 message 透传 toast,无需特殊分支。并按 §11「建议」落地表单提示增强:TravelerInfoEditor submit 校验通过后对「最终生效集合」判定,无任何成人(复用 isChildTraveler,travelerType 或 birthday<12 兜底)phone 非空(脱敏含*算已有) message.warning 提前提示至少需要一名成人出行人填写手机号用于合同签署」,不阻断由后端 581136 兜底测试:useMessage mock warning,+2 用例(无成人手机提示且仍返回 payload/有则不提示),TravelerInfoEditor 11 全绿,checkpoint 精确文件集全过。"
updated_at: "2026-08-11"
base: "dev-v3"
---
# 出行人保存新增「至少一名成人必须填手机号」服务端硬校验(#5855 / PR #5858
## 1. 接口背景
电子合同签署要求订单中至少有一名成人出行人预留手机号用于接收签署短信)。此前该约束只在 `traveler/validate` 校验接口里做软提示保存接口本身不拦截导致可以保存出"无成人有手机号"的订单后续签约环节才暴露问题本次在出行人保存链路上补齐服务端硬校验保存时若"最终生效的出行人集合"中没有任何一名成人填写手机号整个保存请求被拒绝不写库),并返回新增错误码 `581136`
## 2. 变更清单
| # | 接口 | 变更类型 | 说明 |
|---|------|----------|------|
| 1 | `PUT /v3/admin/order/{id}/traveler-info` | 新增服务端校验 | 补全出行信息全量同步保存时新增硬校验触发返回 581136 |
| 2 | `POST /v3/admin/order/{id}/traveler/batch-edit` | 新增服务端校验 | 批量编辑出行人保存时新增硬校验触发返回 581136 |
| 3 | `POST /v3/admin/order/{id}/traveler/add` | 新增服务端校验 | 单个新增出行人时新增硬校验触发返回 581136 |
| 4 | `GET /v3/admin/order/{id}/traveler/validate` | 出参文案收紧 | `blockReasons[]` 文案由"至少需要一名出行人填写手机号"收紧为"至少需要一名成人出行人填写手机号",判定口径同步收紧 |
| 5 | `POST /v3/admin/order/{id}/traveler/smart-parse` | 新增服务端校验 | 智能批量导入`dryRun=false` 正式落库保存时新增硬校验触发返回 581136#5867 补入 5 入口同一门禁 |
> 说明:删除出行人接口**不**加此校验;智能导入的 `dryRun=true` 预览模式**不**校验(仅解析不落库)。入参 / 出参结构、字段名、类型均无变化。
## 3. 接口详情
| | |
|---|---|
| 方法 + 路径 | `PUT /v3/admin/order/{id}/traveler-info``POST /v3/admin/order/{id}/traveler/batch-edit``POST /v3/admin/order/{id}/traveler/add``GET /v3/admin/order/{id}/traveler/validate``POST /v3/admin/order/{id}/traveler/smart-parse` |
| 使用场景 | 管理后台订单详情 - 出行人 Tab补全出行信息 / 批量编辑 / 单个新增 / 保存前校验 |
| 认证 | 管理后台 JWTadmin |
| 幂等性 | PUT traveler-info 为全量同步天然幂等batch-edit / add 为普通写操作 |
| 限流 | 无特殊限流 |
## 4. 接口入参
入参结构**无变化**,此处仅强调与本校验相关的字段语义
### 4.1 路径参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | Long | | 订单 ID |
### 4.2 请求体关键字段(出行人行)
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| travelerType | String | | 出行人类型`ADULT`=成人本校验只统计成人行 |
| phone | String | | 手机号更新时传 `null`=保留原值(不修改),传 `""` 空串=清空;若清空后无任何成人有手机,触发 581136 |
## 5. 出参字段
三个保存接口出参结构**无变化**,仍为统一 `Result<T>`
| 字段 | 类型 | 说明 |
|------|------|------|
| code | Integer | `200`=成功`581136`=本次新增的"无成人有手机号"业务错误 |
| success | Boolean | 成功 true / 失败 false |
| message | String | 失败时为错误文案前端直接 toast |
| data | T | 成功时的业务数据结构不变 |
`GET /traveler/validate` 出参 `blockReasons[]`String 数组中文案变化
| 原来 | 现在 |
|------|------|
| 至少需要一名出行人填写手机号用于合同签署 | 至少需要一名**成人**出行人填写手机号用于合同签署 |
## 6. 枚举 / 数据字典
| 枚举 | 取值 | 说明 |
|------|------|------|
| travelerType | `ADULT` | 成人本校验的统计对象 |
| travelerType | 其他儿童等 | 不计入"是否有手机"判定 |
## 7. 错误码
| code | message | 触发条件 |
|------|---------|----------|
| 581136 | 至少需要一名成人出行人填写手机号用于合同签署 | 保存后"最终生效的出行人集合"中没有任何一名成人travelerType=ADULT填写手机号;整个请求被拒,不写库。适用接口traveler-info 全量同步 / batch-edit 批量编辑 / add 单个新增 / smart-parse 智能批量导入dryRun=false |
## 8. 示例
### 8.1 典型成功(至少 1 名成人有手机)
请求 `PUT /v3/admin/order/123/traveler-info`出行人中含成人且至少一名成人 phone 非空
```json
{
"code": 200,
"success": true,
"message": "success",
"data": { }
}
```
### 8.2 边界(成人 phone 传 null 保留原值)
更新出行人时成人行 `phone: null` 表示保留原手机号不修改只要原有数据里仍有成人有手机即通过校验响应同 8.1
### 8.3 业务失败(无任何成人有手机 → 581136
请求 `PUT /v3/admin/order/123/traveler-info`提交的所有成人 phone 均为空或清空
```json
{
"code": 581136,
"success": false,
"message": "至少需要一名成人出行人填写手机号用于合同签署",
"data": null
}
```
出行人**未落库**,前端按 Result 约定 `code != 200` toast `message` 即可
## 9. 业务边界
- 适用订单出行人的补全 / 批量编辑 / 单个新增 / 智能批量导入`smart-parse` `dryRun=false`保存
- 不适用删除出行人接口删除不加此校验即使删完后无成人有手机也不拦截删除动作本身);智能导入 `dryRun=true` 预览模式仅解析不落库不校验)。
- 特殊边界校验看的是"保存后最终生效的集合",不是单条提交行——例如 batch-edit 把唯一有手机的成人 phone 清空即使其他行不变也会触发 581136智能导入为**追加式**最终集合 = 库中现有 + 本次解析行),只要合并后存在一名成人有手机即放行
## 10. 修改前后对比
| 维度 | 原来 | 现在 |
|------|------|------|
| 保存接口校验 | 不校验"成人是否有手机",可保存出无成人手机号的订单 | 保存时硬校验无成人有手机则整单拒存返回 581136 |
| validate 判定口径 | 任意出行人有手机即通过 | 必须是**成人**有手机才通过 |
| validate blockReasons 文案 | 至少需要一名出行人填写手机号用于合同签署 | 至少需要一名成人出行人填写手机号用于合同签署 |
| 入参 / 出参结构 | | 无变化 |
## 11. 影响评估 / 回滚
- 破坏兼容入参 / 出参结构不变仅新增一个业务错误码与文案收紧
- 前端同步上线非强制前端按现有 `code != 200` toast 约定即可天然兼容建议在补全 / 编辑出行人表单对成人行补充"至少一名成人需填手机号"的提示提升体验
- 回滚方案后端回滚 PR #5858 即恢复原行为前端无需改动
## 12. 注意事项
- 581136 通过 HTTP 200 + `code=581136` 返回Result 约定),**不是** HTTP 4xx/5xx前端拦截器按业务 code 处理
- `phone` 字段更新语义`null`=保留原值`""`=清空前端表单回显时注意区分"未改动""主动清空"。
- 删除出行人不受此校验约束
- 智能批量导入 `dryRun=false` 正式落库时校验`dryRun=true` 预览不校验导入文本中无法识别手机号属正常门禁统计的是"最终集合里是否有成人带手机",不是"每行是否都有手机"。
## 13. 关联 / 联系人
- Issue: https://git.1814.love:8443/wx/HL/issues/5855
- PR: https://git.1814.love:8443/wx/HL/pulls/5858
- Commit: https://git.1814.love:8443/wx/HL/commit/06f03e40c3
- 关联补充智能批量导入纳入同一门禁Issue https://git.1814.love:8443/wx/HL/issues/5867 PR https://git.1814.love:8443/wx/HL/pulls/5868
- 后端负责人腰苏图yst