fix: 统一馆内三维模型返回初始状态

This commit is contained in:
lyf
2026-07-14 21:57:31 +08:00
parent d813f0b375
commit 84fbbc0694
8 changed files with 319 additions and 168 deletions

View File

@@ -325,9 +325,9 @@ import type {
PoiSearchContext
} from '@/domain/poiSearch'
import {
toTargetFocusRequestViewModel,
type TargetPoiFocusRequestViewModel
} from '@/view-models/guideViewModels'
import { useGuideModelState } from '@/composables/useGuideModelState'
import {
ARRIVAL_TARGETS_BY_TYPE,
type ArrivalSearchTarget,
@@ -344,6 +344,8 @@ import type {
type GuideIndoorView = 'overview' | 'floor' | 'multi'
type LayerDisplayMode = 'single' | 'multi'
const guideModelState = useGuideModelState()
const isIndexHashRoute = () => {
if (typeof window === 'undefined') return false
@@ -416,6 +418,7 @@ const returningToOverview = ref(false)
const guideMapShellRef = ref<{
clearRoute?: () => void
showOverview?: () => Promise<void> | void
resetToInitialState?: () => Promise<boolean> | boolean
} | null>(null)
const homeSearchPanelRef = ref<{
collapseHomePanel?: () => void
@@ -427,9 +430,7 @@ const homeSearchExpanded = ref(false)
const homeCategoryModeActive = ref(false)
const searchVisiblePoiIds = ref<string[] | null>(null)
const searchTargetFocusRequest = ref<TargetPoiFocusRequestViewModel | null>(null)
let searchTargetFocusRequestId = 0
let pendingCollapseSearchAfterDetail = false
let pendingSearchDetailFocusRequest: TargetPoiFocusRequestViewModel | null = null
let pendingGuideModelResetUntilReady = false
type PoiSearchOverlayHistoryState = {
museumGuideOverlay?: 'poi-search'
@@ -916,6 +917,7 @@ const loadGuideFloors = async () => {
|| floors[0]?.id
|| activeGuideFloor.value
renderedFloorId.value = activeGuideFloor.value
guideModelState.initializeModel(activeGuideFloor.value)
} catch (error) {
console.error('加载导览楼层失败:', error)
guideFloors.value = []
@@ -1031,7 +1033,12 @@ const handleAutoSwitch = (event: { from: 'overview' | 'floor'; to: 'overview' |
}
const handleInitialModelReady = (event: { view: GuideIndoorView; floorId?: string; elapsedMs?: number }) => {
guideModelState.initializeModel(event.floorId || activeGuideFloor.value)
settleLaunchOverlayByModel('ready', event)
if (pendingGuideModelResetUntilReady) {
pendingGuideModelResetUntilReady = false
void resetGuideModelToInitial({ reason: 'queued-poi-detail-close' })
}
}
const handleInitialModelFailed = (event: { view: GuideIndoorView; floorId?: string; message: string; elapsedMs?: number }) => {
@@ -1449,27 +1456,45 @@ const closeHomeSearchDock = () => {
homeSearchExpanded.value = false
}
const resetGuideModelToInitial = async ({ reason }: { reason: 'poi-detail-close' | 'queued-poi-detail-close' }) => {
const initial = guideModelState.initialState.value
guideModelState.invalidatePendingRequests()
searchTargetFocusRequest.value = null
searchVisiblePoiIds.value = null
homeCategoryModeActive.value = false
selectedGuidePoi.value = null
isPoiCardCollapsed.value = false
showRoutePlanner.value = false
activeRoutePreview.value = null
routeStartPoint.value = null
routeEndPoint.value = null
routePlanError.value = ''
isSimulatingRoute.value = false
requestedFloorId.value = ''
requestedFloorLabel.value = ''
loadingFloorId.value = ''
failedFloorId.value = ''
is3DMode.value = true
guideOutdoorState.value = 'home'
indoorView.value = initial.indoorView
activeGuideFloor.value = initial.defaultActiveFloorId || activeGuideFloor.value
renderedFloorId.value = initial.loadedFloorId || activeGuideFloor.value
closeArrivalPanel()
await homeSearchPanelRef.value?.resetSearchState?.()
closeHomeSearchDock()
const resetApplied = await guideMapShellRef.value?.resetToInitialState?.()
if (!resetApplied) {
// The renderer is still becoming ready; retain only the latest requested reset.
pendingGuideModelResetUntilReady = true
}
console.info('馆内三维模型已恢复统一初始状态:', { reason })
}
onShow(async () => {
await nextTick()
if (pendingCollapseSearchAfterDetail) {
pendingCollapseSearchAfterDetail = false
const pendingFocusRequest = pendingSearchDetailFocusRequest
pendingSearchDetailFocusRequest = null
await homeSearchPanelRef.value?.returnToCollapsedAfterDetail?.()
homeSearchExpanded.value = false
homeCategoryModeActive.value = false
searchVisiblePoiIds.value = null
if (pendingFocusRequest) {
closeArrivalPanel()
showRoutePlanner.value = false
isSimulatingRoute.value = false
selectedGuidePoi.value = null
isPoiCardCollapsed.value = false
is3DMode.value = true
indoorView.value = 'floor'
activeGuideFloor.value = pendingFocusRequest.floorId
searchTargetFocusRequest.value = pendingFocusRequest
}
if (guideModelState.consumePoiDetailReturn()) {
await resetGuideModelToInitial({ reason: 'poi-detail-close' })
return
}
@@ -1569,29 +1594,13 @@ const createSearchDetailUrl = (poi: MuseumPoi, context: PoiSearchContext) => {
}
const handleHomeSearchResultTap = async (poi: MuseumPoi, context: PoiSearchContext) => {
searchTargetFocusRequestId += 1
pendingSearchDetailFocusRequest = toTargetFocusRequestViewModel({
poiId: poi.id,
name: poi.name,
floorId: poi.floorId,
floorLabel: poi.floorLabel,
primaryCategoryZh: poi.primaryCategory.label,
positionGltf: poi.positionGltf,
sourceObjectName: poi.sourceObjectName,
kind: poi.kind,
hallId: poi.hallId,
hallName: poi.hallName,
entrances: poi.entrances
}, searchTargetFocusRequestId)
// 详情页会一次性挂载目标楼层;首页不再先启动并销毁 ThreeMap。
// The homepage keeps its renderer mounted; detail close is consumed by onShow once.
searchTargetFocusRequest.value = null
pendingCollapseSearchAfterDetail = true
guideModelState.beginPoiDetailReturn()
uni.navigateTo({
url: createSearchDetailUrl(poi, context),
fail: () => {
pendingCollapseSearchAfterDetail = false
pendingSearchDetailFocusRequest = null
guideModelState.cancelPoiDetailReturn()
uni.showToast({
title: '点位详情打开失败,请重试',
icon: 'none'