修复导览与讲解位置预览逻辑

This commit is contained in:
lyf
2026-06-30 11:00:49 +08:00
parent f2a33888b1
commit 1c2cc788d1
29 changed files with 1111 additions and 756 deletions

View File

@@ -61,7 +61,7 @@
<view class="action-bar">
<view
class="location-btn"
:class="{ disabled: !exhibit.location }"
:class="{ disabled: !hallLocationId }"
@tap="handleNavigate"
>
<svg class="location-icon" width="19" height="19" viewBox="0 0 24 24" fill="none">
@@ -134,12 +134,45 @@ const showAudioPlayer = ref(false)
const currentAudio = ref<AudioItem | null>(null)
const isPlaying = ref(false)
const activeTopTab = ref<GuideTopTab>('explain')
const resolvedHallId = ref('')
const heroImage = computed(() => exhibit.value.coverImages[0])
const detailMeta = computed(() => [
exhibit.value.hallName,
exhibit.value.floorLabel
].filter(Boolean).join(' · '))
const hallLocationId = computed(() => exhibit.value.hallId || resolvedHallId.value)
const normalizePoiName = (value: string) => value
.trim()
.replace(/[\s()【】[\]_-]/g, '')
.toLowerCase()
// 讲解详情页只定位到所属展厅,不再追踪具体展品点位。
const resolveHallGuidePoi = async () => {
const hallId = exhibit.value.hallId
if (hallId) {
const hallPoi = await guideUseCase.getPoiById(hallId)
if (hallPoi?.kind === 'hall' || hallPoi?.primaryCategory.id === 'exhibition_hall') {
return hallPoi
}
}
const normalizedTarget = normalizePoiName(exhibit.value.hallName || '')
if (!normalizedTarget) return null
const candidates = await guideUseCase.searchPois(exhibit.value.hallName || exhibit.value.title || '')
return candidates.find((candidate) => {
const candidateName = normalizePoiName(candidate.name)
const candidateHallName = normalizePoiName(candidate.hallName || '')
return candidate.kind === 'hall'
|| candidate.primaryCategory.id === 'exhibition_hall'
|| candidateName === normalizedTarget
|| candidateHallName === normalizedTarget
|| candidateName.includes(normalizedTarget)
|| normalizedTarget.includes(candidateName)
}) || candidates[0] || null
}
onLoad(async (options: any = {}) => {
const tab = Array.isArray(options.tab) ? options.tab[0] : options.tab
@@ -153,6 +186,9 @@ onLoad(async (options: any = {}) => {
const exhibitData = await explainUseCase.getExhibitById(exhibitId)
if (exhibitData) {
exhibit.value = toExplainDetailPageViewModel(exhibitData)
if (exhibitData.hallId) {
resolvedHallId.value = exhibitData.hallId
}
}
})
@@ -247,25 +283,34 @@ const handleAudioError = (_audio: AudioItem | null, message: string) => {
}
const handleNavigate = async () => {
if (!exhibit.value.location?.poiId) {
const matchedHallPoi = await resolveHallGuidePoi()
if (!matchedHallPoi) {
uni.showToast({
title: '该讲解暂无三维位置数据',
title: '该讲解暂无所属展厅位置数据',
icon: 'none'
})
return
}
const matchedPoi = await guideUseCase.getPoiById(exhibit.value.location.poiId)
if (!matchedPoi) {
uni.showToast({
title: '该讲解位置尚未映射到当前三维导览资源',
icon: 'none'
})
return
resolvedHallId.value = matchedHallPoi.id
exhibit.value = {
...exhibit.value,
hallId: matchedHallPoi.id,
hallName: matchedHallPoi.hallName || matchedHallPoi.name,
location: exhibit.value.location || {
status: 'hallFallback',
poiId: matchedHallPoi.id,
sourcePoiId: matchedHallPoi.id,
actionText: '查看所属展厅',
previewOnly: true,
floorId: matchedHallPoi.floorId,
floorLabel: matchedHallPoi.floorLabel,
note: '已定位到该讲解所属展厅。'
}
}
uni.navigateTo({
url: `/pages/route/detail?facilityId=${encodeURIComponent(exhibit.value.location.poiId)}&target=${encodeURIComponent(exhibit.value.title)}&state=preview`
url: `/pages/route/detail?facilityId=${encodeURIComponent(matchedHallPoi.id)}&target=${encodeURIComponent(exhibit.value.hallName || exhibit.value.title)}&state=preview`
})
}