feat: wire guide data source and POI focus UI

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
lyf
2026-06-12 09:25:22 +08:00
parent a6bfda30e1
commit 2055b13b90
58 changed files with 5768 additions and 1898 deletions

View File

@@ -0,0 +1,90 @@
import type {
MuseumExhibit,
MuseumHall,
SearchIndexItem
} from '@/domain/museum'
export interface ExplainExhibitViewModel {
id: string
name: string
hall?: string
floor?: string
image?: string
hasAudio: boolean
audioUnavailableReason?: string
poiId?: string
}
export interface ExplainDetailViewModel {
id: string
name: string
artist?: string
year?: string
material?: string
size?: string
hall?: string
image: string
description: string
hasAudio: boolean
audioUnavailableReason?: string
poiId?: string
}
export interface HallDetailViewModel {
id: string
name: string
floorLabel: string
description: string
image: string
exhibitCount: number
area?: string
poiId?: string
}
export const toExplainExhibitViewModel = (exhibit: MuseumExhibit): ExplainExhibitViewModel => ({
id: exhibit.id,
name: exhibit.name,
hall: exhibit.hallName && exhibit.floorLabel
? `${exhibit.hallName} ${exhibit.floorLabel}`
: exhibit.hallName || exhibit.floorLabel,
floor: exhibit.floorLabel,
image: exhibit.image,
hasAudio: false,
audioUnavailableReason: '正式讲解音频尚未接入媒体仓储',
poiId: exhibit.poiId
})
export const toExplainDetailViewModel = (exhibit: MuseumExhibit): ExplainDetailViewModel => ({
id: exhibit.id,
name: exhibit.name,
artist: exhibit.artist,
year: exhibit.year,
material: exhibit.material,
size: exhibit.size,
hall: exhibit.hallName && exhibit.floorLabel
? `${exhibit.hallName} ${exhibit.floorLabel}`
: exhibit.hallName || exhibit.floorLabel,
image: exhibit.image || '/static/exhibit-placeholder.jpg',
description: exhibit.description || '该展项介绍待正式内容库补充。',
hasAudio: false,
audioUnavailableReason: '正式讲解音频尚未接入媒体仓储',
poiId: exhibit.poiId
})
export const toHallDetailViewModel = (hall: MuseumHall): HallDetailViewModel => ({
id: hall.id,
name: hall.name,
floorLabel: hall.floorLabel || '楼层待补充',
description: hall.description || '该展厅介绍待正式内容库补充。',
image: hall.image || '/static/hall-placeholder.jpg',
exhibitCount: hall.exhibitCount || 0,
area: hall.area,
poiId: hall.poiId
})
export const toExplainSearchResultViewModel = (item: SearchIndexItem) => ({
id: item.id,
name: item.name,
desc: item.desc,
type: item.type
})

View File

@@ -0,0 +1,70 @@
import type {
GuideLocationPreview,
GuideLocationPreviewPlan,
MuseumPoi
} from '@/domain/museum'
export interface FacilityResultViewModel {
id: string
name: string
floor: string
meta: string
accessible: boolean
action: '查看'
}
export interface FacilityDetailViewModel {
id: string
name: string
status: string
location: string
traffic: string
tags: string[]
}
export interface TargetPoiFocusRequestViewModel extends GuideLocationPreview {
requestId: number | string
}
export const toFacilityResultViewModel = (poi: MuseumPoi): FacilityResultViewModel => ({
id: poi.id,
name: poi.name,
floor: poi.floorLabel,
meta: `${poi.floorLabel}${poi.primaryCategory.label}${poi.navigationReadiness || '展示点位'}`,
accessible: poi.accessible,
action: '查看'
})
export const toFacilityDetailViewModel = (
poi: MuseumPoi,
routeUnavailableMessage: string
): FacilityDetailViewModel => ({
id: poi.id,
name: poi.name,
status: '可预览',
location: `${poi.floorLabel} · ${poi.primaryCategory.label}`,
traffic: routeUnavailableMessage,
tags: [
poi.floorLabel,
poi.primaryCategory.label,
poi.accessible ? '无障碍相关' : '展示点位'
]
})
export const toTargetFocusRequestViewModel = (
targetLocation: GuideLocationPreview,
requestId: number | string
): TargetPoiFocusRequestViewModel => ({
...targetLocation,
requestId
})
export const initialLocationPreviewPlan = (): GuideLocationPreviewPlan => ({
id: 'route-custom',
facilityId: '',
target: '目标地点',
summary: '位置预览 · 尚未接入正式路线图',
steps: [],
targetLocation: null,
startLocation: null
})