修复搜索与点位定位闭环
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
lyf
2026-07-12 03:07:49 +08:00
parent e006333c0a
commit d8420fc7c2
18 changed files with 2961 additions and 621 deletions

View File

@@ -3,6 +3,9 @@ import type {
GuideLocationPreviewPlan,
MuseumPoi
} from '@/domain/museum'
import {
resolvePoiCategory
} from '@/domain/poiCategories'
export interface FacilityResultViewModel {
id: string
@@ -16,10 +19,22 @@ export interface FacilityResultViewModel {
export interface FacilityDetailViewModel {
id: string
name: string
status: string
location: string
traffic: string
tags: string[]
category: string
floor: string
description: string
}
export interface FacilityDetailSearchContext {
source: 'search' | 'direct'
searchOrigin: 'home' | 'page' | ''
searchKeyword: string
searchCategoryId: string
searchFloorId: string
searchFloorLabel: string
resultCount: number
floorResultCount: number
visiblePoiIds: string[]
listScrollTop: number
}
export interface TargetPoiFocusRequestViewModel extends GuideLocationPreview {
@@ -42,21 +57,53 @@ export const toFacilityResultViewModel = (poi: MuseumPoi): FacilityResultViewMod
})
export const toFacilityDetailViewModel = (
poi: MuseumPoi,
routeUnavailableMessage: string
poi: MuseumPoi
): FacilityDetailViewModel => ({
id: poi.id,
name: poi.name,
status: '可预览',
location: `${poi.floorLabel} · ${poi.primaryCategory.label}`,
traffic: routeUnavailableMessage,
tags: [
poi.floorLabel,
poi.primaryCategory.label,
poi.accessible ? '无障碍相关' : '展示点位'
]
category: resolvePoiCategory(poi)?.label || poi.primaryCategory.label || '未分类',
floor: poi.floorLabel || '楼层信息缺失',
description: ''
})
const decodeQueryText = (value: unknown) => {
if (typeof value !== 'string') return ''
try {
return decodeURIComponent(value)
} catch {
return value
}
}
const parseNonNegativeInteger = (value: unknown) => {
const parsed = Number.parseInt(decodeQueryText(value), 10)
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0
}
export const parseFacilityDetailSearchContext = (
options: Record<string, unknown> = {}
): FacilityDetailSearchContext => {
const searchOrigin = decodeQueryText(options.searchOrigin)
const visiblePoiIds = decodeQueryText(options.visiblePoiIds)
.split(',')
.map((id) => id.trim())
.filter(Boolean)
return {
source: decodeQueryText(options.source) === 'search' ? 'search' : 'direct',
searchOrigin: searchOrigin === 'home' || searchOrigin === 'page' ? searchOrigin : '',
searchKeyword: decodeQueryText(options.searchKeyword),
searchCategoryId: decodeQueryText(options.searchCategoryId),
searchFloorId: decodeQueryText(options.searchFloorId),
searchFloorLabel: decodeQueryText(options.searchFloorLabel),
resultCount: parseNonNegativeInteger(options.resultCount),
floorResultCount: parseNonNegativeInteger(options.floorResultCount),
visiblePoiIds: Array.from(new Set(visiblePoiIds)),
listScrollTop: parseNonNegativeInteger(options.listScrollTop)
}
}
export const toTargetFocusRequestViewModel = (
targetLocation: GuideLocationPreview,
requestId: number | string