hl-api-changelog/changelogs/2026-05/08_1500_arrival-mode.md

529 行
17 KiB
Markdown

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

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

# API 变更通知
**更新时间**: 2026-05-08 15:00
**PR**: #1878 feat(order-v2): 到达/返程信息支持区分一起/多批两种模式 + #1887 修正接口描述
---
## 破坏性变更POST /mp/order/{orderId}/arrival 语义彻底变更
### 变了什么(前端视角)
**单数接口从「追加一条」变成「该方向全量替换 1 条」。**
| 行为 | 旧逻辑PR 前) | 新逻辑PR 后) |
|------|----------------|----------------|
| 连续调 2 次 | 产生 2 条批次(追加) | 第 2 次会把第 1 次清掉,只保留最新 1 条 |
| 想分批到达 | 多次调单数接口 | 必须改用 /arrival/batch提交多元素数组 |
| 已有批次被覆盖范围 | 无此逻辑 | 只清同一 direction 的旧批次,不影响另一方向 |
如果小程序之前通过多次调 POST /arrival 实现「分批到达」,现在必须改为调 POST /arrival/batch。
---
## Bug 修复POST /mp/order/{orderId}/arrival/batch 不再误删另一方向
| 行为 | 旧行为(有 bug | 新行为(已修复) |
|------|----------------|----------------|
| 提交返程多批 | 把已填的到达批次也一起删掉 | 只删 direction=DEPARTURE 的旧批次,ARRIVAL 不受影响 |
| 提交到达多批 | 把已填的返程批次也一起删掉 | 只删 direction=ARRIVAL 的旧批次,DEPARTURE 不受影响 |
如果前端之前因为这个 bug 做了「先查再保」之类的 workaround,可以清理掉。
---
## 新增GET 接口返回 mode + modeLabel 字段
GET /mp/order/{orderId}/arrival 返回的每个批次对象新增 2 个字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| mode | String | 模式枚举TOGETHER 或 SEPARATE |
| modeLabel | String | 按方向拼出的中文标签(见下表) |
modeLabel 的 4 种值:
| direction | mode | modeLabel |
|-----------|------|----------|
| ARRIVAL | TOGETHER | 一起到达 |
| ARRIVAL | SEPARATE | 多批到达 |
| DEPARTURE | TOGETHER | 一起返程 |
| DEPARTURE | SEPARATE | 多批返程 |
前端可以用 arrivals[0]?.mode或 departures[0]?.mode来判断该方向当前 tab 模式,决定进入页面时默认选中哪个选项卡。
---
## 新增错误码580010 BATCH_DIRECTION_MIXED
POST /mp/order/{orderId}/arrival/batch 增加新校验:请求数组里所有元素的 direction 必须一致(不能同一次 batch 里混提 ARRIVAL 和 DEPARTURE
| 错误码 | message |
|--------|--------|
| 580010 | 批量提交的批次必须同一方向(到达或返程) |
响应示例(错误):
```json
{
"code": 580010,
"message": "批量提交的批次必须同一方向(到达或返程)",
"data": null
}
```
---
## 涉及的接口汇总
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---|------|------|------|----------|------|
| 1 | 查询订单全量批次 | GET | /mp/order/{orderId}/arrival | 字段新增 | 每个批次对象新增 mode + modeLabel |
| 2 | 新增交通批次 | POST | /mp/order/{orderId}/arrival | 语义破坏性变更 | 从追加改为该方向全量替换 1 条 |
| 3 | 全量替换批次(多批) | POST | /mp/order/{orderId}/arrival/batch | Bug 修复 + 新增校验 | 修方向隔离 bug;新增 direction 混用校验 |
| 4 | 修改交通批次 | PUT | /mp/order/{orderId}/arrival/plan/{planId} | 无变化 | - |
| 5 | 删除交通批次 | DELETE | /mp/order/{orderId}/arrival/plan/{planId} | 无变化 | - |
---
## 接口详细定义
### 1. GET /mp/order/{orderId}/arrival — 查询订单全量到达/离开批次
- **使用场景**:进入订单详情/行程页时查询,用返回的 arrivals[0]?.mode 和 departures[0]?.mode 决定各方向 tab 默认状态
- **路径参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | Long | 是 | 订单 ID |
- **响应字段data 对象)**
| 字段 | 类型 | 说明 |
|------|------|------|
| orderId | Long | 订单 ID |
| arrivals | Array | direction=ARRIVAL 的批次列表 |
| departures | Array | direction=DEPARTURE 的批次列表 |
arrivals/departures 内每个批次对象字段MpArrivalPlanRespVO
| 字段 | 类型 | 说明 |
|------|------|------|
| planId | Long | 批次 ID |
| orderId | Long | 订单 ID |
| direction | String | ARRIVAL/DEPARTURE |
| directionLabel | String | 到达/离开 |
| mode | String | **[本次新增]** TOGETHER/SEPARATE |
| modeLabel | String | **[本次新增]** 一起到达/多批到达/一起返程/多批返程 |
| transportType | String | FLIGHT/TRAIN/SELF_DRIVE |
| transportTypeLabel | String | 飞机/火车/自驾 |
| transportNo | String | 航班号/车次号(自驾为 null |
| carrier | String | 航司/铁路公司 |
| departStation | String | 出发站/机场 |
| arriveStation | String | 到达站/机场 |
| departTime | String | 出发时间,格式 yyyy-MM-dd HH:mm:ss |
| arriveTime | String | 到达时间,格式 yyyy-MM-dd HH:mm:ss |
| selfDrivePeriod | String | 自驾时段MORNING/AFTERNOON/EVENING,非自驾为 null |
| selfDrivePeriodLabel | String | 上午/下午/晚上,非自驾为 null |
| selfDriveEta | String | 自驾预计到达精确时间,非自驾为 null |
| remark | String | 用户备注 |
| creatorType | String | USER/ADMIN |
| createTime | String | 创建时间 |
| travelers | Array | 本批次出行人列表 |
travelers 内每个出行人字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| travelerId | Long | 出行人 ID |
| name | String | 姓名 |
| travelerType | String | ADULT/CHILD/YOUNG_CHILD/BABY |
- **响应示例(完整)**
```json
{
"code": 200,
"message": "success",
"data": {
"orderId": 700001,
"arrivals": [
{
"planId": 800001,
"orderId": 700001,
"direction": "ARRIVAL",
"directionLabel": "到达",
"mode": "TOGETHER",
"modeLabel": "一起到达",
"transportType": "FLIGHT",
"transportTypeLabel": "飞机",
"transportNo": "CZ6255",
"carrier": "南方航空",
"departStation": "北京首都T3",
"arriveStation": "海拉尔东山",
"departTime": "2026-07-10 08:30:00",
"arriveTime": "2026-07-10 11:00:00",
"selfDrivePeriod": null,
"selfDrivePeriodLabel": null,
"selfDriveEta": null,
"remark": "带小孩,需婴儿座椅",
"creatorType": "USER",
"createTime": "2026-07-01 10:00:00",
"travelers": [
{
"travelerId": 10001,
"name": "张三",
"travelerType": "ADULT"
}
]
}
],
"departures": [
{
"planId": 800002,
"orderId": 700001,
"direction": "DEPARTURE",
"directionLabel": "离开",
"mode": "SEPARATE",
"modeLabel": "多批返程",
"transportType": "TRAIN",
"transportTypeLabel": "火车",
"transportNo": "K209",
"carrier": null,
"departStation": "海拉尔",
"arriveStation": "北京",
"departTime": "2026-07-15 10:00:00",
"arriveTime": "2026-07-16 08:00:00",
"selfDrivePeriod": null,
"selfDrivePeriodLabel": null,
"selfDriveEta": null,
"remark": null,
"creatorType": "USER",
"createTime": "2026-07-02 09:00:00",
"travelers": [
{
"travelerId": 10001,
"name": "张三",
"travelerType": "ADULT"
}
]
}
]
}
}
```
---
### 2. POST /mp/order/{orderId}/arrival — 新增交通批次(单条,该方向全量替换)
- **使用场景**用户在「一起到达」或「一起返程」tab 填写单条信息并提交
- **语义重申**:调用此接口会把同 direction 的所有旧批次软删,再插入 1 条新批次。最终该方向只剩 1 条,mode 固定为 TOGETHER
- **路径参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | Long | 是 | 订单 ID |
- **请求参数JSON Body**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| direction | String | 是 | ARRIVAL=到达 / DEPARTURE=离开 |
| transportType | String | 是 | FLIGHT=飞机 / TRAIN=火车 / SELF_DRIVE=自驾 |
| transportNo | String | 条件必填 | 航班号/车次号;FLIGHT/TRAIN 必填,SELF_DRIVE 不填 |
| carrier | String | 否 | 航司/铁路公司,最长 64 字符 |
| departStation | String | 条件必填 | 出发站/机场;DEPARTURE+FLIGHT/TRAIN 必填;ARRIVAL 可选 |
| arriveStation | String | 条件必填 | 到达站/机场;ARRIVAL+FLIGHT/TRAIN 必填;DEPARTURE 可选 |
| departTime | String | 条件必填 | 出发时间;DEPARTURE+FLIGHT/TRAIN 必填;格式 yyyy-MM-dd HH:mm:ss |
| arriveTime | String | 条件必填 | 到达时间;ARRIVAL+FLIGHT/TRAIN 必填;格式 yyyy-MM-dd HH:mm:ss |
| selfDrivePeriod | String | 条件必填 | 自驾时段;SELF_DRIVE 必填;MORNING/AFTERNOON/EVENING |
| selfDriveEta | String | 否 | 自驾预计到达精确时间;SELF_DRIVE 可选;格式 yyyy-MM-dd HH:mm:ss |
| remark | String | 否 | 用户备注,最长 255 字符 |
| travelerIds | Array | 是 | 出行人 ID 列表,至少 1 人,必须属于本订单 |
- **请求示例(到达+飞机)**
```json
{
"direction": "ARRIVAL",
"transportType": "FLIGHT",
"transportNo": "CZ6255",
"carrier": "南方航空",
"departStation": "北京首都T3",
"arriveStation": "海拉尔东山",
"departTime": "2026-07-10 08:30:00",
"arriveTime": "2026-07-10 11:00:00",
"remark": "带小孩,需婴儿座椅",
"travelerIds": [
10001,
10002
]
}
```
- **响应示例(完整)**
```json
{
"code": 200,
"message": "success",
"data": {
"planId": 800001,
"orderId": 700001,
"direction": "ARRIVAL",
"directionLabel": "到达",
"mode": "TOGETHER",
"modeLabel": "一起到达",
"transportType": "FLIGHT",
"transportTypeLabel": "飞机",
"transportNo": "CZ6255",
"carrier": "南方航空",
"departStation": "北京首都T3",
"arriveStation": "海拉尔东山",
"departTime": "2026-07-10 08:30:00",
"arriveTime": "2026-07-10 11:00:00",
"selfDrivePeriod": null,
"selfDrivePeriodLabel": null,
"selfDriveEta": null,
"remark": "带小孩,需婴儿座椅",
"creatorType": "USER",
"createTime": "2026-07-01 10:00:00",
"travelers": [
{
"travelerId": 10001,
"name": "张三",
"travelerType": "ADULT"
},
{
"travelerId": 10002,
"name": "李四",
"travelerType": "CHILD"
}
]
}
}
```
---
### 3. POST /mp/order/{orderId}/arrival/batch — 全量替换批次(多批模式)
- **使用场景**用户在「多批到达」或「多批返程」tab,一次性提交该方向所有批次
- **Bug 修复**:旧版本会把订单全部旧批次删掉(含另一方向),新版本只删 body 第一条元素对应的 direction
- **新增校验**body 数组里所有元素的 direction 必须一致,混提返回 code=580010
- **路径参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| orderId | Long | 是 | 订单 ID |
- **请求参数JSON Body,数组**:字段同上面单条接口,外层包数组
- **请求示例(多批返程)**
```json
[
{
"direction": "DEPARTURE",
"transportType": "FLIGHT",
"transportNo": "CZ6256",
"carrier": "南方航空",
"departStation": "海拉尔东山",
"arriveStation": "北京首都T3",
"departTime": "2026-07-15 12:00:00",
"arriveTime": "2026-07-15 15:30:00",
"travelerIds": [
10001
]
},
{
"direction": "DEPARTURE",
"transportType": "TRAIN",
"transportNo": "K209",
"departStation": "海拉尔",
"arriveStation": "北京",
"departTime": "2026-07-15 10:00:00",
"arriveTime": "2026-07-16 08:00:00",
"travelerIds": [
10002
]
}
]
```
- **响应示例(完整)**
```json
{
"code": 200,
"message": "success",
"data": {
"orderId": 700001,
"arrivals": [],
"departures": [
{
"planId": 800003,
"orderId": 700001,
"direction": "DEPARTURE",
"directionLabel": "离开",
"mode": "SEPARATE",
"modeLabel": "多批返程",
"transportType": "FLIGHT",
"transportTypeLabel": "飞机",
"transportNo": "CZ6256",
"carrier": "南方航空",
"departStation": "海拉尔东山",
"arriveStation": "北京首都T3",
"departTime": "2026-07-15 12:00:00",
"arriveTime": "2026-07-15 15:30:00",
"selfDrivePeriod": null,
"selfDrivePeriodLabel": null,
"selfDriveEta": null,
"remark": null,
"creatorType": "USER",
"createTime": "2026-07-01 11:00:00",
"travelers": [
{
"travelerId": 10001,
"name": "张三",
"travelerType": "ADULT"
}
]
},
{
"planId": 800004,
"orderId": 700001,
"direction": "DEPARTURE",
"directionLabel": "离开",
"mode": "SEPARATE",
"modeLabel": "多批返程",
"transportType": "TRAIN",
"transportTypeLabel": "火车",
"transportNo": "K209",
"carrier": null,
"departStation": "海拉尔",
"arriveStation": "北京",
"departTime": "2026-07-15 10:00:00",
"arriveTime": "2026-07-16 08:00:00",
"selfDrivePeriod": null,
"selfDrivePeriodLabel": null,
"selfDriveEta": null,
"remark": null,
"creatorType": "USER",
"createTime": "2026-07-01 11:00:00",
"travelers": [
{
"travelerId": 10002,
"name": "李四",
"travelerType": "CHILD"
}
]
}
]
}
}
```
---
## 枚举 / 字典值(完整)
### transport_direction方向
| 值 | 中文 | 说明 |
|----|------|------|
| ARRIVAL | 到达 | 游客到达目的地 |
| DEPARTURE | 离开 | 游客离开目的地(返程) |
### mode模式,本次新增
| 值 | 中文 | 说明 |
|----|------|------|
| TOGETHER | 一起 | 该方向所有出行人同一批次 |
| SEPARATE | 多批 | 该方向出行人分多个批次 |
### modeLabel按 direction + mode 拼,本次新增)
| direction | mode | modeLabel |
|-----------|------|-----------|
| ARRIVAL | TOGETHER | 一起到达 |
| ARRIVAL | SEPARATE | 多批到达 |
| DEPARTURE | TOGETHER | 一起返程 |
| DEPARTURE | SEPARATE | 多批返程 |
### transport_type交通方式
| 值 | 中文 |
|----|------|
| FLIGHT | 飞机 |
| TRAIN | 火车 |
| SELF_DRIVE | 自驾 |
### self_drive_period自驾时段
| 值 | 中文 | 时间范围 |
|----|------|---------|
| MORNING | 上午 | 06:00-12:00 |
| AFTERNOON | 下午 | 12:00-18:00 |
| EVENING | 晚上 | 18:00 以后 |
### creator_type创建者类型
| 值 | 中文 |
|----|------|
| USER | 用户自填 |
| ADMIN | 定制师代录 |
### traveler_type出行人类型
| 值 | 中文 |
|----|------|
| ADULT | 成人 |
| CHILD | 儿童 |
| YOUNG_CHILD | 幼儿 |
| BABY | 婴儿 |
---
## 错误码(本模块完整)
| code | message | 触发场景 |
|------|---------|---------|
| 580001 | 订单当前状态不可修改交通信息: {状态} | 订单不在可编辑状态 |
| 580002 | 出行人列表不能为空 | travelerIds 为空 |
| 580003 | 以下出行人不属于本订单: {ids} | travelerIds 包含不属于此订单的 ID |
| 580004 | 航班号/车次号不能为空 | FLIGHT/TRAIN 时 transportNo 未填 |
| 580005 | 到达机场/车站不能为空 | ARRIVAL+FLIGHT/TRAIN 时 arriveStation 未填 |
| 580006 | 到达时间不能为空 | ARRIVAL+FLIGHT/TRAIN 时 arriveTime 未填 |
| 580007 | 出发机场/车站不能为空 | DEPARTURE+FLIGHT/TRAIN 时 departStation 未填 |
| 580008 | 出发时间不能为空 | DEPARTURE+FLIGHT/TRAIN 时 departTime 未填 |
| 580009 | 自驾时段不能为空 | SELF_DRIVE 时 selfDrivePeriod 未填 |
| 580010 | 批量提交的批次必须同一方向(到达或返程) | batch 接口 body 内 direction 混用(本次新增) |
---
## 业务规则 / 校验规则
1. POST /arrival单数提交即清空同 direction 旧批次,再插入 1 条。最终该方向只有 1 条批次,mode 固定为 TOGETHER。
2. POST /arrival/batch提交即清空同 direction 旧批次,再批量插入。有 2 条及以上时 mode 为 SEPARATE;仅 1 条时 mode 也是 SEPARATE因为用户选择了「多批」入口
3. 两个接口只影响自己提交的 direction,不互相干扰本次 bug 修复要点)。
4. PUT /arrival/plan/{planId} 修改单条,不影响其他批次,不改变 mode。
5. DELETE /arrival/plan/{planId} 只软删单条。
6. 以上操作均需订单处于可编辑状态,否则返回 580001。
---
## 前端实现建议
---
## 补充说明
- GET 接口新增 mode/modeLabel 字段,向后兼容(纯新增,无删改名),已有代码不受影响
- POST 单数接口语义变更属于破坏性变更,旧版用多次调单数接口实现分批的需改用 batch
- 服务重启:需重启 hl-order-service-v2 和 hl-mp-service 后生效