提交室内导览交互与讲解优化
This commit is contained in:
@@ -21,16 +21,21 @@
|
||||
:normalize-floor-id="normalizeGuideFloorId"
|
||||
indoor-initial-view="overview"
|
||||
:indoor-view="indoorView"
|
||||
:layer-mode="indoorLayerMode"
|
||||
:active-floor="activeGuideFloor"
|
||||
indoor-view-toggle-top="154px"
|
||||
layer-mode-toggle-top="154px"
|
||||
floor-top="244px"
|
||||
:show-indoor-view-toggle="is3DMode"
|
||||
:show-floor="is3DMode && indoorView === 'floor'"
|
||||
:tools="[]"
|
||||
:show-layer-mode-toggle="is3DMode"
|
||||
:show-floor="is3DMode"
|
||||
:tools="guide3DTools"
|
||||
@search-tap="handleGuideSearchTap"
|
||||
@mode-change="handleModeChange"
|
||||
@floor-change="handleFloorChange"
|
||||
@indoor-view-change="handleIndoorViewChange"
|
||||
@poi-click="handleGuidePoiClick"
|
||||
@selection-clear="handleGuideSelectionClear"
|
||||
@tool-click="handleGuideToolClick"
|
||||
@auto-switch="handleAutoSwitch"
|
||||
>
|
||||
<template #overlay>
|
||||
<view v-if="guideOutdoorState === 'entrance' && !is3DMode" class="entrance-tip">
|
||||
@@ -135,15 +140,22 @@ import {
|
||||
import {
|
||||
toExplainCardViewModel
|
||||
} from '@/view-models/explainViewModels'
|
||||
import type {
|
||||
GuideRenderPoi
|
||||
} from '@/domain/guideModel'
|
||||
import type {
|
||||
MuseumFloor
|
||||
} from '@/domain/museum'
|
||||
|
||||
type GuideIndoorView = 'overview' | 'floor' | 'multi'
|
||||
type LayerDisplayMode = 'single' | 'multi'
|
||||
|
||||
// 3D 模式状态
|
||||
const is3DMode = ref(false)
|
||||
const guideOutdoorState = ref<'home' | 'entrance'>('home')
|
||||
const indoorView = ref<'overview' | 'floor'>('overview')
|
||||
const indoorView = ref<GuideIndoorView>('overview')
|
||||
const activeGuideFloor = ref('1F')
|
||||
const selectedGuidePoi = ref<GuideRenderPoi | null>(null)
|
||||
|
||||
// 状态
|
||||
const searchKeyword = ref('')
|
||||
@@ -157,6 +169,16 @@ const indoorNavAssetBaseUrl = guideUseCase.getAssetBaseUrl()
|
||||
const indoorModelSource = guideUseCase.getModelSource()
|
||||
const guideFloors = ref<MuseumFloor[]>([])
|
||||
const normalizeGuideFloorId = (labelOrId: string) => guideUseCase.normalizeFloorId(labelOrId)
|
||||
const indoorLayerMode = computed<LayerDisplayMode>(() => (
|
||||
indoorView.value === 'multi' ? 'multi' : 'single'
|
||||
))
|
||||
const guide3DTools = computed(() => {
|
||||
if (!is3DMode.value) return []
|
||||
|
||||
return selectedGuidePoi.value
|
||||
? ['重置', '俯视', '斜视', '清除']
|
||||
: ['重置', '俯视', '斜视']
|
||||
})
|
||||
|
||||
const shortcutItems = [
|
||||
{ id: 'toilet', name: '卫生间', abbr: '卫' },
|
||||
@@ -351,11 +373,40 @@ const handleCollectMarker = (marker: MarkerDetail) => {
|
||||
const handleFloorChange = (floor: string) => {
|
||||
activeGuideFloor.value = floor
|
||||
indoorView.value = 'floor'
|
||||
selectedGuidePoi.value = null
|
||||
console.log('切换楼层:', floor)
|
||||
}
|
||||
|
||||
const handleIndoorViewChange = (view: 'overview' | 'floor') => {
|
||||
const handleIndoorViewChange = (view: GuideIndoorView) => {
|
||||
indoorView.value = view
|
||||
if (view !== 'floor') {
|
||||
selectedGuidePoi.value = null
|
||||
}
|
||||
}
|
||||
|
||||
const handleAutoSwitch = (event: { from: 'overview' | 'floor'; to: 'overview' | 'floor'; trigger: string; distance: number }) => {
|
||||
console.log('自动切换视图:', event)
|
||||
indoorView.value = event.to
|
||||
if (event.to !== 'floor') {
|
||||
selectedGuidePoi.value = null
|
||||
}
|
||||
}
|
||||
|
||||
const handleGuidePoiClick = (poi: GuideRenderPoi) => {
|
||||
selectedGuidePoi.value = poi
|
||||
indoorView.value = 'floor'
|
||||
const matchedFloor = guideFloors.value.find((floor) => floor.id === poi.floorId)
|
||||
activeGuideFloor.value = matchedFloor?.label || poi.floorId
|
||||
}
|
||||
|
||||
const handleGuideSelectionClear = () => {
|
||||
selectedGuidePoi.value = null
|
||||
}
|
||||
|
||||
const handleGuideToolClick = (tool: string) => {
|
||||
if (tool === '清除') {
|
||||
selectedGuidePoi.value = null
|
||||
}
|
||||
}
|
||||
|
||||
// 进入 3D 室内模式
|
||||
@@ -364,6 +415,7 @@ const handleEnter3DMode = () => {
|
||||
indoorView.value = 'overview'
|
||||
is3DMode.value = true
|
||||
guideOutdoorState.value = 'home'
|
||||
selectedGuidePoi.value = null
|
||||
}
|
||||
|
||||
const handleModeChange = (mode: '2d' | '3d') => {
|
||||
@@ -372,6 +424,7 @@ const handleModeChange = (mode: '2d' | '3d') => {
|
||||
if (mode === '2d') {
|
||||
indoorView.value = 'overview'
|
||||
guideOutdoorState.value = 'home'
|
||||
selectedGuidePoi.value = null
|
||||
} else {
|
||||
indoorView.value = 'overview'
|
||||
}
|
||||
@@ -379,7 +432,9 @@ const handleModeChange = (mode: '2d' | '3d') => {
|
||||
|
||||
const guideStatusLabel = computed(() => {
|
||||
if (is3DMode.value) {
|
||||
return indoorView.value === 'overview' ? '室内全馆' : '室内楼层'
|
||||
if (indoorView.value === 'overview') return '建筑外观'
|
||||
if (indoorView.value === 'multi') return '室内多层'
|
||||
return '室内单层'
|
||||
}
|
||||
|
||||
if (guideOutdoorState.value === 'entrance') {
|
||||
@@ -391,16 +446,26 @@ const guideStatusLabel = computed(() => {
|
||||
|
||||
const guideTaskTitle = computed(() => {
|
||||
if (is3DMode.value) {
|
||||
return indoorView.value === 'overview' ? '查看完整建筑' : '查看楼层位置'
|
||||
if (selectedGuidePoi.value) return selectedGuidePoi.value.name
|
||||
if (indoorView.value === 'overview') return '查看建筑外观'
|
||||
if (indoorView.value === 'multi') return '查看多层关系'
|
||||
return '查看单层位置'
|
||||
}
|
||||
return '从室外进入馆内'
|
||||
})
|
||||
|
||||
const guideTaskSubtitle = computed(() => {
|
||||
if (is3DMode.value) {
|
||||
return indoorView.value === 'overview'
|
||||
? '切换到楼层后,可查看 POI 与三维位置预览'
|
||||
: '选择目标设施后,可查看楼层与三维位置预览'
|
||||
if (selectedGuidePoi.value) {
|
||||
return `${activeGuideFloor.value} · ${selectedGuidePoi.value.primaryCategoryZh || '位置预览'} · 已高亮`
|
||||
}
|
||||
if (indoorView.value === 'overview') {
|
||||
return '放大模型可自动进入当前楼层'
|
||||
}
|
||||
if (indoorView.value === 'multi') {
|
||||
return '用于比较楼层关系,选择具体楼层可回到单层'
|
||||
}
|
||||
return '缩小模型可自动回到建筑外观,也可切换多层展示'
|
||||
}
|
||||
|
||||
return ''
|
||||
@@ -408,6 +473,7 @@ const guideTaskSubtitle = computed(() => {
|
||||
|
||||
const guidePrimaryAction = computed(() => {
|
||||
if (is3DMode.value) {
|
||||
if (selectedGuidePoi.value) return '查看相关内容'
|
||||
return '选择目标地点'
|
||||
}
|
||||
|
||||
@@ -416,6 +482,13 @@ const guidePrimaryAction = computed(() => {
|
||||
|
||||
const handleGuidePrimaryAction = () => {
|
||||
if (is3DMode.value) {
|
||||
if (selectedGuidePoi.value) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/search/index?keyword=${encodeURIComponent(selectedGuidePoi.value.name)}`
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pages/search/index'
|
||||
})
|
||||
@@ -507,7 +580,7 @@ const handleExplainFeaturedClick = async (exhibit: Exhibit) => {
|
||||
await handleAudioClick(exhibit)
|
||||
}
|
||||
|
||||
const handleExplainLocationClick = (exhibit: Exhibit) => {
|
||||
const handleExplainLocationClick = async (exhibit: Exhibit) => {
|
||||
if (!exhibit.poiId) {
|
||||
uni.showToast({
|
||||
title: '该讲解暂无三维位置数据',
|
||||
@@ -516,6 +589,15 @@ const handleExplainLocationClick = (exhibit: Exhibit) => {
|
||||
return
|
||||
}
|
||||
|
||||
const matchedPoi = await guideUseCase.getPoiById(exhibit.poiId)
|
||||
if (!matchedPoi) {
|
||||
uni.showToast({
|
||||
title: '该讲解位置尚未映射到当前三维导览资源',
|
||||
icon: 'none'
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.navigateTo({
|
||||
url: `/pages/route/detail?facilityId=${encodeURIComponent(exhibit.poiId)}&target=${encodeURIComponent(exhibit.title)}&state=preview`
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user