修复导览点位可见性与构建门禁

This commit is contained in:
cxk
2026-07-20 23:54:19 +08:00
parent 735c5cd1ee
commit 1f89e8b3e0
14 changed files with 499 additions and 168 deletions

View File

@@ -183,6 +183,7 @@ export type PoiCategorySource = Pick<
| 'sourcePlaceId'
| 'sourceSpaceId'
| 'sourceObjectName'
| 'visitorVisible'
>
const normalizeValue = (value?: string | null) => (value || '')
@@ -192,6 +193,13 @@ const normalizeValue = (value?: string | null) => (value || '')
.replace(/[\s-]+/g, '_')
.replace(/^_+|_+$/g, '')
const visitorRestrictedPlaceNamePattern = /(?:贵宾|vip|员工|职工|后勤|办公|行政|库房|仓库|机房|设备间|配电|弱电|强电|保洁|值班|消防控制|监控室|staff|employee|back[_ -]?of[_ -]?house|maintenance)/i
/** Legacy sources without an explicit flag must not expose staff-only places. */
export const isVisitorRestrictedPlaceName = (value?: string | null) => (
visitorRestrictedPlaceNamePattern.test(normalizeValue(value))
)
const poiSemanticAliases: Readonly<Record<string, string>> = {
exhibition: 'exhibition_hall',
exhibition_hall: 'exhibition_hall',
@@ -397,7 +405,7 @@ export const resolvePoiCategory = (poi: PoiCategorySource) => (
POI_CATEGORIES.find((category) => matchesPoiCategory(poi, category)) || null
)
const hiddenVisitorPrimaryTypes = new Set([
const hiddenVisitorTypes = new Set([
'entrance_exit',
'hall_entrance',
'entrance_anchor',
@@ -406,7 +414,7 @@ const hiddenVisitorPrimaryTypes = new Set([
'operation_experience'
])
const primaryTypeValues = (poi: PoiCategorySource) => [
const visitorTypeValues = (poi: PoiCategorySource) => [
poi.primaryCategory.id,
poi.primaryCategory.label,
poi.primaryCategory.iconType || ''
@@ -414,10 +422,18 @@ const primaryTypeValues = (poi: PoiCategorySource) => [
.map(normalizePoiSemanticValue)
.filter(Boolean)
const isHiddenVisitorType = (value: string) => {
const normalizedValue = normalizePoiSemanticValue(value)
const sourceWrappedValue = normalizedValue.replace(/^(?:space|poi|facility|business)_/, '')
return hiddenVisitorTypes.has(normalizedValue)
|| hiddenVisitorTypes.has(sourceWrappedValue)
}
/** A visitor result must never be a guide point, door, entrance anchor, or route node. */
export const isVisitorSearchPoi = (poi: PoiCategorySource) => {
if (poi.visitorVisible === false) return false
if (poi.kind === 'guide' || poi.kind === 'hall_entrance') return false
return !primaryTypeValues(poi).some((value) => hiddenVisitorPrimaryTypes.has(value))
return !visitorTypeValues(poi).some(isHiddenVisitorType)
}
/** Default floor browse only contains canonical halls and valid destination spaces. */
@@ -516,8 +532,6 @@ export const getPoiDataIssues = (poi: MuseumPoi): PoiDataIssue[] => {
} else if (!hasFinitePosition(poi.positionGltf)) {
issues.push({ code: 'invalid-position', ...issueBase })
}
if (!isPoiSearchCategorySupported(poi)) issues.push({ code: 'unsupported-category', ...issueBase })
return issues
}
@@ -548,6 +562,6 @@ export const warnPoiCollectionIssues = (source: string, pois: MuseumPoi[]) => {
const inspection = inspectPoiCollection(pois)
if (!inspection.issues.length && !inspection.duplicateIds.length) return
// 开发期集中输出数据契约问题,避免在页面组件中散落源数据校验。
console.warn(`[POI 数据校验] ${source}`, inspection)
// This is an aggregate development diagnostic, not a visitor-facing failure.
console.debug(`[POI 数据诊断] ${source}`, inspection)
}