@@ -36,14 +36,13 @@
|
||||
show-floor-header
|
||||
:show-layer-mode-toggle="false"
|
||||
:show-floor="is3DMode && !showRoutePlanner"
|
||||
show-zoom-controls
|
||||
:show-zoom-controls="is3DMode"
|
||||
zoom-controls-top="calc(100vh - 292px)"
|
||||
:route-preview="activeRoutePreview"
|
||||
:show-route="Boolean(activeRoutePreview)"
|
||||
:disable-auto-exit="disableIndoorAutoExit"
|
||||
:auto-switch-threshold-low="0.58"
|
||||
:auto-switch-threshold-high="1.18"
|
||||
:outdoor-nav-polylines="outdoorNavPolylines"
|
||||
@mode-change="handleModeChange"
|
||||
@floor-request="handleFloorRequest"
|
||||
@floor-change="handleFloorChange"
|
||||
@@ -56,7 +55,6 @@
|
||||
@initial-model-ready="handleInitialModelReady"
|
||||
@initial-model-failed="handleInitialModelFailed"
|
||||
@tool-click="handleIndoorToolClick"
|
||||
@map-tap="handleMapTapForOutdoorNav"
|
||||
>
|
||||
<template #overlay>
|
||||
<view v-if="guideOutdoorState === 'entrance' && !is3DMode" class="entrance-tip">
|
||||
@@ -228,25 +226,10 @@
|
||||
</view>
|
||||
</GuideMapShell>
|
||||
|
||||
<OutdoorNavigationPanel
|
||||
v-if="currentTab === 'guide' && isOutdoorGuidePanelEnabled"
|
||||
:visible="showOutdoorNavPanel"
|
||||
:loading="outdoorNavLoading"
|
||||
:route-error="outdoorNavError"
|
||||
:route-distance="outdoorNavRoute?.distance ?? 0"
|
||||
:route-duration="outdoorNavRoute?.duration ?? 0"
|
||||
:selecting-manual-start="outdoorNavSelectingManualStart"
|
||||
:start-point="outdoorNavStartPoint ? { ...outdoorNavStartPoint, name: '已选位置' } : null"
|
||||
:start-mode="outdoorNavManualMode || outdoorNavStartPoint ? 'manual' : 'gps'"
|
||||
@close="handleOutdoorNavClose"
|
||||
@gps-start="handleOutdoorNavGpsStart"
|
||||
@manual-start-request="handleOutdoorNavManualStartRequest"
|
||||
@manual-start-cancel="handleOutdoorNavManualStartCancel"
|
||||
@manual-start-confirm="handleOutdoorNavManualStartConfirm"
|
||||
@travel-mode-change="handleOutdoorNavTravelModeChange"
|
||||
@start-navigation="handleOutdoorNavStartNavigation"
|
||||
@clear-route="handleOutdoorNavClearRoute"
|
||||
@back="handleOutdoorNavBack"
|
||||
<ArrivalPanel
|
||||
v-if="currentTab === 'guide'"
|
||||
:visible="showArrivalPanel"
|
||||
@close="closeArrivalPanel"
|
||||
/>
|
||||
|
||||
<view v-else-if="currentTab === 'explain'" class="explain-page">
|
||||
@@ -308,7 +291,7 @@ import { onLoad } 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'
|
||||
import OutdoorNavigationPanel from '@/components/navigation/OutdoorNavigationPanel.vue'
|
||||
import ArrivalPanel from '@/components/navigation/ArrivalPanel.vue'
|
||||
import PoiSearchPanel from '@/components/search/PoiSearchPanel.vue'
|
||||
import type {
|
||||
RoutePointOption
|
||||
@@ -346,17 +329,6 @@ import type {
|
||||
MuseumFloor,
|
||||
MuseumHall
|
||||
} from '@/domain/museum'
|
||||
import { MUSEUM_LOCATION, type TravelMode } from '@/config/museum'
|
||||
import {
|
||||
planWalkingRoute,
|
||||
planDrivingRoute,
|
||||
planTransitRoute,
|
||||
type Route,
|
||||
type RoutePoint
|
||||
} from '@/services/tencent/TencentMapService'
|
||||
import {
|
||||
navigateToMuseum
|
||||
} from '@/services/MapNavigationService'
|
||||
|
||||
type GuideIndoorView = 'overview' | 'floor' | 'multi'
|
||||
type LayerDisplayMode = 'single' | 'multi'
|
||||
@@ -566,17 +538,7 @@ const handleLaunchContinue = () => {
|
||||
hideLaunchOverlay()
|
||||
}
|
||||
|
||||
// 馆外导航相关状态
|
||||
const isOutdoorGuidePanelEnabled = false
|
||||
const showOutdoorNavPanel = ref(false)
|
||||
const outdoorNavLoading = ref(false)
|
||||
const outdoorNavError = ref('')
|
||||
const outdoorNavRoute = ref<Route | null>(null)
|
||||
const outdoorNavPolylines = ref<Array<{ points: Array<{ latitude: number; longitude: number }>; color: string; width: number }>>([])
|
||||
const outdoorNavStartPoint = ref<{ latitude: number; longitude: number } | null>(null)
|
||||
const outdoorNavTravelMode = ref<TravelMode>('walking')
|
||||
const outdoorNavSelectingManualStart = ref(false)
|
||||
const outdoorNavManualMode = ref(false)
|
||||
const showArrivalPanel = ref(false)
|
||||
|
||||
const indoorNavAssetBaseUrl = guideUseCase.getAssetBaseUrl()
|
||||
const indoorModelSource = guideUseCase.getModelSource()
|
||||
@@ -634,8 +596,9 @@ const disableIndoorAutoExit = computed(() => (
|
||||
|
||||
const showGuideHomeDock = computed(() => (
|
||||
currentTab.value === 'guide'
|
||||
&& is3DMode.value
|
||||
&& !showRoutePlanner.value
|
||||
&& !showOutdoorNavPanel.value
|
||||
&& !showArrivalPanel.value
|
||||
&& !selectedGuidePoi.value
|
||||
&& !isSimulatingRoute.value
|
||||
&& !(guideOutdoorState.value === 'entrance' && !is3DMode.value)
|
||||
@@ -644,7 +607,7 @@ const showGuideHomeDock = computed(() => (
|
||||
const showGuideFloatingActions = computed(() => (
|
||||
currentTab.value === 'guide'
|
||||
&& !showRoutePlanner.value
|
||||
&& !showOutdoorNavPanel.value
|
||||
&& !showArrivalPanel.value
|
||||
&& !selectedGuidePoi.value
|
||||
&& !isSimulatingRoute.value
|
||||
&& (!showGuideHomeDock.value || !homeSearchExpanded.value)
|
||||
@@ -652,6 +615,7 @@ const showGuideFloatingActions = computed(() => (
|
||||
|
||||
const guideQuickActiveAction = computed<'indoor' | 'arrival' | 'explain'>(() => {
|
||||
if (currentTab.value === 'explain') return 'explain'
|
||||
if (showArrivalPanel.value) return 'arrival'
|
||||
return is3DMode.value ? 'indoor' : 'arrival'
|
||||
})
|
||||
|
||||
@@ -777,8 +741,7 @@ const handleTabChange = (tabId: GuideTopTab) => {
|
||||
showRoutePlanner.value = false
|
||||
isSimulatingRoute.value = false
|
||||
isPoiCardCollapsed.value = false
|
||||
showOutdoorNavPanel.value = false
|
||||
clearOutdoorNavState()
|
||||
closeArrivalPanel()
|
||||
}
|
||||
|
||||
const syncTopTabFromHash = () => {
|
||||
@@ -793,6 +756,7 @@ const syncTopTabFromHash = () => {
|
||||
showRoutePlanner.value = false
|
||||
isSimulatingRoute.value = false
|
||||
isPoiCardCollapsed.value = false
|
||||
closeArrivalPanel()
|
||||
}
|
||||
syncTopTabToUrl(tab)
|
||||
return
|
||||
@@ -1239,7 +1203,7 @@ const handleRouteSimulate = () => {
|
||||
// 进入 3D 馆内模式
|
||||
const handleEnter3DMode = () => {
|
||||
console.log('进入 3D 馆内模式')
|
||||
closeOutdoorNavPanel()
|
||||
closeArrivalPanel()
|
||||
indoorView.value = 'overview'
|
||||
is3DMode.value = true
|
||||
guideOutdoorState.value = 'home'
|
||||
@@ -1253,6 +1217,7 @@ const handleModeChange = (mode: '2d' | '3d') => {
|
||||
is3DMode.value = mode === '3d'
|
||||
|
||||
if (mode === '2d') {
|
||||
closeHomeSearchDock()
|
||||
indoorView.value = 'overview'
|
||||
guideOutdoorState.value = 'home'
|
||||
selectedGuidePoi.value = null
|
||||
@@ -1261,7 +1226,7 @@ const handleModeChange = (mode: '2d' | '3d') => {
|
||||
isSimulatingRoute.value = false
|
||||
clearRoutePreviewState()
|
||||
} else {
|
||||
closeOutdoorNavPanel()
|
||||
closeArrivalPanel()
|
||||
indoorView.value = 'overview'
|
||||
showIndoorHint()
|
||||
if (!routePointOptions.value.length) {
|
||||
@@ -1295,7 +1260,7 @@ const handleSwitchEntrance = () => {
|
||||
}
|
||||
|
||||
const handleMoreRouteGuide = () => {
|
||||
closeOutdoorNavPanel()
|
||||
closeArrivalPanel()
|
||||
showRoutePlanner.value = false
|
||||
is3DMode.value = true
|
||||
indoorView.value = 'floor'
|
||||
@@ -1306,44 +1271,24 @@ const handleMoreRouteGuide = () => {
|
||||
showIndoorHint(`当前楼层:${getGuideFloorLabel(renderedFloorId.value || activeGuideFloor.value) || '馆内单层'}`, 3200)
|
||||
}
|
||||
|
||||
// 馆外导航处理函数
|
||||
const openOutdoorNavPanel = () => {
|
||||
if (!isOutdoorGuidePanelEnabled) {
|
||||
showOutdoorNavPanel.value = false
|
||||
showRoutePlanner.value = false
|
||||
selectedGuidePoi.value = null
|
||||
isPoiCardCollapsed.value = false
|
||||
is3DMode.value = false
|
||||
clearOutdoorNavState()
|
||||
return
|
||||
}
|
||||
|
||||
showOutdoorNavPanel.value = true
|
||||
showRoutePlanner.value = false
|
||||
selectedGuidePoi.value = null
|
||||
isPoiCardCollapsed.value = false
|
||||
// 切换到馆外 2D 地图
|
||||
is3DMode.value = false
|
||||
clearOutdoorNavState()
|
||||
const closeArrivalPanel = () => {
|
||||
showArrivalPanel.value = false
|
||||
}
|
||||
|
||||
const clearOutdoorNavState = () => {
|
||||
outdoorNavRoute.value = null
|
||||
outdoorNavPolylines.value = []
|
||||
outdoorNavStartPoint.value = null
|
||||
outdoorNavError.value = ''
|
||||
outdoorNavLoading.value = false
|
||||
outdoorNavSelectingManualStart.value = false
|
||||
outdoorNavManualMode.value = false
|
||||
}
|
||||
|
||||
const closeOutdoorNavPanel = () => {
|
||||
showOutdoorNavPanel.value = false
|
||||
clearOutdoorNavState()
|
||||
const closeHomeSearchDock = () => {
|
||||
homeSearchPanelRef.value?.collapseHomePanel?.()
|
||||
homeSearchExpanded.value = false
|
||||
}
|
||||
|
||||
const handleMoreOutdoorNav = () => {
|
||||
openOutdoorNavPanel()
|
||||
showArrivalPanel.value = true
|
||||
showRoutePlanner.value = false
|
||||
is3DMode.value = false
|
||||
guideOutdoorState.value = 'home'
|
||||
selectedGuidePoi.value = null
|
||||
isPoiCardCollapsed.value = false
|
||||
isSimulatingRoute.value = false
|
||||
closeHomeSearchDock()
|
||||
}
|
||||
|
||||
const handleExplainQuickTap = () => {
|
||||
@@ -1355,8 +1300,7 @@ const handleHomeSearchExpandedChange = (expanded: boolean) => {
|
||||
}
|
||||
|
||||
const handleHomeSearchOutsideTap = () => {
|
||||
homeSearchPanelRef.value?.collapseHomePanel?.()
|
||||
homeSearchExpanded.value = false
|
||||
closeHomeSearchDock()
|
||||
}
|
||||
|
||||
const handleHomeDockActivate = () => {
|
||||
@@ -1366,155 +1310,6 @@ const handleHomeDockActivate = () => {
|
||||
homeSearchExpanded.value = true
|
||||
}
|
||||
|
||||
const handleOutdoorNavClose = () => {
|
||||
closeOutdoorNavPanel()
|
||||
}
|
||||
|
||||
const handleOutdoorNavBack = () => {
|
||||
closeOutdoorNavPanel()
|
||||
}
|
||||
|
||||
const handleOutdoorNavGpsStart = () => {
|
||||
outdoorNavLoading.value = true
|
||||
outdoorNavError.value = ''
|
||||
|
||||
uni.getLocation({
|
||||
type: 'gcj02',
|
||||
success: (res) => {
|
||||
console.log('GPS 定位成功:', res)
|
||||
outdoorNavStartPoint.value = {
|
||||
latitude: res.latitude,
|
||||
longitude: res.longitude
|
||||
}
|
||||
void planOutdoorRoute({
|
||||
latitude: res.latitude,
|
||||
longitude: res.longitude
|
||||
})
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('GPS 定位失败:', err)
|
||||
const errMsg = err.errMsg || ''
|
||||
if (errMsg.includes('auth deny') || errMsg.includes('auth reject')) {
|
||||
outdoorNavError.value = '定位权限被拒绝,请在设置中开启'
|
||||
} else if (errMsg.includes('timeout')) {
|
||||
outdoorNavError.value = '定位超时,请重试'
|
||||
} else if (errMsg.includes('unavailable')) {
|
||||
outdoorNavError.value = '位置服务不可用,请检查设备设置'
|
||||
} else {
|
||||
outdoorNavError.value = '定位失败,请检查位置权限'
|
||||
}
|
||||
outdoorNavLoading.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const handleOutdoorNavManualStartRequest = () => {
|
||||
outdoorNavManualMode.value = true
|
||||
outdoorNavSelectingManualStart.value = true
|
||||
uni.showToast({
|
||||
title: '输入地址搜索,或点击地图选择起点',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
|
||||
const handleOutdoorNavManualStartCancel = () => {
|
||||
outdoorNavManualMode.value = false
|
||||
outdoorNavSelectingManualStart.value = false
|
||||
}
|
||||
|
||||
const handleOutdoorNavManualStartConfirm = (location: { latitude: number; longitude: number }) => {
|
||||
outdoorNavStartPoint.value = location
|
||||
outdoorNavManualMode.value = false
|
||||
outdoorNavSelectingManualStart.value = false
|
||||
void planOutdoorRoute(location)
|
||||
}
|
||||
|
||||
const handleOutdoorNavTravelModeChange = (mode: TravelMode) => {
|
||||
outdoorNavTravelMode.value = mode
|
||||
if (outdoorNavStartPoint.value) {
|
||||
outdoorNavLoading.value = true
|
||||
void planOutdoorRoute(outdoorNavStartPoint.value)
|
||||
}
|
||||
}
|
||||
|
||||
const planOutdoorRoute = async (from: { latitude: number; longitude: number }) => {
|
||||
outdoorNavLoading.value = true
|
||||
outdoorNavError.value = ''
|
||||
|
||||
const to: RoutePoint = {
|
||||
latitude: MUSEUM_LOCATION.latitude,
|
||||
longitude: MUSEUM_LOCATION.longitude
|
||||
}
|
||||
|
||||
try {
|
||||
let result
|
||||
switch (outdoorNavTravelMode.value) {
|
||||
case 'walking':
|
||||
result = await planWalkingRoute(from, to)
|
||||
break
|
||||
case 'driving':
|
||||
result = await planDrivingRoute(from, to)
|
||||
break
|
||||
case 'transit':
|
||||
result = await planTransitRoute(from, to)
|
||||
break
|
||||
default:
|
||||
result = await planWalkingRoute(from, to)
|
||||
}
|
||||
|
||||
if (result.status === 0 && result.routes && result.routes.length > 0) {
|
||||
const route = result.routes[0]
|
||||
outdoorNavRoute.value = route
|
||||
outdoorNavPolylines.value = [{
|
||||
points: route.polyline,
|
||||
color: '#E0E100',
|
||||
width: 6
|
||||
}]
|
||||
console.log('路线规划成功:', {
|
||||
distance: route.distance,
|
||||
duration: route.duration,
|
||||
steps: route.steps.length
|
||||
})
|
||||
} else {
|
||||
outdoorNavError.value = result.message || '路线规划失败'
|
||||
outdoorNavRoute.value = null
|
||||
outdoorNavPolylines.value = []
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('路线规划异常:', error)
|
||||
outdoorNavError.value = '路线规划失败,请重试'
|
||||
outdoorNavRoute.value = null
|
||||
outdoorNavPolylines.value = []
|
||||
} finally {
|
||||
outdoorNavLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleOutdoorNavStartNavigation = async () => {
|
||||
// 直接调起导航
|
||||
await navigateToMuseum()
|
||||
}
|
||||
|
||||
const handleOutdoorNavClearRoute = () => {
|
||||
outdoorNavRoute.value = null
|
||||
outdoorNavPolylines.value = []
|
||||
outdoorNavStartPoint.value = null
|
||||
outdoorNavError.value = ''
|
||||
}
|
||||
|
||||
// 处理地图点击(用于手动选择起点)
|
||||
const handleMapTapForOutdoorNav = (location: { latitude?: number; longitude?: number }) => {
|
||||
if (!outdoorNavSelectingManualStart.value) return
|
||||
|
||||
const latitude = location.latitude
|
||||
const longitude = location.longitude
|
||||
if (latitude !== undefined && longitude !== undefined) {
|
||||
outdoorNavStartPoint.value = { latitude, longitude }
|
||||
outdoorNavSelectingManualStart.value = false
|
||||
void planOutdoorRoute({ latitude, longitude })
|
||||
}
|
||||
}
|
||||
|
||||
const guideShellMode = computed(() => (is3DMode.value ? '3d' : '2d'))
|
||||
const guideMapType = computed(() => (is3DMode.value ? 'indoor' : 'outdoor'))
|
||||
const guideOutdoorVariant = computed(() => (
|
||||
|
||||
Reference in New Issue
Block a user