docs(changelog): 04-23 mp 批次标题/影响面显式标注「微信小程序」端(7 篇)

这个提交包含在:
yaosutu 2026-04-23 16:46:18 +08:00
父节点 bc43b65dc1
当前提交 a1467cbbea
共有 8 个文件被更改,包括 347 次插入19 次删除

查看文件

@ -1,8 +1,9 @@
# MP 合同接口 5 个:返回值从 Map 改为强类型 VO # 微信小程序 · 合同接口 5 个:返回值从 Map 改为强类型 VO
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1314 - **PR**: #1314
- **影响面**: 小程序端 · 合同列表 / 合同详情 / 订单关联合同(管理端不涉及) - **端**: 微信小程序(管理端不涉及)
- **影响面**: 合同列表 / 合同详情 / 订单关联合同
- **兼容性**: **字段契约规范化**。返回 Map 改为具名 VO,前端按本文列出的字段接入即可;Swagger 以 `MpContractVO` / `MpContractDetailVO` 为准 - **兼容性**: **字段契约规范化**。返回 Map 改为具名 VO,前端按本文列出的字段接入即可;Swagger 以 `MpContractVO` / `MpContractDetailVO` 为准
--- ---
@ -17,7 +18,7 @@
| 4 | 按订单查合同TOUR+INSURANCE 全部) | GET | `/mp/contract/by-order/{orderId}/all` | `List<MpContractVO>` | | 4 | 按订单查合同TOUR+INSURANCE 全部) | GET | `/mp/contract/by-order/{orderId}/all` | `List<MpContractVO>` |
| 5 | 重发签署短信 | POST | `/mp/contract/{contractId}/resend-sms` | `Result<Void>` | | 5 | 重发签署短信 | POST | `/mp/contract/{contractId}/resend-sms` | `Result<Void>` |
鉴权:小程序登录态 token,网关解析 `X-User-Id` 后透传 order-v2。 鉴权:微信小程序登录态 token,网关解析 `X-User-Id` 后透传 order-v2。
--- ---

查看文件

@ -1,8 +1,9 @@
# MP 小蒙马下单 · youngChildCount 不再被强制清零 # 微信小程序 · 小蒙马下单 youngChildCount 不再被强制清零
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1298 - **PR**: #1298
- **影响面**: 小程序端 · 小蒙马GROUP下单 / 订单详情 人群结构展示 - **端**: 微信小程序(管理端不涉及)
- **影响面**: 小蒙马GROUP下单 / 订单详情 人群结构展示
- **兼容性**: **接口契约零变化**。前端原来传的 `youngChildCount` 从"传了也没用"变成"被保留" - **兼容性**: **接口契约零变化**。前端原来传的 `youngChildCount` 从"传了也没用"变成"被保留"
--- ---

查看文件

@ -1,8 +1,9 @@
# MP 订单详情 · 尾款金额balanceAmount计算口径统一 # 微信小程序 · 订单详情尾款金额balanceAmount计算口径统一
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1306 - **PR**: #1306
- **影响面**: 小程序端 · 订单详情页尾款金额展示 + 下单流程 `paymentType` 回填 - **端**: 微信小程序(管理端同步生效)
- **影响面**: 订单详情页尾款金额展示 + 下单流程 `paymentType` 回填
- **兼容性**: **前端零改动**;已付款的订单 balanceAmount 语义更严谨、更广泛 - **兼容性**: **前端零改动**;已付款的订单 balanceAmount 语义更严谨、更广泛
--- ---

查看文件

@ -1,15 +1,16 @@
# MP 订单详情 · 新增 groupBatchId团期 ID # 微信小程序 · 订单详情新增 groupBatchId团期 ID
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1300 - **PR**: #1300
- **影响面**: 小程序端 · 订单详情(仅小蒙马 GROUP 订单有值) - **端**: 微信小程序(管理端不涉及)
- **影响面**: 订单详情(仅小蒙马 GROUP 订单有值)
- **兼容性**: **完全向后兼容**(纯新增字段,旧前端不读即可忽略) - **兼容性**: **完全向后兼容**(纯新增字段,旧前端不读即可忽略)
--- ---
## 变化一句话 ## 变化一句话
MP 订单详情返回体 `MpOrderDetailVO` 新增 `groupBatchId` 字段,仅小蒙马 GROUP 订单有值,前端可据此跳转到对应团期详情页。 微信小程序订单详情返回体 `MpOrderDetailVO` 新增 `groupBatchId` 字段,仅小蒙马 GROUP 订单有值,前端可据此跳转到对应团期详情页。
--- ---

查看文件

@ -1,15 +1,16 @@
# MP 订单详情 · 领队/摄影师头像 avatarUrl 之前为 null — 已修复 # 微信小程序 · 订单详情领队/摄影师头像 avatarUrl 之前为 null — 已修复
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1309 - **PR**: #1309
- **影响面**: 小程序端 · 订单详情「领队」「摄影师」弹窗 / 卡片的头像展示 - **端**: 微信小程序(管理端不涉及)
- **影响面**: 订单详情「领队」「摄影师」弹窗 / 卡片的头像展示
- **兼容性**: **字段结构零变化**,原本 null 的字段现在会填充有效 URL - **兼容性**: **字段结构零变化**,原本 null 的字段现在会填充有效 URL
--- ---
## 变化一句话 ## 变化一句话
MP 订单详情相关接口中的员工头像 `avatarUrl` 字段之前恒为 null,现在会返回有效的头像 OSS URL。 微信小程序订单详情相关接口中的员工头像 `avatarUrl` 字段之前恒为 null,现在会返回有效的头像 OSS URL。
--- ---

查看文件

@ -1,8 +1,9 @@
# MP 出发准备清单 · 「接送机」拆成「到达」+「离开」两项 + 按出行人覆盖三态 # 微信小程序 · 出发准备清单「接送机」拆成「到达」+「离开」两项 + 按出行人覆盖三态
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1289 - **PR**: #1289
- **影响面**: 小程序端 · 行前准备清单(出发倒计时聚合接口) - **端**: 微信小程序(管理端不涉及)
- **影响面**: 行前准备清单(出发倒计时聚合接口)
- **兼容性**: **需要前端同步调整**(清单项数量从 6 变 7,单项 key 新增,状态值新增 `WARNING` - **兼容性**: **需要前端同步调整**(清单项数量从 6 变 7,单项 key 新增,状态值新增 `WARNING`
--- ---

查看文件

@ -1,15 +1,16 @@
# MP 退款预览 refundRatio 之前永远为 0 — 已修复 # 微信小程序 · 退款预览 refundRatio 之前永远为 0 — 已修复
- **变更日期**: 2026-04-23 - **变更日期**: 2026-04-23
- **PR**: #1313 - **PR**: #1313
- **影响面**: 小程序端 · 订单退款预览弹窗 - **端**: 微信小程序(管理端不涉及)
- **影响面**: 订单退款预览弹窗
- **兼容性**: **纯 bug 修复**,接口/字段/调用方式零变化,前端无需改动 - **兼容性**: **纯 bug 修复**,接口/字段/调用方式零变化,前端无需改动
--- ---
## 变化一句话 ## 变化一句话
调用 MP 退款预览接口时,返回的 `refundRatio`(退款比例,如 `50` = 50%)之前**永远返回 0**;现在会按订单实际绑定的退款政策和出发日期返回正确的比例值。 调用微信小程序退款预览接口时,返回的 `refundRatio`(退款比例,如 `50` = 50%)之前**永远返回 0**;现在会按订单实际绑定的退款政策和出发日期返回正确的比例值。
--- ---
@ -31,7 +32,7 @@
## 根因(一句话,前端可忽略) ## 根因(一句话,前端可忽略)
MP 侧 Feign 只传了 `orderId`,后端 Service 期望同时传 `policyId/paidAmount/departureDate` 才能匹配策略;旧版直接拿 null 去查,匹配不到策略导致 ratio=0。本次后端按 `orderId` 反查订单主表自动补齐这些参数。 微信小程序侧 Feign 只传了 `orderId`,后端 Service 期望同时传 `policyId/paidAmount/departureDate` 才能匹配策略;旧版直接拿 null 去查,匹配不到策略导致 ratio=0。本次后端按 `orderId` 反查订单主表自动补齐这些参数。
--- ---

查看文件

@ -0,0 +1,321 @@
# mp-service: 保险/合同详情 5 个接口梳理 + 合同接口返回值强类型化
> **服务** hl-mp-service端口 8085→ 透传 hl-order-service-v2端口 8094
> **PR**: wx/HL#1314 · **Issue**: wx/HL#1312
> **日期**: 2026-04-23
> **影响范围**: C 端「订单详情页」保险详情弹窗、合同详情、保单 PDF 下载
---
## ⚠️ 关键变化
合同相关 3 个接口(`GET /mp/contract/list` / `GET /mp/contract/{id}` / `GET /mp/contract/by-order/{orderId}`)的返回值类型从后端弱类型 `Map<String, Object>` 改为具名 VO`MpContractVO` / `MpContractDetailVO`)。**JSON 结构与字段名均未改变**,Swagger 上能看到具名 schema 了,前端无需改动;本 changelog 重点是一次性把这 5 个接口契约梳理清楚。
---
## 一、接口清单
| # | 接口 | 方法 | 路径 | 返回类型 |
|---|------|------|------|----------|
| 1 | 订单详情聚合(含保险详情) | GET | `/mp/order/{orderId}/dashboard` | `MpOrderDashboardVO`(取 `.insurance` 字段) |
| 2 | 合同详情(按订单) | GET | `/mp/contract/by-order/{orderId}` | `MpContractVO` |
| 3 | 合同详情(按合同 ID | GET | `/mp/contract/{id}` | `MpContractDetailVO` |
| 4 | 订单保单合并 PDF | GET | `/mp/insurance/policy-pdf/{orderId}` | `Map<String,Object>`(透传 `PolicyShareVO` |
| 5 | 单张保单下载 | GET | `/mp/insurance/policy/{insuranceOrderId}/download` | `String`Base64 |
- 全部需要登录,`userId` 由 mp-service 从 token 中取出后透传给 order-v2
- 仅 5 号需要 `insuranceOrderId`,该 ID 来自订单详情出行人的 `insurancePolicies[].insuranceOrderId`
---
## 二、接口详情
### 1. 保险详情 `GET /mp/order/{orderId}/dashboard`
保险详情没有独立接口,走订单详情聚合 `MpOrderDashboardVO`,取 `.insurance` 字段(`MpInsuranceDetailVO`)。未投保或查询失败时该字段为 `null`(降级,不阻断页面)。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| `orderId` | Path | Long | ✅ | 订单 ID |
#### 出参 `Result<MpOrderDashboardVO>` — 聚合 VO 全字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `order` | `MpOrderDetailVO` | 订单主体(详见 2026-04-17 订单详情 changelog |
| `preTripChecklist` | `MpPreTripChecklistVO` | 出发准备清单(降级时 null |
| `files.contract` | `MpContractSummaryVO` | 合同摘要(无合同 null |
| `files.invoice` | `MpInvoiceSummaryVO` | 发票摘要(未开票 null |
| `files.insurancePolicyPdfUrl` | `String` | 保单合并 PDF 下载路径,固定为 `/mp/insurance/policy-pdf/{orderId}` |
| `insurance` | `MpInsuranceDetailVO` | **保险详情(本 changelog 重点字段)** |
| `refund` | `RefundVO` | 退款模块(仅取消/退款中状态有值) |
#### `insurance``MpInsuranceDetailVO`)字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `schemeId` | Long | 方案 ID |
| `schemeName` | String | 方案名称 |
| `description` | String | 方案描述 |
| `isOverseas` | Boolean | 是否境外 |
| `totalDays` | Integer | 适用行程天数 |
| `notice` | String | 保险告知状态:`INCLUDED` / `OPTIONAL` / `EXCLUDED` |
| `segments` | `List<CoverageSegment>` | 保障分段列表 |
| `segments[].segmentName` | String | 分段名称 |
| `segments[].dayOffsetStart` | Integer | 起始天 |
| `segments[].dayOffsetEnd` | Integer | 结束天(`-1` = 最后一天) |
| `segments[].productName` | String | 保险产品名称 |
| `segments[].planName` | String | 保险计划名称 |
| `policies` | `List<PolicyItem>` | 投保记录列表(未投保为空数组) |
| `policies[].insuranceOrderId` | Long | 保险订单 ID用于接口 5 下载) |
| `policies[].policyNo` | String | 保单号 |
| `policies[].productName` | String | 保险产品名称 |
| `policies[].planName` | String | 计划名称 |
| `policies[].premium` | BigDecimal | 保费(元) |
| `policies[].insuredCount` | Integer | 被保人数 |
| `policies[].coverageStartDate` | LocalDate | 保障开始日期 |
| `policies[].coverageEndDate` | LocalDate | 保障结束日期 |
| `policies[].status` | String | 保险状态:`PENDING` / `INSURING` / `INSURED` / `FAILED``CANCELLED` 已过滤不返回) |
| `policies[].statusLabel` | String | 状态中文标签 |
| `policies[].insuredPersons` | `List<InsuredPerson>` | 被保人列表 |
| `insuredPersons[].name` | String | 姓名(明文,脱敏由前端处理) |
| `insuredPersons[].idCardType` | String | 证件类型:`ID_CARD` / `PASSPORT` |
| `insuredPersons[].idCardNo` | String | 证件号码(明文) |
| `insuredPersons[].birthday` | LocalDate | 出生日期 |
| `insuredPersons[].gender` | String | `MALE` / `FEMALE` |
| `insuredPersons[].phone` | String | 手机号(明文) |
---
### 2. 合同详情(按订单) `GET /mp/contract/by-order/{orderId}`
返回订单关联的**最新**有效合同(非作废),一般用于订单详情页的"合同"入口。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| `orderId` | Path | Long | ✅ | 订单 ID |
#### 出参 `Result<MpContractVO>`
| 字段 | 类型 | 说明 |
|------|------|------|
| `contractId` | Long | 合同 ID |
| `orderId` | Long | 订单 ID |
| `templateCode` | String | 模板编码 |
| `templateName` | String | 模板名称 |
| `contractNumber` | String | 合同编号 |
| `platform` | String | 签约平台 |
| `contractType` | String | 字典 `contract_type``TOUR` / `INSURANCE` |
| `contractTypeLabel` | String | 合同类型标签 |
| `mode` | String | 字典 `contract_mode``ONLINE` / `OFFLINE` |
| `modeLabel` | String | 签约模式标签 |
| `status` | String | 字典 `contract_status` |
| `statusLabel` | String | 合同状态标签 |
| `signUrl` | String | 签署 URL |
| `qrCodeUrl` | String | 签署二维码 URL |
| `fileUrl` | String | 合同文件 URL |
| `agencyCode` | String | 旅行社编号 |
| `travelAgencyName` | String | 旅行社名称 |
| `destination` | String | 目的地 |
| `departureDate` | LocalDate | 出发日期 |
| `returnDate` | LocalDate | 返回日期 |
| `totalAmount` | BigDecimal | 合同总金额 |
| `touristCount` | Integer | 出行人数 |
| `contactName` | String | 联系人姓名(明文,脱敏由前端处理) |
| `contactPhone` | String | 联系人电话(明文,脱敏由前端处理) |
| `createTime` | LocalDateTime | 创建时间 |
无合同时 `data``null`
---
### 3. 合同详情(按合同 ID `GET /mp/contract/{id}`
按合同 ID 查完整详情,返回合同基本信息 + 出行人签署详情 + 状态变更日志。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| `id` | Path | Long | ✅ | 合同 ID |
#### 出参 `Result<MpContractDetailVO>`
`MpContractDetailVO` 继承 `MpContractVO`(字段见接口 2,额外字段
| 字段 | 类型 | 说明 |
|------|------|------|
| `supplementaryClause` | String | 补充约定内容 |
| `travelers` | `List<TravelerInfo>` | 出行人列表 |
| `travelers[].travelerId` | Long | 出行人 ID |
| `travelers[].name` | String | 姓名(明文) |
| `travelers[].idCardType` | String | `ID_CARD` / `PASSPORT` |
| `travelers[].idCardNo` | String | 证件号码(明文) |
| `travelers[].phone` | String | 手机号(明文) |
| `travelers[].isSigner` | Boolean | 是否签署人 |
| `statusLogs` | `List<MpContractStatusLogVO>` | 状态变更日志 |
| `statusLogs[].logId` | Long | 日志 ID |
| `statusLogs[].contractId` | Long | 合同 ID |
| `statusLogs[].oldStatus` | String | 旧状态 |
| `statusLogs[].newStatus` | String | 新状态 |
| `statusLogs[].source` | String | 变更来源:`CALLBACK` / `POLLING` / `MANUAL` |
| `statusLogs[].rawPayload` | String | 原始载荷(仅调试用) |
| `statusLogs[].createTime` | LocalDateTime | 创建时间 |
权限:合同 `userId` 必须与登录用户一致,否则 403。
---
### 4. 订单保单合并 PDF `GET /mp/insurance/policy-pdf/{orderId}`
合并订单下所有出行人的有效保单为一个 PDF,返回 Base64。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| `orderId` | Path | Long | ✅ | 订单 ID |
#### 出参 `Result<Map<String,Object>>`BFF 当前透传 order-v2 `PolicyShareVO`
| 字段 | 类型 | 说明 |
|------|------|------|
| `pdfBase64` | String | 合并后的保单 PDFBase64 编码) |
| `personName` | String | 出行人姓名(订单范围分享时一般为空/null |
| `policyCount` | Integer | 成功合并的保单数量 |
| `failedCount` | Integer | 下载失败的保单数量 |
---
### 5. 单张保单下载 `GET /mp/insurance/policy/{insuranceOrderId}/download`
下载指定保险订单的单张保单 PDF,返回 Base64 字符串。`insuranceOrderId` 从接口 1 的 `insurance.policies[].insuranceOrderId` 取。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| `insuranceOrderId` | Path | Long | ✅ | 保险订单 ID非订单 ID |
#### 出参 `Result<String>`
| 字段 | 类型 | 说明 |
|------|------|------|
| `data` | String | 保单 PDFBase64 编码) |
---
## 三、响应示例
### 接口 2 `GET /mp/contract/by-order/{orderId}`
```json
{
"code": 200,
"message": "成功",
"data": {
"contractId": 9001,
"orderId": 20439,
"templateCode": "TOUR_STANDARD",
"templateName": "旅游服务合同(标准版)",
"contractNumber": "HL-2026-0423-0001",
"platform": "fadada",
"contractType": "TOUR",
"contractTypeLabel": "旅游合同",
"mode": "ONLINE",
"modeLabel": "线上签署",
"status": "SIGNED",
"statusLabel": "已签署",
"signUrl": "https://sign.fadada.com/xxx",
"qrCodeUrl": "https://cdn.1814.love/qr-9001.png",
"fileUrl": "https://cdn.1814.love/contract-9001.pdf",
"agencyCode": "HULAL001",
"travelAgencyName": "呼籁旅行",
"destination": "呼伦贝尔",
"departureDate": "2026-07-01",
"returnDate": "2026-07-07",
"totalAmount": "12600.00",
"touristCount": 4,
"contactName": "张三",
"contactPhone": "13800138000",
"createTime": "2026-04-20 10:30:00"
},
"success": true
}
```
### 接口 4 `GET /mp/insurance/policy-pdf/{orderId}`
```json
{
"code": 200,
"message": "成功",
"data": {
"pdfBase64": "JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeX...(截断)",
"personName": null,
"policyCount": 4,
"failedCount": 0
},
"success": true
}
```
---
## 四、边界行为
- 未登录 → 401网关拦截
- 订单/合同不属于当前 `userId` → 403
- 订单无合同(接口 2`data: null`
- 订单未投保(接口 1 的 `insurance` 字段)→ `insurance: null`,不阻断页面
- 保单 PDF 下载失败(接口 4`failedCount > 0``pdfBase64` 仍返回已合并部分;下游整体失败时 BFF 返 `500`
- 合同服务整体不可用(接口 2/3→ BFF 返 `500 合同服务不可用,请稍后重试`
---
## 五、不影响范围
- **仅影响**C 端订单详情页的保险详情弹窗 / 合同详情 / 保单 PDF 下载入口
- **零影响**
- 下单、支付、退款、发票所有接口
- 合同列表 `GET /mp/contract/list`(未列出,字段同接口 2 `MpContractVO`
- 管理后台合同/保险所有接口(不走 `/mp/` 前缀)
- JSON 字段名与取值逻辑(本次仅后端 VO 强类型化)
---
## 六、相关历史 PR
| PR | Issue | 说明 | 是否仍有效 |
|----|-------|------|------------|
| wx/HL#1314 | wx/HL#1312 | 合同接口返回值从 Map 改为强类型 VO本 PR | ✅ 最新 |
| 2026-04-17 `mp-order-detail-refactor` | - | 订单详情聚合 VO `MpOrderDashboardVO` | ✅ 有效 |
---
## 七、代码位置
- Controller
- `hl-mp-service` · `com.hulalv.mp.controller.MpOrderController#getOrderDashboard`
- `hl-mp-service` · `com.hulalv.mp.controller.MpContractController`
- `hl-mp-service` · `com.hulalv.mp.controller.MpInsuranceController`
- VO
- `hl-mp-service` · `com.hulalv.mp.vo.MpOrderDashboardVO`
- `hl-mp-service` · `com.hulalv.mp.vo.MpInsuranceDetailVO`
- `hl-mp-service` · `com.hulalv.mp.vo.MpContractVO` / `MpContractDetailVO` / `MpContractStatusLogVO`
- 下游
- `hl-order-service-v2` · `com.hulalv.contract.controller.internal.InternalMpContractController`
- `hl-order-service-v2` · `com.hulalv.insurance.controller.internal.InternalInsuranceController`
- `hl-order-service-v2` · `com.hulalv.insurance.vo.PolicyShareVO`
---
## 八、相关文档
- 关联 Issue: [wx/HL#1312](https://git.1814.love:8443/wx/HL/issues/1312)
- 关联 PR: [wx/HL#1314](https://git.1814.love:8443/wx/HL/pulls/1314)
- 订单详情聚合 VO 参考: `changelogs/2026-04/2026-04-17_order-v2_mp-order-detail-refactor.md`