优化三维导览模型加载与交互体验
This commit is contained in:
@@ -7,6 +7,9 @@ import type {
|
||||
import {
|
||||
dataSourceConfig
|
||||
} from '@/config/dataSource'
|
||||
import {
|
||||
isIndoorNavigableFloor
|
||||
} from '@/domain/guideFloor'
|
||||
import {
|
||||
formatSgsFloorLabel,
|
||||
toMuseumPoiFromSgs
|
||||
@@ -17,7 +20,8 @@ import {
|
||||
type SgsSdkFloorSummaryPayload
|
||||
} from '@/data/providers/sgsSdkApiProvider'
|
||||
import {
|
||||
formatNavFloorLabel
|
||||
formatNavFloorLabel,
|
||||
isStaticIndoorNavigableFloorId
|
||||
} from '@/data/adapters/navAssetsAdapter'
|
||||
import {
|
||||
defaultStaticNavAssetsProvider,
|
||||
@@ -97,6 +101,7 @@ export class StaticGuideModelRepository implements GuideModelRepository {
|
||||
])
|
||||
|
||||
const floors: GuideModelFloorAsset[] = [...floorIndex.floors]
|
||||
.filter((floor) => isStaticIndoorNavigableFloorId(floor.floorId))
|
||||
.sort((a, b) => a.order - b.order)
|
||||
.map((floor) => ({
|
||||
floorId: floor.floorId,
|
||||
@@ -115,7 +120,7 @@ export class StaticGuideModelRepository implements GuideModelRepository {
|
||||
async loadFloorPois(floorId: string) {
|
||||
const floorIndex = await this.provider.loadFloorIndex()
|
||||
const floor = floorIndex.floors.find((item) => item.floorId === floorId)
|
||||
if (!floor) return []
|
||||
if (!floor || !isStaticIndoorNavigableFloorId(floor.floorId)) return []
|
||||
|
||||
const pois = await this.provider.loadFloorPois(floor.poiDataAsset)
|
||||
return pois
|
||||
@@ -131,7 +136,8 @@ export class SgsSdkGuideModelRepository implements GuideModelRepository {
|
||||
|
||||
async loadPackage(): Promise<GuideModelRenderPackage> {
|
||||
const manifest = await this.provider.getManifest()
|
||||
const floors = sortSgsFloors(manifest.floors)
|
||||
const allFloors = sortSgsFloors(manifest.floors)
|
||||
const floors = allFloors.filter(isIndoorNavigableFloor)
|
||||
this.floorsCache = floors
|
||||
|
||||
const bundles = await Promise.all(
|
||||
@@ -153,8 +159,13 @@ export class SgsSdkGuideModelRepository implements GuideModelRepository {
|
||||
})
|
||||
.filter((asset) => asset.modelUrl)
|
||||
|
||||
const overviewFloorIndex = floors.findIndex((floor) => floor.floorCode === 'EXTERIOR')
|
||||
const overviewModelUrl = floorAssets[overviewFloorIndex]?.modelUrl || floorAssets[0]?.modelUrl || ''
|
||||
const overviewFloor = allFloors.find((floor) => !isIndoorNavigableFloor(floor))
|
||||
const overviewBundle = overviewFloor
|
||||
? await this.provider.getFloorBundle(String(overviewFloor.floorId)).catch(() => null)
|
||||
: null
|
||||
const overviewModelUrl = resolveSgsAssetUrl(
|
||||
overviewBundle?.model?.modelUrl || overviewBundle?.model?.fallbackModelUrl
|
||||
) || floorAssets[0]?.modelUrl || ''
|
||||
|
||||
return {
|
||||
overviewModelUrl,
|
||||
@@ -164,7 +175,7 @@ export class SgsSdkGuideModelRepository implements GuideModelRepository {
|
||||
|
||||
async loadFloorPois(floorId: string) {
|
||||
const manifest = await this.provider.getManifest()
|
||||
this.floorsCache = sortSgsFloors(manifest.floors)
|
||||
this.floorsCache = sortSgsFloors(manifest.floors).filter(isIndoorNavigableFloor)
|
||||
const matchedFloor = this.floorsCache.find((floor) => (
|
||||
String(floor.floorId) === floorId
|
||||
|| floor.floorCode === floorId
|
||||
|
||||
@@ -10,8 +10,13 @@ import type {
|
||||
import {
|
||||
NAV_ROUTE_READINESS
|
||||
} from '@/domain/guideReadiness'
|
||||
import {
|
||||
isIndoorNavigableFloor,
|
||||
isPoiOnIndoorNavigableFloor
|
||||
} from '@/domain/guideFloor'
|
||||
import {
|
||||
formatNavFloorLabel,
|
||||
isStaticIndoorNavigableFloorId,
|
||||
navFloorIdFromLabel,
|
||||
toMuseumPoi
|
||||
} from '@/data/adapters/navAssetsAdapter'
|
||||
@@ -68,6 +73,11 @@ const toLocationPreview = (poi: MuseumPoi): GuideLocationPreview => ({
|
||||
sourceObjectName: poi.sourceObjectName
|
||||
})
|
||||
|
||||
const isSearchableIndoorPoi = (poi: MuseumPoi) => (
|
||||
searchableCategories.has(poi.primaryCategory.id)
|
||||
&& isPoiOnIndoorNavigableFloor(poi)
|
||||
)
|
||||
|
||||
export interface GuideRepository {
|
||||
getAssetBaseUrl(): string
|
||||
getFloors(): Promise<MuseumFloor[]>
|
||||
@@ -94,6 +104,7 @@ export class StaticGuideRepository implements GuideRepository {
|
||||
async getFloors() {
|
||||
const floorIndex = await this.provider.loadFloorIndex()
|
||||
return [...floorIndex.floors]
|
||||
.filter((floor) => isStaticIndoorNavigableFloorId(floor.floorId))
|
||||
.sort((a, b) => b.order - a.order)
|
||||
.map((floor) => ({
|
||||
id: floor.floorId,
|
||||
@@ -111,8 +122,8 @@ export class StaticGuideRepository implements GuideRepository {
|
||||
|
||||
const pois = await this.provider.loadPoiIndex()
|
||||
this.poiCache = pois
|
||||
.filter((poi) => searchableCategories.has(poi.primaryCategory))
|
||||
.map(toMuseumPoi)
|
||||
.filter(isSearchableIndoorPoi)
|
||||
|
||||
return this.poiCache
|
||||
}
|
||||
@@ -208,8 +219,10 @@ export class SgsSdkGuideRepository implements GuideRepository {
|
||||
if (this.floorsCache) return this.floorsCache
|
||||
|
||||
const manifest = await this.provider.getManifest()
|
||||
this.floorAliases = buildSgsFloorAliases(manifest.floors)
|
||||
const indoorFloors = manifest.floors.filter(isIndoorNavigableFloor)
|
||||
this.floorAliases = buildSgsFloorAliases(indoorFloors)
|
||||
this.floorsCache = [...manifest.floors]
|
||||
.filter(isIndoorNavigableFloor)
|
||||
.sort((a, b) => Number(a.sortOrder || 0) - Number(b.sortOrder || 0))
|
||||
.map(toMuseumFloorFromSgs)
|
||||
|
||||
@@ -228,15 +241,18 @@ export class SgsSdkGuideRepository implements GuideRepository {
|
||||
if (this.poiCache) return this.poiCache
|
||||
|
||||
const manifest = await this.provider.getManifest()
|
||||
this.floorAliases = buildSgsFloorAliases(manifest.floors)
|
||||
const indoorFloors = manifest.floors.filter(isIndoorNavigableFloor)
|
||||
const indoorFloorIds = new Set(indoorFloors.map((floor) => String(floor.floorId)))
|
||||
this.floorAliases = buildSgsFloorAliases(indoorFloors)
|
||||
const poiGroups = await Promise.all(
|
||||
manifest.floors.map((floor) => this.provider.getFloorPois(String(floor.floorId)))
|
||||
indoorFloors.map((floor) => this.provider.getFloorPois(String(floor.floorId)))
|
||||
)
|
||||
|
||||
this.poiCache = poiGroups
|
||||
.flat()
|
||||
.map((poi) => toMuseumPoiFromSgs(poi, manifest.floors))
|
||||
.filter((poi) => poi.id && poi.name)
|
||||
.filter((poi) => indoorFloorIds.has(String(poi.floorId)) || isPoiOnIndoorNavigableFloor(poi))
|
||||
|
||||
return this.poiCache
|
||||
}
|
||||
@@ -271,11 +287,11 @@ export class SgsSdkGuideRepository implements GuideRepository {
|
||||
const normalizedFloorId = this.normalizeFloorId(floorId)
|
||||
try {
|
||||
const diagnostics = await this.provider.getFloorDiagnostics(normalizedFloorId)
|
||||
return toGuideFloorDetailFromSgs(diagnostics)
|
||||
return isIndoorNavigableFloor(diagnostics) ? toGuideFloorDetailFromSgs(diagnostics) : null
|
||||
} catch {
|
||||
const manifest = await this.provider.getManifest()
|
||||
const floor = manifest.floors.find((item) => String(item.floorId) === normalizedFloorId)
|
||||
return floor ? toGuideFloorDetailFromSgs(floor) : null
|
||||
return floor && isIndoorNavigableFloor(floor) ? toGuideFloorDetailFromSgs(floor) : null
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,9 @@ import type {
|
||||
GuideRouteResult,
|
||||
GuideRouteTarget
|
||||
} from '@/domain/museum'
|
||||
import {
|
||||
isIndoorNavigableFloor
|
||||
} from '@/domain/guideFloor'
|
||||
import {
|
||||
applyRouteReadinessGate,
|
||||
NAV_ROUTE_UNAVAILABLE_MESSAGE,
|
||||
@@ -164,7 +167,10 @@ export class StaticGuideRouteRepository implements GuideRouteRepository {
|
||||
|
||||
async listRouteTargets() {
|
||||
const dataset = await this.loadDataset()
|
||||
return dataset.targets
|
||||
return dataset.targets.filter((target) => isIndoorNavigableFloor({
|
||||
floorId: target.floorId,
|
||||
label: target.floorLabel
|
||||
}))
|
||||
}
|
||||
|
||||
async findRoute(startPoiId: string, endPoiId: string) {
|
||||
|
||||
@@ -6,6 +6,9 @@ import type {
|
||||
import {
|
||||
NAV_ROUTE_READINESS
|
||||
} from '@/domain/guideReadiness'
|
||||
import {
|
||||
isIndoorNavigableFloor
|
||||
} from '@/domain/guideFloor'
|
||||
import {
|
||||
GuideRouteError
|
||||
} from '@/repositories/GuideRouteRepository'
|
||||
@@ -63,7 +66,7 @@ export class SdkGuideRouteRepository {
|
||||
async getRouteReadiness(): Promise<GuideRouteReadiness> {
|
||||
try {
|
||||
const diagnostics = await this.sdkApiProvider.getMapDiagnostics()
|
||||
const floors = diagnostics.floors || []
|
||||
const floors = (diagnostics.floors || []).filter(isIndoorNavigableFloor)
|
||||
|
||||
if (!floors.length) {
|
||||
return createUnavailableReadiness('SDK 地图楼层数据为空')
|
||||
@@ -115,7 +118,7 @@ export class SdkGuideRouteRepository {
|
||||
if (this.targetsCache) return this.targetsCache
|
||||
|
||||
const diagnostics = await this.sdkApiProvider.getMapDiagnostics()
|
||||
const floors = diagnostics.floors || []
|
||||
const floors = (diagnostics.floors || []).filter(isIndoorNavigableFloor)
|
||||
|
||||
const targets: GuideRouteTarget[] = []
|
||||
|
||||
@@ -196,7 +199,7 @@ export class SdkGuideRouteRepository {
|
||||
// 获取原始 floorId 用于 API 调用
|
||||
const diagnostics = await this.sdkApiProvider.getMapDiagnostics()
|
||||
const floorIdMap = new Map<string, string>()
|
||||
for (const floor of diagnostics.floors || []) {
|
||||
for (const floor of (diagnostics.floors || []).filter(isIndoorNavigableFloor)) {
|
||||
floorIdMap.set(toAppFloorId(floor.floorId), stringifyId(floor.floorId))
|
||||
}
|
||||
const rawStartFloorId = floorIdMap.get(startTarget.floorId) || startTarget.floorId
|
||||
|
||||
Reference in New Issue
Block a user