修正楼层显示顺序
This commit is contained in:
@@ -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'
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user