新增: 小程序产品详情 earlyBirdLadder 多档 + 订单级立减语义说明

这个提交包含在:
wx 2026-04-20 17:33:13 +08:00
父节点 72b51663f4
当前提交 3c11072d12

查看文件

@ -0,0 +1,110 @@
# 早鸟优惠多档 + 订单级立减(小程序产品详情)
**日期**2026-04-20
**PR**:无(纯文档更正,代码语义一直是订单立减)
**影响**:小程序产品详情页 早鸟展示
---
## 核心结论(给前端的一句话)
`/mp/product/detail``earlyBirdLadder` 字段**已经支持「一个产品多档早鸟」**,每档的折扣语义是**订单总立减**(不是每人减),可以直接按阶梯画。
---
## 业务语义(最重要)
早鸟优惠 = **订单总立减固定金额**,**不是**每人立减。
### 举例
- 满 3 人订单立减 **300 元**(订单总价减 300,不论 3 人还是 30 人)
- 满 4 人订单立减 **500 元**
这在 `earlyBirdLadder` 里是**两个 item**,前端按 `minPeople` 升序画阶梯:
```jsonc
// GET /mp/product/detail?productId=xxx
{
"earlyBirdTip": "最低订单总价优惠 300 元(共 2 档早鸟方案)", // 概览,首屏标签用
"earlyBirdLadder": [
{
"planId": 1001,
"planName": "满3人早鸟",
"minPeople": 3,
"maxPeople": 3, // 档位上限(含),下一档 4 人以上不归它管
"peopleRangeText": "3 人",
"discountText": "满 3 人订单总价优惠 300 元", // ⭐ 订单级立减
"startDate": "2026-04-01",
"endDate": "2026-12-31"
},
{
"planId": 1002,
"planName": "满4人早鸟",
"minPeople": 4,
"maxPeople": null, // null = 不限上限
"peopleRangeText": "4 人及以上",
"discountText": "满 4 人订单总价优惠 500 元",
"startDate": "2026-04-01",
"endDate": "2026-12-31"
}
]
}
```
## 字段清单
| 字段 | 类型 | 说明 |
|---|---|---|
| `earlyBirdTip` | `String` | 概览文案(无人数上下文),无绑定返 `null` |
| `earlyBirdLadder` | `List<EarlyBirdLadderItem>` | 阶梯数组,按 `minPeople` 升序,无绑定返 `[]` |
| `earlyBirdLadder[].planId` | `Long` | 早鸟计划 ID |
| `earlyBirdLadder[].planName` | `String` | 计划名(管理端命名,展示可选) |
| `earlyBirdLadder[].minPeople` | `Integer` | 最低人数(含)|
| `earlyBirdLadder[].maxPeople` | `Integer\|null` | 最高人数,null 表示不限 |
| `earlyBirdLadder[].peopleRangeText` | `String` | 人数区间文案,如 "3-5 人" / "4 人及以上" |
| `earlyBirdLadder[].discountText` | `String` | **订单总立减**文案,如 "满 3 人订单总价优惠 300 元" |
| `earlyBirdLadder[].startDate` | `LocalDate` | 下单日期窗口起 |
| `earlyBirdLadder[].endDate` | `LocalDate` | 下单日期窗口止 |
## 前端展示建议
### 产品详情 —— 早鸟阶梯卡片
```
🐦 早鸟优惠 最低订单总价优惠 300 元
┌─────────────────────────────────┐
│ 3 人 -300 元 │ ← earlyBirdLadder[0]
│ 4 人及以上 -500 元 │ ← earlyBirdLadder[1]
└─────────────────────────────────┘
生效2026-04-01 至 2026-12-31
```
- 用 `peopleRangeText` + `discountText` 拼行
- 如果只想展示金额不展示文案,从 `discountText` 里正则抽数字即可,但直接用 `discountText` 最稳(后端拼好的)
### 下单前匹配
- 下单时按选中人数 `n`,在 `earlyBirdLadder` 里找第一个满足 `minPeople ≤ n ≤ (maxPeople ?? ∞)` 的 item
- 展示"预计优惠 X 元"给用户,X 直接取这一档的金额(不再乘人数)
- 最终折扣以后端订单接口返回的 `OrderDiscount` 为准(前端只做预估展示)
## 不是(防误读)
- ❌ 不是"每人立减 X 元"—— 之前 Entity 注释里 `"优惠金额(元/人)"` 是过期文档,实际金额计算在 `OrderFinanceService.tryApplyEarlyBirdDiscount` 里**没有乘人数**
- ❌ 不是"订单总价按折扣比例打折"—— 是固定金额直减
- ❌ 不是"每个人都减 X 元"—— 订单总价减一次 X 元
## 单选 / 多档的关系
- 一个产品可以绑定**多个**早鸟计划(通过 `product_early_bird_plan` 关联表)
- 每个计划一档,前端合并展示成阶梯
- 运营侧在管理端配置:每档的 `minPeople` + `discountAmount` + 生效日期
## 已知注释问题(后端会修,不影响接口)
- `EarlyBirdPlan.java:25` 注释 "元/人" 会改成 "订单总立减金额(元)"
- `EarlyBirdPlanDTO.java:25` 注释会明确 "订单优惠金额"
- `EarlyBirdLadderItemDTO.java:31` 示例会从 "每人立减 100 元" 改为 "订单总价优惠 300 元"
前端**不用等这个 PR**,接口响应结构不变,语义本来就是订单立减。