修复馆内模型初始视图与点位返回复位
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-15 18:20:18 +08:00
parent 1072b25c46
commit 6566d38cb0
11 changed files with 568 additions and 44 deletions

View File

@@ -1,6 +1,6 @@
---
name: shenzhen-natural-museum-dev
description: Shenzhen Natural Museum mobile H5 spatial content guide architecture and client visual specification standards. Use when working in this frontend-miniapp project on guide and explain businesses, visual styling, typography, hall icons, homepage tab labels, indoor 3D/Three.js/GLB, SGS Map SDK H5 integration, iframe/postMessage SDK rendering, API/static data-source switching, POI/location preview, exhibit/hall/facility content, audio explanation, transcript/media data, Tencent Map/outdoor reference logic, static nav assets, Museum Content/Guide/Explain Data Access Layers, provider/adapter/repository architecture, route_graph/nav_data readiness, browser-simulated H5 user-flow audits, business-logic audits, engineering architecture reviews, legacy demo data cleanup, mobile overlay/canvas compatibility, and quality gates. Treat mini-program/mp-weixin as out of scope unless the user explicitly asks for it.
description: Shenzhen Natural Museum mobile H5 guide/explain architecture, indoor spatial rendering, content data, and client visual standards. Use in frontend-miniapp for guide/explain flows; visual styling, typography, hall icons, and homepage tabs; Three.js/GLB; unified guide-model initial state; deterministic overview/floor camera baselines; POI-detail return resets; async request invalidation; SGS Map SDK/iframe/postMessage integration; static/API data-source switching; POI/location previews; exhibit, hall, facility, audio, transcript, or media work; Tencent Map/outdoor logic; nav assets and data-layer architecture; route readiness; H5 browser-flow or business-logic audits; legacy-data cleanup; mobile canvas overlays; and quality gates. Treat mp-weixin as out of scope unless explicitly requested.
---
# Shenzhen Natural Museum Dev
@@ -234,6 +234,9 @@ Use this workflow when the user asks to connect the SGS Map SDK to the H5 guide
- Indoor 3D should load GLB/GLTF resources from the clean package under `static/nav-assets/...` while preserving texture/bin relationships.
- Initial indoor 3D entry should load the full building model when that is the product requirement; switch to a single floor only after zoom/focus/explicit floor action.
- Treat guide-model state restoration as one state-management contract, not as page-specific cleanup. Read and follow [references/guide-model-state-baseline.md](references/guide-model-state-baseline.md) whenever work touches initial model state, overview/floor camera baselines, POI focus, detail navigation/return, floor loading, reset behavior, or model async races.
- Keep `GUIDE_MODEL_INITIAL_STATE`, floor-view baselines, reset actions, and one-shot POI-detail return context behind the existing shared guide-model state boundary. Do not let search, map-click, hall, exhibit, or facility flows own separate reset behavior.
- Preserve the mounted `ThreeMap`, WebGL renderer, scene, and valid model cache during business-state reset. Never use reload, `reLaunch`, component keys, renderer recreation, or repeated cached GLB parsing as a reset mechanism.
- Provide side controls or equivalent for full-building/multi-floor versus single-floor views.
- Always provide loading, error, retry, and recovery paths for model loading.
- Keep canvas sizing constrained by the guide layout. It must not cover fixed navigation, cards, buttons, floor controls, search, top tabs, or explain/player controls.

View File

@@ -0,0 +1,113 @@
# Guide Model State And View Baseline Contract
Use this contract for every change or audit involving the indoor guide model, POI focus, floor switching, detail-page return, camera reset, or model async work.
## Contents
- State ownership and initial state
- Overview and floor baselines
- Reset action contract
- POI detail return contract
- Async invalidation
- Prohibited reset mechanisms
- Required tests and audit checks
## State Ownership And Initial State
- Keep one shared business-state owner, preferably the existing `useGuideModelState` boundary. Do not introduce per-page reset flags or duplicate state managers.
- Keep `GUIDE_MODEL_INITIAL_STATE` immutable. Define it as the stable overview state captured only after the exterior/full-building model becomes ready for the first time.
- Derive the default floor and initial camera from model configuration, floor data, or the first stable ready state. Never hardcode `1F`, a floor ID, camera coordinates, target, or distance.
- Route state changes through explicit actions such as `initializeModel`, `enterOverview`, `switchFloor`, `focusPoi`, `clearPoiSelection`, `enterRoutePreview`, and `resetToViewBaseline`.
- Include at least these business fields in the shared contract:
- 3D/indoor mode, `indoorView`, and `layerMode`.
- Default active floor, requested floor, loading floor, and committed/rendered floor.
- Camera position, up, fov, zoom, controls target, and camera distance.
- Selected POI, active/highlighted POI, target focus request, and pending target focus.
- Visible POI IDs, temporary focus markers, focus labels, pulses, and hall highlights.
- Route preview, navigation simulation, and automatic floor-switch state.
- Model ready/loading/error state, model-load version, focus request ID, and reset generation.
## Overview And Floor Baselines
- Preserve the first stable exterior/full-building ready snapshot as the overview baseline.
- Maintain deterministic `FloorViewBaseline` values keyed by stable floor ID and a baseline cache key.
- Inherit observation direction, camera up, fov, zoom, composition, and screen-offset rules from the overview baseline.
- Compute each floor's controls target and camera distance from that floor's visible model bounding box. Do not copy the overview's absolute position and target to every floor.
- Never capture a floor baseline from a user-dragged camera, an animated camera, or a POI-focus camera.
- Return identical position, target, distance, direction, tilt, occupied-screen ratio, and visual center for repeated resets of the same floor within a reasonable epsilon.
- Invalidate a cached floor baseline when model/package version, visible model bounds, composition rules, or canvas aspect ratio changes.
## Reset Action Contract
Expose one renderer operation:
```ts
resetToViewBaseline({
view: 'overview' | 'floor',
floorId?: string,
reason: 'poi-detail-close' | 'manual-reset' | 'floor-reset'
})
```
Perform a floor reset in this order:
1. Increment the shared generation/request ID so old floor loads and focus requests become stale.
2. Cancel camera animation, target-focus work, and queued focus callbacks.
3. Clear selected POI, active/highlighted POI, target focus request, and pending target focus.
4. Dispose temporary markers, focus labels/pulses/bases, hall highlights, route previews, and navigation simulation.
5. Restore `visiblePoiIds` to `null`, reset search state, and collapse the search dock.
6. Switch to or confirm the target floor without remounting the renderer.
7. Apply the deterministic floor baseline only after that floor's model commit succeeds.
8. Reset automatic floor switching using the final restored camera distance.
9. Keep `ThreeMap`, WebGL, scene resources, and valid loaded-model caches alive.
- Make reset idempotent. Repeated calls with the same target view and floor must converge on the same business and camera state.
- If the renderer is not ready, retain only the newest reset request and apply it after ready. A failed model state must fail safely without reviving old POI state.
## POI Detail Return Contract
- Use a one-shot context instead of a boolean:
```ts
type PoiDetailReturnContext = Readonly<{
floorId: string
resetMode: 'floor-baseline'
requestId: number
}>
```
- Set the context before every guide-originated POI detail navigation, including search results, direct model/map POI selection, hall detail, exhibit detail, facility detail, and related-explanation actions.
- Cancel the context when `navigateTo` fails or the target cannot be resolved/opened.
- Consume it once in the guide homepage `onShow`, clear it immediately, and then reset to that POI's floor baseline.
- Do not set it for explain-home, deep-link, or other non-guide entry paths to the same detail pages.
- Keep top close, custom back, browser/system back, and other successful detail exits on the normal page-stack return path. Do not make detail pages mutate `ThreeMap` internals.
- Preserve the first normal homepage entry as overview. Never treat initial `onShow` as a detail return.
- Audit all navigation call sites, not only `facility/detail`. Search for `navigateTo`, hall/exhibit/facility detail URLs, map `poiClick`, and related-explanation actions.
## Async Invalidation
- Give floor loads, model commits, POI loads, focus requests, camera animations, and queued resets a comparable request ID, generation, epoch, or abort signal.
- Increment generation before reset cleanup. Check it before every async commit that mutates floor, selection, focus, marker, or camera state.
- Allow only the newest POI/floor request to commit. A completed old cross-floor request must not overwrite a later selection or reset.
- Invalidate preloads separately when necessary, but never let a preload commit become active business state after reset.
- Treat stale-request completion as a no-op, not as a user-visible load failure.
## Prohibited Reset Mechanisms
- Do not use `window.location.reload()`, `location.href`, or equivalent page reloads.
- Do not use `uni.reLaunch()` to reopen the current guide homepage.
- Do not change a component key to remount `GuideMapShell` or `ThreeMap`.
- Do not destroy and recreate `ThreeMap`, `WebGLRenderer`, controls, or scene solely to reset business state.
- Do not redownload or reparse an already valid cached GLB/model package.
- Do not add floor-, category-, type-, or POI-ID-specific reset branches.
## Required Tests And Audit Checks
- Cover search-result and direct map/model POI entry paths for facilities, halls, exhibits, and temporary focus markers.
- Cover same-floor and cross-floor targets, focus animation in progress, floor load in progress, repeated close/onShow, detail-open failure, model-not-ready, and model-error states.
- Assert after return that shared business state matches the target baseline contract, selection/highlight/focus are empty, `visiblePoiIds` is `null`, and search is collapsed.
- Assert camera position, controls target, direction, and distance match the appropriate overview/floor baseline within epsilon.
- Assert an old cross-floor focus/load request cannot commit after reset.
- Assert `ThreeMap` mount count, WebGL initialization count, model-package fetch count, and cached GLB parse count do not increase on detail return.
- Assert non-guide detail entry does not reset the guide model.
- Browser-test at least three POI types on different floors and verify identical same-floor reset composition, no white flash, no URL/load-time reset, and no duplicate GLB network request.