# SGS SDK 展厅/公共展陈空间点位展示修复设计 日期:2026-06-29 ## 背景 当前 H5 导览在 `VITE_DATA_SOURCE_MODE=sdk` 时,3D 模型点位由 `GuideModelRepository.loadFloorPois(floorId)` 提供,链路为: ```text index.vue -> GuideMapShell.vue -> ThreeMap.vue -> GuideModelRepository.loadFloorPois(floorId) -> SgsSdkGuideModelRepository -> sgsSdkApiProvider.getFloorPois/getFloorSpaces/getNavigablePlaces -> sgsSdkGuideAdapter -> GuideRenderPoi[] ``` 现有 SGS 后端已经提供多楼层的 `spaces`、`pois`、`navigablePlaces`,其中 B2、1F、2F 等楼层具备展厅空间与出入口点位。但当前展厅点位展示不稳定,原因包括: - `spaces` 仅识别 `type === 'exhibition_hall'`,漏掉影院、报告厅、活动室、展览坡道等业务上属于公共展陈体验的空间。 - 展厅渲染点依赖 `navigablePlaces` 坐标;没有匹配入口时不会展示。 - `getFloorSpaces` / `getNavigablePlaces` 请求失败会被 `.catch(() => [])` 静默吞掉,运行时看起来像“没有展厅点位”。 - `ThreeMap` 在 overview / multi 模式下有点位密度裁剪;用户可能误以为展厅点位没有生成。 本设计选择推荐方案 B:在不做完整行业模型重构的前提下,修复展厅/公共展陈空间点位的生成、诊断与单层展示稳定性。 ## 目标 1. SDK 模式下,3D 单层模型能稳定展示展厅/公共展陈空间点位。 2. 将 `theater`、`education_activity`、`ramp` 等明确公共展陈体验空间纳入展示范围。 3. 保持数据边界清晰:`spaces` 表示空间,`navigablePlaces` 表示入口/可达目的地,渲染层只消费 `GuideRenderPoi`。 4. 路线能力仍以入口 `routeNodeId` 为准;没有路线数据或入口坐标时只做“位置预览”。 5. 增加诊断可观测性,避免接口失败或适配失败无声发生。 ## 非目标 本次不做完整专业化重构: - 不新增完整 `MuseumSpace` 渲染层。 - 不绘制空间 polygon / boundary。 - 不新增独立 label layer。 - 不把 explain/content 仓储切换为 SGS `spaces` 远程数据源。 - 不宣称正式导航、到达引导或定位精度。 ## 设计方案 ### 1. 扩展展陈空间识别 在 `src/data/adapters/sgsSdkGuideAdapter.ts` 中,将当前 `isExhibitionHallSpace(space)` 从单一类型判断扩展为公共展陈空间识别。 建议白名单: - `exhibition_hall`:正式展厅。 - `theater`:球幕影院、巨幕影院、动感多维影院、报告厅等。 - `education_activity`:科普实验室、活动室等可面向公众的教育展陈空间。 - `ramp`:名称包含“展览坡道”时纳入。 名称辅助关键词: - 展厅、临展、展览 - 影院、球幕、巨幕、报告厅 - 活动室、科普、实验室 - 展览坡道 - 宇宙、地球、演化、恐龙、人类、生物、生态、家园 输出仍保持为 `MuseumPoi(kind: 'hall')`,`primaryCategory.id` 保持 `exhibition_hall`,避免扩大页面和组件改动范围。 ### 2. 空间与入口匹配策略 展厅点位生成继续由 `toMuseumHallPoisFromSgs(spaces, navigablePlaces, floors, fallbackFloorId)` 负责,但匹配规则增强: 1. 先筛选 eligible spaces。 2. 从 `navigablePlaces` 中筛选与 eligible spaces 相关的入口/目的地。 3. 优先用 `ownerName` 匹配空间名称。 4. 其次用清洗后的 `place.name` 去掉“出入口/入口/出口/门”等后缀后匹配空间名称。 5. 如果一个空间有多个入口,保留在 `entrances` 中。 6. 展厅 POI 的主坐标优先取第一个有坐标的入口。 ### 3. 空间中心点 fallback 为避免“有空间但没有入口坐标就完全不显示”,增加 fallback: 1. 如果有匹配入口且入口有坐标,使用入口坐标。 2. 如果没有可用入口坐标,但 `space.center` 有坐标,生成仅位置预览的 hall POI。 3. 如果入口坐标和空间中心都没有,则不生成渲染点,但计入诊断。 需要注意:使用 `space.center` 的 hall POI 不能被当作可路线规划的目的地;其 `navigationReadiness` 保持“位置预览”,并且不要伪造 `routeNodeId`。 ### 4. 诊断与错误可观测性 当前 repository 中对 `getFloorPois/getFloorSpaces/getNavigablePlaces` 的错误处理是 `.catch(() => [])`。本次保留页面容错,但增加诊断输出。 建议实现轻量 dev 诊断函数或局部 warn: 每层记录: - `pois` 数量 - `spaces` 数量 - `eligibleSpaces` 数量 - `navigablePlaces` 数量 - `hallPois` 数量 - `hallPoisWithPosition` 数量 - 请求失败的 endpoint 生产环境不刷屏;开发环境可以 `console.warn('[SGS guide model] ...')`。如果项目已有 diagnostics 面板或数据完整性报告入口,优先复用。 ### 5. ThreeMap 展示策略 不做大 UI 改造,仅保证单层模式可验证: - `exhibition_hall` 保持 core category 与高优先级。 - floor/detail 模式展示所有有效展厅点位。 - overview/multi 模式继续允许密度裁剪,避免满屏标签。 - 聚焦/选中的点位继续不受裁剪影响。 如果源码确认 floor 模式仍会裁剪展厅点位,则只在 floor/detail 模式放宽展厅点位裁剪,不改变 overview/multi 策略。 ## 数据与用户语义 - 展厅空间:来自 SGS `spaces`。 - 展厅入口:来自 SGS `navigablePlaces`。 - 普通设施:来自 SGS `pois`。 - 模型渲染:统一消费 `GuideRenderPoi`。 - 用户文案:继续使用“位置预览”“查看位置”,不使用“开始馆内导航”“到达引导”等正式导航表述。 ## 测试与验证 ### 代码级验证 至少覆盖以下样例: - B2:宇宙厅、地球厅、演化厅、恐龙厅。 - 1F:临展厅01、临展厅02、展厅5人类厅,以及影院类公共展陈空间。 - 2F:生物厅、生态厅、家园厅。 - 4F:报告厅或活动室类公共空间在白名单定义内时可生成预览点。 ### 命令验证 实现完成后运行: ```powershell pnpm type-check pnpm lint pnpm build:h5 ``` ### H5 手动验证 如可启动 H5: 1. 使用 SDK 模式进入首页。 2. 切换到 B2、1F、2F 单层模型。 3. 检查展厅/公共展陈空间点位是否可见。 4. 点击点位后确认仍是位置预览语义。 5. 检查控制台诊断不出现接口失败或 hallPois 为 0 的异常。 ## 风险与约束 - 后端空间类型命名可能继续变化,因此类型白名单要集中定义,避免散落在组件中。 - 使用 `space.center` 只能支持位置预览,不能作为路线规划 node。 - overview/multi 模式仍可能因密度裁剪隐藏部分点位,这是预期行为。 - 本次不处理 explain 内容源与 SGS spaces 的正式打通。 ## 交付标准 1. SDK 模式下 `SgsSdkGuideModelRepository.loadFloorPois()` 可生成展厅/公共展陈空间 `GuideRenderPoi`。 2. 单层模型中展厅点位稳定可见。 3. 请求失败或适配失败有开发诊断,不再完全无声。 4. 类型检查、lint、H5 build 通过或如实报告失败原因。