优化讲解数据请求与缓存管理
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-16 14:43:57 +08:00
parent 72885b7f54
commit d86845afeb
11 changed files with 259 additions and 137 deletions

View File

@@ -45,6 +45,12 @@ export interface ExplainDetailEntryRequest {
targetType?: AudioPlayTargetType
targetId?: string
lang?: AudioLanguage
// Navigation context is non-authoritative and keeps deep links independent of catalog loading.
hallId?: string
hallName?: string
floorId?: string
floorLabel?: string
poiId?: string
}
export interface ExplainTextSelection {
@@ -198,11 +204,13 @@ export class ExplainUseCase {
private toExhibitFromStopInfo(
stopInfo: GuideStopInfo,
fallback?: MuseumExhibit | null
fallback?: MuseumExhibit | null,
navigationContext?: ExplainDetailEntryRequest
): MuseumExhibit {
const linkedPrimary = stopInfo.linkedExhibits[0]
const linkedCoverImage = stopInfo.linkedExhibits.find((item) => item.coverImageUrl)?.coverImageUrl
const coverImage = stopInfo.coverImageUrl || linkedCoverImage || fallback?.image
const coverImage = stopInfo.imageStatus === 'READY'
? stopInfo.coverImageUrl
: undefined
const description = stopInfo.description || fallback?.description || '该讲解暂无简介。'
const audioTarget = this.resolveStopInfoAudioTarget(stopInfo)
const audioAvailable = stopInfo.audioStatus === 'READY'
@@ -211,13 +219,13 @@ export class ExplainUseCase {
...(fallback || {}),
id: fallback?.id || linkedPrimary?.id || stopInfo.targetId,
name: stopInfo.title || fallback?.name || linkedPrimary?.name || '讲解内容',
hallId: fallback?.hallId,
hallName: fallback?.hallName,
floorId: stopInfo.floorId || fallback?.floorId,
floorLabel: fallback?.floorLabel,
hallId: fallback?.hallId || navigationContext?.hallId,
hallName: fallback?.hallName || navigationContext?.hallName,
floorId: stopInfo.floorId || fallback?.floorId || navigationContext?.floorId,
floorLabel: fallback?.floorLabel || navigationContext?.floorLabel,
image: coverImage,
description,
poiId: stopInfo.poiId || fallback?.poiId,
poiId: stopInfo.poiId || fallback?.poiId || navigationContext?.poiId,
sourcePoiId: stopInfo.poiId || fallback?.sourcePoiId,
mapX: stopInfo.mapX ?? fallback?.mapX,
mapY: stopInfo.mapY ?? fallback?.mapY,
@@ -244,7 +252,7 @@ export class ExplainUseCase {
supportedLanguages: stopInfo.supportedLanguages,
imageStatus: stopInfo.imageStatus,
imageSource: stopInfo.imageSource,
galleryUrls: stopInfo.galleryUrls,
galleryUrls: stopInfo.imageStatus === 'READY' ? stopInfo.galleryUrls : [],
linkedExhibitCount: stopInfo.linkedExhibitCount,
isSharedStop: stopInfo.isSharedStop,
linkedExhibits: stopInfo.linkedExhibits,
@@ -403,9 +411,15 @@ export class ExplainUseCase {
async enterExplainDetail(request: ExplainDetailEntryRequest) {
const entryTarget = await this.resolveDetailEntryTarget(request)
// Remote stop-info is the authoritative detail source. Never make its first paint wait for catalog.
if (dataSourceConfig.explainContentMode === 'remote') {
const stopInfo = await this.audioPlayInfo.getStopInfo(entryTarget)
return this.toExhibitFromStopInfo(stopInfo, null, request)
}
const fallbackExhibit = await this.resolveStaticDetailFallback(request, entryTarget)
if (fallbackExhibit && dataSourceConfig.explainContentMode !== 'remote') {
if (fallbackExhibit) {
return this.applyLanguageVariant(fallbackExhibit, entryTarget.lang)
}
@@ -414,7 +428,7 @@ export class ExplainUseCase {
.catch((error) => ({ stopInfo: null, error }))
if (stopInfoResult.stopInfo) {
return this.toExhibitFromStopInfo(stopInfoResult.stopInfo, fallbackExhibit)
return this.toExhibitFromStopInfo(stopInfoResult.stopInfo, fallbackExhibit, request)
}
throw stopInfoResult.error || new Error('讲解详情加载失败')
@@ -522,8 +536,7 @@ export class ExplainUseCase {
}
async listGuideStopsByBusinessUnit(hallId: string, unitId: string): Promise<ExplainGuideStop[]> {
const unit = await this.selectBusinessUnit(hallId, unitId)
return unit?.stops || []
return this.explain.listGuideStopsByBusinessUnit(hallId, unitId)
}
openGuideStopDetail(stopId: string) {
@@ -536,8 +549,7 @@ export class ExplainUseCase {
}
async listExhibitsByHallId(hallId: string) {
const exhibits = await this.listExhibits()
return exhibits.filter((exhibit) => exhibit.hallId === hallId)
return this.explain.listExplainExhibitsByHall(hallId)
}
searchExplain(keyword?: string): Promise<SearchIndexItem[]> {