feat: switch explain flow to API data
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-06 23:18:51 +08:00
parent e2b6a331ba
commit 50902eca82
21 changed files with 1417 additions and 632 deletions

View File

@@ -2,14 +2,17 @@ import {
dataSourceConfig
} from '@/config/dataSource'
import {
normalizeSameOriginPublicUrl
} from '@/utils/publicUrl'
import type {
AudioPlayTargetType
type AudioPlayTargetType
} from '@/domain/museum'
import {
toGuideAudioPlayInfo,
toGuideAudioTextInfo,
toGuideStopInfo,
type BackendAudioPlayInfo,
type BackendAudioTextInfo,
type BackendGuideStopInfo,
type GuideAudioPlayInfo,
type GuideAudioTextInfo,
type GuideStopInfo
} from '@/data/adapters/guideStopInfoAdapter'
@@ -19,6 +22,7 @@ export interface AudioPlayInfoRequest {
targetType: AudioPlayTargetType
targetId: string
lang?: AudioLanguage
refresh?: boolean
}
export interface GuideStopInfoRequest {
@@ -33,29 +37,12 @@ interface GuideStopInfoResponse {
data?: BackendGuideStopInfo
}
export interface AudioPlayInfo {
playable: boolean
targetType: AudioPlayTargetType
targetId: string | number
lang: AudioLanguage
narrationTier?: 'STANDARD' | 'EXTENDED'
audioId?: string | number | null
title?: string | null
duration?: number | null
format?: string | null
playUrl?: string | null
expiresAt?: string | null
subtitleUrl?: string | null
hasText?: boolean
fallback?: boolean
fallbackReason?: string | null
reason?: string | null
}
export interface AudioPlayInfo extends GuideAudioPlayInfo {}
interface AudioPlayInfoResponse {
code: number
msg?: string
data?: AudioPlayInfo
data?: BackendAudioPlayInfo
}
export interface AudioTextInfoRequest {
@@ -64,23 +51,12 @@ export interface AudioTextInfoRequest {
lang?: AudioLanguage
}
export interface AudioTextInfo {
available: boolean
targetType: AudioPlayTargetType
targetId: string | number
lang: AudioLanguage
narrationTier?: 'STANDARD' | 'EXTENDED'
title?: string | null
text?: string | null
textLength?: number | null
textHash?: string | null
reason?: string | null
}
export interface AudioTextInfo extends GuideAudioTextInfo {}
interface AudioTextInfoResponse {
code: number
msg?: string
data?: AudioTextInfo
data?: BackendAudioTextInfo
}
export interface AudioPlayInfoRepository {
@@ -143,19 +119,23 @@ const normalizeBaseUrl = (baseUrl: string) => {
}
const resolveAudioApiBaseUrl = () => {
const baseUrl = normalizeBaseUrl(dataSourceConfig.audioApiBaseUrl)
const baseUrl = normalizeBaseUrl(dataSourceConfig.apiBaseUrl)
return baseUrl.endsWith('/app-api') ? baseUrl : `${baseUrl}/app-api`
}
const audioKey = ({ targetType, targetId, lang }: Required<AudioPlayInfoRequest>) => (
type RequiredAudioPlayInfoRequest = Required<Omit<AudioPlayInfoRequest, 'refresh'>>
type RequiredGuideStopInfoRequest = Required<GuideStopInfoRequest>
type RequiredAudioTextInfoRequest = Required<AudioTextInfoRequest>
const audioKey = ({ targetType, targetId, lang }: RequiredAudioPlayInfoRequest) => (
`${targetType}:${targetId}:${lang}`
)
const stopInfoKey = ({ targetType, targetId, lang }: Required<GuideStopInfoRequest>) => (
const stopInfoKey = ({ targetType, targetId, lang }: RequiredGuideStopInfoRequest) => (
`${targetType}:${targetId}:${lang}`
)
const audioTextKey = ({ targetType, targetId, lang }: Required<AudioTextInfoRequest>) => (
const audioTextKey = ({ targetType, targetId, lang }: RequiredAudioTextInfoRequest) => (
`${targetType}:${targetId}:${lang}`
)
@@ -190,7 +170,7 @@ export class DefaultAudioPlayInfoRepository implements AudioPlayInfoRepository {
throw new Error('讲解展示信息接口暂不可用')
}
const normalizedRequest: Required<GuideStopInfoRequest> = {
const normalizedRequest: RequiredGuideStopInfoRequest = {
targetType: request.targetType,
targetId: request.targetId,
lang: request.lang || (dataSourceConfig.audioLanguage as AudioLanguage)
@@ -221,7 +201,7 @@ export class DefaultAudioPlayInfoRepository implements AudioPlayInfoRepository {
}
async getPlayInfo(request: AudioPlayInfoRequest): Promise<AudioPlayInfo> {
const normalizedRequest: Required<AudioPlayInfoRequest> = {
const normalizedRequest: RequiredAudioPlayInfoRequest = {
targetType: request.targetType,
targetId: request.targetId,
lang: request.lang || (dataSourceConfig.audioLanguage as AudioLanguage)
@@ -233,13 +213,15 @@ export class DefaultAudioPlayInfoRepository implements AudioPlayInfoRepository {
targetType: normalizedRequest.targetType,
targetId: normalizedRequest.targetId,
lang: normalizedRequest.lang,
hasText: false,
fallback: false,
reason: 'SERVICE_ERROR'
}
}
const cached = this.cache.get(key)
if (cached && !isExpired(cached.expiresAt)) {
if (!request.refresh && cached && !isExpired(cached.expiresAt)) {
return cached
}
@@ -256,17 +238,16 @@ export class DefaultAudioPlayInfoRepository implements AudioPlayInfoRepository {
throw new Error(response.msg || '语音播放解析失败')
}
response.data.playUrl = normalizeSameOriginPublicUrl(response.data.playUrl)
response.data.subtitleUrl = normalizeSameOriginPublicUrl(response.data.subtitleUrl)
const playInfo = toGuideAudioPlayInfo(response.data, normalizedRequest)
if (response.data.playable || response.data.reason !== 'TARGET_NOT_FOUND') {
this.cache.set(key, response.data)
if (playInfo.playable || playInfo.reason !== 'TARGET_NOT_FOUND') {
this.cache.set(key, playInfo)
}
return response.data
return playInfo
}
async getTextInfo(request: AudioTextInfoRequest): Promise<AudioTextInfo> {
const normalizedRequest: Required<AudioTextInfoRequest> = {
const normalizedRequest: RequiredAudioTextInfoRequest = {
targetType: request.targetType,
targetId: request.targetId,
lang: request.lang || (dataSourceConfig.audioLanguage as AudioLanguage)
@@ -301,11 +282,13 @@ export class DefaultAudioPlayInfoRepository implements AudioPlayInfoRepository {
throw new Error(response.msg || '讲解词正文解析失败')
}
if (response.data.available) {
this.textCache.set(key, response.data)
const textInfo = toGuideAudioTextInfo(response.data, normalizedRequest)
if (textInfo.available) {
this.textCache.set(key, textInfo)
}
return response.data
return textInfo
}
clearCache(lang?: AudioLanguage) {