# 接口变更记录 — 2026-04-13 > **变更类型**:接口合并 + 定价模型说明 > **在线文档**: > - 局域网:http://192.168.100.236:8080/doc.html → `1. 管理端 - 产品管理` > - 公网:https://api.test.1814.love:9443/doc.html(需认证) --- ## 一、创建产品和Step1基础信息合并为一个接口 ### 旧接口(已删除) | 接口 | 说明 | |------|------| | ~~POST /admin/product/item~~ | ~~独立创建接口,已删除~~ | | ~~PUT /admin/product/item/{id}/basic~~ | ~~独立Step1保存,已删除~~ | ### 新接口 **`POST /admin/product/item/basic`** — 创建+更新合一 - **productId 不传** = 创建新产品(草稿),返回新 productId - **productId 传了** = 更新已有产品,返回原 productId ### 创建时请求示例(productId不传) ```json { "productType": "CORE", "name": "额吉的故乡·亲子版", "tripDays": 6, "lineId": 100, "coverImageUrl": "https://...", "seasons": ["summer"], "tags": ["亲子"] } ``` - `productType` **创建时必传**(CORE/GROUP/CUSTOM) - `version` **创建时不传** - 其他字段可选,创建时可以只传最少信息,也可以一次性填完全部 ### 更新时请求示例(productId传已有ID) ```json { "productId": 2043246204711550977, "version": 0, "name": "额吉的故乡·亲子版(修改)", "tripDays": 6, "lineId": 100, "coverImageUrl": "https://...", "seasons": ["summer", "autumn"], "tags": ["亲子", "研学"], "tiers": [ {"tierSeq": 1, "tierName": "舒适"}, {"tierSeq": 2, "tierName": "豪华"} ] } ``` - `version` **更新时必传**(从详情接口获取,乐观锁校验) - `productType` 更新时传了也会被忽略(创建后不可改) ### 响应 ```json { "code": 200, "message": "成功", "data": 2043246204711550977 } ``` 返回 `Long` 类型的产品ID(创建时是新ID,更新时是原ID)。 --- ## 二、定价模型:哪种产品用哪个接口 ### 核心规则 | 产品类型 | 定价模型 | 用户选什么 | 用哪组接口 | |---------|---------|-----------|-----------| | **CORE**(核心产品) | 价格日历 | 用户从日历选出发日期 | `price-calendar` 系列 | | **CUSTOM**(私人定制) | 价格日历 | 同上 | `price-calendar` 系列 | | **GROUP**(小蒙马) | 班期制 | 用户从班期列表选第N期 | `schedule` 系列 | ### 前端判断逻辑 ``` if (productType === 'CORE' || productType === 'CUSTOM') { // Step4 显示【价格日历】界面 // 用 price-calendar 系列接口 } else if (productType === 'GROUP') { // Step4 显示【班期管理】界面 // 用 schedule 系列接口 } ``` ### 价格日历接口(CORE / CUSTOM 产品用) | 场景 | 方法 | 路径 | 说明 | |------|------|------|------| | 查询价格日历 | GET | `/admin/product/item/{id}/price-calendar?month=2026-07&tierSeq=1` | 按月+档位查询 | | 批量设置价格 | POST | `/admin/product/item/{id}/price-calendar/batch` | 按日期范围设价 | | 删除价格区间 | DELETE | `/admin/product/item/{id}/price-calendar` | 按日期范围删除 | **批量设置请求示例**: ```json { "productId": 123, "version": 3, "startDate": "2026-07-01", "endDate": "2026-07-31", "tierSeq": 1, "priceType": "PEAK", "adultSellPrice": 4980, "childSellPrice": 3980, "toddlerDiscount": -500, "infantPrice": 0, "dailyStock": 10 } ``` **价格日历查询响应**: ```json [ { "id": 1, "productId": 123, "tierSeq": 1, "date": "2026-07-01", "priceType": "PEAK", "adultSellPrice": 4980, "childSellPrice": 3980, "toddlerDiscount": -500, "infantPrice": 0, "dailyStock": 10, "sold": 2 } ] ``` ### 班期接口(GROUP 小蒙马产品用) | 场景 | 方法 | 路径 | 说明 | |------|------|------|------| | 班期列表 | GET | `/admin/product/item/{id}/schedule/list` | 返回全部班期 | | 创建班期 | POST | `/admin/product/item/{id}/schedule` | 不传batchId | | 修改班期 | PUT | `/admin/product/item/{id}/schedule` | 传batchId | | 删除班期 | DELETE | `/admin/product/item/{id}/schedule/{scheduleId}` | 有订单不可删 | | 取消班期 | POST | `/admin/product/item/{id}/schedule/{scheduleId}/cancel` | 触发退款 | | 批量创建 | POST | `/admin/product/item/{id}/schedule/batch-create` | 按重复模式 | | 班期团队查询 | GET | `/admin/product/item/{id}/schedule/team?batchId=xxx` | 团队成员 | | 班期团队保存 | PUT | `/admin/product/item/{id}/schedule/team?batchId=xxx` | 全量替换 | **创建班期请求示例**: ```json { "productId": 123, "batchName": "第1期", "departureDate": "2026-07-01", "enrollmentDeadline": "2026-06-30", "adultPrice": 4980, "childPrice": 3980, "toddlerDiscount": -500, "infantPrice": 0, "maxParticipants": 20, "maxRooms": 10, "productStockLimit": 20 } ``` **班期列表响应**: ```json [ { "batchId": 456, "productId": 123, "batchNo": "B20260701001", "batchName": "第1期", "departureDate": "2026-07-01", "endDate": "2026-07-06", "enrollmentDeadline": "2026-06-30", "adultPrice": 4980, "childPrice": 3980, "toddlerDiscount": -500, "infantPrice": 0, "maxParticipants": 20, "enrolledCount": 8, "maxRooms": 10, "bookedRooms": 4, "productStockLimit": 20, "batchStatus": "ENROLLING", "version": 0 } ] ``` **批量创建班期请求示例**: ```json { "productId": 123, "startDate": "2026-07-01", "endDate": "2026-09-30", "repeatMode": "WEEKLY", "dayOfWeek": 1, "adultPrice": 4980, "childPrice": 3980, "maxParticipants": 20, "maxRooms": 10 } ``` ### 价格日历 vs 班期对比 | 维度 | 价格日历(CORE/CUSTOM) | 班期(GROUP) | |------|----------------------|-------------| | 定价粒度 | 每天独立价格 | 每期一个固定价格 | | 库存 | 按天(dailyStock=每天可接几单) | 按期(maxParticipants=总人数+maxRooms=总房间数) | | 档位 | 支持多档(tierSeq区分) | 单一档位 | | 用户选择 | C端日历选日期 | C端列表选第N期 | | 团队配置 | 无 | 每期可配领队/摄影师等 | | 价格类型 | 平日/旺季/节假日/特价(颜色区分) | 无(每期统一价) | ### 班期状态说明 | 状态 | 中文 | 说明 | |------|------|------| | ENROLLING | 报名中 | 正常接受报名 | | NEARLY_FULL | 即将满员 | 剩余房间≤阈值(默认2间) | | FULL | 已满 | 剩余房间=0 | | FINISHED | 已结束 | 出发日期已过 | | CANCELLING | 取消中 | 有订单,退款处理中 | | CANCELLED | 已取消 | 取消完成 | --- ## 三、后端与前端名词对照 | 后端术语 | 后端字段 | 前端术语 | 说明 | |---------|---------|---------|------| | 产品线 | lineId / lineName | **主题** | 如"额吉的故乡""草原环线" | | 产品 | productId / name | **版本** | 如"亲子版""旷野版""舒适版" | | 档位 | tierSeq / tierName / tierCount | **规格** | 如"舒适""豪华",tierCount=规格数量 | **前端展示映射**: - 主题列表 → 调 `/admin/product/line/list` - 版本列表 → 调 `/admin/product/item/list`(tierCount=该版本有几个规格) - 规格详情 → 在产品详情的 `tiers` 字段中(`[{tierSeq:1, tierName:"舒适"}, {tierSeq:2, tierName:"豪华"}]`)