refactor: 重构数据层支持 SGS SDK 集成
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import type {
|
||||
GuideDataIntegrityReport,
|
||||
GuideFloorDetail,
|
||||
GuideLocationPreview,
|
||||
GuideMapDiagnostics,
|
||||
GuideRouteReadiness,
|
||||
MuseumFloor,
|
||||
MuseumPoi
|
||||
@@ -16,6 +19,20 @@ import {
|
||||
defaultStaticNavAssetsProvider,
|
||||
type StaticNavAssetsProvider
|
||||
} from '@/data/providers/staticNavAssetsProvider'
|
||||
import {
|
||||
defaultSgsSdkApiProvider,
|
||||
type SgsSdkApiProvider
|
||||
} from '@/data/providers/sgsSdkApiProvider'
|
||||
import {
|
||||
buildSgsFloorAliases,
|
||||
createGuideDataIntegrityReport,
|
||||
toGuideFloorDetailFromSgs,
|
||||
toGuideMapDiagnostics,
|
||||
toLocationPreviewFromPoi,
|
||||
toMuseumFloorFromSgs,
|
||||
toMuseumPoiFromSgs,
|
||||
toRouteReadinessFromSgsDiagnostics
|
||||
} from '@/data/adapters/sgsSdkGuideAdapter'
|
||||
|
||||
const searchableCategories = new Set([
|
||||
'touring_poi',
|
||||
@@ -60,6 +77,9 @@ export interface GuideRepository {
|
||||
searchPois(keyword?: string): Promise<MuseumPoi[]>
|
||||
getLocationPreview(poiId: string): Promise<GuideLocationPreview | null>
|
||||
getRouteReadiness(): Promise<GuideRouteReadiness>
|
||||
getFloorDetail?(floorId: string): Promise<GuideFloorDetail | null>
|
||||
getMapDiagnostics?(): Promise<GuideMapDiagnostics>
|
||||
checkDataIntegrity?(): Promise<GuideDataIntegrityReport>
|
||||
}
|
||||
|
||||
export class StaticGuideRepository implements GuideRepository {
|
||||
@@ -120,6 +140,161 @@ export class StaticGuideRepository implements GuideRepository {
|
||||
return this.provider.loadRouteReadiness()
|
||||
.catch(() => NAV_ROUTE_READINESS)
|
||||
}
|
||||
|
||||
async getFloorDetail(floorId: string) {
|
||||
const floors = await this.getFloors()
|
||||
const normalizedFloorId = this.normalizeFloorId(floorId)
|
||||
const floor = floors.find((item) => item.id === normalizedFloorId)
|
||||
return floor
|
||||
? {
|
||||
...floor,
|
||||
warnings: []
|
||||
}
|
||||
: null
|
||||
}
|
||||
|
||||
async getMapDiagnostics(): Promise<GuideMapDiagnostics> {
|
||||
const [floors, pois] = await Promise.all([
|
||||
this.getFloors(),
|
||||
this.listPois()
|
||||
])
|
||||
|
||||
return {
|
||||
mapId: 'static',
|
||||
mapName: '本地静态导览数据',
|
||||
status: 'WARN',
|
||||
floors: floors.map((floor) => ({
|
||||
...floor,
|
||||
poiCount: pois.filter((poi) => poi.floorId === floor.id).length,
|
||||
warnings: []
|
||||
})),
|
||||
summary: {
|
||||
floorCount: floors.length,
|
||||
modelReadyFloorCount: floors.length,
|
||||
poiCount: pois.length,
|
||||
spaceCount: 0,
|
||||
guideStopCount: 0,
|
||||
navigablePlaceCount: 0,
|
||||
routeNodeCount: 0,
|
||||
routeEdgeCount: 0
|
||||
},
|
||||
warnings: ['static 模式仅提供本地导览资源基础检查']
|
||||
}
|
||||
}
|
||||
|
||||
async checkDataIntegrity() {
|
||||
const [floors, pois, diagnostics] = await Promise.all([
|
||||
this.getFloors(),
|
||||
this.listPois(),
|
||||
this.getMapDiagnostics()
|
||||
])
|
||||
|
||||
return createGuideDataIntegrityReport(diagnostics, floors, pois)
|
||||
}
|
||||
}
|
||||
|
||||
export const guideRepository = new StaticGuideRepository()
|
||||
export class SgsSdkGuideRepository implements GuideRepository {
|
||||
private floorsCache: MuseumFloor[] | null = null
|
||||
private poiCache: MuseumPoi[] | null = null
|
||||
private floorAliases: Map<string, string> | null = null
|
||||
|
||||
constructor(private readonly provider: SgsSdkApiProvider = defaultSgsSdkApiProvider) {}
|
||||
|
||||
getAssetBaseUrl() {
|
||||
return ''
|
||||
}
|
||||
|
||||
async getFloors() {
|
||||
if (this.floorsCache) return this.floorsCache
|
||||
|
||||
const manifest = await this.provider.getManifest()
|
||||
this.floorAliases = buildSgsFloorAliases(manifest.floors)
|
||||
this.floorsCache = [...manifest.floors]
|
||||
.sort((a, b) => Number(a.sortOrder || 0) - Number(b.sortOrder || 0))
|
||||
.map(toMuseumFloorFromSgs)
|
||||
|
||||
return this.floorsCache
|
||||
}
|
||||
|
||||
normalizeFloorId(labelOrId: string) {
|
||||
const normalized = labelOrId.trim()
|
||||
const aliases = this.floorAliases
|
||||
if (!aliases) return normalized
|
||||
|
||||
return aliases.get(normalized) || aliases.get(normalized.toLowerCase()) || normalized
|
||||
}
|
||||
|
||||
async listPois() {
|
||||
if (this.poiCache) return this.poiCache
|
||||
|
||||
const manifest = await this.provider.getManifest()
|
||||
this.floorAliases = buildSgsFloorAliases(manifest.floors)
|
||||
const poiGroups = await Promise.all(
|
||||
manifest.floors.map((floor) => this.provider.getFloorPois(String(floor.floorId)))
|
||||
)
|
||||
|
||||
this.poiCache = poiGroups
|
||||
.flat()
|
||||
.map((poi) => toMuseumPoiFromSgs(poi, manifest.floors))
|
||||
.filter((poi) => poi.id && poi.name)
|
||||
|
||||
return this.poiCache
|
||||
}
|
||||
|
||||
async getPoiById(id: string) {
|
||||
const pois = await this.listPois()
|
||||
return pois.find((poi) => poi.id === id) || null
|
||||
}
|
||||
|
||||
async searchPois(keyword = '') {
|
||||
const pois = await this.listPois()
|
||||
const normalizedKeyword = keyword.trim().toLowerCase()
|
||||
|
||||
if (!normalizedKeyword) return pois
|
||||
|
||||
return pois.filter((poi) => toSearchText(poi).includes(normalizedKeyword))
|
||||
}
|
||||
|
||||
async getLocationPreview(poiId: string) {
|
||||
const poi = await this.getPoiById(poiId)
|
||||
return poi ? toLocationPreviewFromPoi(poi) : null
|
||||
}
|
||||
|
||||
async getRouteReadiness() {
|
||||
return this.provider.getMapDiagnostics()
|
||||
.then(toRouteReadinessFromSgsDiagnostics)
|
||||
.catch(() => NAV_ROUTE_READINESS)
|
||||
}
|
||||
|
||||
async getFloorDetail(floorId: string) {
|
||||
await this.getFloors()
|
||||
const normalizedFloorId = this.normalizeFloorId(floorId)
|
||||
try {
|
||||
const diagnostics = await this.provider.getFloorDiagnostics(normalizedFloorId)
|
||||
return toGuideFloorDetailFromSgs(diagnostics)
|
||||
} catch {
|
||||
const manifest = await this.provider.getManifest()
|
||||
const floor = manifest.floors.find((item) => String(item.floorId) === normalizedFloorId)
|
||||
return floor ? toGuideFloorDetailFromSgs(floor) : null
|
||||
}
|
||||
}
|
||||
|
||||
async getMapDiagnostics() {
|
||||
const [manifest, diagnostics] = await Promise.all([
|
||||
this.provider.getManifest(),
|
||||
this.provider.getMapDiagnostics()
|
||||
])
|
||||
|
||||
return toGuideMapDiagnostics(diagnostics, manifest)
|
||||
}
|
||||
|
||||
async checkDataIntegrity() {
|
||||
const [floors, pois, diagnostics] = await Promise.all([
|
||||
this.getFloors(),
|
||||
this.listPois(),
|
||||
this.getMapDiagnostics()
|
||||
])
|
||||
|
||||
return createGuideDataIntegrityReport(diagnostics, floors, pois)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user