# 产品地图支持高德自动生成（BUG 10）

**日期**：2026-04-20
**PR**：#962
**影响**：管理端产品编辑 Step3（路线地图）+ 小程序产品详情页

---

## 业务变化

运营反馈：定制路线没人有时间做线路图。期望一键用高德自动生成路径图。

**能力**：产品地图新增 3 模式，互斥：

| mapMode | 含义 | route_map_url |
|---|---|---|
| `UPLOAD`（默认，老数据行为） | 手动上传图片 | 前端上传后的 OSS URL |
| `AMOUNT_AUTO` | 高德根据行程坐标自动生成 | 后端生成、上传后的 OSS URL |
| `NONE` | 隐藏该模块（小程序不展示） | 可保留或清空 |

---

## 新增接口

### 1. `POST /admin/product/item/{id}/map/generate-by-amap`

**一键触发**：后端取产品行程所有坐标（首天 `gatherPlace.center` → 每天 SCENIC/ACTIVITY/HOTEL 节点 → 末天 `dismissalPlace.center`），调高德静态地图 API，下载 PNG 后落 OSS，写回 `routeMapUrl` + `mapMode=AMAP_AUTO`。

**请求**（全部可选，均有默认值）：
```ts
{
  "size": "750*500",  // 可选，默认 750*500
  "scale": 2          // 可选，默认 2（高清）
}
```

**响应**：
```ts
{
  "mapUrl": "https://oss.../product-route-map/....png",
  "mapMode": "AMAP_AUTO",
  "pointCount": 8,
  "generatedAt": "2026-04-20T12:34:56"
}
```

**异常场景**：
- 坐标 < 2 个 → 400 `行程坐标不足，无法生成地图，请先完善行程`
- 高德返回非图片 → 400 `高德地图生成失败: <错误详情>`
- OSS 上传失败 → 500
- 幂等：10 秒内重复调用会被拦截（`@Idempotent(10)`）

### 2. `PUT /admin/product/item/{id}/map/mode`

**切换地图模式**。

**请求**：
```ts
{
  "mapMode": "NONE",       // @Pattern: NONE|AMAP_AUTO|UPLOAD
  "clearMapUrl": false     // 可选，true 时同时清空 routeMapUrl
}
```

**响应**：`{"code":200,"message":"地图模式切换成功"}`

### 3. 老接口 `PUT /admin/product/item/{id}/route` 扩展

`ProductRouteSaveReqVO` 新增：
```ts
{
  "routeMapUrl": "...",
  "mapMode": "UPLOAD"      // NEW 可选，前端手动上传后可一并传 UPLOAD
}
```

手动上传流程不变：前端走现有 `/admin/file/upload/token` 拿预签名 URL → 上传 OSS → 回填 `routeMapUrl`，顺带把 `mapMode` 设为 `UPLOAD`。

---

## 小程序详情页字段扩展

`MpProductDetailRespVO` 新增：
```ts
{
  "routeMapUrl": "...",
  "mapMode": "UPLOAD"                 // NEW NONE/AMAP_AUTO/UPLOAD
}
```

**管理端详情 VO `ProductDetailRespVO.RouteInfoVO`** 新增 3 字段：
```ts
{
  "mapMode": "AMAP_AUTO",
  "mapGeneratedAt": "2026-04-20T12:34:56",
  "mapAmapSnapshot": {                // 高德生成快照，用于展示"最近生成时间"
    "points": [...],
    "size": "750*500",
    "scale": 2,
    "generatedAt": "..."
  }
}
```

**Internal VO**（供订单服务 / mp 聚合服务 Feign 使用）也同步加了 `mapMode`：`InternalProductDetailVO.RouteInfoVO`、`InternalMpCustomProductDetailVO`、`MpProductDetailInternalVO`。

---

## 前端 TODO

### 管理端产品编辑 Step3
1. "路线地图"模块顶部加 **3 选 1 切换**：
   - 🙈 隐藏（`NONE`）→ 下方模块折叠
   - 🗺️ 高德自动生成（`AMAP_AUTO`）→ 显示"用高德生成"按钮
   - 📤 手动上传（`UPLOAD`）→ 显示上传组件
2. 切换模式调 `PUT /map/mode`
3. "用高德生成"按钮调 `POST /map/generate-by-amap`，成功后回显 URL + "最近生成于 X" 提示
4. 手动上传提示文案：**建议图片 ≤ 2MB，尺寸 4:3 或 3:2，格式 jpg/png**（后端目前不强校验，靠前端提示）
5. 编辑页可显示"行程已更新，建议重新生成地图"（若 `mapGeneratedAt < product.updateTime`）

### 小程序产品详情页
1. 读 `mapMode` 判断：
   - `NONE` → 不渲染地图模块
   - `AMAP_AUTO` / `UPLOAD` → 渲染 `routeMapUrl`
2. 支持 `routeMapUrl` 为空时兜底隐藏

---

## 部署前置（已在测试环境完成，生产部署前运维注意）

- [ ] Nacos `hl-product-service-v2-dev.yml` / `-prod.yml` 需配置 `amap.web-service-key`（与现有 AmapDrivingService 共用同一个 key）
- [ ] OSS 存储类 `product-route-map` groupKey 权限放通
- [ ] 先 DDL 后重启服务（`sql/alter_product_route_info_add_map_mode.sql`）

---

## 兼容性

- 老数据：`product_route_info.map_mode` 默认 `UPLOAD`，已有图片保留，小程序端展示不变
- 老接口：`ProductRouteSaveReqVO.mapMode` 可选，不传走原路径
- 老前端：不读 `mapMode` 也能工作（`routeMapUrl` 字段语义未变）
