修复馆内预览状态与点位展示
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-19 14:05:54 +08:00
parent 58887d928a
commit 215428db90
11 changed files with 280 additions and 35 deletions

View File

@@ -17,7 +17,7 @@
<button
v-if="!shouldUseHostNavigation"
class="hero-back"
aria-label="返回讲解详情"
aria-label="返回讲解对象列表"
@tap.stop="handleBack"
>
<text class="hero-back-icon"></text>

View File

@@ -424,6 +424,7 @@ const returningToOverview = ref(false)
// GuideMapShell 组件引用,用于显式调用路线清除方法
const guideMapShellRef = ref<{
clearRoute?: () => void
switchFloor?: (floorId: string) => Promise<void> | void
showOverview?: () => Promise<void> | void
resetToViewBaseline?: (options: {
view: 'overview' | 'floor'
@@ -1482,12 +1483,24 @@ const handleMoreRouteGuide = async () => {
closeArrivalPanel()
showRoutePlanner.value = false
is3DMode.value = true
indoorView.value = 'floor'
guideOutdoorState.value = 'home'
selectedGuidePoi.value = null
isPoiCardCollapsed.value = false
isSimulatingRoute.value = false
showIndoorHint(`当前楼层:${getGuideFloorLabel(renderedFloorId.value || activeGuideFloor.value) || '馆内单层'}`, 3200)
const floorId = activeGuideFloor.value
const floorLabel = getGuideFloorLabel(floorId) || '默认楼层'
if (!floorId) {
showIndoorHint('暂未获取到可进入的楼层,请稍后重试', 3200)
return
}
requestedFloorId.value = floorId
requestedFloorLabel.value = floorLabel
loadingFloorId.value = floorId
failedFloorId.value = ''
// 渲染器提交 floor-change 前仍保持建筑外观,避免楼层控件显示假状态。
showIndoorHint(`正在进入 ${floorLabel}`, 3200)
await guideMapShellRef.value?.switchFloor?.(floorId)
}
const selectFirstArrivalTarget = () => {

View File

@@ -132,6 +132,12 @@
<view v-if="routePlanError" class="indoor-guide-error">
<text class="indoor-guide-error-text">{{ routePlanError }}</text>
</view>
<view class="start-point-select" @tap="openStartPointPicker">
<text class="start-point-select-label">起点</text>
<text class="start-point-select-value" :class="{ placeholder: !selectedStartPoint }">
{{ selectedStartPoint ? `${selectedStartPoint.name} · ${selectedStartPoint.floorLabel}` : '请选择起点' }}
</text>
</view>
<view class="indoor-guide-actions">
<view
class="indoor-guide-btn secondary"
@@ -159,6 +165,19 @@
<view class="indoor-guide-peek-handle"></view>
<text class="indoor-guide-peek-text">点位预览</text>
</view>
<RoutePointPicker
:visible="startPointPickerVisible"
title="选择起点"
placeholder="搜索起点"
:options="routePointOptions"
:selected-poi-id="selectedStartPoint?.poiId || ''"
:loading="startPointPickerLoading"
:error="startPointPickerError"
empty-text="暂无可作为起点的位置"
close-text="返回"
@close="startPointPickerVisible = false"
@select="handleStartPointSelect"
/>
</GuideMapShell>
</GuidePageFrame>
</template>
@@ -168,6 +187,7 @@ import { computed, onMounted, onUnmounted, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import GuidePageFrame from '@/components/navigation/GuidePageFrame.vue'
import GuideMapShell from '@/components/navigation/GuideMapShell.vue'
import RoutePointPicker, { type RoutePointOption } from '@/components/navigation/RoutePointPicker.vue'
import {
guideUseCase
} from '@/usecases/guideUseCase'
@@ -226,6 +246,11 @@ const routeReadinessMessage = ref('')
const routePlanning = ref(false)
const routePlanError = ref('')
const activeRoutePreview = ref<GuideRouteResult | null>(null)
const selectedStartPoint = ref<RoutePointOption | null>(null)
const routePointOptions = ref<RoutePointOption[]>([])
const startPointPickerVisible = ref(false)
const startPointPickerLoading = ref(false)
const startPointPickerError = ref('')
const isIndoorGuidePanelHidden = ref(false)
const indoorGuideTouchStartY = ref(0)
const indoorGuideTouchCurrentY = ref(0)
@@ -724,9 +749,41 @@ const handleConfirmLocation = async () => {
activeFloor.value = startLocation.floor || activeFloor.value
isManualLocationPanelOpen.value = false
activeRoutePreview.value = null
selectedStartPoint.value = null
routeViewState.value = 'preview'
requestTargetFocus(route.value.targetLocation)
saveCurrentLocationPreviewUrl()
routePlanError.value = '请选择起点'
}
const openStartPointPicker = async () => {
startPointPickerVisible.value = true
startPointPickerError.value = ''
if (routePointOptions.value.length || startPointPickerLoading.value) return
startPointPickerLoading.value = true
try {
routePointOptions.value = (await guideRouteUseCase.listTargets())
.filter((target) => Boolean(target.poiId && target.routeNodeId))
.map((target) => ({
poiId: target.poiId,
name: target.name,
floorId: target.floorId,
floorLabel: target.floorLabel,
categoryLabel: target.categoryLabel
}))
} catch (error) {
startPointPickerError.value = error instanceof Error ? error.message : '起点列表加载失败,请重试'
} finally {
startPointPickerLoading.value = false
}
}
const handleStartPointSelect = (point: RoutePointOption) => {
selectedStartPoint.value = point
startPointPickerVisible.value = false
routePlanError.value = ''
activeRoutePreview.value = null
}
const handleStartIndoorGuide = async () => {
@@ -734,37 +791,31 @@ const handleStartIndoorGuide = async () => {
await refreshRouteReadinessState()
if (!routeReady.value) return
if (!selectedStartPoint.value?.poiId) {
routePlanError.value = '请选择起点'
return
}
routePlanning.value = true
routePlanError.value = ''
try {
const targets = await guideRouteUseCase.listTargets()
const startName = route.value.startLocation?.label || ''
const startFloor = route.value.startLocation?.floor || ''
const targetLocation = route.value.targetLocation
const fallbackStart = targets.find((target) => (
startName
? target.name.includes(startName) || startName.includes(target.name)
: false
)) || targets.find((target) => (
startFloor
? target.floorLabel === startFloor || target.floorId === normalizeGuideFloorId(startFloor)
: false
)) || targets.find((target) => target.poiId !== route.value.facilityId)
const selectedStart = targets.find((target) => target.poiId === selectedStartPoint.value?.poiId)
const endTarget = targets.find((target) => target.poiId === route.value.facilityId)
|| (targetLocation
? targets.find((target) => target.floorId === targetLocation.floorId && target.name === targetLocation.name)
: null)
if (!fallbackStart || !endTarget) {
routePlanError.value = '未找到可用于位置关系预览的起点或终点'
if (!selectedStart || !selectedStart.routeNodeId || !endTarget) {
routePlanError.value = selectedStart ? '未找到可用于位置关系预览的终点' : '请选择起点'
return
}
const result = await guideRouteUseCase.planRoute({
startPoiId: fallbackStart.poiId,
startPoiId: selectedStart.poiId,
endPoiId: endTarget.poiId
})
@@ -952,6 +1003,41 @@ const handlePageBack = () => {
color: #b44b42;
}
.start-point-select {
min-height: 44px;
padding: 0 12px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
box-sizing: border-box;
background: #f5f7f2;
border: 1px solid #e4e5df;
border-radius: 8px;
}
.start-point-select-label {
flex: 0 0 auto;
font-size: 13px;
line-height: 18px;
color: #545861;
}
.start-point-select-value {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 14px;
line-height: 19px;
font-weight: 500;
color: #151713;
}
.start-point-select-value.placeholder {
color: #7a7e76;
}
.indoor-guide-actions {
display: flex;
gap: 10px;