Files
frontend-miniapp/docs/Data/data-audit-2026-05-28.md
lyf 8fed715235
Some checks failed
CI / verify (push) Has been cancelled
chore: sync latest project updates
2026-07-03 14:42:38 +08:00

42 KiB
Raw Permalink Blame History

frontend-miniapp 数据层全面审计报告

审计日期2026-05-28
审计分支:analysis/ux-ui-audit-2026-05-28
审计对象:museum-guide-v4.0/frontend-miniapp
审计范围Mock 数据、类型定义、数据加载、搜索/地图/详情页硬编码数据、静态资源、3D/馆内 POI 数据、数据治理与性能策略。

执行摘要

当前 frontend-miniapp 的数据层处于“多套 Mock 数据并存”的原型状态,不能直接作为深圳自然博物馆导览的数据基础。最高风险集中在三类:业务定位数据错配、数据源不统一、资源与关联关系不可验证。

优先级 关键风险 影响 建议
P0 核心 JSON 仍是“深圳国际艺术馆/世界名画”内容,而产品标识是“深圳自然博物馆” 搜索、详情、路线、讲解内容与真实馆方定位冲突 立即建立自然博物馆数据字典和迁移清单,冻结旧艺术馆 Mock 数据新增
P0 列表、详情、地图、搜索各自硬编码不同实体与 ID 用户从搜索/地图进入详情会看到不一致内容,甚至找不到对应数据 建立单一数据源,所有页面按 entityId 查询同一仓库
P0 15 个图片/音频 URL 指向不存在资源,另有 https://example.com/audio.mp3 占位 展品图、展厅图、语音讲解失败,影响核心导览体验 建立资源清单校验,缺失资源上线前阻断
P1 类型定义与真实 POI/地图数据不匹配 TypeScript 无法保护 3D 坐标、入口/展厅/设施枚举,后续扩展易破 扩展 PositionPOIFacilityType、多语言与状态字段
P1 无数据版本、校验、缓存、错误分级 数据异常会静默返回空数组,难以监控和降级 引入 schema 校验、数据版本元信息和错误态 UI

建议采用两步治理:先用 1 周完成“数据源收敛和阻断性校验”,再用 2 到 4 周完成自然博物馆正式数据迁移、地图 POI 绑定、资源治理与多语言模型。

审计方法

本次审计使用静态扫描和结构化脚本校验,未修改业务代码。

方法 覆盖内容 证据来源
JSON 结构扫描 展品、展厅、设施、路线、楼层、馆内 POI 数量与字段 src/assets/data/*.jsonstatic/data/f1-indoor-pois.json
引用完整性校验 展品到展厅、楼层到展厅/设施、路线到站点 Node 脚本读取 JSON 后交叉比对
静态资源存在性校验 图片、音频、展厅图是否存在于 static/ 文件系统校验
硬编码扫描 页面、组件、地图、搜索中的本地数组和占位 URL rg 搜索
类型与数据流审查 TypeScript 接口、数据加载、搜索工具、服务层 src/types/index.tssrc/utils/dataLoader.tssrc/utils/search.tssrc/services/map/Map3DManager.ts

数据资产盘点

数据源 数量 现状判断 主要问题
src/assets/data/exhibits.json 5 艺术馆展品 Mock 全部是世界名画,不是自然博物馆展品;图片/音频缺失
src/assets/data/halls.json 5 艺术馆展厅 Mock 展厅主题为文艺复兴、印象派、现代艺术;展品数量与实际 JSON 不一致
src/assets/data/facilities.json 8 基础设施/模型坐标混合数据 点位坐标来自 f1-floor.glb 提取,应保留;但实体名称、类型、描述仍与真实 1F POI 和自然博物馆语义不一致
src/assets/data/routes.json 3 艺术馆路线 Mock 路线名称、站点均围绕艺术作品;不适配自然博物馆参观动线
src/assets/data/floors.json 4 楼层索引 B1 引用不存在设施,且无展厅
static/data/f1-indoor-pois.json 67 真实 1F 馆内点位基准 其它设施、展厅、搜索、地图详情数据未以它为准,存在大面积冲突
static/models/*.glb 2 真实 1F 3D 模型资产 f1-indoor.glbf1-floor.glb 均为自然博物馆 1F 真实模型;需补模型清单、坐标系与部署目录策略
static/icons/*.svg 8 地图图标 可用,但 POI 类型枚举与图标映射未统一

当前数据流可以概括为:

flowchart TD
  A["assets/data/*.json<br/>艺术馆核心 Mock"] --> B["dataLoader.ts"]
  B --> C["部分列表/工具函数"]
  D["pages/detail.vue<br/>硬编码详情"] --> E["详情页展示"]
  F["SearchPanel / ExplainList<br/>自然博物馆硬编码 Mock"] --> G["搜索/讲解抽屉"]
  H["TencentMap / ThreeMap<br/>硬编码地图点"] --> I["地图弹层"]
  J["static/data/f1-indoor-pois.json<br/>67 个馆内 POI"] -.未统一接入.-> I

1. 数据完整性审计

1.1 Mock 数据覆盖度

实体 当前覆盖 与真实自然博物馆导览的差距 严重性
展品 5 个艺术作品 缺少标本、化石、矿物、动植物、年代、分类、馆藏编号、展陈状态、讲解文本层级 P0
展厅 5 个艺术主题展厅 缺少自然史展厅分区、楼层分布、入口/出口、展厅开放状态、人流/容量 P0
设施 8 个基础设施 馆内 POI 有 58 个设施,但未与设施表合并;缺少服务台、母婴室、寄存、无障碍、楼梯等正式类型 P1
路线 3 条艺术馆路线 缺少亲子、研学、无障碍、快速参观、自然史主题路线 P0
楼层 4 层索引 只有简单数组引用,无真实地图区域、楼层坐标系、模型版本、开放状态 P1
POI F1 有 67 个模型点 只覆盖 1F,未绑定展品/展厅/路线/设施详情 P1

1.2 必填字段缺失与占位符

结构字段层面,展品、展厅、设施、路线大多包含基础字段,但业务必填字段明显不足:没有馆藏编号、自然史分类、状态、更新时间、版权、资源元信息、语种、坐标系。

静态校验结果:

COUNTS
exhibits: 5
halls: 5
facilities: 8
routes: 3
floors: 4
pois: 67

MISSING REQUIRED
exhibits: none
halls: none
facilities: none
routes: none
floors: floor_b1:halls

虽然基础字段未大量为空,但资源字段失效非常严重:

exhibit_1.image -> /static/exhibits/mona-lisa.jpg missing
exhibit_1.audioUrl -> /static/audio/exhibit-1.mp3 missing
exhibit_2.image -> /static/exhibits/last-supper.jpg missing
exhibit_2.audioUrl -> /static/audio/exhibit-2.mp3 missing
exhibit_3.image -> /static/exhibits/starry-night.jpg missing
exhibit_3.audioUrl -> /static/audio/exhibit-3.mp3 missing
exhibit_4.image -> /static/exhibits/sunflowers.jpg missing
exhibit_4.audioUrl -> /static/audio/exhibit-4.mp3 missing
exhibit_5.image -> /static/exhibits/david.jpg missing
exhibit_5.audioUrl -> /static/audio/exhibit-5.mp3 missing
hall_1.image -> /static/halls/hall-1.jpg missing
hall_2.image -> /static/halls/hall-2.jpg missing
hall_3.image -> /static/halls/hall-3.jpg missing
hall_4.image -> /static/halls/hall-4.jpg missing
hall_5.image -> /static/halls/hall-5.jpg missing

页面中还存在音频占位 URL

frontend-miniapp/src/pages/index/index.vue:306
audioUrl: exhibit.audioUrl || 'https://example.com/audio.mp3'

frontend-miniapp/src/pages/index/index.vue:355
audioUrl: exhibit.audioUrl || 'https://example.com/audio.mp3'

1.3 数据一致性

展厅统计与实际展品数量完全不一致:

展厅 halls.json 标称展品数 exhibits.json 实际归属数 差异
hall_1 25 3 -22
hall_2 18 2 -16
hall_3 30 0 -30
hall_4 22 0 -22
hall_5 15 0 -15

同一逻辑实体在不同模块中出现了多套 ID 和名称:

模块 示例 问题
核心 JSON exhibit_1蒙娜丽莎 艺术馆实体
搜索页 id: '1', name: '蒙娜丽莎' ID 不是 exhibit_1,进入详情时无法保证匹配
搜索面板 id: '1', name: '霸王龙化石骨架' 同一 ID 1 在另一模块代表自然博物馆展品
讲解抽屉 id: '1', name: '银杏化石' 同一 ID 1 又代表第三个实体
地图首页 exhibit-1恐龙化石展区 ID 命名与核心 JSON 不一致
3D 地图 exhibit-1恐龙化石展区 exhibit_1 不一致,且未绑定详情数据

硬编码证据截图:

frontend-miniapp/src/pages/search/index.vue:101
{ id: '1', name: '蒙娜丽莎', artist: '达芬奇', hall: '1号展厅', hasAudio: true }

frontend-miniapp/src/components/search/SearchPanel.vue:143
{ id: '1', name: '霸王龙化石骨架', desc: '恐龙厅 · 2F', type: 'exhibit' }

frontend-miniapp/src/components/explain/ExplainList.vue:293
{ id: '1', name: '银杏化石', hall: '演化厅 B1', hasAudio: true, audioUrl: '' }

frontend-miniapp/src/pages/index/index.vue:164
'exhibit-1': { id: 'exhibit-1', name: '恐龙化石展区', subtitle: '中生代恐龙化石展示', type: 'exhibit', floor: '2F' }

1.4 关联关系完整性

路线站点都能在艺术馆展品表中找到,但楼层到设施存在断链:

BROKEN REFERENCES
floor floor_b1 facility parking_b1
floor floor_b1 facility storage_b1

更大的关联问题是 static/data/f1-indoor-pois.json 与核心实体完全脱钩。该文件已确认为真实 1F 设施点位基准,包含 67 个 POI类型分布为

POI TYPES
{ hall: 6, facility: 58, entrance: 3 }
POI floors: 1F

这些 POI 的 id 形如 poi_0,没有 entityId 指向 hall_1facility_* 或路线站点,无法支撑“点击地图点打开统一详情”“按路线高亮真实点位”等核心导览能力。

1.5 数据时效性

当前数据没有以下字段,无法判断是否过期:

缺失能力 影响
status / visibility 无法区分开放、临时关闭、下架、维护中
validFrom / validTo 无法表达临展、活动、设施维修周期
updatedAt / sourceVersion 无法追踪数据来源和更新批次
reviewedBy / reviewedAt 无法形成馆方内容审核闭环

因此“已下架展品、已关闭设施”目前无法自动识别,只能依赖人工回归。

2. 数据结构与类型规范性

2.1 TypeScript 类型定义

src/types/index.ts 更像早期 Mock 类型,无法覆盖现有地图和真实业务数据。

类型 当前定义 发现的问题 严重性
Position { x, y } 2D 坐标,不支持馆内 POI 的 { x, y, z },也不支持腾讯地图的 { latitude, longitude } P1
Facility.type restroom/cafe/shop/exit/elevator/info 不包含 entrancehallstairsmother_babyaccessible_restroomservice_desk 等真实 POI 类型 P1
POIMarker.type exhibit/hall/facility/location 不包含 entrance,与 ThreeMapf1-indoor-pois.json 不一致 P1
Exhibit 艺术品字段 artist/year/material/size 自然博物馆需要 taxonomyperiodspecimenTypecollectionNoscientificNameageRange 等字段 P0
全部实体 无多语言、无状态、无版本 无法支撑中英文切换、数据审核、增量更新和下线 P1

建议新增分层模型:

type LocaleText = { zhCN: string; enUS?: string }

type Coordinate =
  | { system: 'indoor_3d'; floorId: string; x: number; y: number; z: number }
  | { system: 'indoor_2d'; floorId: string; x: number; y: number }
  | { system: 'wgs84' | 'gcj02'; latitude: number; longitude: number }

type EntityStatus = 'draft' | 'published' | 'hidden' | 'closed' | 'maintenance'

2.2 API 响应格式

src/services/ 下只有 map/Map3DManager.ts,没有业务 API service。数据加载集中在 src/utils/dataLoader.ts,但返回值未声明类型,错误时统一返回空数组:

export const loadExhibits = async () => {
  try {
    const data = await import('@/assets/data/exhibits.json')
    return data.default || data
  } catch (error) {
    console.error('加载展品数据失败:', error)
    return []
  }
}

风险:

问题 影响
Promise<Exhibit[]> 等返回类型 调用方无法获得类型保护
使用 any 查找 ID 类型、字段缺失、空数据不会被编译期发现
异常统一变成 [] 加载失败、数据为空、校验失败三种状态无法区分
无响应 envelope 后续接 API 时缺少 versionupdatedAtsourceerrorspagination 规范

建议定义统一响应:

interface DataResult<T> {
  ok: boolean
  data: T
  version: string
  updatedAt: string
  source: 'mock' | 'cms' | 'cache'
  errors?: DataError[]
}

2.3 枚举值规范

枚举值目前分散在类型、地图、组件、数据文件中:

位置 枚举/类别 问题
types/index.ts Facility.type 只覆盖 6 种旧设施
components/area/AreaSelector.vue storageaccessible UI 类别未进入类型系统
static/data/f1-indoor-pois.json hall/facility/entrance POIMarker.type 不一致
ThreeMap.vue entrance/exhibit/facility/hall 局部定义,与全局类型重复
TencentMap.vue marker 图标路径 通过硬编码绑定,不受枚举约束

建议将枚举集中到 src/types/enums.tssrc/domain/guideSchema.ts,并由数据校验脚本复用。

2.4 数据转换逻辑

当前没有明确的 adapter/transformer。结果是 2D JSON、3D POI、腾讯地图经纬度、页面详情对象各自拥有不同字段形态。

建议新增三层转换:

层级 职责
Raw Schema 接收 CMS/JSON 原始字段,严格校验
Domain Model 统一实体、坐标、资源、状态、多语言
View Model 为卡片、地图弹层、路线列表、搜索结果生成轻量字段

3. 业务数据合理性

3.1 内容与项目定位不符

项目描述与页面标题已经使用“深圳自然博物馆”,但核心数据仍是艺术馆:

位置 当前内容 业务判断
manifest.json 深圳自然博物馆智能导览应用 项目定位明确为自然博物馆
exhibits.json 蒙娜丽莎最后的晚餐星空向日葵大卫像 与自然博物馆定位冲突
halls.json 文艺复兴、印象派、现代艺术 与自然史展陈冲突
routes.json 经典艺术之旅、印象派精选 与自然博物馆导览路线冲突
SearchPanel.vue / ExplainList.vue 恐龙、化石、银杏、矿石 内容方向正确,但与核心 JSON 脱节

这是 P0 风险,因为它会直接导致“产品名是自然博物馆,但内容是艺术馆”的体验断裂。

3.2 数量级合理性

真实自然博物馆导览通常需要覆盖更多实体:

数据类型 当前数量 建议 MVP 数量 建议正式版数量
展品/标本 5 30 到 60 200+
展厅/展区 5 8 到 12 按真实楼层和展陈分区完整覆盖
设施 8 30 到 60 与馆内 POI 全量绑定
路线 3 5 到 8 支持人群、时长、无障碍、拥堵策略
馆内 POI 67仅 1F 每层 50+ 全楼层、全关键节点

当前数量只适合演示 UI无法支撑真实导览。

3.3 地理坐标准确性

坐标系统存在三套并行:

坐标来源 字段 问题
核心 JSON position: { x, y } 未声明坐标系、楼层、比例尺和原点
3D POI { x, y, z } 未进入 types/index.ts,未绑定实体
腾讯地图 { latitude, longitude } 硬编码在组件内,未与馆内 POI 建立转换关系

TencentMap.vue 里的建筑轮廓和 ThreeMap.vue 的中心点均硬编码为深圳自然博物馆附近坐标,但无法验证这些点与 GLB 模型、馆内 POI、楼层图是否同源。

3.4 多语言数据

当前核心实体没有英文名、英文说明、拼音、别名、检索关键词,也没有语言切换后的字段 fallback。

建议每个可展示字段采用 LocaleText,搜索索引包括:

字段 用途
name.zhCN / name.enUS 中英文展示
aliases.zhCN[] / aliases.enUS[] 同义词、简称、俗名
scientificName 自然史学名
keywords[] 搜索、推荐、路线匹配
audio.zhCN / audio.enUS 多语言讲解

4. 数据管理与维护性

4.1 数据源管理

当前数据分散在至少 11 类位置:

数据位置 数据类型 风险
src/assets/data/*.json 核心 Mock 内容过旧,艺术馆化
static/data/f1-indoor-pois.json 3D 模型 POI 未接入业务实体
pages/search/index.vue 搜索页本地数组 与核心 JSON ID 不一致
components/search/SearchPanel.vue 搜索弹层本地数组 自然博物馆 Mock与核心 JSON 不一致
components/explain/ExplainList.vue 讲解列表本地数组 音频字段为空ID 冲突
pages/index/index.vue 地图详情 markerDataMap 自然博物馆硬编码,与 POI/JSON 不一致
components/map/ThreeMap.vue defaultPOIs 默认值会被空数组 props 覆盖,且 ID 不统一
components/map/TencentMap.vue 经纬度 markers 地图数据不可配置
pages/exhibit/detail.vue 展品详情默认对象 不按 ID 加载真实数据
pages/hall/detail.vue 展厅详情默认对象 不按 ID 加载真实数据
pages/facility/detail.vue 设施详情默认对象 不按 ID 加载真实数据

建议将所有页面改为读取同一份 domain store

flowchart LR
  A["CMS / Mock JSON"] --> B["schema validation"]
  B --> C["domain repository"]
  C --> D["search index"]
  C --> E["map POI view model"]
  C --> F["detail pages"]
  C --> G["route engine"]
  C --> H["offline cache"]

4.2 数据更新机制

当前没有发现以下机制:

机制 当前状态 建议
数据版本控制 version 文件 新增 data-manifest.json
增量更新 按实体类型和 updatedAt 增量拉取
本地缓存 未见 uni.setStorage/uni.getStorage 数据缓存 小程序端缓存核心 JSON 和搜索索引
灰度发布 支持 draft/published 与版本回滚
数据来源追踪 每条记录保留 sourceIdsourceUpdatedAt

4.3 数据校验

建议建立 scripts/audit-data.ts,在 CI 或提交前执行:

校验类型 规则
Schema 校验 必填字段、枚举、坐标类型、资源字段
引用校验 展品到展厅、路线到站点、POI 到实体、楼层到设施
资源校验 图片/音频/模型路径存在,远程 URL 可访问或有降级
业务校验 开放时间格式、路线时长总和、展厅展品数可计算
多语言校验 中文必填,英文按上线策略设阈值
审核状态校验 published 数据不得进入正式包

4.4 错误处理

当前 dataLoader.ts 在异常时返回空数组,页面无法知道错误原因。建议改为:

异常类型 降级方式
JSON 加载失败 展示“数据暂不可用”,上报错误码
Schema 校验失败 阻止使用该批数据,回退到上一个缓存版本
资源缺失 展示占位图,隐藏播放按钮,上报资源 ID
关联断链 从路线/地图中隐藏该站点,保留错误日志
多语言缺失 回退中文,并记录缺失翻译

5. 性能与优化

5.1 数据体积与加载策略

当前 JSON 体积不大;static/models/ 下模型已确认为自然博物馆 1F 真实 3D 模型资产,不应按普通占位资源处理。但模型资产仍需要元数据和部署治理:

资源 路径 大小
馆内模型 static/models/f1-indoor.glb 1,562,816 bytes
楼层模型 static/models/f1-floor.glb 95,720 bytesfacilities.json 点位坐标来源
部署副本 public/models/f1-indoor.glbpublic/models/f1-floor.glb static/models 同大小;如果两端都会打包,需要明确去重或按端分发

风险:

问题 影响
public/modelsstatic/models 同时存在 若二者同时进入同一端包体,会造成重复;若分别服务 web/小程序,需要 manifest 标注用途
图片/音频 URL 缺失 无法验证真实媒体体积和懒加载策略
3D 模型与 POI 分离加载 需要版本锁定,否则 POI 坐标与模型不匹配

建议:

优先级 建议
P1 明确模型部署目录策略:同一端只保留一份,跨端复用则在 manifest 中声明
P1 模型按楼层拆包并懒加载,非当前楼层不加载
P1 图片提供缩略图、详情图、原图三级资源
P2 音频使用按需加载,播放前预取下一站讲解

5.2 请求与预加载

当前没有真实请求层,数据通过动态 import 加载;页面和组件中重复本地数组导致“无请求但重复数据维护”。未来接 API 时建议:

场景 策略
首页启动 加载 data-manifest、楼层、轻量 POI、热门展品
搜索打开 延迟构建或读取本地搜索索引
进入详情 entityId 读取详情,缺资源时显示降级态
开始路线 预加载路线站点、当前位置楼层 POI、下一站音频元信息

5.3 本地存储与离线可用性

导览类小程序对弱网很敏感,应支持基础离线:

数据 离线等级
楼层、展厅、设施、核心 POI 必须离线可用
展品详情、路线 建议离线可用
图片缩略图 建议缓存最近访问和路线相关资源
音频 可选缓存,需考虑版权与包体
3D 模型 按楼层缓存,版本变更后更新

数据问题清单

P0 阻塞性问题

ID 问题 证据 影响 修复建议
D-P0-01 核心数据仍是艺术馆内容 exhibits.json蒙娜丽莎 等世界名画 产品定位与内容冲突 建立自然博物馆实体数据集并替换核心 JSON
D-P0-02 多套硬编码实体互相冲突 同一 id: '1' 分别代表蒙娜丽莎、霸王龙、银杏化石 搜索、讲解、详情跳转不可信 收敛到统一 entityId,禁止页面本地 Mock
D-P0-03 资源 URL 大量失效 5 张展品图、5 个音频、5 张展厅图缺失 图片/音频核心体验失败 上线前加入资源存在性校验
D-P0-04 详情页未按 ID 加载 exhibit/detail.vuehall/detail.vue 等使用默认对象 用户点击任意实体都可能看到同一详情 详情页接入 repository findById
D-P0-05 路线仍为艺术馆路线 routes.json 为经典艺术之旅等 参观规划完全不适配自然博物馆 重建路线数据模型和正式路线

P1 重要问题

ID 问题 证据 影响 修复建议
D-P1-01 楼层引用断链 floor_b1 引用 parking_b1storage_b1 楼层设施展示不完整 补齐设施或删除无效引用
D-P1-02 展厅 exhibitCount 与实际数量不一致 hall_1 标称 25实际 3 统计误导用户 改为派生计算或校验阻断
D-P1-03 3D POI 未绑定实体 67 个 poi_*entityId 地图无法打开统一详情 增加 entityType/entityId
D-P1-04 类型定义不支持 3D/经纬度坐标 Position 只有 {x,y} 地图类型保护失效 定义统一 Coordinate union
D-P1-05 设施枚举不完整 真实 POI 含入口、母婴室、服务台等 UI 图标和筛选无法统一 建立设施类型字典
D-P1-06 无数据版本与缓存策略 未见 manifest 和 storage 机制 无法增量更新、离线弱 新增 data-manifest 和本地缓存
D-P1-07 错误处理吞掉原因 dataLoader 异常返回 [] 无法区分空数据和加载失败 返回 DataResult<T>
D-P1-08 多语言字段缺失 核心 JSON 无英文/别名/学名 国际访客和英文搜索不可用 引入 LocaleText 与搜索索引

P2 优化项

ID 问题 证据 影响 修复建议
D-P2-01 模型部署目录未说明 static/modelspublic/models 同名同大小 可能包体重复,也可能是跨端分发但缺少说明 建立模型 manifest明确每个端使用哪个路径
D-P2-02 搜索工具未统一使用 页面自建数组,utils/search.ts 被绕开 搜索规则重复 搜索统一走 index service
D-P2-03 缺少资源元数据 图片/音频只有 URL 版权、尺寸、时长不可控 建立 Asset 模型
D-P2-04 缺少数据生成文档 无数据字典和维护手册 后续运营难维护 建立数据治理规范

数据迁移方案:从艺术馆到深圳自然博物馆

阶段 0冻结与基线1 到 2 天

目标:防止旧 Mock 继续扩散。

任务 产出
标记艺术馆数据为 legacy legacy-art-gallery 数据目录或删除计划
建立数据审计脚本 可输出数量、断链、资源缺失
定义自然博物馆实体清单 展厅、展品、设施、路线、POI、资源字段
统一 ID 规范 exhibit_dino_trex_001hall_dinosaur_2ffacility_restroom_1f_east

阶段 1核心模型重建3 到 5 天

目标:让所有页面可以读同一套自然博物馆数据。

任务 产出
重写 TypeScript domain 类型 Exhibit 从艺术品模型改为自然史模型
新增 CoordinateAssetLocaleTextEntityStatus 支撑地图、资源、多语言、上下线
建立 mock data v1 至少 30 个展品、8 个展厅、30 个设施、5 条路线
改造 dataLoader 返回 typed DataResult<T>,支持校验错误
改造详情页 按 URL id 从 repository 查询

阶段 2地图与路线绑定5 到 8 天

目标地图、POI、路线、详情形成闭环。

任务 产出
为 67 个 F1 POI 增加 entityType/entityId 点击 POI 打开统一详情
建立楼层坐标系元信息 originscalerotationmodelVersion
TencentMap/ThreeMap 的硬编码 marker 迁出组件 地图 view model
路线站点绑定 POI 路线可在 2D/3D 地图高亮
增加无障碍/亲子/研学路线 覆盖典型人群

阶段 3资源、多语言与离线5 到 10 天

目标:接近可运营数据质量。

任务 产出
建立图片、音频资源清单 路径、尺寸、时长、版权、语言
替换占位 URL 和缺失资源 所有核心展品可展示/播放
建立中英文内容字段 英文名、学名、英文简介、英文音频
生成搜索索引 支持中文、英文、别名、学名
增加本地缓存和版本更新 弱网可用,支持增量更新

阶段 4CMS/API 接入2 到 4 周

目标:从静态 Mock 过渡到可维护的馆方内容系统。

任务 产出
定义 API response envelope version/source/updatedAt/errors
接入 CMS 或后台服务 馆方可维护内容
增加审核流 draft 到 published
增加数据监控 资源失效、断链、翻译缺失告警
建立回滚机制 数据版本可回退

数据治理建议

数据目录建议

src/domain/
  guideTypes.ts
  guideEnums.ts
  guideRepository.ts
  guideAdapters.ts

src/assets/data/
  data-manifest.json
  museum/
    exhibits.json
    halls.json
    facilities.json
    floors.json
    routes.json
    pois.json
    assets.json

scripts/
  audit-data.ts
  build-search-index.ts

数据质量门禁

门禁 触发时机 阻断规则
本地审计 提交前 P0 不允许提交
CI 审计 PR/合并前 P0/P1 必须有处理或豁免
资源审计 打包前 核心图片/音频缺失阻断
内容审计 发布前 未审核、未发布数据不能进正式包
多语言审计 英文版发布前 英文关键字段缺失阻断

数据字典建议

每个实体至少包含:

字段组 必填内容
标识 idtypestatusversion
展示 namesummarydescriptionkeywords
位置 floorIdhallIdcoordinates[]poiIds[]
资源 coverImagegallery[]audio[]modelAssetId
运营 validFromvalidToupdatedAtreviewedAt
多语言 zhCN 必填,enUS 按上线范围要求

预估修复工作量

工作包 角色 预估工时 优先级
数据审计脚本与 CI 门禁 前端/工具链 1 到 2 人日 P0
自然博物馆数据模型重建 前端 + 内容策划 2 到 3 人日 P0
核心 Mock 数据迁移 v1 内容策划 + 前端 3 到 5 人日 P0
详情页/搜索/地图统一接 repository 前端 4 到 6 人日 P0
POI 与实体绑定 前端 + 3D/地图 3 到 5 人日 P1
资源清单与缺失资源替换 内容/设计/前端 3 到 6 人日 P1
多语言字段与搜索索引 前端 + 翻译/内容 4 到 8 人日 P1
离线缓存与增量更新 前端 4 到 7 人日 P1
CMS/API 接入 后端 + 前端 10 到 20 人日 P1

建议最小可交付排期:

周期 目标 验收标准
短期1 周内 解决 P0 核心数据为自然博物馆;搜索/详情/地图 ID 统一;资源缺失校验可运行
中期2 到 4 周 解决主要 P1 POI 绑定、路线可用、缓存和版本机制上线
长期1 到 2 个月 数据治理闭环 CMS/API、审核流、多语言、监控和回滚机制可用

下一步行动清单

  1. 建立 scripts/audit-data.ts,把本报告中的数量、断链、资源缺失、统计不一致变成可重复命令。
  2. 先删除或隔离旧艺术馆 Mock 数据,防止新页面继续引用。
  3. 制定深圳自然博物馆首批 MVP 数据清单8 个展厅、30 个展品、30 个设施、5 条路线、F1 全量 POI 绑定。
  4. 改造 dataLoader 为 typed repository详情页、搜索、地图统一从 repository 读取。
  5. 在发布流程中加入 P0 数据门禁:资源缺失、引用断链、实体冲突、非自然博物馆内容不得进入正式包。

补充审计:以真实 F1 点位为基准

补充前提:static/data/f1-indoor-pois.json 是真实 1 楼设施点位信息。因此它不应被视为普通 Mock而应作为校验 1F 设施、展厅、入口、地图点击、搜索和筛选数据的基准。

基准数据摘要

指标 结果
POI 总数 67
类型分布 facility: 58hall: 6entrance: 3
楼层分布 全部为 1F
坐标范围 x: -106.59 到 150.26y: 0 到 0z: -37.73 到 79.06
重复坐标
加载路径 Map3DManager 会从 /static/models/f1-indoor.glb 推断并加载 /static/data/f1-indoor-pois.json

真实 1F 点位包含的代表性设施和区域:

展厅/场馆:展厅人类厅、巨幕影院、动感多维影院、自然剧场、球幕影院、展厅
入口/服务:售票处、售票机、服务台
设施:女卫、男卫、无障碍卫生间、楼梯、电梯、扶梯、存包处、轮椅及儿童车租车处、贵宾接待区、贵宾卫生间、茶水间、母婴间

真实 F1 点位反查出的新增问题

严重性 问题 证据 影响 建议
P0 facilities.json 的 1F 设施与真实点位完全不匹配 1F 设施只有 洗手间艺术咖啡厅艺术品商店主出口,真实 POI 中均无这些同名点位 设施列表、设施详情、楼层设施入口都会展示不存在或不准确的设施 f1-indoor-pois.json 生成 1F 设施实例,旧艺术馆设施迁入 legacy
P0 halls.json 的 1F 展厅与真实点位完全不匹配 1F 展厅为 1号展厅2号展厅;真实 POI 展厅为 展厅人类厅巨幕影院动感多维影院自然剧场球幕影院展厅 地图点位点击与展厅详情无法对应,展厅统计不可用 建立真实 1F 展厅/场馆实体,并用 poiId 绑定
P0 3D 点击逻辑会忽略大部分真实设施点位 handlePOIClick 只处理 exhibithall;真实 POI 中 58/67 为 facility 用户点击厕所、电梯、楼梯、母婴间、售票处等核心服务点位不会弹出详情 点击逻辑必须支持 facilityentrance,并进入统一设施详情/导航
P1 真实 POI 与 markerDataMap 无法映射 真实 ID 为 poi_0poi_66;首页映射使用 01hall-1exhibit-1 POI 点击只能走临时 fallback无法获得图片、说明、导航策略、收藏状态 poiIdentityId 建立真实映射,删除手写 markerDataMap
P1 floors.json 的 1F 设施引用严重不足 floor_1f.facilities 只引用 3 个设施,真实 1F 有 58 个 facility POI 和 3 个 entrance POI 楼层筛选和设施面板无法覆盖真实服务点 floor_1f 应引用真实 POI 或引用从 POI 派生的 facility instances
P1 设施类型粒度不足 真实 POI 全部压成 facility/entrance/hall,具体类别藏在中文 label 中 搜索、筛选、图标、无障碍路线无法可靠判断类别 增加 category/subtype,如 restroom_femaleelevatorstairsticket_officenursing_room
P1 UI 筛选分类与真实标签没有规范映射 AreaSelector卫生间/电梯/楼梯/停车场/母婴室/服务中心/寄存处/饮水处/影院,真实标签是 女卫001电梯020楼梯.001存包处茶水间 用户选择分类后很难精确筛出真实点位 建立 label 归一化和分类映射表,区分展示名与检索名
P1 搜索数据未覆盖真实 1F 设施 搜索 Mock 只有 洗手间咖啡厅服务中心纪念品商店 搜索不到真实存在的售票机、服务台、母婴间、轮椅及儿童车租车处、贵宾卫生间等 搜索索引从真实 POI 和设施实体生成
P1 存在两套 POI 坐标模型 真实 POI 为 {x,y,z}ThreeMap.vue props/default POI 为 {latitude,longitude} 组件接口同名但数据形态不同,后续接入容易错用 将馆内 3D POI 与馆外经纬度 POI 拆成不同类型
P2 真实 POI label 带模型导出痕迹 电梯001楼梯.001无障碍卫生间.001 直接展示会显得粗糙,也不利于搜索同义词 保留原始 label同时新增 displayNameinstanceNonormalizedName
P2 entrance 类型语义混杂 售票处售票机服务台 被标为 entrance 类型名称无法表达真实服务属性 原始类型可保留,业务层补充 category: ticket/service

与真实 F1 点位冲突的关键文件

文件 冲突点 处理建议
src/assets/data/facilities.json 1F 设施与真实 POI 无同名匹配 用真实 POI 重建 1F facilities
src/assets/data/halls.json 1F 展厅名称和数量与真实 POI 冲突 重建 halls并绑定 poi_0/poi_51poi_55
src/assets/data/floors.json 1F 只引用 3 个旧设施 从真实 POI 派生楼层设施索引
src/pages/index/index.vue markerDataMap 不认识 poi_*,点击设施被忽略 改为根据 poiId/entityId 查询 repository
src/components/map/ThreeMap.vue 默认 POI 使用经纬度,和真实馆内 {x,y,z} POI 混用 拆分 IndoorPOIOutdoorMarker
src/types/index.ts Position 只有 {x,y}POIMarker 不含 entrance 扩展坐标和 POI 类型
src/components/search/SearchPanel.vue 搜索 Mock 未来自真实 POI 搜索索引从 pois + entities 生成
src/components/area/AreaSelector.vue 分类只停留在 UI 文案,没有连接真实 POI subtype 建立设施分类字典和 label 归一化规则

建议的数据归一化模型

真实 POI 文件可以继续作为原始点位数据,但业务层需要派生规范实体:

interface RawIndoorPOI {
  id: string
  label: string
  x: number
  y: number
  z: number
  type: 'hall' | 'facility' | 'entrance'
  floor: '1F'
}

interface FacilityInstance {
  id: string
  poiId: string
  floorId: string
  displayName: string
  normalizedName: string
  category: 'restroom' | 'elevator' | 'stairs' | 'escalator' | 'ticket' | 'service' | 'storage' | 'nursing' | 'theater' | 'vip' | 'water' | 'entrance'
  accessibility?: string[]
  coordinate: { system: 'indoor_3d'; modelId: 'f1-indoor'; x: number; y: number; z: number }
}

更新后的优先修复顺序

  1. P0让 3D POI 点击支持 facilityentrance,否则真实 1F 点位 61 个服务类点位无法交互。
  2. P0用真实 POI 重建 1F facilitieshalls,移除艺术馆设施/展厅对 1F 的覆盖。
  3. P1建立 poiId -> entityId 映射,让地图、搜索、详情、路线共享同一实体。
  4. P1新增设施分类字典女卫001男卫002电梯020楼梯.001 等归一到可筛选类别。
  5. P1floor_1f 从真实 POI 派生设施和展厅索引,避免手工维护数量不一致。
  6. P2保留原始 label 作为 sourceLabel,增加面向用户的 displayName,避免模型导出编号直接暴露。

补充审计:真实模型与 f1-floor.glb 坐标来源

补充前提:frontend-miniapp/static/models/ 下的模型是自然博物馆 1F 真实 3D 模型;facilities.json 中的点位坐标来自 frontend-miniapp/static/models/f1-floor.glb 提取,目的是为后续 web 端页面与模型交互准备数据。

因此,对模型和坐标的审计结论需要修正为:模型资产和部分坐标来源可信,不能简单当作 Mock 删除;真正的问题是缺少模型元数据、坐标系说明、实体语义绑定和跨端资源治理。

修正后的判断

数据/资产 可信部分 仍存在的问题
static/models/f1-indoor.glb 真实 1F 馆内 3D 模型 缺少 modelId、hash、版本、来源、坐标系、比例尺、与 POI 文件的绑定说明
static/models/f1-floor.glb 真实 1F 楼层模型,且是 facilities.json.position 的提取来源 facilities.json 未记录 sourceModel、提取工具、提取时间、坐标原点、单位、投影规则
static/data/f1-indoor-pois.json 真实 1F POI 点位,使用 {x,y,z} 模型空间坐标 未绑定业务实体label 仍是模型导出名称,需要业务归一化
src/assets/data/facilities.json position 字段有真实模型来源 设施名称、类型、描述仍是旧艺术馆语义;坐标字段只有 {x,y},无法判断与 f1-indoor-pois.json{x,y,z} 如何互转
public/models/*.glb 可能用于 web 端静态访问 static/models/*.glb 同名同大小,需说明是否为跨端副本,避免构建重复打包

新增数据风险

严重性 问题 影响 建议
P0 坐标来源真实,但业务实体语义不真实 后续 web 与模型交互可能点位能落到模型上,但弹出的名称、类别、详情仍是错的 facilities.json 拆为“模型点位层”和“业务设施层”,用 poiId/entityId 连接
P1 缺少模型 manifest 无法保证 f1-floor.glbf1-indoor.glb、POI JSON、设施坐标来自同一版本 新增 static/models/model-manifest.jsonsrc/assets/data/model-manifest.json
P1 缺少坐标系/变换元数据 facilities.json.position {x,y}f1-indoor-pois {x,y,z} 可能来自不同模型或投影空间,未来 web 交互容易错位 为每组坐标声明 sourceModelcoordinateSystemunitoriginscaleaxisMapping
P1 Map3DManager 运行时加载 f1-indoor-pois.json,但 facilities.json 坐标来自 f1-floor.glb 运行态点位和业务设施点位可能使用两套坐标基准 明确 f1-floorf1-indoor 的关系,建立统一转换或只让业务层引用同一基准
P2 模型部署目录策略不明确 web 端和小程序端可能各自引用不同路径,造成缓存、版本和包体问题 约定 web 用 public/modelsstatic/models 之一,并通过 manifest 管理

建议新增模型清单

{
  "models": [
    {
      "id": "f1-indoor",
      "path": "/static/models/f1-indoor.glb",
      "purpose": "runtime-3d-indoor-map",
      "floor": "1F",
      "version": "2026-05-28",
      "hash": "<sha256>",
      "poiDataset": "/static/data/f1-indoor-pois.json",
      "coordinateSystem": {
        "type": "model_world_3d",
        "unit": "model_unit",
        "scaleInMap3DManager": 0.3
      }
    },
    {
      "id": "f1-floor",
      "path": "/static/models/f1-floor.glb",
      "purpose": "floor-point-extraction",
      "floor": "1F",
      "version": "2026-05-28",
      "derivedDatasets": [
        "src/assets/data/facilities.json"
      ],
      "coordinateSystem": {
        "type": "model_floor_projection",
        "unit": "model_unit",
        "axisMapping": "to-be-documented"
      }
    }
  ]
}

修正后的下一步

  1. 保留 static/models/f1-indoor.glbstatic/models/f1-floor.glb 作为真实资产,不再按占位资源处理。
  2. facilities.json.position 增加来源字段,例如 sourceModel: "f1-floor"sourceCoordinateSystem: "model_floor_projection"
  3. facilities.json 中的业务字段与模型坐标分离:坐标可来自模型,设施名称/类型/描述需按真实自然博物馆内容重建。
  4. 建立 f1-floor 坐标与 f1-indoor POI 坐标的关系说明,否则 web 端点击、3D 高亮和导航路径会有错位风险。
  5. 明确 public/modelsstatic/models 的分工;如果 public/models 是 web 端专用副本,应写入 README/manifest而不是简单删除。