752 lines
21 KiB
Markdown
752 lines
21 KiB
Markdown
# `/guide/exhibits` 与 miniapp 讲解接口数据源偏差诊断
|
||
|
||
诊断日期:2026-07-02
|
||
|
||
范围:只检查“讲解”业务线数据来源,不展开 SDK 地图渲染、楼层、POI、空间面、路网等地图业务。
|
||
|
||
本次结论基于两类证据:
|
||
|
||
- 本地源码:`E:\MyWork\深圳国际艺术馆\智慧导览\smart-navigation-system`
|
||
- 本项目源码:`E:\MyWork\深圳国际艺术馆\museum-guide\museum-guide-v4.0\frontend-miniapp`
|
||
- 真实 HTTP 接口:`http://1.92.206.90:3001`
|
||
|
||
## 1. 核心结论
|
||
|
||
`http://1.92.206.90:3001/guide/exhibits` 管理端页面展示的数据,与 `frontend-miniapp` 当前讲解业务接口返回的数据不一致,主要不是因为数据库完全不同,而是因为:
|
||
|
||
1. 页面和 miniapp 调用的接口不同。
|
||
2. 接口读取的表层级不同。
|
||
3. 同一张表上的过滤条件不同。
|
||
4. 统计字段的计算口径不同。
|
||
|
||
管理端 `/guide/exhibits` 使用的是完整讲解业务数据链:
|
||
|
||
```text
|
||
SGS_EXHIBITION_HALL
|
||
-> SGS_EXHIBIT_OUTLINE
|
||
-> SGS_EXHIBIT_ITEM / SGS_GUIDE_STOP
|
||
-> SGS_GUIDE_CONTENT
|
||
-> sgs_guide_audio_channel
|
||
```
|
||
|
||
miniapp 当前讲解页虽然已经接入部分 App 端讲解接口,但“业务单元 / 讲解点列表”实际走的是 SDK 地图点位接口:
|
||
|
||
```text
|
||
GET /app-api/gis/sdk/halls/{hallId}/guide-stops
|
||
```
|
||
|
||
该接口只返回 `SGS_GUIDE_STOP` 中已启用且已标定 `mapX/mapY` 的地图点位子集,不等价于管理端 `/guide/exhibits` 所展示的完整讲解业务数据。
|
||
|
||
因此,当前偏差的根因可以概括为:
|
||
|
||
```text
|
||
管理端读完整讲解业务结构;
|
||
miniapp 列表读 SDK 地图标定子集;
|
||
App 展厅统计又直接读 hall 表静态字段;
|
||
所以展厅统计、业务单元、讲解点数量、音频状态都会出现偏差。
|
||
```
|
||
|
||
## 2. 管理端 `/guide/exhibits` 页面实际数据来源
|
||
|
||
### 2.1 前端项目与页面源码
|
||
|
||
页面所属项目:
|
||
|
||
```text
|
||
E:\MyWork\深圳国际艺术馆\智慧导览\smart-navigation-system\sgs-frontend-map
|
||
```
|
||
|
||
页面入口:
|
||
|
||
```text
|
||
sgs-frontend-map/src/app/(main)/guide/exhibits/page.tsx
|
||
```
|
||
|
||
相关前端文件:
|
||
|
||
| 用途 | 文件 |
|
||
| --- | --- |
|
||
| 页面组件 | `sgs-frontend-map/src/app/(main)/guide/exhibits/page.tsx` |
|
||
| 展厅 / 业务单元 / 展品 API client | `sgs-frontend-map/src/api/map/exhibit.ts` |
|
||
| 讲解点 API client | `sgs-frontend-map/src/api/map/space.ts` |
|
||
| 左侧树组件 | `sgs-frontend-map/src/components/v2/exhibits/V2ExhibitTreeBrowser.tsx` |
|
||
| 讲解模式 / 讲解点面板 | `sgs-frontend-map/src/components/v2/exhibits/GuideStopsPanel.tsx` |
|
||
| Axios baseURL | `sgs-frontend-map/src/lib/api.ts`,默认 `/admin-api` |
|
||
|
||
### 2.2 页面实际调用接口
|
||
|
||
| 页面区域 | 前端方法 | 实际接口 |
|
||
| --- | --- | --- |
|
||
| 展厅树 | `ExhibitApi.getTree()` | `GET /admin-api/guide/exhibits/tree` |
|
||
| 业务单元子节点 | `ExhibitApi.getChildren(nodeId)` | `GET /admin-api/guide/exhibits/tree/{nodeId}/children` |
|
||
| 树搜索 | `ExhibitApi.searchTree()` | `GET /admin-api/guide/exhibits/tree/search` |
|
||
| 展品列表 | `ExhibitApi.getPage(params)` | `GET /admin-api/guide/exhibits/list` |
|
||
| 讲解模式 / 讲解点 | `StopApi.list(outlineId)` | `GET /admin-api/gis/guide-stop/list?outlineId=...` |
|
||
| 跨业务单元搜索讲解点 | `StopApi.listByHallId(hallId)` | `GET /admin-api/gis/guide-stop/list-by-hall?hallId=...` |
|
||
|
||
### 2.3 管理端后端链路
|
||
|
||
| 接口 | Controller | Service / Mapper | 主要表 |
|
||
| --- | --- | --- | --- |
|
||
| `/guide/exhibits/tree` | `V2ExhibitTreeController` | `ExhibitHallMapper`、`SgsExhibitOutlineMapper`、`ExhibitItemMapper` | `SGS_EXHIBITION_HALL`、`SGS_EXHIBIT_OUTLINE`、`SGS_EXHIBIT_ITEM`、`SGS_GUIDE_CONTENT` |
|
||
| `/guide/exhibits/tree/{nodeId}/children` | `V2ExhibitTreeController` | `SgsExhibitOutlineMapper`、`ExhibitItemMapper` | `SGS_EXHIBIT_OUTLINE`、`SGS_EXHIBIT_ITEM`、`SGS_GUIDE_CONTENT` |
|
||
| `/guide/exhibits/list` | `V2ExhibitCrudController` | `ExhibitServiceImpl`、`ExhibitItemMapper`、`GuideContentMapper` | `SGS_EXHIBIT_ITEM`、`SGS_GUIDE_CONTENT` |
|
||
| `/gis/guide-stop/list` | `GuideStopController` | `SgsGuideStopServiceImpl`、`SgsGuideStopMapper` | `SGS_GUIDE_STOP` |
|
||
| `/gis/guide-stop/list-by-hall` | `GuideStopController` | `SgsGuideStopServiceImpl`、`SgsExhibitOutlineMapper`、`SgsGuideStopMapper` | `SGS_EXHIBIT_OUTLINE`、`SGS_GUIDE_STOP` |
|
||
|
||
管理端源码里已经明确说明:
|
||
|
||
```text
|
||
展厅 — SGS_EXHIBITION_HALL
|
||
单元 — SGS_EXHIBIT_OUTLINE
|
||
展品 — SGS_EXHIBIT_ITEM
|
||
```
|
||
|
||
对应源码:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/controller/admin/guide/V2ExhibitTreeController.java
|
||
```
|
||
|
||
### 2.4 管理端统计口径
|
||
|
||
管理端 `/guide/exhibits/tree` 不直接使用 `SGS_EXHIBITION_HALL.exhibitCount` 作为展示统计。
|
||
|
||
它会:
|
||
|
||
1. 读取启用展厅:`SGS_EXHIBITION_HALL.status = 1`
|
||
2. 找到展厅下所有 `SGS_EXHIBIT_OUTLINE` 后代节点。
|
||
3. 按 outline 聚合 `SGS_EXHIBIT_ITEM` 数量。
|
||
4. 通过 `SGS_GUIDE_CONTENT` 判断哪些展品有讲解内容。
|
||
5. 汇总到展厅 / 业务单元节点展示。
|
||
|
||
因此管理端页面上的展厅数量、业务单元数量、讲解内容数量是“动态聚合结果”,不是 hall 表上一个静态字段。
|
||
|
||
## 3. miniapp 当前讲解页实际数据来源
|
||
|
||
### 3.1 当前配置
|
||
|
||
本项目:
|
||
|
||
```text
|
||
E:\MyWork\深圳国际艺术馆\museum-guide\museum-guide-v4.0\frontend-miniapp
|
||
```
|
||
|
||
配置文件:
|
||
|
||
```text
|
||
.env
|
||
src/config/dataSource.ts
|
||
```
|
||
|
||
当前配置:
|
||
|
||
```text
|
||
VITE_DATA_SOURCE_MODE=sdk
|
||
VITE_GUIDE_CONTENT_SOURCE_MODE=remote
|
||
VITE_API_BASE_URL=/app-api
|
||
VITE_SGS_API_BASE_URL=/app-api
|
||
```
|
||
|
||
含义:
|
||
|
||
- 地图/导览运行模式是 `sdk`。
|
||
- 讲解内容数据源是 `remote`。
|
||
- App API 基础路径是 `/app-api`。
|
||
- 但 `sdk` 模式不应被理解为讲解业务列表的数据源;SDK 只应服务地图渲染/点位层。
|
||
|
||
### 3.2 miniapp 前端方法与接口
|
||
|
||
| miniapp 展示数据 | 前端方法链路 | 实际接口 |
|
||
| --- | --- | --- |
|
||
| 展厅列表 | `ExplainUseCase.loadExplainHalls()` -> `ExplainRepository.listHalls()` -> `BackendExplainContentProvider.requestHallList()` | `GET /app-api/gis/hall/list` |
|
||
| 业务单元统计 | `loadExplainHallSummaries()` -> `loadTemporaryBusinessUnitsByHall()` -> `groupGuideStopsByOutline()` | 基于 SDK guide-stops 分组 |
|
||
| 讲解点列表 | `BackendExplainContentProvider.listGuideStopsByHall()` -> `sgsSdkApiProvider.getGuideStopsByHall()` | `GET /app-api/gis/sdk/halls/{hallId}/guide-stops` |
|
||
| 讲解点详情 | `AudioPlayInfoRepository.getStopInfo()` | `GET /app-api/gis/guide/stop/info` |
|
||
| 音频播放信息 | `AudioPlayInfoRepository.getPlayInfo()` | `GET /app-api/gis/guide/audio/play-info` |
|
||
| 正文 | `AudioPlayInfoRepository.getTextInfo()` | `GET /app-api/gis/guide/audio/text-info` |
|
||
|
||
关键问题:
|
||
|
||
```text
|
||
miniapp 的“业务单元 / 讲解点列表”不是从讲解业务树接口读取,
|
||
而是从 SDK 地图点位接口读取。
|
||
```
|
||
|
||
## 4. App API 后端读取表与管理端差异
|
||
|
||
### 4.1 `/app-api/gis/hall/list`
|
||
|
||
Controller:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/controller/app/guide/AppExhibitController.java
|
||
```
|
||
|
||
接口:
|
||
|
||
```text
|
||
GET /app-api/gis/hall/list
|
||
```
|
||
|
||
读取:
|
||
|
||
```text
|
||
SGS_EXHIBITION_HALL
|
||
```
|
||
|
||
过滤:
|
||
|
||
```text
|
||
status = 1
|
||
```
|
||
|
||
返回 `exhibitCount` 的方式:
|
||
|
||
```text
|
||
vo.setExhibitCount(h.getExhibitCount())
|
||
```
|
||
|
||
也就是说,App 端 hall/list 的 `exhibitCount` 直接来自 `SGS_EXHIBITION_HALL.exhibitCount` 字段。
|
||
|
||
这与管理端 `/guide/exhibits/tree` 动态聚合 `SGS_EXHIBIT_OUTLINE + SGS_EXHIBIT_ITEM + SGS_GUIDE_CONTENT` 的口径不同。
|
||
|
||
结论:
|
||
|
||
```text
|
||
即使两边都读取 SGS_EXHIBITION_HALL,
|
||
展厅统计也可能不同。
|
||
管理端显示的是动态聚合数量;
|
||
App API 返回的是 hall 表静态 exhibitCount 字段。
|
||
```
|
||
|
||
### 4.2 `/app-api/gis/zone/list-by-hall`
|
||
|
||
Controller:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/controller/app/guide/AppExhibitController.java
|
||
```
|
||
|
||
接口:
|
||
|
||
```text
|
||
GET /app-api/gis/zone/list-by-hall?hallId=...
|
||
```
|
||
|
||
源码注释:
|
||
|
||
```text
|
||
展区数据应该从 SGS_EXHIBIT_OUTLINE 读取,这里返回空列表
|
||
TODO: 如果需要展区功能,应该查询 SGS_EXHIBIT_OUTLINE 表
|
||
```
|
||
|
||
结论:
|
||
|
||
```text
|
||
App 端目前没有真正提供与管理端业务单元一致的接口。
|
||
管理端业务单元来自 SGS_EXHIBIT_OUTLINE;
|
||
App 端 zone/list-by-hall 当前返回空数组。
|
||
```
|
||
|
||
### 4.3 `/app-api/gis/sdk/halls/{hallId}/guide-stops`
|
||
|
||
Controller:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/controller/app/spatial/SdkMapController.java
|
||
```
|
||
|
||
Service:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/service/sdk/SdkMapServiceImpl.java
|
||
```
|
||
|
||
接口:
|
||
|
||
```text
|
||
GET /app-api/gis/sdk/halls/{hallId}/guide-stops
|
||
```
|
||
|
||
读取主表:
|
||
|
||
```text
|
||
SGS_GUIDE_STOP
|
||
```
|
||
|
||
过滤条件:
|
||
|
||
```text
|
||
status in GuideStopAvailability.AVAILABLE_STATUSES
|
||
mapX is not null
|
||
mapY is not null
|
||
```
|
||
|
||
其中 `GuideStopAvailability.AVAILABLE_STATUSES = {0, 1}`,用于兼容历史数据中 `0=启用`、`1=启用` 两套状态。
|
||
|
||
源码注释明确说明:
|
||
|
||
```text
|
||
SDK 只输出可落到地图上的讲解点;未标定的属于讲解内容,不进入点位层。
|
||
```
|
||
|
||
结论:
|
||
|
||
```text
|
||
该接口是 SDK 地图点位接口,不是完整讲解业务列表接口。
|
||
它只返回已启用且已地图标定 mapX/mapY 的讲解点。
|
||
未标定但有讲解内容、有音频、有正文的讲解点,会被该接口过滤掉。
|
||
```
|
||
|
||
### 4.4 `/app-api/gis/guide/stop/info`
|
||
|
||
Controller:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/controller/app/guide/AppGuideStopController.java
|
||
```
|
||
|
||
Service:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/service/guide/AppGuideStopServiceImpl.java
|
||
```
|
||
|
||
接口:
|
||
|
||
```text
|
||
GET /app-api/gis/guide/stop/info?targetType=STOP&targetId=...&lang=zh-CN
|
||
```
|
||
|
||
读取:
|
||
|
||
```text
|
||
SGS_GUIDE_STOP
|
||
SGS_GUIDE_CONTENT
|
||
```
|
||
|
||
音频摘要复用:
|
||
|
||
```text
|
||
GuideAudioPlayService
|
||
```
|
||
|
||
注意:单点详情不需要叠加 `mapX/mapY` 过滤。`GuideStopAvailability.java` 源码注释明确说明:
|
||
|
||
```text
|
||
SDK 列表查询需要叠加 mapX/mapY 过滤,但单点 ID 查询(stop-info / play-info / text-info)不需要叠加。
|
||
```
|
||
|
||
结论:
|
||
|
||
```text
|
||
同一个 stopId 可能不出现在 SDK 地图列表中,
|
||
但仍然可以通过 stop-info / play-info / text-info 查到讲解详情、音频、正文。
|
||
```
|
||
|
||
### 4.5 `/app-api/gis/guide/audio/play-info` 与 `text-info`
|
||
|
||
Controller:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/controller/app/guide/AppGuideAudioController.java
|
||
```
|
||
|
||
Service:
|
||
|
||
```text
|
||
yudao-module-gis/src/main/java/cn/iocoder/yudao/module/gis/service/guide/GuideAudioPlayServiceImpl.java
|
||
```
|
||
|
||
读取:
|
||
|
||
```text
|
||
SGS_GUIDE_STOP
|
||
SGS_GUIDE_CONTENT
|
||
sgs_guide_audio_channel
|
||
```
|
||
|
||
主要逻辑:
|
||
|
||
- `play-info` 判断是否有可播放音频。
|
||
- `text-info` 判断是否有同语言正文。
|
||
- 播放状态以 `SGS_GUIDE_CONTENT` 和 `sgs_guide_audio_channel` 的发布状态为准。
|
||
- 不以 SDK guide-stops 返回的 `hasAudio` 为准。
|
||
|
||
结论:
|
||
|
||
```text
|
||
SDK guide-stops 的 hasAudio 不等价于讲解播放服务的 hasAudio / playable。
|
||
SDK 列表的 hasAudio 主要看点位自身字段;
|
||
play-info 的 playable 看讲解内容和正式音频通道。
|
||
```
|
||
|
||
## 5. 真实接口测试结果
|
||
|
||
本轮复测基础地址:
|
||
|
||
```text
|
||
http://1.92.206.90:3001
|
||
```
|
||
|
||
### 5.1 展厅列表
|
||
|
||
请求:
|
||
|
||
```bash
|
||
GET http://1.92.206.90:3001/app-api/gis/hall/list
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
HTTP 200
|
||
code = 0
|
||
msg = ""
|
||
data.length = 8
|
||
```
|
||
|
||
前 5 条:
|
||
|
||
| id | name | exhibitCount |
|
||
| --- | --- | --- |
|
||
| `715792102100832258` | 宇宙厅 | 0 |
|
||
| `715792102100832257` | 地球厅 | 0 |
|
||
| `715792102100832259` | 演化厅 | 0 |
|
||
| `715792102100832260` | 恐龙厅 | 0 |
|
||
| `715792102100832256` | 人类厅 | 0 |
|
||
|
||
说明:
|
||
|
||
```text
|
||
这里的 exhibitCount 来自 SGS_EXHIBITION_HALL.exhibitCount,
|
||
不能直接拿来对比管理端 /guide/exhibits 页面动态聚合出的展品/讲解数量。
|
||
```
|
||
|
||
### 5.2 宇宙厅 SDK guide-stops
|
||
|
||
取 hallId:
|
||
|
||
```text
|
||
715792102100832258
|
||
```
|
||
|
||
请求:
|
||
|
||
```bash
|
||
GET http://1.92.206.90:3001/app-api/gis/sdk/halls/715792102100832258/guide-stops
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
HTTP 200
|
||
code = 0
|
||
msg = ""
|
||
data.length = 2
|
||
```
|
||
|
||
返回样例:
|
||
|
||
| id | name | targetType | targetId | outlineId | outlineName | hasAudio |
|
||
| --- | --- | --- | --- | --- | --- | --- |
|
||
| `1823450596808612` | 古典星盘 讲解 | `GUIDE_STOP` | `1823450596808612` | `7467940240901013505` | 第一单元:仰望苍穹——人类对宇宙认识的历程 | false |
|
||
| `1823450596814245` | 火星提森特陨石 讲解 | `GUIDE_STOP` | `1823450596814245` | `7467940240901013507` | 第三单元:采石知天——行星科学与深空探测 | false |
|
||
|
||
说明:
|
||
|
||
```text
|
||
这里的 2 条不是宇宙厅完整讲解点数量,
|
||
而是宇宙厅下已启用且已标定 mapX/mapY 的 SDK 地图点位数量。
|
||
```
|
||
|
||
### 5.3 stop-info
|
||
|
||
取 guideStop.id:
|
||
|
||
```text
|
||
1823450596808612
|
||
```
|
||
|
||
请求:
|
||
|
||
```bash
|
||
GET http://1.92.206.90:3001/app-api/gis/guide/stop/info?targetType=STOP&targetId=1823450596808612&lang=zh-CN
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
HTTP 200
|
||
code = 0
|
||
msg = ""
|
||
```
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 值 |
|
||
| --- | --- |
|
||
| `available` | true |
|
||
| `targetType` | STOP |
|
||
| `targetId` | 1823450596808612 |
|
||
| `resolvedStopId` | 1823450596808612 |
|
||
| `title` | 古典星盘 讲解 |
|
||
| `playTargetType` | STOP |
|
||
| `playTargetId` | 1823450596808612 |
|
||
| `hasAudio` | true |
|
||
| `hasText` | true |
|
||
| `audioStatus` | READY |
|
||
| `reason` | null |
|
||
|
||
### 5.4 play-info
|
||
|
||
请求:
|
||
|
||
```bash
|
||
GET http://1.92.206.90:3001/app-api/gis/guide/audio/play-info?targetType=STOP&targetId=1823450596808612&lang=zh-CN
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
HTTP 200
|
||
code = 0
|
||
msg = ""
|
||
```
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 值 |
|
||
| --- | --- |
|
||
| `playable` | true |
|
||
| `playUrl` | 存在 |
|
||
| `duration` | 57 |
|
||
| `audioId` | 1253 |
|
||
| `title` | `[古典星盘] 标准解说` |
|
||
| `reason` | null |
|
||
|
||
### 5.5 text-info
|
||
|
||
请求:
|
||
|
||
```bash
|
||
GET http://1.92.206.90:3001/app-api/gis/guide/audio/text-info?targetType=STOP&targetId=1823450596808612&lang=zh-CN
|
||
```
|
||
|
||
结果:
|
||
|
||
```text
|
||
HTTP 200
|
||
code = 0
|
||
msg = ""
|
||
```
|
||
|
||
关键字段:
|
||
|
||
| 字段 | 值 |
|
||
| --- | --- |
|
||
| `available` | true |
|
||
| `textLength` | 269 |
|
||
| `title` | `[古典星盘] 标准解说` |
|
||
| `reason` | null |
|
||
|
||
正文摘要:
|
||
|
||
```text
|
||
这九个16至19世纪的金属星盘,是前卫星时代的“科学计算器”,集导航、计时、天文功能于一体……
|
||
```
|
||
|
||
## 6. 为什么 `/guide/exhibits` 与 miniapp 接口返回数据不一致
|
||
|
||
### 6.1 展厅列表看起来同源,但统计字段不同源
|
||
|
||
两边都可能读取 `SGS_EXHIBITION_HALL`,但:
|
||
|
||
| 端 | 展厅基础表 | 数量/统计口径 |
|
||
| --- | --- | --- |
|
||
| 管理端 `/guide/exhibits` | `SGS_EXHIBITION_HALL` | 通过 `SGS_EXHIBIT_OUTLINE` 后代聚合 `SGS_EXHIBIT_ITEM`、`SGS_GUIDE_CONTENT` |
|
||
| miniapp `/app-api/gis/hall/list` | `SGS_EXHIBITION_HALL` | 直接返回 `SGS_EXHIBITION_HALL.exhibitCount` |
|
||
|
||
所以线上 App API 返回的 `exhibitCount=0`,不能证明管理端页面也应该显示 0。
|
||
|
||
偏差原因:
|
||
|
||
```text
|
||
管理端动态算;
|
||
App API 直接读静态字段。
|
||
```
|
||
|
||
### 6.2 业务单元不是同一个接口来源
|
||
|
||
| 端 | 接口 | 表 |
|
||
| --- | --- | --- |
|
||
| 管理端 | `/admin-api/guide/exhibits/tree/{hallId}/children` | `SGS_EXHIBIT_OUTLINE` |
|
||
| miniapp 当前 | `/app-api/gis/zone/list-by-hall` | 源码 TODO,当前返回空数组 |
|
||
| miniapp 实际展示分组 | 基于 `/app-api/gis/sdk/halls/{hallId}/guide-stops` 的 `outlineId/outlineName` 分组 | SDK 点位子集 |
|
||
|
||
偏差原因:
|
||
|
||
```text
|
||
管理端业务单元来自完整 SGS_EXHIBIT_OUTLINE;
|
||
miniapp 没有使用等价 App 端 outline 接口,
|
||
而是从 SDK guide-stops 返回的少量点位里反推业务单元。
|
||
```
|
||
|
||
这会导致:
|
||
|
||
- 没有已标定讲解点的业务单元不显示。
|
||
- 有业务单元但未落图的讲解点不显示。
|
||
- 业务单元数量比管理端少。
|
||
|
||
### 6.3 讲解点列表不是同一个业务口径
|
||
|
||
| 端 | 接口 | 表 | 过滤 |
|
||
| --- | --- | --- | --- |
|
||
| 管理端讲解模式面板 | `/admin-api/gis/guide-stop/list?outlineId=...` | `SGS_GUIDE_STOP` | 按 `outlineId` |
|
||
| miniapp 当前列表 | `/app-api/gis/sdk/halls/{hallId}/guide-stops` | `SGS_GUIDE_STOP` | `status in {0,1}` 且 `mapX/mapY` 非空 |
|
||
|
||
偏差原因:
|
||
|
||
```text
|
||
管理端展示讲解业务点;
|
||
miniapp 当前展示 SDK 地图可落点。
|
||
```
|
||
|
||
这两个集合的关系是:
|
||
|
||
```text
|
||
SDK guide-stops ⊂ 管理端讲解业务 guide-stops
|
||
```
|
||
|
||
即 SDK guide-stops 通常是管理端讲解点中的一个子集。
|
||
|
||
### 6.4 音频状态字段不是同一个口径
|
||
|
||
真实接口已证明同一个 `stopId=1823450596808612`:
|
||
|
||
| 接口 | 字段 | 值 |
|
||
| --- | --- | --- |
|
||
| `/app-api/gis/sdk/halls/{hallId}/guide-stops` | `hasAudio` | false |
|
||
| `/app-api/gis/guide/stop/info` | `hasAudio` | true |
|
||
| `/app-api/gis/guide/audio/play-info` | `playable` | true |
|
||
| `/app-api/gis/guide/audio/text-info` | `available` | true |
|
||
|
||
偏差原因:
|
||
|
||
```text
|
||
SDK guide-stops 的 hasAudio 主要看 SGS_GUIDE_STOP.audioUrl;
|
||
讲解播放接口的 playable 看 SGS_GUIDE_CONTENT 与 sgs_guide_audio_channel。
|
||
```
|
||
|
||
所以 SDK 列表中的 `hasAudio=false` 不应作为讲解业务播放状态。
|
||
|
||
## 7. 与接口契约的关系
|
||
|
||
`docs/miniapp_integration.md` 中的 App 端讲解接口契约约定:
|
||
|
||
- `stop-info` 用于进入讲解页时获取标题、图片、绑定展品、当前语言音频/正文状态。
|
||
- `play-info` 用于点击播放时获取唯一可播放 `playUrl`。
|
||
- `text-info` 用于展开正文时按需获取讲解词全文。
|
||
- `available=false` / `playable=false` 是业务不可用,不一定代表 HTTP 失败。
|
||
- 不可用响应仍可返回 `code=0`,客户端应看 `data.available`、`data.playable` 和 `reason`。
|
||
|
||
这套契约解决的是“单个 ITEM / STOP 的展示、播放、正文”问题。
|
||
|
||
它没有解决:
|
||
|
||
```text
|
||
按展厅获取完整业务单元树;
|
||
按业务单元获取完整讲解点列表;
|
||
按管理端相同口径统计展品数/讲解数。
|
||
```
|
||
|
||
因此当前 miniapp 需要补充“讲解业务列表 / 树”类 App API,而不是继续用 SDK 地图点位接口替代。
|
||
|
||
## 8. 推荐修复方向
|
||
|
||
### 8.1 后端补 App 端讲解业务接口
|
||
|
||
建议新增或实现以下接口之一:
|
||
|
||
```text
|
||
GET /app-api/gis/guide/halls/{hallId}/outlines
|
||
GET /app-api/gis/guide/outlines/{outlineId}/stops
|
||
```
|
||
|
||
或组合接口:
|
||
|
||
```text
|
||
GET /app-api/gis/guide/halls/{hallId}/explain-tree
|
||
```
|
||
|
||
接口读取口径应对齐管理端:
|
||
|
||
```text
|
||
SGS_EXHIBITION_HALL
|
||
SGS_EXHIBIT_OUTLINE
|
||
SGS_GUIDE_STOP
|
||
SGS_EXHIBIT_ITEM
|
||
SGS_GUIDE_CONTENT
|
||
sgs_guide_audio_channel
|
||
```
|
||
|
||
要求:
|
||
|
||
- 不按 `mapX/mapY` 过滤讲解点。
|
||
- 业务单元从 `SGS_EXHIBIT_OUTLINE` 获取。
|
||
- 讲解点从 `SGS_GUIDE_STOP` 获取。
|
||
- 展品绑定关系从 `SGS_EXHIBIT_ITEM.stopId` 获取。
|
||
- 音频状态复用 `GuideAudioPlayService` 的摘要口径。
|
||
- 展厅/业务单元统计口径对齐管理端 `/guide/exhibits/tree`。
|
||
|
||
### 8.2 前端替换列表数据源
|
||
|
||
miniapp 前端应调整:
|
||
|
||
```text
|
||
BackendExplainContentProvider.listGuideStopsByHall()
|
||
BackendExplainContentProvider.listTemporaryBusinessUnitsByHall()
|
||
```
|
||
|
||
不要再从:
|
||
|
||
```text
|
||
/app-api/gis/sdk/halls/{hallId}/guide-stops
|
||
```
|
||
|
||
生成完整讲解业务单元和讲解点列表。
|
||
|
||
SDK guide-stops 可以保留为“查看位置 / 地图落点预览”的辅助数据,但不能作为讲解业务完整列表数据源。
|
||
|
||
### 8.3 展厅统计修复
|
||
|
||
`/app-api/gis/hall/list` 的 `exhibitCount` 当前直接来自 `SGS_EXHIBITION_HALL.exhibitCount`。
|
||
|
||
如果 miniapp 需要展示与管理端一致的统计,应选择其一:
|
||
|
||
1. 后端在 `hall/list` 中动态聚合管理端同口径统计。
|
||
2. 新增 `guide/halls/{hallId}/explain-tree` 时返回统计。
|
||
3. 定期维护 `SGS_EXHIBITION_HALL.exhibitCount`,并明确它与管理端动态统计一致。
|
||
|
||
推荐优先采用第 2 种:在讲解业务树接口中返回统计,避免让通用 hall/list 承担复杂业务聚合。
|
||
|
||
## 9. 最终判断
|
||
|
||
`/guide/exhibits` 页面展示数据和 `frontend-miniapp` 当前接口返回数据不一致,根因不是简单的“接口坏了”,而是:
|
||
|
||
```text
|
||
管理端 /guide/exhibits 读取完整讲解业务表,并动态聚合统计;
|
||
miniapp 当前展厅列表读取 hall 表静态 exhibitCount;
|
||
miniapp 当前业务单元和讲解点列表读取 SDK 地图标定点位子集;
|
||
miniapp 单点详情/播放/正文又读取讲解业务内容表和音频通道表。
|
||
```
|
||
|
||
因此当前 miniapp 同时混用了:
|
||
|
||
- 讲解业务数据源:`SGS_EXHIBITION_HALL`、`SGS_GUIDE_STOP`、`SGS_GUIDE_CONTENT`、`sgs_guide_audio_channel`
|
||
- SDK 地图数据源/点位口径:`SGS_GUIDE_STOP` 中已标定 `mapX/mapY` 的子集
|
||
- 静态统计字段:`SGS_EXHIBITION_HALL.exhibitCount`
|
||
|
||
正确方向是把“讲解业务列表 / 业务单元 / 讲解点数量 / 讲解模式”统一切回讲解业务接口,SDK 接口只作为地图落点和位置预览的辅助数据。
|