# 产品v2 - 今日变更汇总 (2026-04-14)

**日期**: 2026-04-14
**服务**: product-service-v2
**类型**: 新增接口 + bug修复 + 模块搬迁

---

## 一、新增接口

### 1. 计算行程总里程
- `GET /admin/product/item/{productId}/calculate-mileage`
- 根据行程途经点调用高德驾车路线API自动计算里程(km)
- 返回: `{"code":200, "data": 690.2}`
- 前端建议: Step3页面提供"自动计算"按钮调此接口填充总里程

### 2. 温馨提示管理 `/admin/product/warm-tips/**`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /list | 全部列表(含禁用) |
| GET | /enabled | 启用的列表(下拉用) |
| GET | /{tipsId} | 详情 |
| POST | / | 创建 |
| PUT | /{tipsId} | 修改 |
| DELETE | /{tipsId} | 删除(软删) |
| PUT | /{tipsId}/toggle?enabled=true/false | 启用/禁用 |

### 3. 预订条款管理 `/admin/product/booking-terms/**`
接口结构同温馨提示，字段: termsId/termsName/content/enabled/remark

### 4. 报价公式管理 `/admin/product/formula/**`
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /group/list?productType= | 公式组列表 |
| GET | /group/{groupId} | 公式组详情 |
| POST | /group | 创建公式组 |
| PUT | /group/{groupId} | 更新公式组 |
| PUT | /group/{groupId}/activate | 激活公式组 |
| DELETE | /group/{groupId} | 删除公式组 |
| GET | /group/{groupId}/steps | 步骤列表 |
| GET | /step/{formulaId} | 步骤详情 |
| POST | /step | 创建步骤 |
| PUT | /step/{formulaId} | 更新步骤 |
| PUT | /step/{formulaId}/toggle | 启用/禁用步骤 |
| DELETE | /step/{formulaId} | 删除步骤 |
| GET | /step/{formulaId}/versions | 版本历史 |
| PUT | /step/{formulaId}/rollback/{versionNum} | 回滚 |
| POST | /test | 测试公式执行 |
| GET | /var/list?category= | 变量列表 |
| POST | /var | 创建变量 |
| PUT | /var/{varId} | 更新变量 |
| DELETE | /var/{varId} | 删除变量 |

**注意**: 公式相关RespVO中ID字段类型为Long(不是String)

---

## 二、Bug修复

### 1. 产品详情routeInfo返回null (已修)
- 原因: SQL返回扁平字段(totalMileage/routeDescription/routeMapUrl)，VO是嵌套对象，BeanUtil无法映射
- 修复: 手动组装routeInfo/supplement/crowdBenefit嵌套对象

### 2. 行程子数据返回多余审计字段 (已修)
- 原因: nodes/hotels/routePoints直接返回DO对象，包含createTime/updatedBy等
- 修复: 返回前去掉BaseDO字段，JSON字段(images/extraData/photoUrls)正确反序列化

### 3. Step1创建时多个字段丢失 (已修)
- 原因: doCreate方法只set了name/productType/lineId/tripDays，漏了subtitle/category/introduction/seasons/carouselImages等
- 修复: 补全全部字段

### 4. 行程保存事务不生效 (已修)
- 原因: saveItinerary()自调用doSaveItinerary()绕过AOP代理
- 修复: @Lazy setter注入自身代理

---

## 三、前端注意事项

### Step1 基础信息
- `seasons`和`carouselImages`现在能正常保存和返回了
- `balanceDueDays`(尾款截止天数)字段**不需要展示**，尾款在行程中由领队收取，前端隐藏"尾款须在出发前N天付清"输入框

### Step2 行程编排
- routePoints返回字段精简为: `id/resourceId/name/longitude/latitude/sortOrder` (无审计字段)
- nodes的`images`和`extraData`已从JSON字符串反序列化为对象
- days的`photoUrls`和`customFields`同样已反序列化

### Step3 路线与备品
- `GET /{productId}/calculate-mileage` 可用于自动计算里程

### Step5 补充信息
- 详情返回中`supplement`和`crowdBenefit`现在是嵌套对象(之前是null)
- `supplement`包含: quickUnderstand/childExperience/growthGains/insuranceNotice/equipmentAdvice/refundPolicyIds/feeIgnoredTypes/vehicleModelIds
- `crowdBenefit`包含: tips
