修复馆内导览楼层点位展示

This commit is contained in:
lyf
2026-07-01 00:07:25 +08:00
parent f13d53d536
commit cf37e7a40e
5 changed files with 1379 additions and 781 deletions

View File

@@ -150,7 +150,12 @@
:id="floor.scrollId"
:key="floor.id"
class="floor-item"
:class="{ active: activeFloorId === floor.id && layerMode !== 'multi' }"
:class="{
active: activeFloorId === floor.id && layerMode !== 'multi',
pending: loadingFloorId === floor.id,
failed: failedFloorId === floor.id,
disabled: isFloorSwitchDisabled(floor.id)
}"
@tap.stop="handleFloorChange(floor)"
>
<text class="floor-label">{{ floor.label }}</text>
@@ -247,6 +252,11 @@ interface GuideFloorOption {
label: string
}
interface FloorSwitchEvent {
floorId: string
floorLabel: string
}
interface OutdoorNavPolyline {
points: Array<{ latitude: number; longitude: number }>
color: string
@@ -381,7 +391,9 @@ const props = withDefaults(defineProps<{
const emit = defineEmits<{
searchTap: []
modeChange: [mode: '2d' | '3d']
floorRequest: [event: FloorSwitchEvent]
floorChange: [floor: string]
floorSwitchFailed: [event: FloorSwitchEvent]
toolClick: [tool: string]
moreClick: []
indoorViewChange: [view: IndoorViewMode]
@@ -445,8 +457,15 @@ const activeFloorId = computed(() => {
return normalizedFloor?.id || normalizedFloorId
})
const activeFloorScrollIntoView = ref('')
const pendingFloorId = ref('')
let suppressFloorAutoScrollUntil = 0
const requestedFloorId = ref('')
const requestedFloorLabel = ref('')
const loadingFloorId = ref('')
const renderedFloorId = ref(activeFloorId.value)
const activeFloorSwitchRequestSeq = ref(0)
const renderedFloorSwitchRequestSeq = ref(0)
const failedFloorId = ref('')
let suppressFloorAutoScrollForFloorId = ''
let floorSwitchRequestSeq = 0
const syncActiveFloorScroll = () => {
if (props.mapType !== 'indoor' || props.indoorView === 'overview' || props.layerMode === 'multi') {
@@ -454,10 +473,12 @@ const syncActiveFloorScroll = () => {
return
}
if (Date.now() < suppressFloorAutoScrollUntil) {
if (activeFloorId.value === suppressFloorAutoScrollForFloorId) {
activeFloorScrollIntoView.value = ''
suppressFloorAutoScrollForFloorId = ''
return
}
suppressFloorAutoScrollForFloorId = ''
const matchedFloor = floorItems.value.find((floor) => floor.id === activeFloorId.value)
activeFloorScrollIntoView.value = matchedFloor?.scrollId || ''
@@ -475,6 +496,11 @@ watch(
{ immediate: true }
)
watch(activeFloorId, (floorId) => {
if (!floorId || loadingFloorId.value === floorId) return
renderedFloorId.value = floorId
})
const searchFieldStyle = computed(() => ({
top: props.searchTop
}))
@@ -528,27 +554,77 @@ const isStaleFloorSwitchError = (error: unknown) => (
error instanceof Error && error.message === 'STALE_MODEL_LOAD'
)
const handleFloorChange = (floor: { id: string; label: string }) => {
const floorId = floor.id || props.normalizeFloorId(floor.label)
if (!floorId || pendingFloorId.value === floorId) return
const findFloorItemById = (floorId: string) => (
floorItems.value.find((floor) => floor.id === floorId)
)
pendingFloorId.value = floorId
suppressFloorAutoScrollUntil = Date.now() + 650
const isFloorSwitchDisabled = (floorId: string) => (
Boolean(loadingFloorId.value) && loadingFloorId.value !== floorId
)
const clearFloorLoadingIfCurrent = (floorId: string) => {
if (loadingFloorId.value === floorId) {
loadingFloorId.value = ''
}
}
const markFloorSwitchFailedIfUnrendered = (floorId: string, requestSeq: number) => {
if (
loadingFloorId.value !== floorId
|| activeFloorSwitchRequestSeq.value !== requestSeq
|| renderedFloorSwitchRequestSeq.value === requestSeq
) return
failedFloorId.value = floorId
clearFloorLoadingIfCurrent(floorId)
emit('floorSwitchFailed', {
floorId,
floorLabel: requestedFloorId.value === floorId
? requestedFloorLabel.value || findFloorItemById(floorId)?.label || floorId
: findFloorItemById(floorId)?.label || floorId
})
}
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') {
emit('floorChange', floorId)
emit('indoorViewChange', 'floor')
emit('layerModeChange', 'single')
return
}
requestedFloorId.value = floorId
requestedFloorLabel.value = floor.label
loadingFloorId.value = floorId
const requestSeq = ++floorSwitchRequestSeq
activeFloorSwitchRequestSeq.value = requestSeq
failedFloorId.value = ''
suppressFloorAutoScrollForFloorId = floorId
activeFloorScrollIntoView.value = ''
indoorRendererRef.value?.disableAutoSwitchTemporarily?.(10000)
emit('floorRequest', {
floorId,
floorLabel: floor.label
})
emit('indoorViewChange', 'floor')
emit('layerModeChange', 'single')
Promise.resolve(indoorRendererRef.value?.switchFloor?.(floorId))
.then(() => {
markFloorSwitchFailedIfUnrendered(floorId, requestSeq)
})
.catch((error) => {
if (isStaleFloorSwitchError(error)) return
failedFloorId.value = floorId
clearFloorLoadingIfCurrent(floorId)
emit('floorSwitchFailed', {
floorId,
floorLabel: floor.label
})
console.error('楼层切换失败:', error)
})
.finally(() => {
if (pendingFloorId.value === floorId) {
pendingFloorId.value = ''
}
})
}
const handleLayerModeChange = (mode: LayerDisplayMode) => {
@@ -556,22 +632,45 @@ const handleLayerModeChange = (mode: LayerDisplayMode) => {
indoorRendererRef.value?.disableAutoSwitchTemporarily?.(10000)
if (mode === 'multi') {
pendingFloorId.value = ''
loadingFloorId.value = ''
requestedFloorId.value = ''
requestedFloorLabel.value = ''
void indoorRendererRef.value?.showMultiFloor?.()
emit('indoorViewChange', 'multi')
} else {
const floorId = activeFloorId.value
pendingFloorId.value = floorId
const floorLabel = findFloorItemById(floorId)?.label || floorId
if (!floorId) return
if (floorId === renderedFloorId.value && props.layerMode !== 'multi') {
emit('indoorViewChange', 'floor')
emit('layerModeChange', mode)
return
}
requestedFloorId.value = floorId
requestedFloorLabel.value = floorLabel
loadingFloorId.value = floorId
const requestSeq = ++floorSwitchRequestSeq
activeFloorSwitchRequestSeq.value = requestSeq
failedFloorId.value = ''
emit('floorRequest', {
floorId,
floorLabel
})
Promise.resolve(indoorRendererRef.value?.switchFloor?.(floorId))
.then(() => {
markFloorSwitchFailedIfUnrendered(floorId, requestSeq)
})
.catch((error) => {
if (isStaleFloorSwitchError(error)) return
failedFloorId.value = floorId
clearFloorLoadingIfCurrent(floorId)
emit('floorSwitchFailed', {
floorId,
floorLabel
})
console.error('楼层切换失败:', error)
})
.finally(() => {
if (pendingFloorId.value === floorId) {
pendingFloorId.value = ''
}
})
emit('indoorViewChange', 'floor')
}
@@ -622,6 +721,14 @@ const handleMoreTap = () => {
}
const handleThreeFloorChange = (floorId: string) => {
renderedFloorId.value = floorId
if (loadingFloorId.value === floorId) {
renderedFloorSwitchRequestSeq.value = activeFloorSwitchRequestSeq.value
}
if (failedFloorId.value === floorId) {
failedFloorId.value = ''
}
clearFloorLoadingIfCurrent(floorId)
emit('floorChange', floorId)
emit('indoorViewChange', 'floor')
emit('layerModeChange', 'single')
@@ -1120,6 +1227,28 @@ defineExpose({
background: #000000;
}
.floor-item.pending {
pointer-events: none;
opacity: 0.72;
}
.floor-item.pending::before {
content: '';
position: absolute;
inset: 7px;
border: 1px solid rgba(224, 225, 0, 0.9);
border-radius: 6px;
}
.floor-item.disabled {
pointer-events: none;
opacity: 0.46;
}
.floor-item.failed:not(.pending) .floor-label {
color: #b84a4a;
}
.floor-label {
font-size: 13px;
line-height: 18px;