fix: 联调指南补全所有接口的完整字段定义和请求/响应示例

前端AI无法访问Knife4j,所有内容必须自包含在文档中。
补全:产品列表请求参数表+响应字段表、创建产品请求/响应示例、
Step1完整字段表(37字段)、Step3路线请求示例、Step5补充信息请求示例、
费用推导预览响应、产品线请求/响应字段、状态变更请求示例。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
这个提交包含在:
API Changelog Bot 2026-04-13 09:14:46 +08:00
父节点 0c40eb0022
当前提交 7cfdf70f8d

查看文件

@ -13,7 +13,7 @@
> >
> **网关路由**:管理端 `/admin/product/**` → hl-product-service-v2,C端 `/mp/product/**` → hl-product-service-v2 > **网关路由**:管理端 `/admin/product/**` → hl-product-service-v2,C端 `/mp/product/**` → hl-product-service-v2
> **重要**:本模块是全新服务,与旧 hl-product-service 并行运行。所有接口路径相同但路由已切换到v2。 > **重要**:本模块是全新服务,与旧 hl-product-service 并行运行。所有接口路径相同但路由已切换到v2。
> **参考**:完整接口字段定义见同目录 `2026-04-12_1538_273bef51_feat_product-v2_Co.md``2026-04-12_1538_ff42bed5_feat_product-v2_VO.md` > **本文档包含全部接口定义**,无需查看其他文件或在线文档。
--- ---
@ -62,13 +62,67 @@
| 场景 | 方法 | 路径 | 说明 | | 场景 | 方法 | 路径 | 说明 |
|------|------|------|------| |------|------|------|------|
| 产品列表 | GET | `/admin/product/item/list` | 分页,支持keyword/productType/lineId/status/tag筛选 | | 产品列表 | GET | `/admin/product/item/list` | 分页,支持keyword/productType/lineId/status/tag筛选 |
| 产品线下拉 | GET | `/admin/product/line/simple-list` | 返回 `[{lineId, name}]`,用于筛选和创建 | | 产品线下拉 | GET | `/admin/product/line/simple-list` | 返回 `[{lineId, name, productType}]`,用于筛选和创建 |
| 创建产品 | POST | `/admin/product/item` | 传 name+productType+lineId+tripDays,返回productId | | 创建产品 | POST | `/admin/product/item` | 传 name+productType+lineId+tripDays,返回productId |
| 删除产品 | DELETE | `/admin/product/item/{id}` | 需先下架 | | 删除产品 | DELETE | `/admin/product/item/{id}` | 需先下架 |
| 复制产品 | POST | `/admin/product/item/{id}/copy` | 返回新productId | | 复制产品 | POST | `/admin/product/item/{id}/copy` | 返回新productId |
| 状态变更 | PUT | `/admin/product/item/{id}/action` | 传 action 枚举,见下方状态操作表 | | 状态变更 | PUT | `/admin/product/item/{id}/action` | 传 action 枚举,见下方状态操作表 |
| 操作记录 | GET | `/admin/product/item/{id}/operation-logs` | 分页,查看历史操作 | | 操作记录 | GET | `/admin/product/item/{id}/operation-logs` | 分页,查看历史操作 |
**产品列表请求参数**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| keyword | String | 否 | 搜索关键词(匹配名称/编号) |
| productType | String | 否 | 产品类型筛选(CORE/GROUP/CUSTOM) |
| lineId | Long | 否 | 产品线ID筛选 |
| status | String | 否 | 状态筛选(DRAFT/PUBLISHED等) |
| tag | String | 否 | 标签筛选 |
| page | Integer | 否 | 页码(默认1) |
| pageSize | Integer | 否 | 每页条数(默认20) |
**产品列表响应字段**`PageResult<ProductListRespVO>`中每条):
| 字段 | 类型 | 说明 |
|------|------|------|
| productId | Long | 产品ID |
| productNo | String | 产品编号(如C260409001) |
| name | String | 产品名称 |
| productType | String | 产品类型 |
| status | String | 产品状态 |
| coverImageUrl | String | 封面图 |
| tripDays | Integer | 行程天数 |
| lineId | Long | 产品线ID |
| lineName | String | 产品线名称 |
| tags | List\<String\> | 产品标签 |
| startPrice | BigDecimal | 起步价 |
| createBy | Long | 创建人ID |
| createTime | LocalDateTime | 创建时间 |
| publishedAt | LocalDateTime | 上架时间 |
**创建产品请求**
```json
{
"name": "额吉的故乡·亲子版",
"productType": "CORE",
"lineId": 100,
"tripDays": 6
}
```
**创建产品响应**`Result<Long>` — 返回新产品ID
**状态变更请求**
```json
{
"productId": 123,
"action": "SUBMIT_PUBLISH",
"remark": "提交上架"
}
```
**状态操作枚举**action字段 **状态操作枚举**action字段
| action值 | 操作 | 前置状态 | 目标状态 | | action值 | 操作 | 前置状态 | 目标状态 |
@ -111,11 +165,54 @@
| 场景 | 方法 | 路径 | 说明 | | 场景 | 方法 | 路径 | 说明 |
|------|------|------|------| |------|------|------|------|
| 获取详情(回显) | GET | `/admin/product/item/{id}` | 返回全部5步数据,取basic部分回显 | | 获取详情(回显) | GET | `/admin/product/item/{id}` | 返回全部5步数据`ProductDetailRespVO`),各步骤取对应部分回显 |
| 保存基础信息 | PUT | `/admin/product/item/{id}/basic` | `ProductBasicSaveReqVO`,带version | | 保存基础信息 | PUT | `/admin/product/item/{id}/basic` | `ProductBasicSaveReqVO`,带version |
| 产品线下拉 | GET | `/admin/product/line/simple-list` | 创建/修改时选产品线 | | 产品线下拉 | GET | `/admin/product/line/simple-list` | 创建/修改时选产品线 |
**关键字段** **Step1 基础信息完整字段表**
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| version | Integer | ✅ | 乐观锁版本号(从详情接口获取) |
| name | String | ✅ | 产品名称≤30字 |
| subtitle | String | 否 | 副标题≤128字 |
| introduction | String | 否 | 产品简介富文本HTML |
| lineId | Long | CORE/GROUP必填 | 产品线ID私人定制可空 |
| tripDays | Integer | ✅ | 行程天数≥1 |
| tripNights | Integer | 否 | 行程晚数(不传自动=天数-1 |
| tiers | List | 否 | 档位列表 `[{tierSeq:1, tierName:"舒适"}]` |
| seasons | List\<String\> | 否 | 适用季节(spring/summer/autumn/winter) |
| tags | List\<String\> | 否 | 产品标签(亲子/研学/露营等) |
| coverImageUrl | String | 上架必填 | 封面图URL |
| carouselImages | List\<String\> | 否 | 轮播图URL列表≤10张 |
| infantAgeMax | Integer | 否 | 幼童年龄上限默认1岁 |
| toddlerAgeMax | Integer | 否 | 小童年龄上限默认3岁 |
| childAgeMin | Integer | 否 | 儿童年龄下限默认4岁 |
| childAgeMax | Integer | 否 | 儿童年龄上限默认12岁 |
| infantDefaultPrice | BigDecimal | 否 | 幼童默认价元,0=免费) |
| isBooking | Boolean | 否 | 是否预约产品默认false |
| paymentType | String | 否 | 支付方式(FULL=全款/DEPOSIT=订金) |
| depositRatio | Integer | 否 | 订金比例%DEPOSIT时用,与固定额二选一 |
| depositAmount | BigDecimal | 否 | 订金固定额DEPOSIT时用 |
| balanceDueDays | Integer | 否 | 尾款期限出发前N天 |
| defaultDailyStock | Integer | 否 | 每日库存默认值NULL=不限量) |
| defaultRoomCount | Integer | 否 | 默认房间数(小蒙马用) |
| minGroupSize | Integer | 否 | 最低成团人数(小蒙马用) |
| showReview | Boolean | 否 | C端展示评价默认true |
| showChatGroup | Boolean | 否 | 展示群聊入口 |
| showTripTime | Boolean | 否 | 展示行程时间 |
| showTripDistance | Boolean | 否 | 展示行程距离 |
| creatorAvatarUrl | String | 否 | 创建者头像URL |
| creatorIntro | String | 否 | 创建者简介≤512字 |
| customizerId | Long | 否 | 定制师ID私人定制用 |
| customerName | String | 否 | 客户姓名(私人定制用) |
| contactPhone | String | 否 | 联系电话(私人定制用) |
| departureDate | LocalDate | 否 | 出发日期私人定制用,格式yyyy-MM-dd |
| safetyItems | List | 否 | 安全保障项 `[{icon,title,description}]` |
| photographyItems | List | 否 | 摄影跟拍项 `[{name,description}]` |
| diningHighlights | List | 否 | 餐饮亮点 `[{name,description}]` |
**请求示例**
```json ```json
{ {
@ -279,6 +376,52 @@
| 人员下拉 | — | 调资源服务 `/internal/staff/list` | 从资源模块获取人员列表 | | 人员下拉 | — | 调资源服务 `/internal/staff/list` | 从资源模块获取人员列表 |
| 备品下拉 | — | 调资源服务 `/internal/supplies/list` | 从资源模块获取备品列表 | | 备品下拉 | — | 调资源服务 `/internal/supplies/list` | 从资源模块获取备品列表 |
**路线与备品请求示例**
```json
{
"productId": 123,
"version": 3,
"routeName": "草原环线体验",
"routeMapUrl": "https://...",
"totalMileage": 1200,
"routeDescription": "海拉尔起止,途经莫日格勒河、额尔古纳...",
"vehicleModelId": 10,
"staffCostIds": [20, 21],
"supplies": [
{
"id": null,
"suppliesResourceId": 30,
"suppliesName": "防晒霜SPF50+",
"category": "防护用品",
"hasCost": false,
"sortOrder": 1
},
{
"id": null,
"suppliesResourceId": null,
"suppliesName": "一次性雨衣",
"category": "防护用品",
"hasCost": true,
"billingType": "PER_PERSON",
"unitPrice": 5,
"quantity": null,
"sortOrder": 2
}
],
"extraCosts": [
{
"id": null,
"name": "接机费",
"unitPrice": 200,
"quantity": 1,
"daily": false,
"sortOrder": 1
}
]
}
```
--- ---
### 页面5产品编辑 — Step4 定价管理 ### 页面5产品编辑 — Step4 定价管理
@ -387,9 +530,56 @@
|------|------|------|------| |------|------|------|------|
| 保存补充信息 | PUT | `/admin/product/item/{id}/supplement` | `ProductSupplementSaveReqVO` | | 保存补充信息 | PUT | `/admin/product/item/{id}/supplement` | `ProductSupplementSaveReqVO` |
| 费用推导预览 | GET | `/admin/product/item/{id}/fee-deduction-preview` | 根据行程自动计算费用包含 | | 费用推导预览 | GET | `/admin/product/item/{id}/fee-deduction-preview` | 根据行程自动计算费用包含 |
| 退改政策模板 | GET | `/admin/product/refund-policy/enabled` | 下拉选择 | | 退改政策模板 | GET | `/admin/product/refund-policy/enabled` | 下拉选择,返回 `[{policyId, policyName}]` |
| 预订条款模板 | GET | `/admin/product/booking-terms/enabled` | 下拉选择 | | 预订条款模板 | GET | `/admin/product/booking-terms/enabled` | 下拉选择,返回 `[{termsId, termsName}]` |
| 温馨提示模板 | GET | `/admin/product/warm-tips/enabled` | 下拉选择 | | 温馨提示模板 | GET | `/admin/product/warm-tips/enabled` | 下拉选择,返回 `[{tipsId, tipsName}]` |
**补充信息请求示例**
```json
{
"productId": 123,
"version": 4,
"includedFees": [
{"id": null, "feeType": "TICKET", "name": "门票", "source": "AUTO", "description": "含所有景区门票", "sortOrder": 1},
{"id": null, "feeType": "ACCOMMODATION", "name": "住宿", "source": "AUTO", "sortOrder": 2}
],
"excludedFees": [
{"id": null, "feeType": "PERSONAL", "name": "个人消费", "description": "如纪念品、零食等", "sortOrder": 1}
],
"customFees": [],
"feeIgnoredTypes": [],
"childTicket": "FREE",
"childAccommodation": "NO_BED",
"childMeal": "HALF",
"elderTicket": "HALF_PRICE",
"elderAccommodation": "SAME_AS_ADULT",
"crowdBenefitTips": "12岁以下儿童门票免费",
"vehicleModelIds": [10, 11],
"vehicleRuleText": "5人以下推荐SUV,6-9人推荐商务车",
"bookingTermsId": 1,
"warmTipsId": 1,
"equipmentAdvice": "<p>必备:防晒霜、遮阳帽...</p>",
"insuranceNotice": "INCLUDED",
"insuranceSchemeId": 1,
"contractSchemeId": 1,
"quickUnderstand": {"text": "6天5晚,深入草原腹地...", "images": ["https://..."]},
"childExperience": {"text": "骑马、射箭、挤牛奶...", "images": ["https://..."]},
"growthGains": [
{"dimension": "探索力", "description": "在辽阔草原培养探索精神"},
{"dimension": "协作力", "description": "团队活动锻炼合作意识"}
]
}
```
**费用推导预览响应**进入Step5前先调用
```json
[
{"feeType": "TICKET", "name": "门票", "source": "AUTO", "sourceNodeName": "莫日格勒河观景台"},
{"feeType": "ACCOMMODATION", "name": "住宿", "source": "AUTO", "sourceNodeName": "额尔古纳大酒店"}
]
```
--- ---
@ -411,10 +601,38 @@
| 场景 | 方法 | 路径 | 说明 | | 场景 | 方法 | 路径 | 说明 |
|------|------|------|------| |------|------|------|------|
| 产品线列表 | GET | `/admin/product/line/list` | 分页 | | 产品线列表 | GET | `/admin/product/line/list` | 分页 |
| 创建产品线 | POST | `/admin/product/line` | name+productType+coverImageUrl+seasons+tags | | 创建产品线 | POST | `/admin/product/line` | 见下方请求 |
| 编辑产品线 | PUT | `/admin/product/line/{lineId}` | | | 编辑产品线 | PUT | `/admin/product/line/{lineId}` | 同创建 |
| 删除产品线 | DELETE | `/admin/product/line/{lineId}` | 有产品时不可删 | | 删除产品线 | DELETE | `/admin/product/line/{lineId}` | 有产品时不可删 |
| 简单列表(下拉) | GET | `/admin/product/line/simple-list` | 返回 [{lineId, name, productType}] | | 简单列表(下拉) | GET | `/admin/product/line/simple-list` | 返回 `[{lineId, name, productType}]` |
**产品线创建/编辑请求**
```json
{
"name": "额吉的故乡",
"description": "呼伦贝尔夏季亲子游",
"productType": "CORE",
"coverImageUrl": "https://...",
"seasons": ["summer", "autumn"],
"tags": ["亲子游", "深度游"]
}
```
**产品线列表响应字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| lineId | Long | 产品线ID |
| name | String | 名称 |
| description | String | 描述 |
| productType | String | 绑定的产品类型 |
| coverImageUrl | String | 封面图 |
| seasons | List\<String\> | 适用季节 |
| tags | List\<String\> | 产品线标签 |
| productCount | Integer | 旗下产品数量 |
| startPrice | BigDecimal | 起步价(旗下已上架产品最低成人价) |
| createTime | LocalDateTime | 创建时间 |
--- ---
@ -640,4 +858,5 @@
4. **多档位**——tierSeq从1开始递增,单一档位=1。价格日历和住宿都按tierSeq关联 4. **多档位**——tierSeq从1开始递增,单一档位=1。价格日历和住宿都按tierSeq关联
5. **小童价格特殊**——前端传的是优惠额(负数),实际小童价=儿童价-|优惠额| 5. **小童价格特殊**——前端传的是优惠额(负数),实际小童价=儿童价-|优惠额|
6. **C端只展示PUBLISHED产品**——其他状态的产品C端接口不会返回 6. **C端只展示PUBLISHED产品**——其他状态的产品C端接口不会返回
7. **Knife4j文档**——本地启动服务后访问 `http://localhost:{port}/doc.html` 查看完整Swagger文档 7. **HTTP始终返回200**——业务错误通过 `Result.code` 区分,`code=0` 为成功,非0为失败,`msg` 为中文错误信息
8. **产品详情接口**——GET `/admin/product/item/{id}` 一次返回全部5步数据基础+行程+路线+价格+补充,前端按当前Step取对应部分回显