changelog(mp): 04-23 下午批次 7 篇 — 合同强类型 VO / 退款 ratio / balance 统一 / 头像 / groupBatchId / 小童保留 / 行前清单拆分

- #1314 mp-contract: Map → MpContractVO / MpContractDetailVO 强类型化
- #1313 mp-refund preview refundRatio 恒 0 bug 修复
- #1306 mp-order balanceAmount 计算口径统一(FULL 也返回, 公式含 paid)
- #1309 mp-order guide/photographer avatarUrl 快照补齐(新订单生效)
- #1300 mp-order detail 新增 groupBatchId(GROUP 才有值)
- #1298 mp-group order youngChildCount 保留不再强制清零
- #1289 mp-pre-trip checklist 6→7 项 + DEPARTURE_INFO + WARNING 状态
这个提交包含在:
yaosutu 2026-04-23 16:43:36 +08:00
父节点 3894e88ba9
当前提交 17648b8961
共有 7 个文件被更改,包括 500 次插入0 次删除

查看文件

@ -0,0 +1,91 @@
# MP 合同接口 5 个:返回值从 Map 改为强类型 VO
- **变更日期**: 2026-04-23
- **PR**: #1314
- **影响面**: 小程序端 · 合同列表 / 合同详情 / 订单关联合同(管理端不涉及)
- **兼容性**: **字段契约规范化**。返回 Map 改为具名 VO,前端按本文列出的字段接入即可;Swagger 以 `MpContractVO` / `MpContractDetailVO` 为准
---
## 涉及接口5 个)
| # | 功能 | 方法 | 路径 | 返回类型 |
|---|---|---|---|---|
| 1 | 合同列表 | GET | `/mp/contract/list?status=&page=&pageSize=` | `PageResult<MpContractVO>` |
| 2 | 合同详情 | GET | `/mp/contract/{id}` | `MpContractDetailVO` |
| 3 | 按订单查合同(单条最新) | GET | `/mp/contract/by-order/{orderId}` | `MpContractVO` |
| 4 | 按订单查合同TOUR+INSURANCE 全部) | GET | `/mp/contract/by-order/{orderId}/all` | `List<MpContractVO>` |
| 5 | 重发签署短信 | POST | `/mp/contract/{contractId}/resend-sms` | `Result<Void>` |
鉴权:小程序登录态 token,网关解析 `X-User-Id` 后透传 order-v2。
---
## 列表/查单:`MpContractVO` 字段清单
| 字段 | 类型 | 说明 |
|---|---|---|
| contractId | Long | 合同 ID |
| orderId | Long | 订单 ID |
| templateCode / templateName | String | 合同模板编码 / 名称 |
| contractNumber | String | 合同编号 |
| platform | String | 签约平台 |
| contractType | String | 合同类型(字典 `contract_type`TOUR=旅游 / INSURANCE=保险单)|
| contractTypeLabel | String | 合同类型显示文案BFF 翻译好)|
| mode | String | 签约模式(字典 `contract_mode`ONLINE / OFFLINE|
| modeLabel | String | 签约模式显示文案 |
| status | String | 合同状态(字典 `contract_status`|
| statusLabel | String | 合同状态显示文案 |
| signUrl | String | 签署 URL待签时跳转用|
| qrCodeUrl | String | 签署二维码 URL |
| fileUrl | String | 已签合同 PDF 下载 URL |
| agencyCode / travelAgencyName | String | 旅行社编号 / 名称 |
| destination | String | 目的地 |
| departureDate / returnDate | LocalDate`yyyy-MM-dd`| 出发日期 / 返回日期 |
| totalAmount | BigDecimal | 合同总金额 |
| touristCount | Integer | 出行人数 |
| contactName | String | 联系人姓名(明文,前端自行脱敏)|
| contactPhone | String | 联系人电话(明文,前端自行脱敏)|
| createTime | LocalDateTime`yyyy-MM-dd HH:mm:ss`| 创建时间 |
---
## 详情:`MpContractDetailVO`(继承 `MpContractVO`,额外三段)
| 字段 | 类型 | 说明 |
|---|---|---|
| supplementaryClause | String | 补充约定正文 |
| travelers | `List<TravelerInfo>` | 合同关联出行人 |
| statusLogs | `List<MpContractStatusLogVO>` | 状态变更日志(按时间倒序)|
`TravelerInfo` 字段:`travelerId / name / idCardType(ID_CARD,PASSPORT) / idCardNo / phone / isSigner`,姓名/证件号/电话均为**明文**,前端按需脱敏。
`MpContractStatusLogVO` 字段:`logId / contractId / oldStatus / newStatus / source(CALLBACK/POLLING/MANUAL) / rawPayload / createTime`
---
## 重发签署短信入参变化
以前前端不需要传 body后端内部拼,现在**透传 VO 需要显式传 `userId`**Gateway 已从 token 注入,前端取当前登录用户 id 即可):
```json
POST /mp/contract/{contractId}/resend-sms
{ "userId": 1001 }
```
> `userId` 未传 → 400 `userId 不能为空`
---
## 不影响范围
- 管理端合同接口(`/admin/contract/**`)零影响
- 下单/支付/合同生成链路无变化
- 合同 webhook / 回调 / 状态机零影响
---
## 相关
- PR[wx/HL#1314](https://git.1814.love:8443/wx/HL/pulls/1314)
- 部署:`hl-mp-service`8085

查看文件

@ -0,0 +1,57 @@
# MP 小蒙马下单 · youngChildCount 不再被强制清零
- **变更日期**: 2026-04-23
- **PR**: #1298
- **影响面**: 小程序端 · 小蒙马GROUP下单 / 订单详情 人群结构展示
- **兼容性**: **接口契约零变化**。前端原来传的 `youngChildCount` 从"传了也没用"变成"被保留"
---
## 变化一句话
小蒙马下单接口原本强制把 `youngChildCount`(小童数)清零,现在会**保留前端传入的数值**写入订单。小童仍然不参与计价(金额 0,仅作为随行人数展示。
---
## 相关接口
`POST /mp/order/create`(小蒙马 GROUP 路径)
### 入参 `youngChildCount` 行为变化
| 场景 | 以前 | 现在 |
|---|---|---|
| 前端传 `youngChildCount=2` | 后端覆盖为 `0` | **保留为 `2`** |
| 前端不传 / 传 null | 后端存 `0` | 保留 `null` → 实际存 `0`(兼容)|
### 计价规则
| 项 | 行为 |
|---|---|
| 小童young child | **不参与计价**`youngChildPrice = 0``youngChildTotal = 0`),仅作为随行头数写入订单 |
| 幼童baby | 仍强制 `babyCount = 0`(规则未变)|
| 是否加床(`childNeedBed` | 仍强制 `false`(规则未变)|
---
## 订单详情展示侧
订单详情 `adultCount / childCount / youngChildCount / babyCount` 字段:
- `youngChildCount` 现在会反映前端下单时实际提交的小童数
- 价格结构 `priceBreakdown` 中小童相关小计仍为 0未参与计价
---
## 不影响范围
- 价格汇总 `totalPrice / adultTotal / childTotal` **零影响**(不加小童价)
- CORE / CUSTOM 产品下单流程 **零影响**(它们原本就按普通逻辑处理小童计价)
- 出行人列表(`travelers`**零影响**
---
## 相关
- PR[wx/HL#1298](https://git.1814.love:8443/wx/HL/pulls/1298)
- 部署:`hl-order-service-v2`8094

查看文件

@ -0,0 +1,65 @@
# MP 订单详情 · 尾款金额balanceAmount计算口径统一
- **变更日期**: 2026-04-23
- **PR**: #1306
- **影响面**: 小程序端 · 订单详情页尾款金额展示 + 下单流程 `paymentType` 回填
- **兼容性**: **前端零改动**;已付款的订单 balanceAmount 语义更严谨、更广泛
---
## 变化一:订单详情 `balanceAmount` 字段适用范围扩大 + 公式统一
### 以前
只在订金订单(`paymentType=DEPOSIT`)且 `depositAmount` 非空时返回 `balanceAmount`。全款订单(`paymentType=FULL`**不返回该字段**(或为 null
### 现在
**所有订单**都返回 `balanceAmount`,统一口径:
```
balanceAmount = max(0, totalPrice - discountAmount + surchargeAmount - paidAmount)
```
- `paidAmount`:已支付金额(订金支付后 = 订金金额;尾款已付 = 全款)
- 永远 ≥ 0不会出现负数
- 全款订单 paidAmount=0 时 balance = totalPrice未付;paidAmount=totalPrice 时 balance = 0已付清
### 前端接入影响
- **原先用 `paymentType===DEPOSIT` 判断才读 `balanceAmount` 的逻辑可以保留**,仍然工作
- 如果想给全款订单也展示「待支付金额」,直接读 `balanceAmount` 即可
- "待支付金额 = 0" 代表订单已付清(可用于隐藏支付按钮)
---
## 变化二:下单时 `paymentType` 不再被 quote 覆盖为 `FULL`
### 以前
CORE 产品下单时,如果 quote 接口没返回 `paymentType`,后端会强制把订单 `paymentType` 设为 `FULL`,覆盖产品快照里的默认值。
### 现在
quote 返回 `paymentType` 非空 → 使用 quote 的值;quote 返回 null → **保留产品快照里的默认值**`setProductInfoOnOrder` 阶段已设好)。
### 前端接入影响
- 下单后拿到的订单 `paymentType`(详情接口)会**更准确地反映产品本身的支付模式**FULL / DEPOSIT
- 原来因为这个覆盖逻辑导致 DEPOSIT 订金订单被错写成 FULL 的情况,不会再发生
---
## 不影响范围
- 下单请求体(`/mp/order/create`**零变化**
- 订金/尾款金额(`depositAmount / depositRatio`**零变化**
- 管理端订单详情 `balanceAmount` 逻辑**本次同步生效**(口径一致)
- 历史订单不回迁数据,但下次读详情时按新公式现算,**立即生效**
---
## 相关
- PR[wx/HL#1306](https://git.1814.love:8443/wx/HL/pulls/1306)
- 部署:`hl-order-service-v2`8094

查看文件

@ -0,0 +1,63 @@
# MP 订单详情 · 新增 groupBatchId团期 ID
- **变更日期**: 2026-04-23
- **PR**: #1300
- **影响面**: 小程序端 · 订单详情(仅小蒙马 GROUP 订单有值)
- **兼容性**: **完全向后兼容**(纯新增字段,旧前端不读即可忽略)
---
## 变化一句话
MP 订单详情返回体 `MpOrderDetailVO` 新增 `groupBatchId` 字段,仅小蒙马 GROUP 订单有值,前端可据此跳转到对应团期详情页。
---
## 接口
`GET /mp/order/{orderId}`(以及走 BFF 的同类接口)
### 新增字段
| 字段 | 类型 | 说明 |
|---|---|---|
| `groupBatchId` | Long | 团期 ID。仅 GROUP小蒙马订单有值;CORE自驾/自助游、CUSTOM定制等订单为 null |
### 返回示例
```json
{
"code": 200,
"data": {
"orderId": 1900001,
"orderNo": "XMM20260423001",
"groupCode": "0001",
"groupBatchId": 2045401225939079169,
"productId": 1893012345678901234,
"productName": "...",
"...": "..."
},
"success": true
}
```
---
## 前端接入场景(参考)
「我的订单 → 订单详情 → 团期入口」点击后用 `groupBatchId` 跳团期详情页;非 GROUP 订单为 null 时隐藏入口即可。
---
## 不影响范围
- 其它订单字段(`orderNo / groupCode / productId / productName / ...`**零变化**
- 管理端订单详情 DTO **不涉及**
- 下单/支付/退款链路 **零影响**
---
## 相关
- PR[wx/HL#1300](https://git.1814.love:8443/wx/HL/pulls/1300)
- 部署:`hl-order-service-v2`8094+ `hl-mp-service`8085

查看文件

@ -0,0 +1,57 @@
# MP 订单详情 · 领队/摄影师头像 avatarUrl 之前为 null — 已修复
- **变更日期**: 2026-04-23
- **PR**: #1309
- **影响面**: 小程序端 · 订单详情「领队」「摄影师」弹窗 / 卡片的头像展示
- **兼容性**: **字段结构零变化**,原本 null 的字段现在会填充有效 URL
---
## 变化一句话
MP 订单详情相关接口中的员工头像 `avatarUrl` 字段之前恒为 null,现在会返回有效的头像 OSS URL。
---
## 涉及接口
下列接口返回体中的 `avatarUrl` 字段:
| 接口 | 返回体中的位置 |
|---|---|
| `GET /mp/order/{orderId}/guide` | `guide.avatarUrl` |
| `GET /mp/order/{orderId}/photographer` | `photographer.avatarUrl` |
---
## 头像生成规则(前端可了解优先级)
1. 优先取员工档案 `coverMaterialId` 对应的物料库封面OSS URL
2. 若无,fallback 取员工相册 `photoUrls` 的第一张
3. 都没有 → `avatarUrl` 为 null前端走默认占位图即可
---
## 生效范围(⚠️ 重要)
| 订单类型 | 是否生效 |
|---|---|
| **新下单的小蒙马GROUP订单** | ✅ 立即生效 |
| 历史已下单的 GROUP 订单 | ❌ 下单时已固化的员工快照未补头像,avatarUrl 仍为 null如需回填可后台批量补修,本次未做|
| CORE核心/自驾/自助游)订单 | N/A本来就不含领队/摄影师)|
---
## 不影响范围
- 领队/摄影师接口的其它字段(`staffName / staffPhone / staffRole / remark` 等)**零变化**
- 下单请求体、订单详情主体**零变化**
- 管理端员工档案(`/admin/staff/**`**零变化**
- 订单班期员工列表接口(`/mp/order/{orderId}/staff-list` 等)同步生效
---
## 相关
- PR[wx/HL#1309](https://git.1814.love:8443/wx/HL/pulls/1309)
- 部署:`hl-product-service-v2`8093+ `hl-resource-service`8082

查看文件

@ -0,0 +1,112 @@
# MP 出发准备清单 · 「接送机」拆成「到达」+「离开」两项 + 按出行人覆盖三态
- **变更日期**: 2026-04-23
- **PR**: #1289
- **影响面**: 小程序端 · 行前准备清单(出发倒计时聚合接口)
- **兼容性**: **需要前端同步调整**(清单项数量从 6 变 7,单项 key 新增,状态值新增 `WARNING`
---
## 变化一:清单项数量 6 → 7
| 之前 | 现在 |
|---|---|
| 6 项:`DEPOSIT_PAID` / `TRAVELER_INFO` / **`ARRIVAL_INFO`**(接送机合一)/ `CONTRACT_SIGN` / `INSURANCE` / `CHECKLIST_CONFIRMED` | 7 项:`DEPOSIT_PAID` / `TRAVELER_INFO` / **`ARRIVAL_INFO`**(到达)/ **`DEPARTURE_INFO`**(离开)/ `CONTRACT_SIGN` / `INSURANCE` / `CHECKLIST_CONFIRMED` |
### `ChecklistItemKey` 取值对照
| 新 key | 之前文案 | 现在文案 |
|---|---|---|
| `ARRIVAL_INFO` | `接送机信息` | **`到达信息`** |
| `DEPARTURE_INFO`(新增) | — | **`离开信息`** |
前端如果用 `ARRIVAL_INFO` 这个枚举值做判断:逻辑保留即可,但文案"接送机"需要改为"到达";新增 `DEPARTURE_INFO` 需要渲染一项。
---
## 变化二:状态新增 `WARNING`(黄色提示态)
之前单项状态只有两个:`DONE / PENDING`;现在在到达/离开两项上新增 **`WARNING`**。
### 到达 / 离开项的三态判断
| 状态 | 触发条件 | 文案示例title + subtitle |
|---|---|---|
| `DONE` | 订单有至少 1 批到达/离开,且**所有出行人都已被某个批次覆盖** | 「到达信息已填」 · 「N 批 · 全员已覆盖」 |
| `WARNING`(新)| 有批次但**漏填了部分出行人** | 「到达信息未填全」 · 「还有 X 人未安排」 |
| `PENDING` | **0 批次** | 「填写到达信息」 · 「司机将根据此信息接机」 |
离开项同理,文案里"到达 / 接机" → "离开 / 送机"。
> 前端如果沿用「DONE=绿色 / PENDING=灰色」两色方案,新增一个"黄色"`WARNING`)即可。
---
## 变化三:`actionPayload` 新增 `section` 字段
点击「到达 / 离开」项跳转表单时,`actionPayload` 新增 `section` 区分是到达还是离开:
```json
{
"title": "填写到达信息",
"status": "PENDING",
"actionType": "NAVIGATE",
"actionPayload": {
"target": "arrival_form",
"orderId": 1900001,
"section": "arrival" // ← 新增,取值 arrival | departure
}
}
```
前端跳到达/离开表单页时,可用 `section` 定位默认展开的 tab。
---
## 接口
路径不变(以 Swagger 为准)。返回体结构:
```json
{
"code": 200,
"data": {
"items": [
{ "key": "DEPOSIT_PAID", "status": "DONE", "title": "...", "subtitle": "..." },
{ "key": "TRAVELER_INFO", "status": "PENDING", "title": "...", "subtitle": "..." },
{ "key": "ARRIVAL_INFO", "status": "WARNING", "title": "到达信息未填全", "subtitle": "还有 1 人未安排",
"actionType": "NAVIGATE", "actionPayload": { "target": "arrival_form", "orderId": 1900001, "section": "arrival" } },
{ "key": "DEPARTURE_INFO", "status": "PENDING", "title": "填写离开信息", "subtitle": "司机将根据此信息送机",
"actionType": "NAVIGATE", "actionPayload": { "target": "arrival_form", "orderId": 1900001, "section": "departure" } },
{ "key": "CONTRACT_SIGN", "status": "DONE" },
{ "key": "INSURANCE", "status": "DONE" },
{ "key": "CHECKLIST_CONFIRMED", "status": "PENDING" }
]
},
"success": true
}
```
---
## 前端需要做的事
1. 清单项渲染循环:从 6 项改为按后端返回 `items` 数组长度渲染(避免硬编码数量)
2. 新增 `DEPARTURE_INFO` 的 icon / 文案映射
3. 新增 `WARNING` 状态的颜色 / 图标样式
4. 点击到达/离开项跳转时,从 `actionPayload.section` 判断 tab 默认态
---
## 不影响范围
- 其它 5 项(`DEPOSIT_PAID / TRAVELER_INFO / CONTRACT_SIGN / INSURANCE / CHECKLIST_CONFIRMED`)行为**零变化**
- 到达 / 离开信息的 CRUD 接口(`/mp/order/{orderId}/arrival` 等)**零变化**
- 管理端行前清单(若有)**不涉及**
---
## 相关
- PR[wx/HL#1289](https://git.1814.love:8443/wx/HL/pulls/1289)
- 部署:`hl-order-service-v2`8094

查看文件

@ -0,0 +1,55 @@
# MP 退款预览 refundRatio 之前永远为 0 — 已修复
- **变更日期**: 2026-04-23
- **PR**: #1313
- **影响面**: 小程序端 · 订单退款预览弹窗
- **兼容性**: **纯 bug 修复**,接口/字段/调用方式零变化,前端无需改动
---
## 变化一句话
调用 MP 退款预览接口时,返回的 `refundRatio`(退款比例,如 `50` = 50%)之前**永远返回 0**;现在会按订单实际绑定的退款政策和出发日期返回正确的比例值。
---
## 相关接口
`POST /mp/refund/preview`(实际路径以 Swagger 为准)
入参结构不变,继续按之前传 `orderId` 即可。
返回 `RefundPreviewVO` 里的字段:
| 字段 | 之前 | 现在 |
|---|---|---|
| `refundRatio` | 恒 `0` | 按退款政策 + 距离出发天数查表得出的真实比例0~100|
| `refundAmount` | 基于 ratio=0 计算 → 恒 `0` | 按真实比例计算 |
| 其它字段 | 正常 | 不变 |
---
## 根因(一句话,前端可忽略)
MP 侧 Feign 只传了 `orderId`,后端 Service 期望同时传 `policyId/paidAmount/departureDate` 才能匹配策略;旧版直接拿 null 去查,匹配不到策略导致 ratio=0。本次后端按 `orderId` 反查订单主表自动补齐这些参数。
---
## 不影响范围
- 管理端退款预览(`/admin/refund/preview`)已经传齐参数,**零影响**
- 实际退款提交流程preview 之后的 `apply / approve`**零影响**
- 退款政策、订单金额、已付金额等字段**零影响**
---
## 建议前端验收一个点
之前因为 ratio 恒 0 导致"退款弹窗金额显示 0、用户不敢点"的场景,现在应回到正常金额。发布后请重点点一次"申请退款"弹窗确认数字正确。
---
## 相关
- PR[wx/HL#1313](https://git.1814.love:8443/wx/HL/pulls/1313)
- 部署:`hl-order-service-v2`8094