修复 SGS SDK 导览数据源与模型加载
升级 SDK API 数据契约,补齐 guideStops、业务 POI、诊断与路线数据接口。 修复 SDK 模式下 POI/模型/楼层混用静态数据的问题,并为 ThreeMap 模型加载增加短退避重试。
This commit is contained in:
@@ -6,10 +6,12 @@ import type {
|
||||
GuideLocationPreview,
|
||||
GuideMapDiagnostics,
|
||||
GuideRouteReadiness,
|
||||
MuseumCategory,
|
||||
MuseumFloor,
|
||||
MuseumPoi
|
||||
} from '@/domain/museum'
|
||||
MuseumCategory,
|
||||
MuseumFloor,
|
||||
MuseumPoi,
|
||||
ExplainGuideStop,
|
||||
AudioPlayTargetType
|
||||
} from '@/domain/museum'
|
||||
import {
|
||||
NAV_ROUTE_UNAVAILABLE_MESSAGE
|
||||
} from '@/domain/guideReadiness'
|
||||
@@ -17,23 +19,30 @@ import {
|
||||
isIndoorNavigableFloor
|
||||
} from '@/domain/guideFloor'
|
||||
import type {
|
||||
SgsFloorDiagnosticsPayload,
|
||||
SgsMapDiagnosticsPayload,
|
||||
SgsNavigablePlacePayload,
|
||||
SgsPoiPayload,
|
||||
SgsFloorDiagnosticsPayload,
|
||||
SgsGuideStopPayload,
|
||||
SgsMapDiagnosticsPayload,
|
||||
SgsNavigablePlacePayload,
|
||||
SgsPoiPayload,
|
||||
SgsPositionPayload,
|
||||
SgsSdkFloorSummaryPayload,
|
||||
SgsSdkManifestPayload,
|
||||
SgsSpacePayload
|
||||
} from '@/data/providers/sgsSdkApiProvider'
|
||||
|
||||
const defaultCategory: MuseumCategory = {
|
||||
id: 'operation_experience',
|
||||
label: '导览点位',
|
||||
iconType: 'poi'
|
||||
}
|
||||
|
||||
const hallCategory: MuseumCategory = {
|
||||
const defaultCategory: MuseumCategory = {
|
||||
id: 'operation_experience',
|
||||
label: '导览点位',
|
||||
iconType: 'poi'
|
||||
}
|
||||
|
||||
const businessCategory: MuseumCategory = {
|
||||
id: 'business_poi',
|
||||
label: '运营服务',
|
||||
iconType: 'business'
|
||||
}
|
||||
|
||||
const hallCategory: MuseumCategory = {
|
||||
id: 'exhibition_hall',
|
||||
label: '展厅',
|
||||
iconType: 'exhibition_hall'
|
||||
@@ -45,7 +54,7 @@ const hallEntranceCategory: MuseumCategory = {
|
||||
iconType: 'hall_entrance'
|
||||
}
|
||||
|
||||
const categoryBySgsType: Record<string, MuseumCategory & { accessible?: boolean }> = {
|
||||
const categoryBySgsType: Record<string, MuseumCategory & { accessible?: boolean }> = {
|
||||
toilet: {
|
||||
id: 'basic_service_facility',
|
||||
label: '卫生间',
|
||||
@@ -237,6 +246,16 @@ export interface SgsHallPoiDiagnostics {
|
||||
skippedPlaceCount: number
|
||||
}
|
||||
|
||||
const businessTypeLabels: Record<string, string> = {
|
||||
shop: '商店',
|
||||
restaurant: '餐饮',
|
||||
cafe: '咖啡',
|
||||
vending: '售卖机',
|
||||
bookstore: '书店',
|
||||
cultural_shop: '文创商店',
|
||||
photo_spot: '打卡点'
|
||||
}
|
||||
|
||||
interface SgsHallPoiBuildOptions {
|
||||
fallbackY?: number
|
||||
}
|
||||
@@ -381,13 +400,23 @@ const normalizePlacePosition = (
|
||||
fallbackY
|
||||
)
|
||||
|
||||
const categoryFor = (poi: SgsPoiPayload): MuseumCategory & { accessible?: boolean } => {
|
||||
const normalizedType = poi.type?.trim()
|
||||
if (normalizedType && categoryBySgsType[normalizedType]) {
|
||||
return categoryBySgsType[normalizedType]
|
||||
}
|
||||
|
||||
if (poi.typeName) {
|
||||
const categoryFor = (poi: SgsPoiPayload): MuseumCategory & { accessible?: boolean } => {
|
||||
const normalizedType = poi.type?.trim().toLowerCase()
|
||||
const normalizedBusinessType = poi.businessType?.trim().toLowerCase()
|
||||
|
||||
if (String(poi.poiGroup || '').toUpperCase() === 'BUSINESS') {
|
||||
return {
|
||||
...businessCategory,
|
||||
label: normalizedBusinessType ? businessTypeLabels[normalizedBusinessType] || poi.typeName || businessCategory.label : poi.typeName || businessCategory.label,
|
||||
iconType: normalizedBusinessType || businessCategory.iconType
|
||||
}
|
||||
}
|
||||
|
||||
if (normalizedType && categoryBySgsType[normalizedType]) {
|
||||
return categoryBySgsType[normalizedType]
|
||||
}
|
||||
|
||||
if (poi.typeName) {
|
||||
return {
|
||||
...defaultCategory,
|
||||
label: poi.typeName,
|
||||
@@ -395,8 +424,15 @@ const categoryFor = (poi: SgsPoiPayload): MuseumCategory & { accessible?: boolea
|
||||
}
|
||||
}
|
||||
|
||||
return defaultCategory
|
||||
}
|
||||
return defaultCategory
|
||||
}
|
||||
|
||||
const kindForSgsPoi = (poi: SgsPoiPayload, category: MuseumCategory) => {
|
||||
if (category.id === 'business_poi') return 'facility'
|
||||
if (category.id === 'operation_experience') return 'guide'
|
||||
|
||||
return 'facility'
|
||||
}
|
||||
|
||||
export const toMuseumPoiFromSgs = (
|
||||
poi: SgsPoiPayload,
|
||||
@@ -425,12 +461,41 @@ export const toMuseumPoiFromSgs = (
|
||||
],
|
||||
positionGltf: normalizePosition(poi),
|
||||
sourceObjectName: poi.anchorNodeName || undefined,
|
||||
sourceConfidence: 'backend-sgs-sdk',
|
||||
navigationReadiness: '位置预览',
|
||||
accessible: category.accessible === true,
|
||||
kind: category.id === 'operation_experience' ? 'guide' : 'facility'
|
||||
}
|
||||
}
|
||||
sourceConfidence: 'backend-sgs-sdk',
|
||||
navigationReadiness: '位置预览',
|
||||
accessible: category.accessible === true,
|
||||
kind: kindForSgsPoi(poi, category)
|
||||
}
|
||||
}
|
||||
|
||||
const normalizeAudioTargetType = (targetType?: string | null): AudioPlayTargetType | undefined => {
|
||||
const normalized = targetType?.toUpperCase()
|
||||
if (normalized === 'ITEM' || normalized === 'STOP') return normalized
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
export const toExplainGuideStopFromSgs = (stop: SgsGuideStopPayload): ExplainGuideStop | null => {
|
||||
const id = stringifyId(stop.id)
|
||||
if (!id) return null
|
||||
|
||||
return {
|
||||
id,
|
||||
name: normalizedText(stop.name) || `讲解点${id}`,
|
||||
hallId: stringifyId(stop.hallId) || undefined,
|
||||
hallName: normalizedText(stop.hallName) || undefined,
|
||||
floorId: stringifyId(stop.floorId) || undefined,
|
||||
targetType: normalizeAudioTargetType(stop.targetType) || 'STOP',
|
||||
targetId: stringifyId(stop.targetId) || id,
|
||||
coverImageUrl: normalizedText(stop.coverImageUrl) || undefined,
|
||||
description: normalizedText(stop.description) || undefined,
|
||||
hasAudio: stop.hasAudio === true || Boolean(normalizedText(stop.audioUrl)),
|
||||
poiId: stringifyId(stop.poiId) || undefined,
|
||||
outlineId: stringifyId(stop.outlineId || stop.routeId) || undefined,
|
||||
outlineName: normalizedText(stop.outlineName || stop.routeName) || undefined,
|
||||
sort: optionalNumber(stop.sort ?? stop.seqOrder)
|
||||
}
|
||||
}
|
||||
|
||||
export const toLocationPreviewFromPoi = (poi: MuseumPoi): GuideLocationPreview => ({
|
||||
poiId: poi.id,
|
||||
|
||||
Reference in New Issue
Block a user