hl-api-changelog/changelogs-v2/2026-05/18_§2_traveler模块-新增接口-管理后台.md
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: #1
- 验证代码 commit: HL@dev-v3 47d24228
- 验证报告: HL/.claude/tmp-changelog/issue1-analysis.md(仅本地)
2026-05-19 10:28:11 +08:00

33 KiB

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

更新时间: 2026-05-18 端类型: 管理后台 设计文档版本: v5.50API-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}/travelersinternal 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 出行人补全页 认证JWTadmin 角色 + 公司隔离) 敏感字段idNo / phone / emergencyPhone 明文返回admin JWT 鉴权保护)

入参

id (path, Long) — 订单 ID

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

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

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

TravelerEditItem12 字段):

字段 类型 必填 说明
id Long 出行人 IDnull=新增 / 非 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 订单 IDpath
travelerId Long 出行人 IDpath

出参(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.5ARRIVAL / DEPARTURE
mode String 枚举见 §6.6TOGETHER / SEPARATE
transportType String 枚举见 §6.7FLIGHT / 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 订单 IDpath
planId Long 批次 IDpath
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 订单 IDpath
planId Long 批次 IDpath

出参(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 订单 IDpath
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.9v5.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.htmlorder_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