feat(product): 行程集合地/解散地从行政区改高德 POI 精准定位 (#1570)
@mmg 前端 picker 切换 + 落库 JSON schema 升级。后端 PR #1570 已合 dev + 部署测试服 round-trip 完成 (#1563)。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
这个提交包含在:
父节点
4c376c73dc
当前提交
85f2f9e946
@ -0,0 +1,144 @@
|
||||
# 行程编排集合地/解散地:行政区 → 高德 POI 精准定位
|
||||
|
||||
**类型**: 后端 FEAT(字段扩展+读路径增强) + 前端 picker 切换
|
||||
**关联**: 工单 #1563 / PR #1570
|
||||
**日期**: 2026-04-30
|
||||
**前端处理者**: mmg
|
||||
**影响范围**: 管理后台产品编辑页 Step 2「行程编排」→ DAY X 的「开始 / 结束」字段(即 `gatherPlace` / `dismissalPlace`)
|
||||
|
||||
---
|
||||
|
||||
## 业务目的
|
||||
|
||||
集合地 / 解散地从「行政区」(如「海拉尔区」)升级为「精准 POI」(如「海拉尔东山国际机场 / 海拉尔火车站」)。前端 `gatherPlace/dismissalPlace` 选择器从行政区下拉换成**高德 POI Autocomplete**。
|
||||
|
||||
途经路线 (`routePoints`) 不在本次范围内(已是 lng/lat 结构)。
|
||||
|
||||
---
|
||||
|
||||
## JSON Schema 升级
|
||||
|
||||
### 新格式(POI 精准定位,2026-04-30 起新数据按这个落库)
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"name": "海拉尔东山国际机场", // POI 名称
|
||||
"address": "内蒙古呼伦贝尔市海拉尔区机场路", // 详细地址
|
||||
"location": { "lng": 119.825, "lat": 49.205 },// 嵌套对象,POI 精确坐标
|
||||
"poiId": "B0FFGTEST1", // 高德 POI ID
|
||||
"adcode": "150702", // POI 解析所属行政区编码
|
||||
"cityName": "呼伦贝尔市", // POI 解析所属城市
|
||||
"districtName": "海拉尔区" // POI 解析所属行政区
|
||||
}
|
||||
```
|
||||
|
||||
### 老格式(行政区,2026-04-30 之前已落库的存量数据,零迁移继续工作)
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"name": "海拉尔区",
|
||||
"level": "district",
|
||||
"adcode": "150702",
|
||||
"fullPath": "内蒙古自治区/呼伦贝尔市/海拉尔区",
|
||||
"levelName": "区/县"
|
||||
}
|
||||
```
|
||||
|
||||
后端**同时兼容三种格式**:
|
||||
- 新 POI 精准定位(含 `location`)
|
||||
- 老行政区无 `center`(依赖 `adcode` 反查)
|
||||
- 更早期行政区带 `center: 'lng,lat'`(直接 split)
|
||||
|
||||
---
|
||||
|
||||
## mmg 前端要做的事(hl-ui 仓库)
|
||||
|
||||
### 1. 替换 picker 组件
|
||||
|
||||
`src/views/product/edit/Step2*.vue` 行程编排 DAY X 块里,「开始」「结束」两个 `n-select` / 行政区 picker,**替换成高德 POI Autocomplete 输入框**。
|
||||
|
||||
参考高德 JS API:[`AMap.Autocomplete` + `AMap.PlaceSearch`](https://lbs.amap.com/api/javascript-api-v2/documentation#autocomplete);输入关键字 → 用户选择 POI → 把 POI 数据组装成上面的新 JSON 结构。
|
||||
|
||||
### 2. 落库 JSON 字段映射(高德 POI → 后端字段)
|
||||
|
||||
```js
|
||||
// 高德 PlaceSearch 单个 POI 结果 → 后端 gatherPlace/dismissalPlace
|
||||
function poiToPlace(poi) {
|
||||
return {
|
||||
name: poi.name, // POI 名称
|
||||
address: poi.address || '', // 详细地址
|
||||
location: {
|
||||
lng: Number(poi.location.lng), // 高德 LngLat 对象
|
||||
lat: Number(poi.location.lat)
|
||||
},
|
||||
poiId: poi.id || '',
|
||||
adcode: poi.adcode || '', // POI 自带 adcode
|
||||
cityName: poi.cityname || '', // 高德 cityname 全小写
|
||||
districtName: poi.adname || '' // 高德 adname
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### 3. PUT 行程接口
|
||||
|
||||
接口路径不变:`PUT /admin/product/item/{productId}/itinerary`,`days[].gatherPlace` / `days[].dismissalPlace` 用上面的新 JSON 结构。后端字段全保留(向后兼容)。
|
||||
|
||||
### 4. 详情回显
|
||||
|
||||
`GET /admin/product/item/{productId}` 的 `data.itinerary[i].gatherPlace` / `dismissalPlace`:
|
||||
- **新数据**:包含 `name / address / location / poiId / adcode / cityName / districtName`(7 字段全在)
|
||||
- **老数据**:包含 `name / level / adcode / fullPath / levelName`(5 字段)
|
||||
- 前端组件渲染时按字段存在性切换:有 `location.lng` 就用 POI 模式回显;否则按老行政区回显(兼容期)
|
||||
|
||||
---
|
||||
|
||||
## 后端测试服 round-trip(已完成)
|
||||
|
||||
测试服部署:commit `982558f9` 已部署 hl-product-service-v2 + hl-order-service-v2 双实例。
|
||||
|
||||
```bash
|
||||
# 1) 老格式产品 GET 详情 → PlaceItem 老字段完整回显(零回归)
|
||||
GET /admin/product/item/2047268852147875842
|
||||
→ day1.gatherPlace = {"name":"海拉尔区","level":"district","adcode":"150702","fullPath":"内蒙古...","levelName":"区/县"} ✅
|
||||
|
||||
# 2) PUT 新 POI 格式 → GET 详情回显 7 字段全在
|
||||
PUT /admin/product/item/{draftId}/itinerary
|
||||
body: { days:[{ gatherPlace:{name,address,location:{lng,lat},poiId,adcode,cityName,districtName} }] }
|
||||
→ HTTP 200 「行程保存成功」
|
||||
GET → day1.gatherPlace 7 字段完整含 location.lng=119.825/lat=49.205 ✅
|
||||
|
||||
# 3) 同 day 混合格式 (gather=POI, dismiss=老) 兼容
|
||||
→ 两边各自字段完整回显,互不干扰 ✅
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 后端改动(参考)
|
||||
|
||||
13 个文件 +846 / -48,PR #1570:
|
||||
|
||||
- `InternalProductDetailVO.PlaceItem` + `ProductDetailVO.PlaceItem` (Feign 镜像) **扩展 7 个 POI 字段 + 嵌套 Location 静态类**,旧字段保留兼容
|
||||
- `MpProductRouteMapService.parsePlaceVO`:路径优先级 `location → center → adcode 反查`
|
||||
- `AmapDrivingService.parseCenterToLngLat`:同上优先级
|
||||
- `TeamReportService.parseCityFromSnapshot`:取城市优先 `cityName/districtName`,回退 `fullPath`
|
||||
- VO 注释批量升级三种格式说明
|
||||
- 单测 +13(含 Hutool BeanUtil 嵌套 Map → Location 运行时验证)
|
||||
- DB schema 不变(仍是 JSON 列)
|
||||
- 老数据零迁移
|
||||
|
||||
---
|
||||
|
||||
## 风险 / 兼容性
|
||||
|
||||
- **零回归承诺**:老行政区数据继续按原行为工作(路线图 origin/destination / 每日里程 / 团报城市 全部正常)
|
||||
- **新旧混合期**:同一产品 itinerary 不同 day 可以混存新 POI / 老行政区结构,互不影响
|
||||
- **降级**:POI 缺 `location` 时自动回退到 `adcode` 反查中心点(高德 API),与现行 `MpProductRouteMapService` 老路径一致
|
||||
|
||||
---
|
||||
|
||||
## 联调建议
|
||||
|
||||
mmg 前端改完后:
|
||||
1. 本地起 mock 服务返回新 POI 结构,验证组件回显
|
||||
2. 接到测试服 `api.test.1814.love:9443` 后端,PUT → GET round-trip 验证字段对齐
|
||||
3. 看路线图 / 团报 / 每日里程,确认坐标用的是 POI 精确坐标(比之前 adcode 中心点更精准)
|
||||
正在加载...
x
在新工单中引用
屏蔽一个用户