@@ -28,6 +28,8 @@
|
||||
:indoor-view="indoorView"
|
||||
:layer-mode="indoorLayerMode"
|
||||
:active-floor="activeGuideFloor"
|
||||
:visible-poi-ids="searchVisiblePoiIds"
|
||||
:target-focus-request="searchTargetFocusRequest"
|
||||
layer-mode-toggle-top="154px"
|
||||
floor-bottom="193px"
|
||||
floor-max-height="206px"
|
||||
@@ -162,17 +164,20 @@
|
||||
></view>
|
||||
|
||||
<view
|
||||
v-if="showGuideHomeDock"
|
||||
v-show="showGuideHomeDock"
|
||||
class="guide-home-dock"
|
||||
:class="{ expanded: homeSearchExpanded }"
|
||||
@mousedown.capture="handleHomeDockActivate"
|
||||
@click.capture="handleHomeDockActivate"
|
||||
@tap.capture="handleHomeDockActivate"
|
||||
>
|
||||
<PoiSearchPanel
|
||||
ref="homeSearchPanelRef"
|
||||
variant="home"
|
||||
:current-floor-id="activeGuideFloor"
|
||||
:current-floor-label="getGuideFloorLabel(activeGuideFloor)"
|
||||
@expanded-change="handleHomeSearchExpandedChange"
|
||||
@category-mode-change="handleHomeCategoryModeChange"
|
||||
@results-change="handleHomeSearchResultsChange"
|
||||
@result-tap="handleHomeSearchResultTap"
|
||||
@cancel="handleHomeSearchCancel"
|
||||
/>
|
||||
</view>
|
||||
|
||||
@@ -299,8 +304,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { onLoad, onShow } from '@dcloudio/uni-app'
|
||||
import GuidePageFrame from '@/components/navigation/GuidePageFrame.vue'
|
||||
import GuideMapShell from '@/components/navigation/GuideMapShell.vue'
|
||||
import RoutePlannerPanel from '@/components/navigation/RoutePlannerPanel.vue'
|
||||
@@ -326,12 +331,17 @@ import {
|
||||
import {
|
||||
explainUseCase
|
||||
} from '@/usecases/explainUseCase'
|
||||
import {
|
||||
normalizeExplainDetailTargetFromGuideStop
|
||||
} from '@/domain/explainDetailTarget'
|
||||
import type {
|
||||
GuideRenderPoi
|
||||
} from '@/domain/guideModel'
|
||||
import type {
|
||||
PoiCategoryResultState,
|
||||
PoiSearchContext
|
||||
} from '@/domain/poiSearch'
|
||||
import {
|
||||
toTargetFocusRequestViewModel,
|
||||
type TargetPoiFocusRequestViewModel
|
||||
} from '@/view-models/guideViewModels'
|
||||
import {
|
||||
ARRIVAL_TARGETS_BY_TYPE,
|
||||
type ArrivalSearchTarget,
|
||||
@@ -341,7 +351,8 @@ import type {
|
||||
GuideRouteResult,
|
||||
GuideRouteTarget,
|
||||
MuseumFloor,
|
||||
MuseumHall
|
||||
MuseumHall,
|
||||
MuseumPoi
|
||||
} from '@/domain/museum'
|
||||
|
||||
type GuideIndoorView = 'overview' | 'floor' | 'multi'
|
||||
@@ -424,10 +435,15 @@ const guideMapShellRef = ref<{
|
||||
showOverview?: () => Promise<void> | void
|
||||
} | null>(null)
|
||||
const homeSearchPanelRef = ref<{
|
||||
expandHomePanel?: () => void
|
||||
collapseHomePanel?: () => void
|
||||
resetSearchState?: () => void
|
||||
restoreResultListScroll?: () => Promise<void>
|
||||
} | null>(null)
|
||||
const homeSearchExpanded = ref(false)
|
||||
const homeCategoryModeActive = ref(false)
|
||||
const searchVisiblePoiIds = ref<string[] | null>(null)
|
||||
const searchTargetFocusRequest = ref<TargetPoiFocusRequestViewModel | null>(null)
|
||||
let searchTargetFocusRequestId = 0
|
||||
|
||||
let launchOverlayFallbackTimer: ReturnType<typeof setTimeout> | null = null
|
||||
let launchOverlayFadeTimer: ReturnType<typeof setTimeout> | null = null
|
||||
@@ -732,7 +748,7 @@ const selectedGuidePoiIsHall = computed(() => {
|
||||
})
|
||||
|
||||
const selectedGuidePoiCollapsedSubtitle = computed(() => (
|
||||
selectedGuidePoiIsHall.value ? '已定位展厅 · 点按展开操作' : '已定位点位'
|
||||
selectedGuidePoiIsHall.value ? '点按展开查看展厅' : selectedGuidePoiSubtitle.value
|
||||
))
|
||||
|
||||
const routeSimulationStepText = computed(() => {
|
||||
@@ -999,7 +1015,7 @@ const handleGuidePoiClick = (poi: GuideRenderPoi) => {
|
||||
isSimulatingRoute.value = false
|
||||
activeGuideFloor.value = poi.floorId
|
||||
renderedFloorId.value = poi.floorId
|
||||
showIndoorHint('已在当前楼层标出点位', 3000)
|
||||
showIndoorHint(`${poi.name} · ${getGuideFloorLabel(poi.floorId)}`, 3000)
|
||||
}
|
||||
|
||||
const handleGuideSelectionClear = () => {
|
||||
@@ -1390,6 +1406,11 @@ const closeHomeSearchDock = () => {
|
||||
homeSearchExpanded.value = false
|
||||
}
|
||||
|
||||
onShow(async () => {
|
||||
await nextTick()
|
||||
await homeSearchPanelRef.value?.restoreResultListScroll?.()
|
||||
})
|
||||
|
||||
const handleMoreOutdoorNav = () => {
|
||||
if (showArrivalPanel.value && showArrivalPanelCollapsed.value) {
|
||||
arrivalPanelRef.value?.expandPanel()
|
||||
@@ -1417,15 +1438,110 @@ const handleHomeSearchExpandedChange = (expanded: boolean) => {
|
||||
homeSearchExpanded.value = expanded
|
||||
}
|
||||
|
||||
const handleHomeSearchOutsideTap = () => {
|
||||
closeHomeSearchDock()
|
||||
const clearHomeSearchMapState = () => {
|
||||
homeCategoryModeActive.value = false
|
||||
searchVisiblePoiIds.value = null
|
||||
searchTargetFocusRequest.value = null
|
||||
}
|
||||
|
||||
const handleHomeDockActivate = () => {
|
||||
if (homeSearchExpanded.value) return
|
||||
const handleHomeCategoryModeChange = (active: boolean) => {
|
||||
homeCategoryModeActive.value = active
|
||||
if (!active) {
|
||||
searchVisiblePoiIds.value = null
|
||||
return
|
||||
}
|
||||
|
||||
homeSearchPanelRef.value?.expandHomePanel?.()
|
||||
homeSearchExpanded.value = true
|
||||
closeArrivalPanel()
|
||||
showRoutePlanner.value = false
|
||||
isSimulatingRoute.value = false
|
||||
selectedGuidePoi.value = null
|
||||
isPoiCardCollapsed.value = false
|
||||
is3DMode.value = true
|
||||
indoorView.value = 'floor'
|
||||
}
|
||||
|
||||
const handleHomeSearchResultsChange = (state: PoiCategoryResultState) => {
|
||||
if (!state.active) {
|
||||
searchVisiblePoiIds.value = null
|
||||
return
|
||||
}
|
||||
|
||||
searchVisiblePoiIds.value = [...state.visiblePoiIds]
|
||||
if (state.floorId) {
|
||||
activeGuideFloor.value = state.floorId
|
||||
}
|
||||
}
|
||||
|
||||
const createSearchDetailUrl = (poi: MuseumPoi, context: PoiSearchContext) => {
|
||||
const resultCount = homeCategoryModeActive.value
|
||||
? context.floorResultCount
|
||||
: context.resultCount
|
||||
const params = new URLSearchParams({
|
||||
source: 'search',
|
||||
searchOrigin: context.origin,
|
||||
searchKeyword: context.keyword,
|
||||
searchCategoryId: context.categoryId,
|
||||
searchFloorId: context.floorId,
|
||||
searchFloorLabel: context.floorLabel,
|
||||
resultCount: String(Math.max(1, resultCount)),
|
||||
floorResultCount: String(context.floorResultCount),
|
||||
visiblePoiIds: context.visiblePoiIds.join(','),
|
||||
listScrollTop: String(context.listScrollTop),
|
||||
id: poi.id,
|
||||
target: poi.name,
|
||||
floorId: poi.floorId,
|
||||
floorLabel: poi.floorLabel
|
||||
})
|
||||
|
||||
return `/pages/facility/detail?${params.toString()}`
|
||||
}
|
||||
|
||||
const handleHomeSearchResultTap = async (poi: MuseumPoi, context: PoiSearchContext) => {
|
||||
closeArrivalPanel()
|
||||
showRoutePlanner.value = false
|
||||
isSimulatingRoute.value = false
|
||||
selectedGuidePoi.value = null
|
||||
isPoiCardCollapsed.value = false
|
||||
is3DMode.value = true
|
||||
indoorView.value = 'floor'
|
||||
activeGuideFloor.value = poi.floorId
|
||||
searchTargetFocusRequestId += 1
|
||||
searchTargetFocusRequest.value = 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)
|
||||
|
||||
// 先把楼层与目标请求交给地图,再进入详情页;返回时列表组件仍保持原状态。
|
||||
await nextTick()
|
||||
uni.navigateTo({
|
||||
url: createSearchDetailUrl(poi, context),
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: '点位详情打开失败,请重试',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleHomeSearchCancel = () => {
|
||||
clearHomeSearchMapState()
|
||||
selectedGuidePoi.value = null
|
||||
isPoiCardCollapsed.value = false
|
||||
homeSearchExpanded.value = false
|
||||
}
|
||||
|
||||
const handleHomeSearchOutsideTap = () => {
|
||||
closeHomeSearchDock()
|
||||
}
|
||||
|
||||
const guideShellMode = computed(() => (is3DMode.value ? '3d' : '2d'))
|
||||
|
||||
Reference in New Issue
Block a user