修正楼层显示顺序

This commit is contained in:
lyf
2026-06-28 19:23:27 +08:00
parent 32c98723e2
commit c4d819021f
5 changed files with 74 additions and 17 deletions

View File

@@ -62,6 +62,9 @@ import type {
GuideRouteFloorSegment,
GuideRouteResult
} from '@/domain/museum'
import {
compareFloorsTopToBottom
} from '@/domain/guideFloor'
type ViewMode = 'overview' | 'floor' | 'multi'
type CameraPreset = 'top' | 'oblique'
@@ -202,7 +205,7 @@ const renderPackage = ref<GuideModelRenderPackage | null>(null)
const floors = computed<FloorOption[]>(() => (
[...floorIndex.value]
.sort((a, b) => b.order - a.order)
.sort(compareFloorsTopToBottom)
.map((floor) => ({
id: floor.floorId,
label: formatFloorLabel(floor.floorId)
@@ -1424,7 +1427,7 @@ const applyMultiFloorLayout = (items: MultiFloorModelItem[]) => {
const centerIndex = (items.length - 1) / 2
items.forEach((item, index) => {
const offsetY = (index - centerIndex) * verticalGap
const offsetY = (centerIndex - index) * verticalGap
item.model.position.y += offsetY
item.model.userData.multiFloorOffsetY = offsetY
item.model.userData.multiFloorVerticalGap = verticalGap
@@ -1892,7 +1895,7 @@ const loadMultiFloor = async () => {
const group = new THREE.Group()
group.name = 'GuideMultiFloorModel'
const orderedFloors = [...floorIndex.value].sort((a, b) => a.order - b.order)
const orderedFloors = [...floorIndex.value].sort(compareFloorsTopToBottom)
const loadedFloors: MultiFloorModelItem[] = []
const sharedModelUrl = getSharedMultiFloorModelUrl(orderedFloors)
@@ -2695,7 +2698,7 @@ const loadModelPackage = async () => {
renderPackage.value = packageData
setProgress(14, '正在读取楼层索引...')
floorIndex.value = [...packageData.floors].sort((a, b) => a.order - b.order)
floorIndex.value = [...packageData.floors].sort(compareFloorsTopToBottom)
if (!floorIndex.value.some((floor) => floor.floorId === currentFloor.value)) {
currentFloor.value = floorIndex.value.find((floor) => floor.floorId === 'L1')?.floorId || floorIndex.value[0]?.floorId || 'L1'

View File

@@ -11,6 +11,8 @@ interface FloorLike {
floorName?: string | null
name?: string | null
modelGroup?: string | null
order?: number | null
sortOrder?: number | null
}
const indoorFloorCodePattern = /^L-?\d+(?:\.\d+)?$/i
@@ -22,6 +24,63 @@ const normalizeValue = (value: unknown) => (
value === null || typeof value === 'undefined' ? '' : String(value).trim()
)
const parseFloorLevelFromToken = (value: unknown) => {
const normalized = normalizeValue(value).toUpperCase()
if (!normalized || isNonNavigableFloorToken(normalized)) return Number.NaN
const basementMatch = normalized.match(/^B(\d+(?:\.\d+)?)$/)
if (basementMatch) return -Number(basementMatch[1])
const prefixedFloorMatch = normalized.match(/^F(\d+(?:\.\d+)?)$/)
if (prefixedFloorMatch) return Number(prefixedFloorMatch[1])
const labelMatch = normalized.match(/^(\d+(?:\.\d+)?)F$/)
if (labelMatch) return Number(labelMatch[1])
const codeMatch = normalized.match(/^L(-?\d+(?:\.\d+)?)$/)
if (codeMatch) return Number(codeMatch[1])
return Number.NaN
}
export const getFloorSortLevel = (floor: FloorLike | null | undefined) => {
if (!floor) return Number.NaN
const semanticTokens = [
floor.label,
floor.floorCode,
floor.floorName,
floor.name,
floor.modelGroup,
floor.id,
floor.floorId
]
for (const token of semanticTokens) {
const level = parseFloorLevelFromToken(token)
if (Number.isFinite(level)) return level
}
const order = Number(floor.order ?? floor.sortOrder)
return Number.isFinite(order) ? order : Number.NaN
}
export const compareFloorsTopToBottom = (a: FloorLike, b: FloorLike) => {
const aLevel = getFloorSortLevel(a)
const bLevel = getFloorSortLevel(b)
if (Number.isFinite(aLevel) && Number.isFinite(bLevel) && aLevel !== bLevel) {
return bLevel - aLevel
}
if (Number.isFinite(aLevel) && !Number.isFinite(bLevel)) return -1
if (!Number.isFinite(aLevel) && Number.isFinite(bLevel)) return 1
const aLabel = normalizeValue(a.label || a.floorCode || a.floorName || a.id || a.floorId)
const bLabel = normalizeValue(b.label || b.floorCode || b.floorName || b.id || b.floorId)
return aLabel.localeCompare(bLabel, 'zh-Hans-CN')
}
export const isNonNavigableFloorToken = (value: unknown) => {
const normalized = normalizeValue(value)
return Boolean(normalized && nonNavigableFloorPattern.test(normalized))

View File

@@ -107,6 +107,7 @@ import type {
MuseumPoi
} from '@/domain/museum'
import {
compareFloorsTopToBottom,
isIndoorNavigableFloor,
isPoiOnIndoorNavigableFloor
} from '@/domain/guideFloor'
@@ -146,7 +147,7 @@ const isLoading = ref(false)
const displayFloors = computed(() => [...floors.value]
.filter(isIndoorNavigableFloor)
.sort((a, b) => floorOrder(a) - floorOrder(b)))
.sort(compareFloorsTopToBottom))
const floorResults = computed(() => {
const matched = pois.value.filter((poi) => poi.floorLabel === activeFloor.value)
@@ -157,14 +158,6 @@ const emptyTitle = computed(() => (
isLoading.value ? '正在读取点位' : '暂无匹配点位'
))
const floorOrder = (floor: MuseumFloor) => {
if (Number.isFinite(floor.order)) return floor.order
const normalized = floor.label.toUpperCase()
if (normalized.startsWith('B')) return -Number(normalized.replace('B', '')) || -1
return Number(normalized.replace('F', '')) || 0
}
const isVisiblePoi = (poi: MuseumPoi) => poi.primaryCategory.id !== 'touring_poi'
&& isPoiOnIndoorNavigableFloor(poi)

View File

@@ -8,6 +8,7 @@ import {
dataSourceConfig
} from '@/config/dataSource'
import {
compareFloorsTopToBottom,
isIndoorNavigableFloor
} from '@/domain/guideFloor'
import {
@@ -87,7 +88,7 @@ const resolveSgsAssetUrl = (url?: string | null) => {
}
const sortSgsFloors = (floors: SgsSdkFloorSummaryPayload[]) => [...floors]
.sort((a, b) => Number(a.sortOrder || 0) - Number(b.sortOrder || 0))
.sort(compareFloorsTopToBottom)
const isSharedSgsModelAsset = (
modelUrl: string,
@@ -122,7 +123,7 @@ export class StaticGuideModelRepository implements GuideModelRepository {
const floors: GuideModelFloorAsset[] = [...floorIndex.floors]
.filter((floor) => isStaticIndoorNavigableFloorId(floor.floorId))
.sort((a, b) => a.order - b.order)
.sort(compareFloorsTopToBottom)
.map((floor) => ({
floorId: floor.floorId,
label: formatNavFloorLabel(floor.floorId),

View File

@@ -11,6 +11,7 @@ import {
NAV_ROUTE_READINESS
} from '@/domain/guideReadiness'
import {
compareFloorsTopToBottom,
isIndoorNavigableFloor,
isPoiOnIndoorNavigableFloor
} from '@/domain/guideFloor'
@@ -105,7 +106,7 @@ export class StaticGuideRepository implements GuideRepository {
const floorIndex = await this.provider.loadFloorIndex()
return [...floorIndex.floors]
.filter((floor) => isStaticIndoorNavigableFloorId(floor.floorId))
.sort((a, b) => b.order - a.order)
.sort(compareFloorsTopToBottom)
.map((floor) => ({
id: floor.floorId,
label: formatNavFloorLabel(floor.floorId),
@@ -223,7 +224,7 @@ export class SgsSdkGuideRepository implements GuideRepository {
this.floorAliases = buildSgsFloorAliases(indoorFloors)
this.floorsCache = [...manifest.floors]
.filter(isIndoorNavigableFloor)
.sort((a, b) => Number(a.sortOrder || 0) - Number(b.sortOrder || 0))
.sort(compareFloorsTopToBottom)
.map(toMuseumFloorFromSgs)
return this.floorsCache