docs(mp-order): 服务详情弹窗 + MpOrderDetailVO 强类型化 changelog
这个提交包含在:
父节点
5260886383
当前提交
a34bbf3efb
@ -0,0 +1,574 @@
|
|||||||
|
# 小程序订单 - 服务详情弹窗接口 + MpOrderDetailVO 字段强类型化
|
||||||
|
|
||||||
|
- **日期**: 2026-04-18
|
||||||
|
- **PR**:
|
||||||
|
- [#818](https://git.1814.love:8443/wx/HL/pulls/818) MpOrderDetailVO 6 字段强类型化
|
||||||
|
- [#853](https://git.1814.love:8443/wx/HL/pulls/853) 补 6 个服务详情透传
|
||||||
|
- [#856](https://git.1814.love:8443/wx/HL/pulls/856) 独立 Controller + Swagger 分组
|
||||||
|
- **类型**: FEATURE + REFACTOR
|
||||||
|
- **状态**: 已合并到 dev + 测试环境部署中
|
||||||
|
- **服务**: hl-mp-service + hl-order-service-v2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 一、本次变更汇总
|
||||||
|
|
||||||
|
### 1. 订单详情 VO 字段强类型化(🔵 前端体验提升,无 Breaking)
|
||||||
|
|
||||||
|
`MpOrderDetailVO`(下单 / 详情 / 编辑 三接口共用返回结构)中的 6 个字段,**字段名完全不变**,仅 JSON Schema 由 `Map<String, Object>` / `List<Map<String, Object>>` 升级为**强类型 VO**。前端 TS 类型提示/自动补全可直接受益。
|
||||||
|
|
||||||
|
| 字段 | 旧类型 | 新类型 |
|
||||||
|
|------|--------|--------|
|
||||||
|
| `priceBreakdown` | `object` (Map) | `MpPriceBreakdownVO` |
|
||||||
|
| `serviceItems` | `object[]` (List<Map>) | `MpServiceItemVO[]` |
|
||||||
|
| `tripProgress` | `object` (Map) | `MpTripProgressVO` |
|
||||||
|
| `refundProgress` | `object` (Map) | `MpRefundProgressVO` |
|
||||||
|
| `travelers` | `object[]` | `MpTravelerVO[]` |
|
||||||
|
| `todos` | `object[]` | `MpOrderTodoVO[]` |
|
||||||
|
|
||||||
|
### 2. 新增 6 个服务详情弹窗接口(🟢 新功能)
|
||||||
|
|
||||||
|
订单详情页 `serviceItems` 列表里每个条目点击后的弹窗数据源,此前前端调不到,现已对外开放。
|
||||||
|
|
||||||
|
独立 **Swagger 分组**:`C端 - 订单接口 - 服务包含`(knife4j 左侧菜单)。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 二、变更接口清单
|
||||||
|
|
||||||
|
| # | 方法 | 路径 | 说明 | 鉴权 | 缓存 |
|
||||||
|
|---|------|------|------|------|------|
|
||||||
|
| 1 | POST | `/mp/order/create` | 创建订单(返回结构升级) | REQUIRED | 否 |
|
||||||
|
| 2 | GET | `/mp/order/{orderId}` | 订单详情(返回结构升级) | REQUIRED | 否 |
|
||||||
|
| 3 | PUT | `/mp/order/{orderId}/edit` | 用户编辑订单(返回结构升级) | REQUIRED | 否 |
|
||||||
|
| 4 | GET | `/mp/order/{orderId}/tickets` | 【新增】门票清单 | REQUIRED | 否 |
|
||||||
|
| 5 | GET | `/mp/order/{orderId}/hotels` | 【新增】住宿清单 | REQUIRED | 否 |
|
||||||
|
| 6 | GET | `/mp/order/{orderId}/meals` | 【新增】餐饮清单 | REQUIRED | 否 |
|
||||||
|
| 7 | GET | `/mp/order/{orderId}/vehicle` | 【新增】用车详情 | REQUIRED | 否 |
|
||||||
|
| 8 | GET | `/mp/order/{orderId}/guide` | 【新增】领队详情 | REQUIRED | 否 |
|
||||||
|
| 9 | GET | `/mp/order/{orderId}/photographer` | 【新增】摄影师详情 | REQUIRED | 否 |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 三、订单创建接口(返回结构升级)
|
||||||
|
|
||||||
|
```
|
||||||
|
POST /mp/order/create
|
||||||
|
```
|
||||||
|
|
||||||
|
### 请求(未变化)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"productId": "1760000000000001",
|
||||||
|
"departureDate": "2026-05-01",
|
||||||
|
"groupBatchId": "1760000000000002",
|
||||||
|
"tierSeq": 1,
|
||||||
|
"adultCount": 2,
|
||||||
|
"childCount": 0,
|
||||||
|
"youngChildCount": 0,
|
||||||
|
"babyCount": 0,
|
||||||
|
"childNeedBed": false,
|
||||||
|
"roomCount": 1,
|
||||||
|
"contactName": "张三",
|
||||||
|
"contactPhone": "13800138000",
|
||||||
|
"remark": "希望安排靠窗",
|
||||||
|
"sharerOpenid": "wx_xxxxx"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 必填 | 说明 |
|
||||||
|
|------|------|------|------|
|
||||||
|
| `productId` | String | 是 | 产品ID |
|
||||||
|
| `departureDate` | String(yyyy-MM-dd) | 否 | 出发日期;GROUP 产品可不传(从团期取) |
|
||||||
|
| `groupBatchId` | String | 条件必填 | GROUP 产品必填 |
|
||||||
|
| `tierSeq` | Integer | 是 | 档位序号,≥1 |
|
||||||
|
| `adultCount` | Integer | 是 | 成人数,默认 1,≥1 |
|
||||||
|
| `childCount` | Integer | 否 | 儿童数,≥0 |
|
||||||
|
| `youngChildCount` | Integer | 否 | 小童数,≥0 |
|
||||||
|
| `babyCount` | Integer | 否 | 幼童数,≥0 |
|
||||||
|
| `childNeedBed` | Boolean | 否 | 儿童是否需要床位 |
|
||||||
|
| `roomCount` | Integer | 否 | 房间数(GROUP 默认 1) |
|
||||||
|
| `contactName` | String | 是 | 联系人姓名,≤50 字 |
|
||||||
|
| `contactPhone` | String | 是 | 联系人电话,≤20 字 |
|
||||||
|
| `remark` | String | 否 | 备注,≤500 字 |
|
||||||
|
| `sharerOpenid` | String | 否 | 分享人 openid,≤64 字 |
|
||||||
|
|
||||||
|
### 返回(结构升级)
|
||||||
|
|
||||||
|
> **⚠️ 关键**:`POST /mp/order/create`、`GET /mp/order/{id}`、`PUT /mp/order/{id}/edit` 三个接口返回结构**完全一致**,均为 `MpOrderDetailVO`。前端可共用一套类型定义 + 渲染组件。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"message": "成功",
|
||||||
|
"data": {
|
||||||
|
"orderId": "2045450312813043713",
|
||||||
|
"orderNo": "HL20260418183211-6560",
|
||||||
|
"groupCode": "6560",
|
||||||
|
"productId": "2045424500610125825",
|
||||||
|
"productName": "E2E-核心版本-V1",
|
||||||
|
"productSubtitle": "去草原看日出",
|
||||||
|
"productCoverUrl": "https://cdn.example.com/cover.jpg",
|
||||||
|
"productType": "CORE",
|
||||||
|
"productTypeLabel": "核心产品",
|
||||||
|
"departureDate": "2026-05-10",
|
||||||
|
"returnDate": "2026-05-12",
|
||||||
|
"tripDays": 3,
|
||||||
|
"tripNights": 2,
|
||||||
|
"adultCount": 1,
|
||||||
|
"childCount": 0,
|
||||||
|
"youngChildCount": 0,
|
||||||
|
"babyCount": 0,
|
||||||
|
"createTime": "2026-04-18 18:32:12",
|
||||||
|
|
||||||
|
"status": "PENDING_PAY",
|
||||||
|
"statusLabel": "待支付",
|
||||||
|
"displayStatus": "PENDING_PAY",
|
||||||
|
"displayStatusLabel": "待支付",
|
||||||
|
"expiryTime": "2026-04-18 20:32:12",
|
||||||
|
|
||||||
|
"totalPrice": 2401280.00,
|
||||||
|
"paidAmount": 0.00,
|
||||||
|
"depositAmount": 500.00,
|
||||||
|
"balanceAmount": 2400780.00,
|
||||||
|
"paymentType": "DEPOSIT",
|
||||||
|
"paymentTypeLabel": "订金+尾款",
|
||||||
|
"payMethodLabel": "微信支付",
|
||||||
|
"balancePayMethodLabel": "落地后由领队收取",
|
||||||
|
|
||||||
|
"priceBreakdown": {
|
||||||
|
"items": [
|
||||||
|
{ "label": "成人", "unitPrice": 2300.00, "quantity": 1, "amount": 2300.00 }
|
||||||
|
],
|
||||||
|
"subtotal": 2300.00,
|
||||||
|
"discounts": [],
|
||||||
|
"totalDiscount": 0.00,
|
||||||
|
"totalPayable": 2300.00
|
||||||
|
},
|
||||||
|
|
||||||
|
"serviceItems": [
|
||||||
|
{ "type": "HOTEL", "title": "住宿", "summary": "2 晚精选当地酒店", "clickable": true },
|
||||||
|
{ "type": "MEAL", "title": "餐饮", "summary": "含早餐 2 次 + 特色正餐 1 次", "clickable": true },
|
||||||
|
{ "type": "VEHICLE", "title": "用车", "summary": "小蒙马车 1 辆", "clickable": true }
|
||||||
|
],
|
||||||
|
"notIncluded": "往返呼伦贝尔大交通、个人消费",
|
||||||
|
|
||||||
|
"tripProgress": null,
|
||||||
|
"refundProgress": null,
|
||||||
|
"travelers": [],
|
||||||
|
"todos": [],
|
||||||
|
|
||||||
|
"contractStatus": "NONE",
|
||||||
|
"contractStatusLabel": "无合同",
|
||||||
|
"insuranceStatus": "NONE",
|
||||||
|
"insuranceStatusLabel": "无保险",
|
||||||
|
"invoiceStatus": "AFTER_TRIP",
|
||||||
|
"invoiceStatusLabel": "出行后开",
|
||||||
|
"reviewed": false,
|
||||||
|
|
||||||
|
"customizerId": "1001",
|
||||||
|
"customizerName": "admin",
|
||||||
|
"customizerAvatarUrl": null,
|
||||||
|
"customizerQrUrl": null,
|
||||||
|
|
||||||
|
"refundPolicy": {
|
||||||
|
"policyId": 1,
|
||||||
|
"policyName": "标准退款",
|
||||||
|
"rules": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### `MpOrderDetailVO` 重点字段类型说明
|
||||||
|
|
||||||
|
#### priceBreakdown - 价格明细
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MpPriceBreakdownVO {
|
||||||
|
items: MpPriceLineItemVO[]; // 按人群类型的单价明细
|
||||||
|
subtotal: number; // 小计(优惠前)
|
||||||
|
discounts: MpDiscountLineItemVO[];// 优惠明细列表
|
||||||
|
totalDiscount: number; // 已优惠总额(负数)
|
||||||
|
totalPayable: number; // 应付总额
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MpPriceLineItemVO {
|
||||||
|
label: string; // "成人" / "儿童" 等
|
||||||
|
unitPrice: number;
|
||||||
|
quantity: number;
|
||||||
|
amount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MpDiscountLineItemVO {
|
||||||
|
tag: string; // "早鸟"
|
||||||
|
description: string; // "提前30天"
|
||||||
|
amount: number; // 负数
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### serviceItems - 服务包含摘要
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MpServiceItemVO {
|
||||||
|
type: 'HOTEL' | 'MEAL' | 'VEHICLE' | 'GUIDE' | 'PHOTOGRAPHER' | 'TICKET' | 'INSURANCE';
|
||||||
|
title: string; // "住宿"
|
||||||
|
summary: string; // "2 晚精选当地酒店"
|
||||||
|
clickable: boolean; // 是否可点击查看详情弹窗(对应下面 6 个弹窗接口)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> 当 `clickable === true` 时,点击该条目调用对应的 `/mp/order/{orderId}/{tickets|hotels|meals|vehicle|guide|photographer}` 接口拉取弹窗详情。映射关系:
|
||||||
|
> - HOTEL → `/hotels`
|
||||||
|
> - MEAL → `/meals`
|
||||||
|
> - VEHICLE → `/vehicle`
|
||||||
|
> - GUIDE → `/guide`
|
||||||
|
> - PHOTOGRAPHER → `/photographer`
|
||||||
|
> - TICKET → `/tickets`
|
||||||
|
|
||||||
|
#### tripProgress - 行程进度
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MpTripProgressVO {
|
||||||
|
currentDay: number; // 当前第几天
|
||||||
|
totalDays: number; // 总天数
|
||||||
|
progressPercent: number; // 进度百分比(0-100)
|
||||||
|
todayDestination: string; // 今日目的地
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> **仅行程中状态有值**,其他状态该字段为 `null`(且因 `@JsonInclude(NON_NULL)` 过滤,可能不在 JSON 中出现)。
|
||||||
|
|
||||||
|
#### refundProgress - 退款进度
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MpRefundProgressVO {
|
||||||
|
steps: MpRefundStepVO[]; // 4 步时间线
|
||||||
|
currentStep: number; // 当前活跃步骤索引(0-based)
|
||||||
|
refundAmount: number;
|
||||||
|
refundMethod: string; // 例 "原路返回·微信"
|
||||||
|
refundArrivalTime: string | null; // 已到账才有值
|
||||||
|
}
|
||||||
|
|
||||||
|
interface MpRefundStepVO {
|
||||||
|
title: string; // "提交申请"
|
||||||
|
description: string;
|
||||||
|
status: 'COMPLETED' | 'ACTIVE' | 'PENDING';
|
||||||
|
time: string | null; // PENDING 时为 null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### travelers - 出行人列表
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MpTravelerVO {
|
||||||
|
travelerId: number;
|
||||||
|
name: string;
|
||||||
|
travelerType: string; // ADULT/CHILD/YOUNG_CHILD/BABY
|
||||||
|
travelerTypeLabel: string; // "成人" 等中文
|
||||||
|
idCardType: string; // ID_CARD/PASSPORT
|
||||||
|
idCardTypeLabel: string; // "身份证" 等中文
|
||||||
|
idCardNo: string;
|
||||||
|
gender: string;
|
||||||
|
birthday: string;
|
||||||
|
phone: string;
|
||||||
|
nationality: string;
|
||||||
|
emergencyContact: string;
|
||||||
|
emergencyPhone: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### todos - 待办列表
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface MpOrderTodoVO {
|
||||||
|
todoId: number;
|
||||||
|
todoType: string;
|
||||||
|
todoTypeLabel: string;
|
||||||
|
todoLabel: string;
|
||||||
|
sequence: number;
|
||||||
|
status: string;
|
||||||
|
assigneeRoleKey: string;
|
||||||
|
assigneeRoleLabel: string;
|
||||||
|
completedAt: string | null;
|
||||||
|
createTime: string;
|
||||||
|
blocked: boolean;
|
||||||
|
blockedReason: string | null;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 四、服务详情弹窗接口(6 个新增)
|
||||||
|
|
||||||
|
所有接口签名一致:
|
||||||
|
- **方法**: GET
|
||||||
|
- **鉴权**: `Authorization: Bearer {mp-token}`(用户登录态)
|
||||||
|
- **Path Var**: `orderId` (Long)
|
||||||
|
- **Query**: 无
|
||||||
|
- **失败降级**: 订单服务不可用时返回 `{"code":500, "message":"订单服务不可用,请稍后重试"}`
|
||||||
|
|
||||||
|
### 1. 门票清单
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /mp/order/{orderId}/tickets
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"seq": 1,
|
||||||
|
"scenicName": "莫日格勒河",
|
||||||
|
"coverUrl": "https://cdn.example.com/scenic/1.jpg",
|
||||||
|
"dayNumber": 2,
|
||||||
|
"originalPrice": 80.00,
|
||||||
|
"included": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"scenicCount": 14,
|
||||||
|
"totalValue": 340.00
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `items[]` | MpTicketItemVO[] | 门票列表 |
|
||||||
|
| `items[].seq` | Integer | 序号 |
|
||||||
|
| `items[].scenicName` | String | 景点名称 |
|
||||||
|
| `items[].coverUrl` | String | 景点封面图 |
|
||||||
|
| `items[].dayNumber` | Integer | 第几天 |
|
||||||
|
| `items[].originalPrice` | BigDecimal | 门票原价/人 |
|
||||||
|
| `items[].included` | Boolean | 是否已包含在套餐内 |
|
||||||
|
| `scenicCount` | Integer | 景点数量 |
|
||||||
|
| `totalValue` | BigDecimal | 门票总价值/人(快照有 price 才有值) |
|
||||||
|
|
||||||
|
### 2. 住宿清单
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /mp/order/{orderId}/hotels
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"hotelId": "2023714929877450753",
|
||||||
|
"hotelName": "呼伦贝尔香格里拉大酒店",
|
||||||
|
"coverUrl": "https://cdn.example.com/hotel/1.jpg",
|
||||||
|
"assignmentDate": "2026-05-10",
|
||||||
|
"roomType": "大床房"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nightCount": 2,
|
||||||
|
"roomTypeStats": [
|
||||||
|
{ "roomType": "大床房", "count": 1 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `items[]` | MpHotelItemVO[] | 每晚酒店列表(按入住日期升序) |
|
||||||
|
| `items[].hotelId` | Long | 酒店ID |
|
||||||
|
| `items[].hotelName` | String | 酒店名称 |
|
||||||
|
| `items[].coverUrl` | String | 酒店封面(产品服务扩展后可用) |
|
||||||
|
| `items[].assignmentDate` | String(yyyy-MM-dd) | 入住日期 |
|
||||||
|
| `items[].roomType` | String | 房型 |
|
||||||
|
| `nightCount` | Integer | 总晚数 |
|
||||||
|
| `roomTypeStats[]` | MpRoomTypeStatVO[] | 按房型统计 |
|
||||||
|
| `roomTypeStats[].roomType` | String | 房型 |
|
||||||
|
| `roomTypeStats[].count` | Integer | 房间数 |
|
||||||
|
|
||||||
|
### 3. 餐饮清单
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /mp/order/{orderId}/meals
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"specialMeals": [
|
||||||
|
{
|
||||||
|
"dayNumber": 2,
|
||||||
|
"mealName": "蒙古包午餐·手把肉宴",
|
||||||
|
"mealType": "午餐",
|
||||||
|
"description": "含奶茶/手把肉/烤包子"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stats": {
|
||||||
|
"breakfastCount": 2,
|
||||||
|
"specialDinnerCount": 1,
|
||||||
|
"regularDinnerCount": 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `specialMeals[]` | MpMealItemVO[] | 特色正餐列表(含描述的餐) |
|
||||||
|
| `specialMeals[].dayNumber` | Integer | 第几天 |
|
||||||
|
| `specialMeals[].mealName` | String | 餐名 |
|
||||||
|
| `specialMeals[].mealType` | String | 餐型:早餐/午餐/晚餐 |
|
||||||
|
| `specialMeals[].description` | String | 菜品描述 |
|
||||||
|
| `stats.breakfastCount` | Integer | 早餐数量 |
|
||||||
|
| `stats.specialDinnerCount` | Integer | 特色正餐数量(有描述的) |
|
||||||
|
| `stats.regularDinnerCount` | Integer | 日常正餐数量 |
|
||||||
|
|
||||||
|
### 4. 用车详情
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /mp/order/{orderId}/vehicle
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"vehicleType": "小蒙马车",
|
||||||
|
"vehicleCount": 1,
|
||||||
|
"coverUrl": "https://cdn.example.com/vehicle/xiaomma.jpg",
|
||||||
|
"plateNumber": "蒙E12345",
|
||||||
|
"driverName": "张师傅",
|
||||||
|
"driverPhone": "138****5678",
|
||||||
|
"matched": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `vehicleType` | String | 车型名称 |
|
||||||
|
| `vehicleCount` | Integer | 车辆数 |
|
||||||
|
| `coverUrl` | String | 车型封面(产品服务扩展后可用) |
|
||||||
|
| `plateNumber` | String | 车牌号(**仅出行前后可见**,其他时间为空) |
|
||||||
|
| `driverName` | String | 司机姓名 |
|
||||||
|
| `driverPhone` | String | 司机电话(脱敏) |
|
||||||
|
| `matched` | Boolean | 是否已匹配车辆 |
|
||||||
|
|
||||||
|
### 5. 领队详情
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /mp/order/{orderId}/guide
|
||||||
|
```
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"data": {
|
||||||
|
"staffId": "5001",
|
||||||
|
"name": "巴特尔",
|
||||||
|
"avatarUrl": "https://cdn.example.com/avatar/5001.jpg",
|
||||||
|
"role": "LEADER",
|
||||||
|
"roleLabel": "领队",
|
||||||
|
"phone": "138****5678",
|
||||||
|
"remark": "10 年草原线路经验,会蒙语",
|
||||||
|
"assigned": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
| 字段 | 类型 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `staffId` | Long | 员工ID |
|
||||||
|
| `name` | String | 姓名 |
|
||||||
|
| `avatarUrl` | String | 头像(员工档案扩展后可用) |
|
||||||
|
| `role` | String | 角色代码 |
|
||||||
|
| `roleLabel` | String | 角色中文 |
|
||||||
|
| `phone` | String | 电话(脱敏) |
|
||||||
|
| `remark` | String | 备注/简介 |
|
||||||
|
| `assigned` | Boolean | 是否已分配 |
|
||||||
|
|
||||||
|
### 6. 摄影师详情
|
||||||
|
|
||||||
|
```
|
||||||
|
GET /mp/order/{orderId}/photographer
|
||||||
|
```
|
||||||
|
|
||||||
|
响应字段与领队详情完全一致,`role` 为 `"PHOTOGRAPHER"`、`roleLabel` 为 `"摄影师"`。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 五、前端接入建议
|
||||||
|
|
||||||
|
### Swagger 入口
|
||||||
|
|
||||||
|
- **mp-service 独立**: http://localhost:8085/doc.html (本地开发)
|
||||||
|
- **网关聚合**: http://localhost:8080/doc.html → 切到 `hl-mp-service`
|
||||||
|
- **测试环境**: https://api.test.1814.love/doc.html → 切到 `hl-mp-service`
|
||||||
|
|
||||||
|
左侧菜单新增分组:**「C端 - 订单接口 - 服务包含」**,6 个弹窗接口在该分组下。
|
||||||
|
|
||||||
|
### 订单详情页渲染建议
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function openOrderDetail(orderId) {
|
||||||
|
const detail = await request.get(`/mp/order/${orderId}`);
|
||||||
|
|
||||||
|
// 1. 渲染基础信息(orderNo/产品/金额/状态/时间轴)
|
||||||
|
renderHeader(detail.data);
|
||||||
|
|
||||||
|
// 2. 价格明细 - 用 priceBreakdown.items / discounts 渲染
|
||||||
|
renderPriceBreakdown(detail.data.priceBreakdown);
|
||||||
|
|
||||||
|
// 3. 服务包含列表
|
||||||
|
detail.data.serviceItems.forEach(item => {
|
||||||
|
renderServiceCard(item, {
|
||||||
|
onClick: item.clickable ? () => openServiceDetail(orderId, item.type) : null
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 类型到接口路径的映射
|
||||||
|
const SERVICE_DETAIL_API = {
|
||||||
|
HOTEL: 'hotels', MEAL: 'meals', VEHICLE: 'vehicle',
|
||||||
|
GUIDE: 'guide', PHOTOGRAPHER: 'photographer', TICKET: 'tickets'
|
||||||
|
};
|
||||||
|
|
||||||
|
async function openServiceDetail(orderId, type) {
|
||||||
|
const path = SERVICE_DETAIL_API[type];
|
||||||
|
if (!path) return; // 非 clickable 类型(如 INSURANCE)
|
||||||
|
const data = await request.get(`/mp/order/${orderId}/${path}`);
|
||||||
|
showServiceDialog(type, data.data);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 六、回归验证
|
||||||
|
|
||||||
|
测试环境部署完成后,用 mp token 依次调用:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 拿个已绑定的订单详情,确认 6 个强类型字段结构
|
||||||
|
curl "https://api.test.1814.love/mp/order/{orderId}" \
|
||||||
|
-H "Authorization: Bearer {mp-token}"
|
||||||
|
|
||||||
|
# 2. 6 个弹窗接口(对应 serviceItems 里 clickable=true 的条目)
|
||||||
|
for path in tickets hotels meals vehicle guide photographer; do
|
||||||
|
curl "https://api.test.1814.love/mp/order/{orderId}/$path" \
|
||||||
|
-H "Authorization: Bearer {mp-token}"
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
**预期**:
|
||||||
|
- 订单详情返回的 `priceBreakdown` 是对象而非无结构 Map,`serviceItems` 是结构化数组
|
||||||
|
- 6 个弹窗接口均返回 `code=200` + 对应 VO 结构,不再出现 403 或路径不存在
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、不兼容变更
|
||||||
|
|
||||||
|
**无**。字段名与语义保持不变,仅 JSON Schema 类型由 Map 升级为结构化对象;Jackson 反序列化对旧的"对象不定键"消费方式零影响。
|
||||||
正在加载...
x
在新工单中引用
屏蔽一个用户