diff --git a/changelogs-v2/2026-06/22_4082_早鸟优惠管理页面v3对接-接口说明-管理后台.md b/changelogs-v2/2026-06/22_4082_早鸟优惠管理页面v3对接-接口说明-管理后台.md new file mode 100644 index 0000000..8d7537d --- /dev/null +++ b/changelogs-v2/2026-06/22_4082_早鸟优惠管理页面v3对接-接口说明-管理后台.md @@ -0,0 +1,372 @@ +# 早鸟优惠管理页面 v3 接口对接说明(管理后台) + +- **端类型**:管理后台 +- **变更类型**:接口说明(路径迁移) +- **日期**:2026-06-22 +- **关联 PR**:[#4053](https://git.1814.love:8443/wx/HL/pulls/4053) / [#4064](https://git.1814.love:8443/wx/HL/pulls/4064) / [#4076](https://git.1814.love:8443/wx/HL/pulls/4076) / [#4082](https://git.1814.love:8443/wx/HL/pulls/4082) +- **负责人**:yst(腰苏图) + +--- + +## 1. 接口背景 + +订单服务 v3(hl-order-service-v3,端口 8086)已完整落地早鸟优惠管理后台 6 个接口(PR #4053 / #4064 / #4076 / #4082)。 + +v3 的早鸟接口与 v2(hl-order-service-v2,端口 8094)的接口**入参、出参、字段语义、枚举值、交互行为完全一致**,唯一区别是**请求路径加了 /v3 前缀**。 + +**前端对接结论:早鸟管理页面无需任何 UI / 字段 / 交互改动,唯一需要做的是切换接口路径。** + +--- + +## 2. 变更清单 + +| # | 方法 | v2 路径(旧) | v3 路径(新) | 备注 | +|---|------|--------------|--------------|------| +| 1 | GET | /admin/order/early-bird 或 /admin/order/early-bird/list | /v3/admin/order/early-bird/list | v3 只有 /list,调空路径返回 404,必须带 /list | +| 2 | GET | /admin/order/early-bird/{planId} | /v3/admin/order/early-bird/{planId} | 路径参数不变 | +| 3 | POST | /admin/order/early-bird | /v3/admin/order/early-bird | 仅加前缀 | +| 4 | PUT | /admin/order/early-bird/{planId} | /v3/admin/order/early-bird/{planId} | 路径参数不变 | +| 5 | DELETE | /admin/order/early-bird/{planId} | /v3/admin/order/early-bird/{planId} | 路径参数不变 | +| 6 | PUT | /admin/order/early-bird/{planId}/toggle | /v3/admin/order/early-bird/{planId}/toggle | Query 参数 enabled 不变 | + +v2 早鸟列表接口历史上同时挂了空路径和 /list 两个映射。v3 只保留 /list,调空路径会返回 404。前端如果之前调的是 /admin/order/early-bird(无 /list 后缀),切换时必须同时补上 /list。 + +--- + +## 3. 接口详情 + +| 项目 | 说明 | +|------|------| +| **Base URL** | /v3/admin/order/early-bird | +| **认证** | 管理后台 JWT Token(Authorization: Bearer token),与 v2 一致 | +| **内容类型** | POST / PUT 请求体 Content-Type: application/json;GET 均为 Query 参数 | +| **幂等性** | POST 创建非幂等;PUT 按 planId 幂等覆盖(全字段覆盖,不支持 PATCH) | +| **限流** | 走全局网关限流,无独立限流规则 | +| **服务端口** | 测试服网关统一 9443,无需直连 8086 | + +--- + +## 4. 接口入参 + +### 4.1 GET /v3/admin/order/early-bird/list — 分页列表 + +Query 参数(继承 PageParam): + +| 参数 | 类型 | 必填 | 说明 | +|------|------|------|------| +| pageNo | Integer | 是 | 页码,从 1 开始 | +| pageSize | Integer | 是 | 每页条数,建议 10 / 20 | + +当前 v3 分页查询无额外筛选字段(EarlyBirdPlanPageReqVO 仅继承 PageParam),与 v2 保持一致。 + +### 4.2 GET /v3/admin/order/early-bird/{planId} — 详情 + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| planId | Long(字符串) | Path | 是 | 早鸟计划 ID(雪花 ID) | + +### 4.3 POST /v3/admin/order/early-bird — 创建 + +请求体(EarlyBirdPlanSaveReqVO): + +| 字段 | 类型 | 必填 | 校验规则 | 说明 | +|------|------|------|----------|------| +| planName | String | 是 | NotBlank | 计划名称 | +| remark | String | 否 | 无 | 优惠描述 | +| discountType | String | 否 | 枚举三选一见第6节 | 折扣方式,默认 AMOUNT_TOTAL | +| discountAmount | BigDecimal | 条件必填 | AMOUNT_PER_PERSON 或 AMOUNT_TOTAL 时必填 | 优惠金额(元) | +| discountPercent | BigDecimal | 条件必填 | PERCENT 时必填,取值 (0, 100) 开区间 | 折扣率,80=8折(不是立减 80%) | +| priority | Integer | 否 | >=0,默认 0 | 优先级,同区间多命中时大者优先 | +| minPeople | Integer | 是 | >=1 | 最低适用人数(含) | +| maxPeople | Integer | 否 | >=minPeople | 最高适用人数(含),不填=不限 | +| startDate | LocalDate | 是 | yyyy-MM-dd | 生效开始日期 | +| endDate | LocalDate | 是 | yyyy-MM-dd,需 >=startDate | 生效结束日期 | +| productIds | List | 否 | 无 | 关联产品 ID 列表,空=不限产品 | +| applicableTravelerTypes | List | 否 | 枚举值见第6节 | 适用人群 code 列表,空=后端自动填充 [ADULT, CHILD, YOUNG_CHILD] | + +### 4.4 PUT /v3/admin/order/early-bird/{planId} — 修改 + +路径参数 planId(Long/字符串)。请求体与 4.3 完全一致,全字段覆盖更新(不支持 PATCH,未传的选填字段会被重置为 null / 默认值)。 + +### 4.5 DELETE /v3/admin/order/early-bird/{planId} — 删除 + +路径参数 planId(Long/字符串)。无请求体。软删除,删除后 planId 不可再查询。 + +### 4.6 PUT /v3/admin/order/early-bird/{planId}/toggle — 启用 / 禁用 + +| 参数 | 类型 | 位置 | 必填 | 说明 | +|------|------|------|------|------| +| planId | Long | Path | 是 | 早鸟计划 ID | +| enabled | Boolean | Query | 是 | true=启用;false=禁用 | + +禁用后不再参与下单时自动匹配。启用时若与已有启用计划冲突(同产品+时间段+人数区间重叠),返回 581610。 + +--- + +## 5. 出参字段 + +所有接口返回 Result 包装,成功 code=200。 + +| 接口 | 出参类型 | +|------|---------| +| 分页列表 | Result> | +| 详情 | Result | +| 创建 | Result | +| 修改 | Result | +| 删除 | Result | +| 启用/禁用 | Result | + +### EarlyBirdPlanVO 字段表 + +| 字段 | 类型 | 说明 | +|------|------|------| +| planId | Long(JSON 已序列化为字符串) | 计划 ID,雪花 ID,前端用字符串类型接收防 JS 精度丢失 | +| planName | String | 计划名称 | +| remark | String / null | 优惠描述 | +| discountType | String | 折扣方式枚举 code(AMOUNT_TOTAL / AMOUNT_PER_PERSON / PERCENT) | +| discountAmount | BigDecimal(JSON 序列化为字符串) / null | 优惠金额(元);discountType=PERCENT 时为 null | +| discountPercent | BigDecimal / null | 折扣率 (0~100);非 PERCENT 时为 null;80=8折 | +| priority | Integer | 优先级,默认 0 | +| minPeople | Integer | 最低适用人数(含) | +| maxPeople | Integer / null | 最高适用人数(含),null=不限 | +| peopleRangeText | String | 后端拼好的人数区间文案,如 3-5 人 / 3 人及以上 | +| discountText | String | 后端拼好的折扣说明,如 每人立减 100 元 / 整单立减 500 元 / 9 折优惠 | +| startDate | String(yyyy-MM-dd) | 生效开始日期 | +| endDate | String(yyyy-MM-dd) | 生效结束日期 | +| enabled | Boolean | 是否启用 | +| applicableTravelerTypes | List | 适用人群 code 列表;配置为空时后端回填并持久化 [ADULT, CHILD, YOUNG_CHILD] | +| applicableTravelerTypesText | String | 后端拼好的适用人群文案,如 成人/儿童/小童 | +| productIds | List | 关联产品 ID 列表,空数组=不限产品 | +| productNames | List | 关联产品名称,下标与 productIds 对齐;产品已删除时填 产品[ID]已删除 | +| products | List<{productId:Long, name:String}> | 关联产品结构化列表,供编辑弹窗 tag 回显用 | +| createTime | String(ISO 8601) | 创建时间,如 2026-06-22T10:00:00 | +| updateTime | String(ISO 8601) | 最后更新时间 | + +--- + +## 6. 枚举 / 数据字典 + +### discountType — 折扣方式 + +| code | 中文 | 计算公式 | 生效字段 | +|------|------|----------|---------| +| AMOUNT_TOTAL | 整单立减(默认) | 优惠额 = discountAmount | discountAmount 必填 | +| AMOUNT_PER_PERSON | 每人立减 | 优惠额 = discountAmount x 计费人数 | discountAmount 必填 | +| PERCENT | 按比例打折 | 优惠额 = 总价 x (100 - discountPercent) / 100 | discountPercent 必填 | + +重要:discountPercent=80 表示打 8 折,不是优惠 80%。前端展示请转换为 X折 格式,切勿直接显示 80%。 + +### applicableTravelerTypes — 适用人群 + +| code | 中文 | 人数匹配规则 | +|------|------|------------| +| ADULT | 成人 | 计入人数口径 | +| CHILD | 儿童 | 计入人数口径 | +| YOUNG_CHILD | 小童 | 计入人数口径 | +| BABY | 婴儿 | 默认不计入;需显式配置才计入 | + +人数匹配口径:统计 applicableTravelerTypes 中包含的人群类别对应人数之和,判断是否满足 minPeople / maxPeople 区间。默认排除婴儿,人数口径 = adult + child + youngChild(不含 baby)。 + +--- + +## 7. 错误码 + +早鸟模块错误码段位:581600 – 581699 + +| 错误码 | 描述 | 触发场景 | +|--------|------|---------| +| 581600 | 早鸟计划不存在 | planId 查不到记录(详情 / 修改 / 删除 / toggle) | +| 581601 | 早鸟计划已禁用 | 对禁用计划执行不允许的操作 | +| 581602 | 当前日期不在早鸟计划有效期内 | 当前日期不在 startDate ~ endDate 范围内 | +| 581603 | 人数不满足最低人数要求({0}) | 计费人数 < minPeople,{0} 为阈值 | +| 581604 | 人数超过最高人数限制({0}) | 计费人数 > maxPeople,{0} 为阈值 | +| 581605 | PERCENT 类型时折扣率不能为空 | discountType=PERCENT 但未传 discountPercent | +| 581606 | {0} 类型时优惠金额不能为空 | 立减类型但未传 discountAmount,{0} 为类型名 | +| 581607 | 最高人数不能小于最低人数 | maxPeople < minPeople | +| 581608 | 结束日期不能早于开始日期 | endDate < startDate | +| 581609 | 适用人群包含非法取值:{0} | applicableTravelerTypes 含未知 code | +| 581610 | 产品已存在生效时间与人数区间重叠的早鸟计划,不能重复创建或启用 | 同一产品同时间段同人数区间已有启用计划(防同订单冲突) | + +--- + +## 8. 示例 + +### 8.1 典型成功 — 创建整单立减计划 + +请求: + + POST /v3/admin/order/early-bird + Content-Type: application/json + +请求体: + + { + planName: 暑期早鸟立减300, + remark: 7月出发整单立减300元, + discountType: AMOUNT_TOTAL, + discountAmount: 300, + priority: 10, + minPeople: 2, + maxPeople: 6, + startDate: 2026-07-01, + endDate: 2026-07-31, + productIds: [1900000000001, 1900000000002], + applicableTravelerTypes: [ADULT, CHILD, YOUNG_CHILD] + } + +响应: + + { + code: 200, + msg: success, + data: { + planId: 1920000000001234, + planName: 暑期早鸟立减300, + discountType: AMOUNT_TOTAL, + discountAmount: 300.00, + discountPercent: null, + priority: 10, + minPeople: 2, + maxPeople: 6, + peopleRangeText: 2-6 人, + discountText: 整单立减 300 元, + startDate: 2026-07-01, + endDate: 2026-07-31, + enabled: true, + applicableTravelerTypes: [ADULT, CHILD, YOUNG_CHILD], + applicableTravelerTypesText: 成人/儿童/小童, + productIds: [1900000000001, 1900000000002], + productNames: [云南大理亲子7日游, 丽江雪山5日徒步], + products: [ + {productId: 1900000000001, name: 云南大理亲子7日游}, + {productId: 1900000000002, name: 丽江雪山5日徒步} + ], + createTime: 2026-06-22T10:00:00 + } + } + +注意:discountAmount 在响应 JSON 中已序列化为字符串(300.00),planId 同理(1920000000001234)。前端用字符串接收,勿用 Number 解析雪花 ID。 + +### 8.2 边界情况 — 折扣率计划,不限人数,不限产品 + +maxPeople 不传=不限;productIds 不传=不限产品;applicableTravelerTypes 不传=后端自动填充默认值。 + +请求体: + + { + planName: 年底全产品9折, + discountType: PERCENT, + discountPercent: 90, + minPeople: 1, + startDate: 2026-12-01, + endDate: 2026-12-31 + } + +响应(关键字段): + + { + code: 200, + data: { + planId: 1920000000001235, + discountType: PERCENT, + discountAmount: null, + discountPercent: 90.00, + maxPeople: null, + peopleRangeText: 1 人及以上, + discountText: 9 折优惠, + applicableTravelerTypes: [ADULT, CHILD, YOUNG_CHILD], + productIds: [], + products: [] + } + } + +### 8.3 业务失败 — 产品时间区间与人数区间均重叠(错误码 581610) + +同一产品在同一时间段、同一人数区间已存在启用状态的早鸟计划,新建或重新启用时返回: + +请求体: + + {planName:冲突测试,discountType:AMOUNT_TOTAL,discountAmount:100,minPeople:2,maxPeople:5,startDate:2026-07-01,endDate:2026-07-15,productIds:[1900000000001]} + +响应: + + {code:581610,msg:产品(ID=1900000000001)已存在生效时间与人数区间重叠的早鸟计划(planId=1920000000001234),不能重复创建或启用,data:null} + +前端按 code === 200 判断成功,失败时把 msg 直接 toast 展示即可,后端消息已是可读中文。 + +--- + +## 9. 业务边界 + +**适用场景**: +- 管理员新建 / 修改 / 删除 / 查询早鸟优惠配置 +- 对已有计划快速启停 +- 查询当前所有早鸟计划状态列表 + +**不适用场景**: +- 小程序 C 端用户查看早鸟优惠展示(走内部 Feign 接口,前端无需关心) +- 下单时自动匹配优惠(订单服务内部逻辑,前端无需干预) +- 已下单订单的优惠金额追溯修改(早鸟仅下单时一次性结算,改计划不追溯已有订单) + +**特殊边界**: +- 同一产品在同一时间段 + 同一人数区间内,只允许存在一个启用状态的早鸟计划;禁用状态不参与冲突检测;人数区间不重叠(阶梯档)不受限制 +- 修改或删除计划不影响已下单订单中已应用的早鸟优惠金额 +- applicableTravelerTypes 传空或不传,后端自动填充 [ADULT, CHILD, YOUNG_CHILD] 并持久化到数据库 + +--- + +## 10. 修改前后对比(前端迁移指引) + +核心结论:早鸟管理页面 UI / 字段 / 交互零改动,唯一动作 = 切换接口路径。 + +| 项目 | v2(旧) | v3(新) | 前端是否需要改动 | +|------|---------|---------|----------------| +| 列表接口路径 | /admin/order/early-bird 或 /admin/order/early-bird/list | /v3/admin/order/early-bird/list | 是,必须加 /v3 前缀且必须带 /list 后缀 | +| 详情接口路径 | /admin/order/early-bird/{planId} | /v3/admin/order/early-bird/{planId} | 是,加 /v3 前缀 | +| 创建接口路径 | /admin/order/early-bird | /v3/admin/order/early-bird | 是,加 /v3 前缀 | +| 修改接口路径 | /admin/order/early-bird/{planId} | /v3/admin/order/early-bird/{planId} | 是,加 /v3 前缀 | +| 删除接口路径 | /admin/order/early-bird/{planId} | /v3/admin/order/early-bird/{planId} | 是,加 /v3 前缀 | +| 启/禁用接口路径 | /admin/order/early-bird/{planId}/toggle | /v3/admin/order/early-bird/{planId}/toggle | 是,加 /v3 前缀 | +| 请求参数(入参字段) | 不变 | 完全一致 | 否 | +| 响应字段(出参字段) | 不变 | 完全一致 | 否 | +| 枚举值 / 数据字典 | 不变 | 完全一致 | 否 | +| 页面 UI / 交互逻辑 | 不变 | 完全一致 | 否 | + +**前端迁移两步走**: + +1. 将所有早鸟管理接口的请求路径加 /v3 前缀(/admin/order/early-bird* 改为 /v3/admin/order/early-bird*) +2. 列表接口如果之前调的是空路径 /admin/order/early-bird(无 /list 后缀),改为 /v3/admin/order/early-bird/list + +--- + +## 11. 影响评估 / 回滚 + +| 项目 | 内容 | +|------|------| +| 破坏兼容 | 无,v3 接口为新增路径,v2 接口同期仍可访问 | +| 前端同步上线 | 无强制同步要求;v3 接口上线后可随时切换,v2 继续可用期间两者均可访问 | +| 回滚方案 | 如切换后遇到问题,将请求路径回退到 v2(去掉 /v3 前缀)即可立即恢复;后端 v2 接口未下线 | + +--- + +## 12. 注意事项 + +1. 列表接口路径必须带 /list:v3 只有 /v3/admin/order/early-bird/list,调 /v3/admin/order/early-bird(无后缀)返回 404。这是 v2 到 v3 唯一的路径语义差异。 +2. discountPercent 陷阱:discountPercent=80 表示打 8 折,不是优惠 80%。页面展示请转换为 8折,切勿直接显示 80%。 +3. 金额字段为字符串:discountAmount、planId 在响应 JSON 中均已序列化为字符串。前端接收时用字符串类型,避免 JS 精度丢失。 +4. PUT 全字段覆盖:修改接口不支持 PATCH,未传的选填字段会被重置为 null / 默认值。前端编辑弹窗提交时需确保把所有当前值一并回传。 +5. toggle 启用触发冲突校验:将已禁用的计划重新启用时,若同产品 + 同时间段 + 同人数区间已有其他启用计划,接口返回 581610 并拒绝操作,前端需处理该错误码并展示 msg。 +6. 早鸟不追溯已有订单:管理员修改或删除计划后,已下单订单中已结算的早鸟优惠金额不变,仅影响后续新下单的订单。 + +--- + +## 13. 关联 / 联系人 + +| 项目 | 内容 | +|------|------| +| PR #4053 | https://git.1814.love:8443/wx/HL/pulls/4053(早鸟 v3 基础 CRUD 落地) | +| PR #4064 | https://git.1814.love:8443/wx/HL/pulls/4064(早鸟管理接口补全) | +| PR #4076 | https://git.1814.love:8443/wx/HL/pulls/4076(早鸟管理 CRUD 6 接口完整上线) | +| PR #4082 | https://git.1814.love:8443/wx/HL/pulls/4082(早鸟 v3 路径对齐与修复) | +| 后端负责人 | yst(腰苏图) | +| 变更服务 | hl-order-service-v3(端口 8086,网关统一走 9443) |