@@ -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[]> {
|
||||
|
||||
Reference in New Issue
Block a user