diff --git a/scripts/get-building-polygon.js b/scripts/get-building-polygon.js index 0dd4f8a..b8211ac 100644 --- a/scripts/get-building-polygon.js +++ b/scripts/get-building-polygon.js @@ -5,8 +5,8 @@ const https = require('https') -// 腾讯地图 WebService API Key(需要在腾讯位置服务申请) -const API_KEY = 'EJPBZ-DQEEQ-PDN5U-4ZDVX-F4I3F-6MBJC' +// 由部署环境注入,避免把地图服务凭据写入仓库。 +const API_KEY = process.env.TENCENT_MAP_WEBSERVICE_KEY // 深圳自然博物馆坐标 const MUSEUM_LAT = 22.692763 @@ -109,6 +109,12 @@ function calculateRectangle(centerLat, centerLng, widthMeters, heightMeters) { return polygon } +if (!API_KEY) { + console.error('缺少 TENCENT_MAP_WEBSERVICE_KEY;请通过环境变量注入受域名/IP 限制的腾讯地图 WebService Key。') + process.exitCode = 1 + return +} + console.log('正在获取深圳自然博物馆建筑围栏信息...\n') // 执行查询 diff --git a/src/components/navigation/GuideMapShell.vue b/src/components/navigation/GuideMapShell.vue index db86624..a6517c7 100644 --- a/src/components/navigation/GuideMapShell.vue +++ b/src/components/navigation/GuideMapShell.vue @@ -586,10 +586,13 @@ const markFloorSwitchFailedIfUnrendered = (floorId: string, requestSeq: number) const handleFloorChange = (floor: { id: string; label: string }) => { const floorId = floor.id if (!floorId || loadingFloorId.value) return - if (floorId === renderedFloorId.value && activeFloorId.value === floorId && props.layerMode !== 'multi') { + if ( + floorId === renderedFloorId.value + && activeFloorId.value === floorId + && props.indoorView === 'floor' + && props.layerMode !== 'multi' + ) { emit('floorChange', floorId) - emit('indoorViewChange', 'floor') - emit('layerModeChange', 'single') return } @@ -604,9 +607,6 @@ const handleFloorChange = (floor: { id: string; label: string }) => { floorId, floorLabel: floor.label }) - emit('indoorViewChange', 'floor') - emit('layerModeChange', 'single') - Promise.resolve(indoorRendererRef.value?.switchFloor?.(floorId)) .then(() => { markFloorSwitchFailedIfUnrendered(floorId, requestSeq) @@ -667,10 +667,12 @@ const handleLayerModeChange = (mode: LayerDisplayMode) => { }) console.error('楼层切换失败:', error) }) - emit('indoorViewChange', 'floor') + // floor-change 才代表 ThreeMap 已提交单层模型。 } - emit('layerModeChange', mode) + if (mode === 'multi') { + emit('layerModeChange', mode) + } } const handleLayerModeToggle = () => { @@ -786,6 +788,8 @@ defineExpose({ clearRoute: () => { indoorRendererRef.value?.clearRoute?.() }, + // 仅发起切换;父级必须以 floor-change 作为已提交的唯一依据。 + switchFloor: (floorId: string) => indoorRendererRef.value?.switchFloor?.(floorId), showOverview: handleShowOverview, resetToViewBaseline: (options: { view: 'overview' | 'floor' diff --git a/src/components/navigation/GuideTopTabs.vue b/src/components/navigation/GuideTopTabs.vue index a1902d3..98abdfd 100644 --- a/src/components/navigation/GuideTopTabs.vue +++ b/src/components/navigation/GuideTopTabs.vue @@ -3,13 +3,21 @@ class="guide-top-tabs" :class="`variant-${variant}`" :style="{ top }" + role="tablist" + aria-label="主功能" > !getPoiDataIssues(poi).some((issue) = const unavailablePoiCount = computed(() => pois.value.filter((poi) => !isPoiLocatable(poi)).length) +// 数据质量统计保留给诊断日志,普通游客只看到可恢复的加载状态。 const dataWarning = computed(() => { - const warnings: string[] = [] - if (excludedPoiCount.value) warnings.push(`${excludedPoiCount.value} 个点位分类或楼层信息不完整`) - if (duplicatePoiCount.value) warnings.push(`${duplicatePoiCount.value} 个重复点位已合并`) - if (unavailablePoiCount.value) warnings.push(`${unavailablePoiCount.value} 个点位暂无地图坐标`) - if (floorLoadError.value) warnings.push('楼层信息读取失败') - return warnings.join(',') + const diagnostic = { + excluded: excludedPoiCount.value, + duplicates: duplicatePoiCount.value, + unavailable: unavailablePoiCount.value, + floorLoadError: floorLoadError.value + } + if (import.meta.env.DEV && Object.values(diagnostic).some(Boolean)) { + console.debug('[guide-poi-diagnostics]', diagnostic) + } + return '' }) const dedupePois = (items: MuseumPoi[]) => { @@ -860,7 +868,10 @@ const restoreResultListScroll = async () => { if (resultListElement) resultListElement.scrollTop = scrollTop } -const poiDisplayName = (poi: MuseumPoi) => poi.name?.trim() || '未命名点位' +const poiPresentations = computed(() => createVisitorPoiPresentations(pois.value)) +const poiDisplayName = (poi: MuseumPoi) => ( + poiPresentations.value.get(poi.id)?.displayName || '未命名点位' +) const poiResultMeta = (poi: MuseumPoi) => { const categoryLabel = resolvePoiCategory(poi)?.label || poi.primaryCategory?.label || '其他' diff --git a/src/pages/exhibit/detail.vue b/src/pages/exhibit/detail.vue index d00102f..b77eba3 100644 --- a/src/pages/exhibit/detail.vue +++ b/src/pages/exhibit/detail.vue @@ -17,7 +17,7 @@