diff --git a/changelogs/2026-03/27_1800_batch_calendar_api_doc.md b/changelogs/2026-03/27_1800_batch_calendar_api_doc.md new file mode 100644 index 0000000..06248be --- /dev/null +++ b/changelogs/2026-03/27_1800_batch_calendar_api_doc.md @@ -0,0 +1,209 @@ +# 接口文档:团期日历数据 + +> **日期**: 2026-03-27 +> **类型**: 📖 接口文档补充(非新增接口,已有接口的完整使用说明) +> **涉及服务**: hl-product-service、hl-mp-service +> **接口状态**: ✅ 已上线可用 + +--- + +## 一、功能说明 + +此接口为 **GROUP(小蒙马拼团)产品** 提供团期日历数据,供小程序端日历选择器展示。 + +**核心能力**: +- 返回指定产品所有**可报名**团期(状态为 ENROLLING 或 CONFIRMED) +- 只返回**今天及以后**的出发日期(历史团期自动过滤) +- 每个团期包含:出发日期、起步价、定金金额、剩余名额、剩余房间数、是否已成团 +- 起步价来源于**价格日历**(product_price_calendar 表的成人售价) +- 定金计算规则:固定金额优先,否则用 `起步价 × 定金比例%`(向上取整) + +--- + +## 二、接口清单 + +| # | 接口 | 方法 | 路径 | 说明 | +|---|------|------|------|------| +| 1 | 团期日历(内部) | GET | `/internal/product/{productId}/batches/calendar` | 服务间调用 | +| 2 | 团期日历(C端) | GET | `/mp/product/{productId}/batches/calendar` | 小程序直接调用(经网关) | + +> 两个接口返回数据完全相同,区别仅在路由层: +> - **内部接口**:hl-mp-service 通过 Feign 调用 hl-product-service +> - **C端接口**:小程序通过网关 `/mp/product/...` 直接请求 + +--- + +## 三、接口详细定义 + +### GET `/mp/product/{productId}/batches/calendar` + +> **前端应调用此路径**(经网关转发),不要直接调用 internal 路径 + +#### 使用场景 +小程序 GROUP 产品详情页,展示**团期日历选择器**,用户选择出发日期后进入报价流程。 + +#### 请求参数 + +| 参数 | 位置 | 类型 | 必填 | 说明 | +|------|------|------|------|------| +| productId | path | Long | ✅ | 产品ID(必须是 GROUP 类型产品) | + +#### 请求示例 + +``` +GET /mp/product/1903770276454400001/batches/calendar +``` + +#### 响应示例 + +```json +{ + "code": 200, + "message": "操作成功", + "data": [ + { + "departureDate": "2026-05-01", + "batchId": "1903770276454400101", + "batchLabel": "五一团", + "batchName": "2026年五一黄金周第一批", + "batchStatus": "ENROLLING", + "startingPrice": 12800.00, + "enrolledCount": 15, + "remainingSlots": 15, + "maxRooms": 15, + "bookedRooms": 5, + "remainingRooms": 10, + "isConfirmed": false, + "depositAmount": 3999.00 + }, + { + "departureDate": "2026-05-08", + "batchId": "1903770276454400102", + "batchLabel": "五一加开团", + "batchName": "2026年五一黄金周第二批", + "batchStatus": "CONFIRMED", + "startingPrice": 11800.00, + "enrolledCount": 28, + "remainingSlots": 2, + "maxRooms": 15, + "bookedRooms": 13, + "remainingRooms": 2, + "isConfirmed": true, + "depositAmount": 3540.00 + } + ] +} +``` + +--- + +## 四、响应字段说明 + +| 字段 | 类型 | 说明 | +|------|------|------| +| `departureDate` | String (yyyy-MM-dd) | 出发日期 | +| `batchId` | String | 批次ID(雪花ID字符串) | +| `batchLabel` | String | 批次标签(短名,如"五一团") | +| `batchName` | String | 批次全称 | +| `batchStatus` | String | 批次状态,见下方枚举 | +| `startingPrice` | BigDecimal | 起步价(元),来自价格日历的成人售价。**可能为 null**(价格日历未配置时) | +| `enrolledCount` | Integer | 已报名人数 | +| `remainingSlots` | Integer | 剩余名额 = maxParticipants - enrolledCount | +| `maxRooms` | Integer | 总房间数 | +| `bookedRooms` | Integer | 已预订房间数 | +| `remainingRooms` | Integer | 剩余房间数 = maxRooms - bookedRooms | +| `isConfirmed` | Boolean | 是否已成团(batchStatus == "CONFIRMED" 时为 true) | +| `depositAmount` | BigDecimal | 定金金额(元/人)。**可能为 null**(未配置定金且无起步价时) | + +--- + +## 五、枚举/字典值 + +### batchStatus 批次状态(本接口只返回前两种) + +| 值 | 中文 | 说明 | +|----|------|------| +| `ENROLLING` | 报名中 | ✅ 本接口会返回,可正常报名 | +| `CONFIRMED` | 已成团 | ✅ 本接口会返回,已达成团人数,仍可继续报名 | +| `PENDING` | 待开放 | ❌ 不会返回 | +| `FULL` | 已满员 | ❌ 不会返回 | +| `DEPARTED` | 已出发 | ❌ 不会返回 | +| `COMPLETED` | 已完成 | ❌ 不会返回 | +| `CANCELLED` | 已取消 | ❌ 不会返回 | + +--- + +## 六、业务规则 + +1. **过滤条件**:只返回 `batchStatus IN ('ENROLLING', 'CONFIRMED')` 且 `departureDate >= 今天` 的团期 +2. **排序**:按出发日期升序 → 排序号升序 +3. **起步价来源**:从 `product_price_calendar` 表查询对应日期的 `adult_sell_price`,状态必须为 AVAILABLE +4. **定金计算**: + - 如果产品配置了固定定金金额(`deposit_amount > 0`)→ 直接使用 + - 否则用 `起步价 × deposit_ratio / 100`,向上取整(RoundingMode.UP) + - 两者都没有配置时 → depositAmount 为 null +5. **非 GROUP 产品调用此接口**:返回空数组 `[]`(不会报错) + +--- + +## 七、调用位置(后端内部使用情况) + +此接口在后端有 **3 处调用**,前端了解即可: + +| 调用位置 | 场景 | 说明 | +|----------|------|------| +| `MpProductController.java:97` | 产品列表接口 | GROUP 产品列表自动追加 `batches` 字段 | +| `ProductAggregationService.java:174` | 产品详情聚合 | GROUP 产品详情页异步加载团期 | +| `MpProductFeignClient.java:57` | Feign 声明 | hl-mp-service → hl-product-service 的 Feign 调用声明 | + +### 前端调用建议 + +**场景1:产品列表页** +- GROUP 产品列表接口 `GET /mp/product/list` 已自动包含 `batches` 字段(数组),无需单独调用 + +**场景2:产品详情页** +- 产品详情聚合接口 `GET /mp/product/{id}/detail` 已自动包含 `batches` 字段,无需单独调用 + +**场景3:需要单独刷新团期** +- 用户在详情页停留较久需要刷新团期时,可单独调用 `GET /mp/product/{productId}/batches/calendar` + +--- + +## 八、前端实现建议 + +``` +┌─────────────────────────────────────────────┐ +│ 团期日历选择器 │ +│ │ +│ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ ┌─────┐ │ +│ │ 4/28│ │ 4/29│ │ 4/30│ │ 5/01│ │ 5/02│ │ +│ │ │ │ │ │ │ │五一团│ │ │ │ +│ │ │ │ │ │ │ │¥12800│ │ │ │ +│ │ — │ │ — │ │ — │ │剩15位│ │ — │ │ +│ └─────┘ └─────┘ └─────┘ └─────┘ └─────┘ │ +│ │ +│ 选中团期信息: │ +│ ┌──────────────────────────────────────┐ │ +│ │ 五一团 · 2026-05-01出发 │ │ +│ │ 起步价 ¥12,800/人 定金 ¥3,999/人 │ │ +│ │ 剩余 15 名额 · 剩余 10 间房 │ │ +│ │ 🔴 报名中(未成团) │ │ +│ └──────────────────────────────────────┘ │ +│ │ +│ [ 立即报名 ] │ +└─────────────────────────────────────────────┘ +``` + +**展示建议**: +- 日历格子:有团期的日期高亮显示,无团期的日期置灰 +- `isConfirmed = true` → 显示 "已成团" 绿色标签 +- `isConfirmed = false` → 显示 "报名中" 橙色标签 +- `remainingSlots <= 3` → 显示 "仅剩X位" 红色提示 +- `remainingRooms <= 2` → 显示 "房间紧张" 提示 +- `startingPrice` 为 null → 显示 "价格待定" +- `depositAmount` 不为 null → 显示 "定金 ¥xxx/人" +- `batchLabel` 作为日历格子内的短标签显示 + +--- + +*📖 此文档为已有接口的详细说明,无代码变更*