# 小蒙马详情页字段补全 + 产品接口优化 **日期**: 2026-03-26 **服务**: hl-product-service **环境**: 测试环境已部署,需重启: product-service --- ## 一、小蒙马(GROUP)详情页新增字段 产品详情接口 `GET /product/{productId}` 和小程序 `GET /internal/mp/product/{productId}` 新增以下字段: ### 1. 数据统计(自动计算,无需配置) | 字段 | 类型 | 说明 | |------|------|------| | `batchCount` | Integer | 历史期数(非散团状态的批次数,仅GROUP产品) | | `hotelSummary` | Array | 住宿安排汇总(连住合并,仅显示连住2晚及以上,仅GROUP产品) | `hotelSummary` 每项结构(连续住同一酒店自动合并): ```json { "dayStart": 3, "dayEnd": 4, "hotelId": "3001000000000000005", "hotelName": "兰其果娃", "coverUrl": "https://xxx/hotel.jpg", "roomTypeName": "亲子房", "nights": 2, "label": "连住2晚" } ``` **注意**:只住1晚的酒店不会出现在 `hotelSummary` 中(设计图只展示连住)。前端可直接用 `label` 字段显示标签,用 `dayStart`-`dayEnd` 显示日期范围(如 "Day3-4")。 ### 2. 年龄说明(后台可配) | 字段 | 类型 | 说明 | 示例 | |------|------|------|------| | `ageMin` | Integer | 适合最小年龄 | `5` | | `ageMax` | Integer | 适合最大年龄 | `12` | | `ageDescription` | String | 年龄说明文案 | `"5-12岁儿童专属,课程按年龄分组"` | ### 3. 摄影跟拍(后台可配) | 字段 | 类型 | 说明 | |------|------|------| | `photographyTags` | String[] | 摄影标签 如 `["200+精修照片", "1对1跟拍"]` | | `photographyImages` | String[] | 摄影作品展示图URL列表 | ### 4. 餐饮亮点(后台可配) | 字段 | 类型 | 说明 | |------|------|------| | `diningHighlights` | Array | 餐饮亮点列表 | 每项结构: ```json { "name": "手把肉", "coverImage": "https://xxx/cover.jpg", "subtitle": "蒙古特色必吃", "detailImages": ["https://xxx/detail1.jpg", "https://xxx/detail2.jpg"] } ``` - `coverImage`: 封面图(列表展示,name叠在图上) - `detailImages`: 详情图列表(点击查看大图) ### 5. 安全保障(后台可配) | 字段 | 类型 | 说明 | |------|------|------| | `safetyItems` | Array | 安全保障列表 | 每项结构: ```json { "icon": "insurance", "title": "保险", "description": "中国人保50万,含意外医疗" } ``` ### 6. 价格档位表(自动计算,无需配置) | 字段 | 类型 | 说明 | |------|------|------| | `priceTiers` | Array | 价格档位列表(从套餐combo自动取每种组合的最低售价,仅GROUP产品) | 每项结构: ```json { "label": "1大1小", "price": 12800, "adultCount": 1, "childCount": 1 } ``` **数据来源**:自动从产品的套餐(GroupBatchCombo)中按 comboCode 分组,取每组跨所有批次的最低 sellPrice。无需后台手动配置。 --- ## 二、推荐餐厅封面图自动补全 行程节点中 `DINING_RECOMMEND` 类型的 `recommendedRestaurants` 列表,`coverUrl` 现在会自动从餐厅资源中补全。前端无需改动,原有字段结构不变。 --- ## 三、上架校验优化 - 移除了上架时商户号(mchId)的强制校验,不再报"商户号不能为空" - GROUP(小蒙马)产品上架新增校验:**至少需要1个可报名的团期**(状态为报名中/已确认,且出发日期在未来)。不满足会提示具体原因 --- ## 四、产品人员配置增加备选人员 人员配置接口 `POST /product/{productId}/staff-config` 和 `PUT /product/staff-config/{id}` 新增字段: | 字段 | 类型 | 说明 | |------|------|------| | `staffIds` | String[] | 备选人员ID列表(从人员资源中选取) | - 数量(quantity)是出行时实际需要的人数,备选人员可以多于此数量 - 团期创建时从备选池中选人分配 ### 领队介绍(自动填充,仅GROUP产品) | 字段 | 类型 | 说明 | |------|------|------| | `leaderInfoList` | Array | 领队详情列表(从人员配置中LEADER类型的staffIds查询) | 每项结构: ```json { "staffId": "123", "name": "巴特尔老师", "avatar": "https://xxx/avatar.jpg", "title": "首席研学导师 · 蒙古族", "experience": "10年儿童户外教育经验", "description": "...", "certificateTags": ["急救证书", "导游证", "教师资格证"] } ``` 前端可滚动展示多个领队。 ### 人员资源新增字段 人员资源 `POST /staff` 和 `PUT /staff/{id}` 新增: | 字段 | 类型 | 说明 | |------|------|------| | `certificateTags` | String[] | 证书标签,如 `["急救证书", "导游证"]` | --- ## 五、预订须知(所有产品类型通用) 小程序产品详情已返回以下字段(点击展开纯文字内容): | 字段 | 位置 | 说明 | |------|------|------| | `product.bookingTermsContent` | ProductVO | 预订条款全文 | | `product.warmTipsContent` | ProductVO | 温馨提示全文 | | `refundPolicies` | MpProductDetailVO | 取消政策(按支付方式分组) | ### 取消政策(退款政策)返回结构 `refundPolicies` 按支付方式分组,每个政策新增 `description` 纯文字字段: ```json { "FULL": { "policyId": 1, "policyName": "标准退款政策", "description": "出发前30天以上取消,退全款;出发前15-30天取消,退80%;出发前15天内取消,不可退", "rules": [ { "ruleId": 1, "minDays": 30, "refundRatio": 100 }, { "ruleId": 2, "minDays": 15, "refundRatio": 80 }, { "ruleId": 3, "minDays": 0, "refundRatio": 0 } ] }, "DEPOSIT": { ... } } ``` 前端可直接用 `description` 展示文字,无需自己拼接规则。按产品的 `pricing.paymentType` 显示对应的退款政策: - `FULL` → 显示 FULL 的 description - `DEPOSIT` → 显示 DEPOSIT 和 BALANCE 的 description --- ## 前端对接要点 1. **batchCount / hotelSummary / priceTiers / leaderInfoList**: 自动计算字段,无需后台录入,GROUP产品详情自动返回 2. **年龄/摄影/餐饮/安全**: 需要在管理后台"编辑产品"时配置对应数据,否则返回 null 3. **所有新字段向后兼容**: 未配置时返回 null,不影响已有字段 4. **保存/更新产品接口同步支持**: `POST /product/save`、`PUT /product/{id}` 都可传入新字段 --- ## 六、人员管理校验增强 **服务**: hl-resource-service 创建/更新人员时,如果填写了 `certificateTags`(证书标签),则 `certificateUrls`(证书文件)不能为空。否则报错: > 添加了证书标签,必须同时上传对应的证书文件 前端在提交人员表单时,如果用户添加了证书标签但没上传证书文件,建议在前端也做提示拦截。 --- ## 七、人员证书改为结构化列表 **服务**: hl-resource-service ### 新增字段 `certificates`(替代旧的 certificateTags + certificateUrls) 人员创建/更新接口新增 `certificates` 字段,标签和附件一一对应: ```json [ { "tag": "急救证书", "url": "https://xxx/cert1.jpg" }, { "tag": "导游证", "url": "https://xxx/cert2.jpg" }, { "tag": "教师资格证", "url": "https://xxx/cert3.jpg" } ] ``` **校验规则**:每项的 `tag` 和 `url` 必须同时存在,缺一报错(如"第1个证书'急救证书'缺少证书附件")。 **兼容**:旧字段 `certificateUrls` / `certificateTags` 保留可用,但建议前端迁移到 `certificates`。 **领队介绍**:小程序详情 `leaderInfoList` 中的 `certificateTags` 优先从 `certificates` 提取,同时也返回完整的 `certificates` 列表。 --- ## 八、安全保障改为模板机制 **服务**: hl-product-service ### 模板管理接口 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/product/safety-template` | 模板列表 | | GET | `/product/safety-template/{id}` | 模板详情 | | POST | `/product/safety-template` | 创建模板 | | PUT | `/product/safety-template/{id}` | 更新模板 | | DELETE | `/product/safety-template/{id}` | 删除模板(默认模板不可删) | 请求体: ```json { "name": "标准安全保障", "items": [ { "icon": "insurance", "title": "保险", "description": "中国人保50万,含意外医疗" }, { "icon": "vehicle", "title": "车辆", "description": "营运资质、儿童安全座椅、司机驾龄10年" }, { "icon": "emergency", "title": "应急", "description": "24h客服,医院30分钟可达" } ], "isDefault": true } ``` ### 产品关联 产品保存/更新时可传 `safetyTemplateId` 指定模板。**不传则自动使用默认模板**,定制师无需手动配置。 ### 详情返回逻辑 `safetyItems` 字段填充优先级:产品指定模板 → 产品自身旧数据 → 默认模板。前端无需改动,`safetyItems` 返回格式不变。 系统已内置默认模板"标准安全保障"(保险/车辆/应急三项)。 --- ## 九、价格档位改为最近一期可报名团期价格 **服务**: hl-product-service `priceTiers` 不再取所有团期的最低价,改为只取**最近一期可报名团期**(ENROLLING/CONFIRMED 且出发日期在未来)的 combo 价格。 返回格式不变: ```json [ { "label": "1大1小", "price": 12800, "adultCount": 1, "childCount": 1 }, { "label": "1大2小", "price": 15800, "adultCount": 1, "childCount": 2 } ] ``` 如果没有可报名团期,`priceTiers` 返回 null。 --- ## 十、人员证书上传说明 **上传流程**:使用通用文件上传接口,和上传其他图片一样。 **步骤**: 1. `POST /file/upload/token` → 获取预签名URL ```json { "fileName": "急救证书.jpg", "bizType": "staff" } ``` 2. 用返回的预签名URL上传文件到OSS 3. `POST /file/upload/confirm` → 确认上传,拿到最终URL 4. 将URL填入 `certificates[].url` **保存人员时传 certificates 字段**: ```json { "certificates": [ { "tag": "急救证书", "url": "https://xxx/cert1.jpg" }, { "tag": "导游证", "url": "https://xxx/cert2.jpg" } ] } ``` 每项 `tag` 和 `url` 必须同时填,缺一报错。旧字段 `certificateTags`/`certificateUrls` 仍可用但建议迁移。 --- ## 补充:行程酒店封面图自动补全 行程天的酒店(`itineraryDays[].hotels[].coverUrl`)如果为空,后端会自动从酒店资源的封面素材中补全。前端无需改动。