113 lines
3.9 KiB
TypeScript
113 lines
3.9 KiB
TypeScript
import type {
|
||
MuseumExhibit,
|
||
MuseumHall
|
||
} from '@/domain/museum'
|
||
import {
|
||
SGS_SCENE_EXPLAIN_DATASET,
|
||
type SgsSceneExhibitMock,
|
||
type SgsSceneSpaceMock
|
||
} from '@/data/mock/sgsSceneExplainData'
|
||
|
||
export interface MuseumContentProvider {
|
||
listExhibits(): Promise<MuseumExhibit[]>
|
||
listHalls(): Promise<MuseumHall[]>
|
||
}
|
||
|
||
const normalizeContentId = (prefix: string, value: string | number) => `${prefix}-sgs-${value}`
|
||
|
||
const categoryLabelMap: Record<SgsSceneSpaceMock['spaceCategory'], string> = {
|
||
EXHIBITION: '展陈空间',
|
||
EXPERIENCE: '体验空间',
|
||
SERVICE: '服务空间',
|
||
COMMERCIAL: '商业空间',
|
||
EDUCATION: '教育空间',
|
||
CIRCULATION: '公共交通空间',
|
||
BACK_OFFICE: '后勤空间'
|
||
}
|
||
|
||
const boundaryLabelMap: Record<NonNullable<SgsSceneSpaceMock['boundaryStatus']>, string> = {
|
||
DEFINED: '已定义空间边界',
|
||
UNDEFINED: '空间边界待完善'
|
||
}
|
||
|
||
const publicSceneSpaces = SGS_SCENE_EXPLAIN_DATASET.spaces.filter((space) => space.isPublic)
|
||
const publicSpaceById = new Map(publicSceneSpaces.map((space) => [space.id, space]))
|
||
|
||
const formatArea = (area?: number) => (typeof area === 'number' ? `${area}㎡` : undefined)
|
||
|
||
const hallDescription = (space: SgsSceneSpaceMock) => {
|
||
const category = categoryLabelMap[space.spaceCategory]
|
||
const area = formatArea(space.area)
|
||
const boundary = space.boundaryStatus ? boundaryLabelMap[space.boundaryStatus] : undefined
|
||
const facts = [space.floorLabel, category, area, boundary].filter(Boolean).join(' · ')
|
||
|
||
return `${space.name}来自 SGS 前端地图项目“场景设置”的空间管理数据。${facts ? `当前空间信息:${facts}。` : ''}讲解业务据此展示展厅/展区内容,并通过稳定空间、展品与 POI ID 关联到位置预览。`
|
||
}
|
||
|
||
const exhibitDescription = (exhibit: SgsSceneExhibitMock, hall: SgsSceneSpaceMock | undefined) => {
|
||
const facts = [
|
||
exhibit.category,
|
||
exhibit.era,
|
||
exhibit.origin,
|
||
exhibit.zoneName
|
||
].filter(Boolean).join(' · ')
|
||
|
||
return [
|
||
exhibit.description,
|
||
facts ? `展陈信息:${facts}。` : '',
|
||
hall ? `所属空间:${hall.name}(${hall.floorLabel})。` : ''
|
||
].filter(Boolean).join('\n\n')
|
||
}
|
||
|
||
const tagsForExhibit = (exhibit: SgsSceneExhibitMock, hall: SgsSceneSpaceMock | undefined) => [
|
||
'SGS场景设置',
|
||
exhibit.category,
|
||
exhibit.zoneName,
|
||
exhibit.audioUrl ? '源数据含音频地址' : '图文讲解',
|
||
hall ? categoryLabelMap[hall.spaceCategory] : undefined
|
||
].filter(Boolean) as string[]
|
||
|
||
const toMuseumHall = (space: SgsSceneSpaceMock): MuseumHall => ({
|
||
id: normalizeContentId('hall', space.id),
|
||
name: space.name,
|
||
floorId: space.floorId,
|
||
floorLabel: space.floorLabel,
|
||
description: hallDescription(space),
|
||
image: '',
|
||
exhibitCount: SGS_SCENE_EXPLAIN_DATASET.exhibits.filter((exhibit) => exhibit.spaceId === space.id).length || space.exhibitCount || 0,
|
||
area: formatArea(space.area),
|
||
poiId: space.poiId
|
||
})
|
||
|
||
const toMuseumExhibit = (exhibit: SgsSceneExhibitMock): MuseumExhibit => {
|
||
const hall = publicSpaceById.get(exhibit.spaceId)
|
||
|
||
return {
|
||
id: normalizeContentId('exhibit', exhibit.id),
|
||
name: exhibit.name,
|
||
hallId: hall ? normalizeContentId('hall', hall.id) : undefined,
|
||
hallName: hall?.name || exhibit.spaceName,
|
||
floorId: hall?.floorId || SGS_SCENE_EXPLAIN_DATASET.floorId,
|
||
floorLabel: hall?.floorLabel || SGS_SCENE_EXPLAIN_DATASET.floorLabel,
|
||
image: '',
|
||
description: exhibitDescription(exhibit, hall),
|
||
poiId: exhibit.poiId || hall?.poiId,
|
||
year: exhibit.era,
|
||
material: exhibit.origin,
|
||
size: exhibit.code,
|
||
tags: tagsForExhibit(exhibit, hall)
|
||
}
|
||
}
|
||
|
||
export class StaticMuseumContentProvider implements MuseumContentProvider {
|
||
async listExhibits() {
|
||
return SGS_SCENE_EXPLAIN_DATASET.exhibits.map(toMuseumExhibit)
|
||
}
|
||
|
||
async listHalls() {
|
||
return publicSceneSpaces.map(toMuseumHall)
|
||
}
|
||
}
|
||
|
||
export const staticMuseumContentProvider = new StaticMuseumContentProvider()
|