Files
frontend-miniapp/docs/QA/guide-exhibits-miniapp-data-source-diagnosis-2026-07-02.md
lyf 8fed715235
Some checks failed
CI / verify (push) Has been cancelled
chore: sync latest project updates
2026-07-03 14:42:38 +08:00

752 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# `/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 接口只作为地图落点和位置预览的辅助数据。