文件
hl-api-changelog/changelogs-v2/2026-05/18_§2_traveler模块-新增接口-管理后台.md
T
yaosutu 89a1938cb9 docs(v3-order): 按代码事实修订 §1/§2 changelog(fix issue #1 + 补充 5 项)
回复 hl-api-changelog#1 前端反馈的 5 处契约不明 / 冲突,并同步补足 4 处文档与代码不一致:

§1 订单核心模块(15 处修改):
- §3.1/§3.2/§3.3/§3.14 示例值:orderStatus/flowStatus 全部从中文标签改为英文枚举值
  (后端 OrderInfo.orderStatus/flowStatus 直接透传 DB 列的英文枚举字符串)
- §3.3 OrderMainVO 字段表:
  * customerName/customerPhone (admin 明文) → customerName + customerPhoneMasked(admin 也脱敏)
  * exceptionBadges/progressStepper 标注「运行时暂返 null,OrderInfoConverter 派生逻辑待 Issue 接通」
  * 新增 6 个 Tab 状态徽标字段(contractStatus/insuranceStatus/refundStatus/hasRefund/hasServiceStandard/hasFinanceDetail)
  * subStatus 枚举补 NOT_APPLICABLE + 列示 ASSIGN_PARALLEL 子项结构
  * 主聚合示例 transportPlanIds 改用真实雪花 ID(19 位)String
- §3.11 取消预览业务边界:粗状态集改英文枚举 + 说明 v3 已删「已确认」
- §3.14 transition:eventCode 入参表内联 9 个值,便于前端跳读
- §6.2 orderStatus:全表替换为 10 个英文枚举(PENDING_PAY/PENDING_COMPLETE/CUSTOMIZING/PENDING_DEPARTURE/PENDING_BALANCE/TRAVELLING/REVIEWING/SETTLED/REFUNDING/CANCELLED)
- §6.3 flowStatus:全表替换为 13 个英文枚举(AWAITING_DEPOSIT/.../CANCELLED_BEFORE_PAY)
- §6.4 consultantSource:补 SHARED + ROUND_ROBIN,说明 user-service 透传规则
- §6.17 加后端 enum 路径备注

§2 traveler 模块(9 处修改):
- §3.1 出行人列表:每条 17 字段 → 16 字段(off-by-one 笔误)
- §3.1/§3.3 curl 示例:路径 /travelers → /traveler/list 和 /traveler/add(对齐字段表与代码 @PostMapping)
- §3.1 transportPlanIds:补全局 Long→String 序列化规则脚注 + 示例值改真实雪花 ID
- §3.4 错误码段位让位:581119 → 581106(已签合同禁删),581120 → 581107(最后成人禁删)
  (DB 段位 581119/581120 已分别被 TRAVELER_ID_CARD_DUPLICATE / TRANSPORT_PLAN_NOT_FOUND 占用)
- §3.9 smart-parse 错误码段位让位:581120/581121/581122/581123 → 581131/581132/100501/581134
  (581122 限流走 HL 全局 CommonErrorCode.RATE_LIMITED)
- §12 注意事项同步删人错误码

关联:
- Issue: https://git.1814.love:8443/wx/hl-api-changelog/issues/1
- 验证代码 commit: HL@dev-v3 47d24228
- 验证报告: HL/.claude/tmp-changelog/issue1-analysis.md(仅本地)
2026-05-19 10:28:11 +08:00

33 KiB
原始文件 Blame 文件历史

【新增接口·管理后台】v3 traveler 模块 §2(出行人 + 大交通)

更新时间: 2026-05-18 端类型: 管理后台 设计文档版本: v5.50(API-SPEC / SRS / DETAIL-DESIGN / DATABASE-SCHEMA 4 份 HTML 同步)


0. 模块全貌

子模块 含接口 接口数 状态
§2A 出行人 admin CRUD §2.1 列表 / §2.2 批量编辑 / §2.3 新增 / §2.4 软删 4 ✅
§2B 大交通批次 admin CRUD §2.6.1 列表 / §2.6.2 新增 / §2.6.3 编辑 / §2.6.4 软删 4 ✅
§2C 动词类操作 §2.8 smart-parse(⚠️ 待新建,Issue #2526)/ §2.9 validate 2 §2.9 ✅,§2.8 ⏳ wx 实现中
§2 合计 — 10 ✅ 本次推送(§2.8 字段先定,wx 实现后接口可立即对接)

不在本 changelog 范围内:§2.7 GET /v3/internal/order/orders/{orderId}/travelers(internal Feign 跨服务查出行人 + 解密审计)属于后端 changelog 范畴(受众=其他后端服务/运维,不是前端),将单独推到 hl-backend-changelog 仓库。


1. 接口背景

订单服务 v3 traveler 模块(hl-order-service-v3)管理订单关联的出行人信息(含敏感字段:身份证 / 手机 / 紧急联系人)+ 大交通批次(接送站 / 航班 / 火车 / 自驾)。

业务边界:

  • 出行人不在 §1.1 创单接口里传,创单后通过 §2 单独添加(v4.8 取消占位行模型)
  • admin 端明文返回 idNo / phone / emergencyPhone(仅 B 端定制师可见,JWT 鉴权保护)
  • 大交通通过 order_transport_plan_traveler 桥接表(M:N)关联出行人,支持「一家分两批到达」场景

本次推送 §2 模块管理后台 10 个接口,对应管理后台原型 F20 / F21 / F27(详情概览 + 出行人补全 + 接送站 + 大交通登记弹窗)。§2.7 internal feign 不在本文档范围(见 §0 说明)。


2. 变更清单

# § 接口名 方法 路径
1 2.1 出行人列表 GET /v3/admin/order/{id}/traveler/list
2 2.2 出行人批量编辑(upsert) POST /v3/admin/order/{id}/traveler/batch-edit
3 2.3 单个出行人新增 POST /v3/admin/order/{id}/traveler/add
4 2.4 出行人软删 POST /v3/admin/order/{id}/traveler/{travelerId}/delete
5 2.6.1 大交通批次列表 GET /v3/admin/order/{id}/transport-plans
6 2.6.2 大交通批次新增 POST /v3/admin/order/{id}/transport-plans
7 2.6.3 大交通批次编辑 PUT /v3/admin/order/{id}/transport-plans/{planId}
8 2.6.4 大交通批次软删 DELETE /v3/admin/order/{id}/transport-plans/{planId}
9 2.8 ⏳ 出行人智能批量解析 POST /v3/admin/order/{id}/traveler/smart-parse
10 2.9 出行人信息校验 GET /v3/admin/order/{id}/traveler/validate

§2.7 internal feign 接口不在本表(属后端 changelog)。


3. 接口详情

每个接口自包含:使用场景 / 入参 / 出参 / 错误码 / 业务边界 / 示例。 跨接口共享枚举集中在 §6。


3.1 §2.1 出行人列表

路径:GET /v3/admin/order/{id}/traveler/list 使用场景:详情页 Tab 1 出行人区块 / F27 出行人补全页 认证:JWT(admin 角色 + 公司隔离) 敏感字段:idNo / phone / emergencyPhone 明文返回(admin JWT 鉴权保护)

入参

id (path, Long) — 订单 ID

出参(Result<List<TravelerVO>>,每条 16 字段)

字段 类型 说明
id String 出行人 ID
orderId String 订单 ID
travelerType String 枚举见 §6.1(ADULT / CHILD / YOUNG_CHILD / BABY)
name String? 姓名(占位行为 null)
gender String 枚举见 §6.2(MALE / FEMALE / UNKNOWN)
birthday LocalDate? 出生日期
idType String 枚举见 §6.3(ID_CARD / PASSPORT / BIRTH_CERT)
idNo String? 证件号(admin 明文)
nationality String 国籍(默认中国)
race String 民族(默认汉族)
phone String? 出行人手机(admin 明文)
emergencyContact String? 紧急联系人姓名
emergencyPhone String? 紧急联系人电话(admin 明文)
roomGroupNo Integer? 同住分组号
profileStatus String 枚举见 §6.4(PENDING / COMPLETED)
transportPlanIds List<Long> 关联的大交通批次 ID 列表

⚠️ transportPlanIds 序列化规则:后端字段类型 List<Long>,但 HL 全局 Jackson NumberSerializer 会自动把超过 JS 安全整数(2^53-1)的 Long 转 String 输出。大交通批次 ID 是雪花 ID(19 位),实际响应中一定是 String 数组;下面示例值 80012345(8 位短整数)仅为可读性目的,生产值类似 "80012345678901234"。前端按 String 数组接收。

错误码

code 含义
581020 订单不存在
581021 无权访问该订单(公司隔离)

示例

典型 - 请求:

GET /v3/admin/order/60123456789012/traveler/list
Authorization: Bearer {admin_jwt}

典型 - 响应:

{
  "code": 200,
  "data": [
    {
      "id": "70123456789012",
      "orderId": "60123456789012",
      "travelerType": "ADULT",
      "name": "张三",
      "gender": "MALE",
      "birthday": "1985-08-12",
      "idType": "ID_CARD",
      "idNo": "220103198508121234",
      "nationality": "中国",
      "race": "汉族",
      "phone": "13800002046",
      "emergencyContact": "李四",
      "emergencyPhone": "13900008888",
      "roomGroupNo": 1,
      "profileStatus": "COMPLETED",
      "transportPlanIds": ["80012345678901234", "80012345678901235"]
    },
    {
      "id": "70123456789013",
      "orderId": "60123456789012",
      "travelerType": "CHILD",
      "name": null,
      "gender": "UNKNOWN",
      "birthday": null,
      "idType": null,
      "idNo": null,
      "nationality": "中国",
      "race": "汉族",
      "phone": null,
      "emergencyContact": null,
      "emergencyPhone": null,
      "roomGroupNo": null,
      "profileStatus": "PENDING",
      "transportPlanIds": []
    }
  ],
  "msg": "success"
}

3.2 §2.2 出行人批量编辑(upsert 语义)

路径:POST /v3/admin/order/{id}/traveler/batch-edit 使用场景:F27 出行人补全 B 端代填,定制师一次性提交订单内 N 行出行人的字段修改/新增(id=null 新增 / id 非 null 更新) 整体事务:任一行字段校验失败 → 全部回滚

入参(TravelerBatchEditReqVO)

字段 类型 必填 说明 校验规则
travelers List<TravelerEditItem> ✅ 待修改/新增出行人数组 @NotEmpty @Size(max=30)

TravelerEditItem(12 字段):

字段 类型 必填 说明
id Long ❌ 出行人 ID(null=新增 / 非 null=更新)
travelerType String 新增必填 枚举见 §6.1(更新时 null 保留原值)
name String ❌ 姓名
gender String ❌ 枚举见 §6.2
birthday LocalDate ❌ 出生日期
idType String ❌ 枚举见 §6.3
idNo String ❌ 证件号(明文传)
nationality String ❌ 国籍(不可为空字符串)
race String ❌ 民族(不可为空字符串)
phone String ❌ 手机(明文传)
emergencyContact String ❌ 紧急联系人姓名
emergencyPhone String ❌ 紧急联系人电话(明文传)
roomGroupNo Integer ❌ 同住分组号

出参(Result<TravelerBatchEditRespVO>)

字段 类型 说明
createdCount Integer 本次新增的出行人数(id=null 行)
updatedCount Integer 本次更新的出行人数(id 非 null 行)
completedCount Integer 本次操作后变为 COMPLETED 的行数
pendingCount Integer 仍为 PENDING 的行数
allCompleted Boolean 该订单所有出行人是否已完善

错误码

code 含义
581020 订单不存在
581100 travelers 列表为空 / 超过 30
581101 字段格式校验失败(idNo 校验和 / phone 格式)
581110 更新时出行人 ID 不属于该订单
581111 已签电子合同后禁止改证件号
581112 新增时缺 travelerType

业务边界

  • ✅ upsert 语义:单次请求可混合新增 + 更新
  • ✅ 整体事务:任一行失败回滚
  • ⚠️ size 上限 30:超出走分批多次调用
  • ⚠️ allCompleted=true 信号:所有出行人字段齐 → 触发"已完善"系统标签 / 进入下一阶段

示例

典型 - 请求:

POST /v3/admin/order/60123456789012/traveler/batch-edit
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "travelers": [
    {
      "id": 70123456789013,
      "name": "王小明",
      "gender": "MALE",
      "birthday": "2018-06-20",
      "idType": "ID_CARD",
      "idNo": "220103201806201234",
      "nationality": "中国",
      "race": "汉族",
      "phone": "13812342046",
      "roomGroupNo": 1
    },
    {
      "id": null,
      "travelerType": "BABY",
      "name": "王小宝",
      "gender": "FEMALE",
      "birthday": "2024-01-15"
    }
  ]
}

典型 - 响应:

{
  "code": 200,
  "data": {
    "createdCount": 1,
    "updatedCount": 1,
    "completedCount": 1,
    "pendingCount": 1,
    "allCompleted": false
  },
  "msg": "success"
}

异常(证件号格式非法 581101) - 响应:

{ "code": 581101, "data": null, "msg": "证件号校验失败(idNo 校验位错误)" }

3.3 §2.3 单个出行人新增(占位补充)

路径:POST /v3/admin/order/{id}/traveler/add 使用场景:F27 改人数场景(如临时加 1 个未声明儿童)。会同步 UPDATE order_main 对应人数字段(adultCount / childCount 等)+ 触发后续:保险重算 / 房车需求需重提示

入参(TravelerCreateReqVO,12 字段)

字段 类型 必填 说明
travelerType String ✅ 枚举见 §6.1
name String ❌ 姓名(可后填)
gender String ❌ 枚举见 §6.2
birthday LocalDate ❌ 出生日期
idType String ❌ 枚举见 §6.3
idNo String ❌ 证件号(明文传)
nationality String ❌ 国籍(默认中国)
race String ❌ 民族(默认汉族)
phone String ❌ 出行人手机(明文传)
emergencyContact String ❌ 紧急联系人姓名
emergencyPhone String ❌ 紧急联系人电话
roomGroupNo Integer ❌ 同住分组号

出参(Result<TravelerVO>)

字段同 §3.1 列表项,含新建行完整字段。

错误码

code 含义
581020 订单不存在
581115 实际人数已等于 order_main 声明人数(v4.8 取消占位模型规则)
581116 订单状态禁止加人(已结算 / 已取消)
581117 travelerType 与现有同住分组冲突

业务边界

  • ✅ 创单后单独添加:v4.8 取消占位模型,按需 INSERT 新行
  • ⚠️ 人数同步:自动 UPDATE order_main.<type>Count +1
  • ⚠️ 应用层数量检查:实际人数 ≥ 声明人数 → 581115,需要先调整人数声明再加人

示例

典型 - 请求:

POST /v3/admin/order/60123456789012/traveler/add
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "travelerType": "CHILD",
  "name": "王小明",
  "gender": "MALE",
  "birthday": "2018-06-20",
  "idType": "ID_CARD",
  "idNo": "220103201806201234",
  "phone": "13812342046",
  "roomGroupNo": 1
}

典型 - 响应:

{
  "code": 200,
  "data": {
    "id": "70123456789013",
    "orderId": "60123456789012",
    "travelerType": "CHILD",
    "name": "王小明",
    "gender": "MALE",
    "birthday": "2018-06-20",
    "idType": "ID_CARD",
    "idNo": "220103201806201234",
    "nationality": "中国",
    "race": "汉族",
    "phone": "13812342046",
    "emergencyContact": null,
    "emergencyPhone": null,
    "roomGroupNo": 1,
    "profileStatus": "COMPLETED",
    "transportPlanIds": []
  },
  "msg": "success"
}

异常(人数已满 581115) - 响应:

{ "code": 581115, "data": null, "msg": "实际人数已达声明上限,请先调整人数再添加" }

3.4 §2.4 出行人软删

路径:POST /v3/admin/order/{id}/traveler/{travelerId}/delete 使用场景:F27 改人数场景(如取消同行 1 人) 关联:同步 UPDATE order_main 对应人数 -1 + 解除其在 order_transport_plan_traveler 桥接表中所有关联 约束:已签电子合同的订单禁止删人

入参

字段 类型 必填 说明
id Long ✅ 订单 ID(path)
travelerId Long ✅ 出行人 ID(path)

出参(Result<Boolean>)

返回 true 表示软删成功。

错误码

code 含义
581020 订单不存在
581110 出行人不属于该订单
581106 已签电子合同,禁止删除出行人(DB 段位让位:581119 已被 TRAVELER_ID_CARD_DUPLICATE 占用,文档原 581119 让位至此)
581107 出行人是订单最后 1 位成人,禁止删除(DB 段位让位:581120 已被 TRANSPORT_PLAN_NOT_FOUND 占用,文档原 581120 让位至此)

业务边界

  • ✅ 软删:UPDATE order_traveler.deleted=1,不真删
  • ✅ 级联解除桥接:UPDATE order_transport_plan_traveler.deleted=1
  • ❌ 已签合同禁删:合同强约束 → 581106
  • ❌ 最后成人禁删:保留至少 1 位成人 → 581107

示例

典型 - 请求:

POST /v3/admin/order/60123456789012/traveler/70123456789013/delete
Authorization: Bearer {admin_jwt}

典型 - 响应:

{ "code": 200, "data": true, "msg": "success" }

异常(已签合同 581106) - 响应:

{ "code": 581106, "data": null, "msg": "订单已签电子合同,禁止删除出行人" }

3.5 §2.6.1 大交通批次列表

路径:GET /v3/admin/order/{id}/transport-plans 使用场景:F21 行程安排 Tab "接送站"区块 业务模型:一个订单可有 N 个批次(实现"一家分两批到达"),按 direction 分 ARRIVAL / DEPARTURE

入参

id (path, Long) — 订单 ID

出参(Result<List<TransportPlanVO>>)

每条 16 字段 + travelers 嵌套:

字段 类型 说明
id String 批次 ID
orderId String 订单 ID
direction String 枚举见 §6.5(ARRIVAL / DEPARTURE)
mode String 枚举见 §6.6(TOGETHER / SEPARATE)
transportType String 枚举见 §6.7(FLIGHT / TRAIN / SELF_DRIVE)
transportNo String? 航班号 / 车次号;SELF_DRIVE 时为空
carrier String? 航司 / 铁路公司
departStation String? 出发站
arriveStation String? 到达站
departTime LocalDateTime? 出发时间(FLIGHT/TRAIN 必有;SELF_DRIVE 为空)
arriveTime LocalDateTime? 到达时间(同上)
selfDrivePeriod String? 枚举见 §6.8(仅 SELF_DRIVE)
selfDriveEta LocalDateTime? 自驾预计到达时间(仅 SELF_DRIVE 可选)
pickupRequired Boolean? 是否需要接送
pickupRemark String? 接送备注
travelers List<{id, name}> 关联出行人简要(桥接表 JOIN)
remark String? 备注

错误码

code 含义
581020 订单不存在
581021 无权访问该订单

示例

典型 - 请求:

GET /v3/admin/order/60123456789012/transport-plans
Authorization: Bearer {admin_jwt}

典型 - 响应:

{
  "code": 200,
  "data": [
    {
      "id": "80012345",
      "orderId": "60123456789012",
      "direction": "ARRIVAL",
      "mode": "TOGETHER",
      "transportType": "FLIGHT",
      "transportNo": "CA1234",
      "carrier": "中国国际航空",
      "departStation": "北京首都T3",
      "arriveStation": "长春龙嘉",
      "departTime": "2026-06-01T08:30:00",
      "arriveTime": "2026-06-01T10:15:00",
      "selfDrivePeriod": null,
      "selfDriveEta": null,
      "pickupRequired": true,
      "pickupRemark": "需在 T3 出口举牌接机",
      "travelers": [
        {"id": "70123456789012", "name": "张三"},
        {"id": "70123456789013", "name": "王小明"}
      ],
      "remark": "需要接机举牌"
    },
    {
      "id": "80012346",
      "orderId": "60123456789012",
      "direction": "DEPARTURE",
      "mode": "TOGETHER",
      "transportType": "SELF_DRIVE",
      "transportNo": null,
      "carrier": null,
      "departStation": null,
      "arriveStation": null,
      "departTime": null,
      "arriveTime": null,
      "selfDrivePeriod": "AFTERNOON",
      "selfDriveEta": "2026-06-05T15:00:00",
      "pickupRequired": false,
      "pickupRemark": null,
      "travelers": [
        {"id": "70123456789012", "name": "张三"}
      ],
      "remark": null
    }
  ],
  "msg": "success"
}

3.6 §2.6.2 大交通批次新增

路径:POST /v3/admin/order/{id}/transport-plans 使用场景:F21 大交通登记弹窗 - 新增 桥接表维护:同事务 INSERT order_transport_plan_traveler(每个 plan 必须关联至少 1 名出行人)

入参(TransportPlanReqVO,11 字段)

字段 类型 必填 说明
direction String ✅ 枚举见 §6.5
transportType String ✅ 枚举见 §6.7
transportNo String 条件 航班号 / 车次号;SELF_DRIVE 时为空
carrier String ❌ 航司 / 铁路公司
departStation / arriveStation String ❌ 出发 / 到达站
departTime / arriveTime LocalDateTime 条件 FLIGHT/TRAIN 必填;SELF_DRIVE 为空
selfDrivePeriod String 条件 枚举见 §6.8,仅 SELF_DRIVE
selfDriveEta LocalDateTime ❌ 仅 SELF_DRIVE 可选
travelerIds List<Long> ✅ 关联出行人 ID(至少 1 个)
remark String ❌ 备注(≤500)

出参(Result<TransportPlanVO>)

字段同 §3.5 列表项。

错误码

code 含义
581020 订单不存在
581140 字段组合非法(FLIGHT 缺航班号 / SELF_DRIVE 错带 transportNo 等)
581141 travelerIds 含订单外的出行人
581142 出发时间晚于到达时间
581143 同方向同一出行人已在另一 plan

业务边界

  • ✅ 字段组合校验:FLIGHT/TRAIN 需 transportNo + 出发/到达时间;SELF_DRIVE 不传 transportNo,可传 selfDrivePeriod + selfDriveEta
  • ⚠️ 桥接约束:同方向同一出行人只能在 1 个 plan,不同方向各 1 个

示例

典型(航班 ARRIVAL) - 请求:

POST /v3/admin/order/60123456789012/transport-plans
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "direction": "ARRIVAL",
  "transportType": "FLIGHT",
  "transportNo": "CA1234",
  "carrier": "中国国际航空",
  "departStation": "北京首都T3",
  "arriveStation": "长春龙嘉",
  "departTime": "2026-06-01T08:30:00",
  "arriveTime": "2026-06-01T10:15:00",
  "travelerIds": [70123456789012, 70123456789013],
  "remark": "需要接机举牌"
}

典型 - 响应:

{
  "code": 200,
  "data": {
    "id": "80012345",
    "orderId": "60123456789012",
    "direction": "ARRIVAL",
    "mode": "TOGETHER",
    "transportType": "FLIGHT",
    "transportNo": "CA1234",
    "carrier": "中国国际航空",
    "departStation": "北京首都T3",
    "arriveStation": "长春龙嘉",
    "departTime": "2026-06-01T08:30:00",
    "arriveTime": "2026-06-01T10:15:00",
    "selfDrivePeriod": null,
    "selfDriveEta": null,
    "pickupRequired": null,
    "pickupRemark": null,
    "travelers": [
      {"id": "70123456789012", "name": "张三"},
      {"id": "70123456789013", "name": "王小明"}
    ],
    "remark": "需要接机举牌"
  },
  "msg": "success"
}

异常(自驾错带 transportNo 581140) - 响应:

{ "code": 581140, "data": null, "msg": "SELF_DRIVE 类型不应传 transportNo" }

3.7 §2.6.3 大交通批次编辑

路径:PUT /v3/admin/order/{id}/transport-plans/{planId} 使用场景:F21 大交通登记弹窗 - 编辑(全量覆盖含 travelerIds) 事务:UPDATE plan + DELETE+INSERT 重建桥接表

入参

字段 类型 必填 说明
id Long ✅ 订单 ID(path)
planId Long ✅ 批次 ID(path)
Body TransportPlanReqVO ✅ 同 §3.6 字段(全量覆盖语义)

出参(Result<TransportPlanVO>)

字段同 §3.5。

错误码

code 含义
581140 ~ 581143 同 §3.6 字段组合校验
581144 plan 不存在 / 不属于该订单

业务边界

  • ⚠️ 全量覆盖语义:所有 Req 字段都会替换原值,包括 travelerIds
  • ⚠️ 桥接表重建:旧 order_transport_plan_traveler 行 DELETE,按新 travelerIds INSERT

示例

典型 - 请求:

PUT /v3/admin/order/60123456789012/transport-plans/80012345
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "direction": "ARRIVAL",
  "transportType": "FLIGHT",
  "transportNo": "CA1235",
  "carrier": "中国国际航空",
  "departStation": "北京首都T3",
  "arriveStation": "长春龙嘉",
  "departTime": "2026-06-01T10:30:00",
  "arriveTime": "2026-06-01T12:15:00",
  "travelerIds": [70123456789012],
  "remark": "改签后的航班"
}

典型 - 响应:

{
  "code": 200,
  "data": {
    "id": "80012345",
    "direction": "ARRIVAL",
    "transportType": "FLIGHT",
    "transportNo": "CA1235",
    "departTime": "2026-06-01T10:30:00",
    "arriveTime": "2026-06-01T12:15:00",
    "travelers": [{"id": "70123456789012", "name": "张三"}],
    "remark": "改签后的航班"
  },
  "msg": "success"
}

3.8 §2.6.4 大交通批次软删

路径:DELETE /v3/admin/order/{id}/transport-plans/{planId} 使用场景:F21 大交通登记弹窗 - 删除 事务:UPDATE order_transport_plan.deleted=1 + UPDATE 桥接表 deleted=1

入参

字段 类型 必填 说明
id Long ✅ 订单 ID(path)
planId Long ✅ 批次 ID(path)

出参(Result<Boolean>)

返回 true 表示软删成功。

错误码

code 含义
581144 plan 不存在 / 不属于该订单

示例

典型 - 请求:

DELETE /v3/admin/order/60123456789012/transport-plans/80012345
Authorization: Bearer {admin_jwt}

典型 - 响应:

{ "code": 200, "data": true, "msg": "success" }

3.9 §2.8 出行人智能批量解析 ⏳

路径:POST /v3/admin/order/{id}/traveler/smart-parse 使用场景:F27 出行人补全 / 一键导入弹窗。定制师粘贴多行文本(姓名+证件号+手机号),后端解析为结构化出行人列表,校验后批量入库 状态:⏳ wx 待实现(Issue #2526)。本节字段先定,wx 实现完即可对接

入参(TravelerSmartParseReqVO)

字段 类型 必填 说明
id Long ✅ 订单 ID(path)
rawText String ✅ 粘贴的多行原文(≤ 20000 字符)
dryRun Boolean ❌ true=仅解析不入库(默认 false=解析+入库)

出参(Result<TravelerSmartParseRespVO>)

字段 类型 说明
successCount Integer 解析成功并入库的行数
failCount Integer 解析失败的行数
successList List<TravelerVO> 成功创建的出行人列表(结构同 §3.1);dryRun=true 时不含 id
failures List<FailureVO> 失败明细:{lineIndex, maskedSnippet, reason}

错误码

code 含义
581131 原文超长(> 20000 字符)(DB 段位让位:原文档 581120 已被 TRANSPORT_PLAN_NOT_FOUND 占用)
581132 原文为空或全行无法解析(DB 段位让位:原文档 581121 改至此)
100501 限流触发(10 次/分钟)—— 走 HL 全局 CommonErrorCode.RATE_LIMITED,不在 traveler 段位
581134 订单状态不允许批量导入(已结算 / 已取消)(DB 段位让位:原文档 581123 改至此)

业务边界 + 审计安全

  • ✅ 限流:每 admin 10 次/分钟(@RateLimiter(count=10, time=60))
  • ✅ PII 不落审计:接口不挂 @OperationLog(避免明文 idNo/phone 写入 audit_log)
  • ✅ 错误行脱敏:failures[].maskedSnippet 严格脱敏(idNo 前 6 后 4、phone 前 3 后 4)
  • ⚠️ dryRun=true:纯解析不落库,前端可用作"试解析预览"
  • ⚠️ dryRun=false:解析+入库一次完成,INSERT N 行 order_traveler + UPDATE order_main.<type>Count 同事务

示例

典型 - 请求:

POST /v3/admin/order/60123456789012/traveler/smart-parse
Authorization: Bearer {admin_jwt}
Content-Type: application/json

{
  "rawText": "张三 350101199001011234 13800138000\n李四 13900139000 110101199201021235\n王五 110101****1234 138****8765",
  "dryRun": false
}

典型 - 响应:

{
  "code": 200,
  "data": {
    "successCount": 2,
    "failCount": 1,
    "successList": [
      {"id": "70123456789014", "name": "张三", "travelerType": "ADULT", "profileStatus": "COMPLETED"},
      {"id": "70123456789015", "name": "李四", "travelerType": "ADULT", "profileStatus": "COMPLETED"}
    ],
    "failures": [
      {"lineIndex": 3, "maskedSnippet": "王五 110101****1234 138****8765", "reason": "身份证号校验失败"}
    ]
  },
  "msg": "success"
}

异常(限流 100501) - 响应:

{ "code": 100501, "data": null, "msg": "请求过于频繁,请稍后再试" }

3.10 §2.9 出行人信息校验

路径:GET /v3/admin/order/{id}/traveler/validate 使用场景:支付前 / 锁单前置校验(同 §1.8 confirm-checklist 的 TRAVELER_COMPLETE 项底层依赖) 校验维度:(1) 实际出行人数 = 订单声明人数;(2) 每个出行人字段齐全(姓名+身份证+手机+证件类型)

入参

id (path, Long) — 订单 ID

出参(Result<TravelerValidateRespVO>)

字段 类型 说明
passed Boolean 是否全部通过
declaredCount Integer 订单声明人数(含所有人群类型)
actualCount Integer 实际 order_traveler 行数(未软删)
countMismatch Boolean 人数是否不一致
incompleteList List<IncompleteTravelerVO> 字段不完整的出行人

IncompleteTravelerVO:

字段 类型 说明
travelerId String 出行人 ID
name String 姓名(脱敏,如 张*)
missingFields List<String> 缺失字段名列表(如 ["idNo", "phone"])

错误码

code 含义
581124 订单不存在

业务边界

  • ✅ 只读校验:不入库、不改状态
  • ⚠️ incompleteList[].name 脱敏:响应里姓名仅留首字(如 张*),不暴露完整姓名
  • ⚠️ 必填判定:缺 name / idType / idNo / phone 任一即进 incompleteList

示例

典型(未通过) - 请求:

GET /v3/admin/order/60123456789012/traveler/validate
Authorization: Bearer {admin_jwt}

典型(未通过) - 响应:

{
  "code": 200,
  "data": {
    "passed": false,
    "declaredCount": 3,
    "actualCount": 2,
    "countMismatch": true,
    "incompleteList": [
      {"travelerId": "70123456789013", "name": "张*", "missingFields": ["idNo", "phone"]}
    ]
  },
  "msg": "success"
}

典型(通过) - 响应:

{
  "code": 200,
  "data": {
    "passed": true,
    "declaredCount": 3,
    "actualCount": 3,
    "countMismatch": false,
    "incompleteList": []
  },
  "msg": "success"
}

6. 枚举 / 数据字典

跨接口共享枚举集中列出,按字段分组,标注「使用字段在哪里」。

6.1 travelerType(出行人类型)

使用字段:§3.1 / §3.2 / §3.3 / §3.9 出入参 travelerType

值 说明
ADULT 成人
CHILD 儿童(有床)
YOUNG_CHILD 幼儿(无床/占座)
BABY 婴儿(无座)

6.2 gender(性别)

使用字段:§3.1 / §3.2 / §3.3 / §3.9 出入参 gender

值 说明
MALE 男
FEMALE 女
UNKNOWN 未填

6.3 idType(证件类型)

使用字段:§3.1 / §3.2 / §3.3 / §3.9 出入参 idType

值 说明
ID_CARD 居民身份证
PASSPORT 护照
BIRTH_CERT 出生证明

6.4 profileStatus(资料完善状态)

使用字段:§3.1 / §3.3 / §3.9 出参 profileStatus

值 说明
PENDING 字段未齐全
COMPLETED 字段已齐全

6.5 direction(大交通方向)

使用字段:§3.5 / §3.6 / §3.7 出入参 direction

值 说明
ARRIVAL 到达(去程)
DEPARTURE 返程(离开)

6.6 mode(大交通模式)

使用字段:§3.5 出参 mode

值 说明
TOGETHER 一起到达 / 返程
SEPARATE 分批到达 / 返程(一家分两批场景)

6.7 transportType(交通工具类型)

使用字段:§3.5 / §3.6 / §3.7 出入参 transportType

值 说明
FLIGHT 航班
TRAIN 火车
SELF_DRIVE 自驾

6.8 selfDrivePeriod(自驾时段)

使用字段:§3.5 / §3.6 / §3.7 出入参 selfDrivePeriod(仅 SELF_DRIVE 类型)

值 说明
MORNING 上午
AFTERNOON 下午
EVENING 晚上

6.9 missingFields(缺失字段名)

使用字段:§3.10 出参 incompleteList[].missingFields[]

可能值(与 §3.1 字段名一致):name / idType / idNo / phone


11. 影响评估

  • 是否破坏向后兼容:否(v3 全新二期,前端 v3 项目仓库首次消费)
  • 前端是否必须同步上线:是
  • 本次推送范围:§2 模块管理后台 10 接口(含 §2.8 smart-parse 字段先定,wx 实现后立即可对接)。§2.7 internal feign 走后端 changelog 仓库,不在本表。

12. 注意事项

  • §2.8 smart-parse 待 wx 新建(Issue #2526):前端可先按本文字段对接 UI,wx 实现完接口立即可调;接口字段已确定不会变
  • 敏感字段明文返回:§2.1 / §2.3 / §2.8 / §2.9 admin 接口返回 idNo / phone / emergencyPhone 明文,前端拿到后不要写本地 log / 不要塞 URL query;§2.9 incompleteList[].name 已脱敏
  • 桥接表约束:§3.6 / §3.7 大交通批次新增/编辑时同方向同一出行人只能在 1 个 plan(错则 581143)
  • 删人合同强约束:§3.4 已签电子合同后禁止删人 → 581106
  • /v3/admin/** 公司隔离:所有 admin 接口均带跨公司隔离校验,跨公司访问返 581021,前端无需自行过滤

13. 关联

  • API 设计文档: docs/order-v3/api/API-SPEC-V5.50.html §2.1 ~ §2.9(v5.50 阶段已对齐 v3 代码现状)
  • SRS 业务规格: docs/order-v3/srs/order-cloud-v3-srs-v5.50.html §1.0i 出行人模型 / §2 大交通
  • 数据库 Schema: docs/order-v3/database/DATABASE-SCHEMA-V5.50.html(order_traveler / order_transport_plan / order_transport_plan_traveler / order_decrypt_audit_log)
  • §1 总 changelog(订单核心模块): changelogs-v2/2026-05/18_§1_订单核心模块-新增接口-管理后台.md(详情主聚合 §1.3.1 引用本模块 §2.1 TravelerVO 字段口径)
  • §2.7 internal feign 单独走后端 changelog: 待推 hl-backend-changelog/.../18_§2.7_traveler-internal-feign-新增接口.md(受众=合同 / 保险服务)
  • 关联 Issue:#2517 ~ #2527 11 个(含 §2.7 #2525 internal feign 单独走后端 changelog),全部 assign wx;§2.8 #2526 为 0→1 新建
  • 后端负责人: @yaosutu / 实施 @wx