chore: initialize frontend miniapp repository
This commit is contained in:
799
docs/Data/data-audit-2026-05-28.md
Normal file
799
docs/Data/data-audit-2026-05-28.md
Normal file
@@ -0,0 +1,799 @@
|
||||
# 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 坐标、入口/展厅/设施枚举,后续扩展易破 | 扩展 `Position`、`POI`、`FacilityType`、多语言与状态字段 |
|
||||
| P1 | 无数据版本、校验、缓存、错误分级 | 数据异常会静默返回空数组,难以监控和降级 | 引入 schema 校验、数据版本元信息和错误态 UI |
|
||||
|
||||
建议采用两步治理:先用 1 周完成“数据源收敛和阻断性校验”,再用 2 到 4 周完成自然博物馆正式数据迁移、地图 POI 绑定、资源治理与多语言模型。
|
||||
|
||||
## 审计方法
|
||||
|
||||
本次审计使用静态扫描和结构化脚本校验,未修改业务代码。
|
||||
|
||||
| 方法 | 覆盖内容 | 证据来源 |
|
||||
| --- | --- | --- |
|
||||
| JSON 结构扫描 | 展品、展厅、设施、路线、楼层、室内 POI 数量与字段 | `src/assets/data/*.json`、`static/data/f1-indoor-pois.json` |
|
||||
| 引用完整性校验 | 展品到展厅、楼层到展厅/设施、路线到站点 | Node 脚本读取 JSON 后交叉比对 |
|
||||
| 静态资源存在性校验 | 图片、音频、展厅图是否存在于 `static/` | 文件系统校验 |
|
||||
| 硬编码扫描 | 页面、组件、地图、搜索中的本地数组和占位 URL | `rg` 搜索 |
|
||||
| 类型与数据流审查 | TypeScript 接口、数据加载、搜索工具、服务层 | `src/types/index.ts`、`src/utils/dataLoader.ts`、`src/utils/search.ts`、`src/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.glb`、`f1-floor.glb` 均为自然博物馆 1F 真实模型;需补模型清单、坐标系与部署目录策略 |
|
||||
| `static/icons/*.svg` | 8 | 地图图标 | 可用,但 POI 类型枚举与图标映射未统一 |
|
||||
|
||||
当前数据流可以概括为:
|
||||
|
||||
```mermaid
|
||||
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 必填字段缺失与占位符
|
||||
|
||||
结构字段层面,展品、展厅、设施、路线大多包含基础字段,但业务必填字段明显不足:没有馆藏编号、自然史分类、状态、更新时间、版权、资源元信息、语种、坐标系。
|
||||
|
||||
静态校验结果:
|
||||
|
||||
```text
|
||||
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
|
||||
```
|
||||
|
||||
虽然基础字段未大量为空,但资源字段失效非常严重:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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` 不一致,且未绑定详情数据 |
|
||||
|
||||
硬编码证据截图:
|
||||
|
||||
```text
|
||||
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 关联关系完整性
|
||||
|
||||
路线站点都能在艺术馆展品表中找到,但楼层到设施存在断链:
|
||||
|
||||
```text
|
||||
BROKEN REFERENCES
|
||||
floor floor_b1 facility parking_b1
|
||||
floor floor_b1 facility storage_b1
|
||||
```
|
||||
|
||||
更大的关联问题是 `static/data/f1-indoor-pois.json` 与核心实体完全脱钩。该文件已确认为真实 1F 设施点位基准,包含 67 个 POI,类型分布为:
|
||||
|
||||
```text
|
||||
POI TYPES
|
||||
{ hall: 6, facility: 58, entrance: 3 }
|
||||
POI floors: 1F
|
||||
```
|
||||
|
||||
这些 POI 的 `id` 形如 `poi_0`,没有 `entityId` 指向 `hall_1`、`facility_*` 或路线站点,无法支撑“点击地图点打开统一详情”“按路线高亮真实点位”等核心导览能力。
|
||||
|
||||
### 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` | 不包含 `entrance`、`hall`、`stairs`、`mother_baby`、`accessible_restroom`、`service_desk` 等真实 POI 类型 | P1 |
|
||||
| `POIMarker.type` | `exhibit/hall/facility/location` | 不包含 `entrance`,与 `ThreeMap`、`f1-indoor-pois.json` 不一致 | P1 |
|
||||
| `Exhibit` | 艺术品字段 `artist/year/material/size` | 自然博物馆需要 `taxonomy`、`period`、`specimenType`、`collectionNo`、`scientificName`、`ageRange` 等字段 | P0 |
|
||||
| 全部实体 | 无多语言、无状态、无版本 | 无法支撑中英文切换、数据审核、增量更新和下线 | P1 |
|
||||
|
||||
建议新增分层模型:
|
||||
|
||||
```ts
|
||||
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`,但返回值未声明类型,错误时统一返回空数组:
|
||||
|
||||
```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 时缺少 `version`、`updatedAt`、`source`、`errors`、`pagination` 规范 |
|
||||
|
||||
建议定义统一响应:
|
||||
|
||||
```ts
|
||||
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` | `storage`、`accessible` 等 | UI 类别未进入类型系统 |
|
||||
| `static/data/f1-indoor-pois.json` | `hall/facility/entrance` | 与 `POIMarker.type` 不一致 |
|
||||
| `ThreeMap.vue` | `entrance/exhibit/facility/hall` | 局部定义,与全局类型重复 |
|
||||
| `TencentMap.vue` | marker 图标路径 | 通过硬编码绑定,不受枚举约束 |
|
||||
|
||||
建议将枚举集中到 `src/types/enums.ts` 或 `src/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:
|
||||
|
||||
```mermaid
|
||||
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` 与版本回滚 |
|
||||
| 数据来源追踪 | 无 | 每条记录保留 `sourceId`、`sourceUpdatedAt` |
|
||||
|
||||
### 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 bytes;`facilities.json` 点位坐标来源 |
|
||||
| 部署副本 | `public/models/f1-indoor.glb`、`public/models/f1-floor.glb` | 与 `static/models` 同大小;如果两端都会打包,需要明确去重或按端分发 |
|
||||
|
||||
风险:
|
||||
|
||||
| 问题 | 影响 |
|
||||
| --- | --- |
|
||||
| `public/models` 和 `static/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.vue`、`hall/detail.vue` 等使用默认对象 | 用户点击任意实体都可能看到同一详情 | 详情页接入 repository `findById` |
|
||||
| D-P0-05 | 路线仍为艺术馆路线 | `routes.json` 为经典艺术之旅等 | 参观规划完全不适配自然博物馆 | 重建路线数据模型和正式路线 |
|
||||
|
||||
### P1 重要问题
|
||||
|
||||
| ID | 问题 | 证据 | 影响 | 修复建议 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| D-P1-01 | 楼层引用断链 | `floor_b1` 引用 `parking_b1`、`storage_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/models` 与 `public/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_001`、`hall_dinosaur_2f`、`facility_restroom_1f_east` |
|
||||
|
||||
### 阶段 1:核心模型重建,3 到 5 天
|
||||
|
||||
目标:让所有页面可以读同一套自然博物馆数据。
|
||||
|
||||
| 任务 | 产出 |
|
||||
| --- | --- |
|
||||
| 重写 TypeScript domain 类型 | `Exhibit` 从艺术品模型改为自然史模型 |
|
||||
| 新增 `Coordinate`、`Asset`、`LocaleText`、`EntityStatus` | 支撑地图、资源、多语言、上下线 |
|
||||
| 建立 mock data v1 | 至少 30 个展品、8 个展厅、30 个设施、5 条路线 |
|
||||
| 改造 `dataLoader` | 返回 typed `DataResult<T>`,支持校验错误 |
|
||||
| 改造详情页 | 按 URL `id` 从 repository 查询 |
|
||||
|
||||
### 阶段 2:地图与路线绑定,5 到 8 天
|
||||
|
||||
目标:地图、POI、路线、详情形成闭环。
|
||||
|
||||
| 任务 | 产出 |
|
||||
| --- | --- |
|
||||
| 为 67 个 F1 POI 增加 `entityType/entityId` | 点击 POI 打开统一详情 |
|
||||
| 建立楼层坐标系元信息 | `origin`、`scale`、`rotation`、`modelVersion` |
|
||||
| 把 `TencentMap`/`ThreeMap` 的硬编码 marker 迁出组件 | 地图 view model |
|
||||
| 路线站点绑定 POI | 路线可在 2D/3D 地图高亮 |
|
||||
| 增加无障碍/亲子/研学路线 | 覆盖典型人群 |
|
||||
|
||||
### 阶段 3:资源、多语言与离线,5 到 10 天
|
||||
|
||||
目标:接近可运营数据质量。
|
||||
|
||||
| 任务 | 产出 |
|
||||
| --- | --- |
|
||||
| 建立图片、音频资源清单 | 路径、尺寸、时长、版权、语言 |
|
||||
| 替换占位 URL 和缺失资源 | 所有核心展品可展示/播放 |
|
||||
| 建立中英文内容字段 | 英文名、学名、英文简介、英文音频 |
|
||||
| 生成搜索索引 | 支持中文、英文、别名、学名 |
|
||||
| 增加本地缓存和版本更新 | 弱网可用,支持增量更新 |
|
||||
|
||||
### 阶段 4:CMS/API 接入,2 到 4 周
|
||||
|
||||
目标:从静态 Mock 过渡到可维护的馆方内容系统。
|
||||
|
||||
| 任务 | 产出 |
|
||||
| --- | --- |
|
||||
| 定义 API response envelope | `version/source/updatedAt/errors` |
|
||||
| 接入 CMS 或后台服务 | 馆方可维护内容 |
|
||||
| 增加审核流 | draft 到 published |
|
||||
| 增加数据监控 | 资源失效、断链、翻译缺失告警 |
|
||||
| 建立回滚机制 | 数据版本可回退 |
|
||||
|
||||
## 数据治理建议
|
||||
|
||||
### 数据目录建议
|
||||
|
||||
```text
|
||||
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 必须有处理或豁免 |
|
||||
| 资源审计 | 打包前 | 核心图片/音频缺失阻断 |
|
||||
| 内容审计 | 发布前 | 未审核、未发布数据不能进正式包 |
|
||||
| 多语言审计 | 英文版发布前 | 英文关键字段缺失阻断 |
|
||||
|
||||
### 数据字典建议
|
||||
|
||||
每个实体至少包含:
|
||||
|
||||
| 字段组 | 必填内容 |
|
||||
| --- | --- |
|
||||
| 标识 | `id`、`type`、`status`、`version` |
|
||||
| 展示 | `name`、`summary`、`description`、`keywords` |
|
||||
| 位置 | `floorId`、`hallId`、`coordinates[]`、`poiIds[]` |
|
||||
| 资源 | `coverImage`、`gallery[]`、`audio[]`、`modelAssetId` |
|
||||
| 运营 | `validFrom`、`validTo`、`updatedAt`、`reviewedAt` |
|
||||
| 多语言 | `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: 58`、`hall: 6`、`entrance: 3` |
|
||||
| 楼层分布 | 全部为 `1F` |
|
||||
| 坐标范围 | `x: -106.59 到 150.26`,`y: 0 到 0`,`z: -37.73 到 79.06` |
|
||||
| 重复坐标 | 无 |
|
||||
| 加载路径 | `Map3DManager` 会从 `/static/models/f1-indoor.glb` 推断并加载 `/static/data/f1-indoor-pois.json` |
|
||||
|
||||
真实 1F 点位包含的代表性设施和区域:
|
||||
|
||||
```text
|
||||
展厅/场馆:展厅人类厅、巨幕影院、动感多维影院、自然剧场、球幕影院、展厅
|
||||
入口/服务:售票处、售票机、服务台
|
||||
设施:女卫、男卫、无障碍卫生间、楼梯、电梯、扶梯、存包处、轮椅及儿童车租车处、贵宾接待区、贵宾卫生间、茶水间、母婴间
|
||||
```
|
||||
|
||||
### 真实 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` 只处理 `exhibit` 和 `hall`;真实 POI 中 58/67 为 `facility` | 用户点击厕所、电梯、楼梯、母婴间、售票处等核心服务点位不会弹出详情 | 点击逻辑必须支持 `facility` 和 `entrance`,并进入统一设施详情/导航 |
|
||||
| P1 | 真实 POI 与 `markerDataMap` 无法映射 | 真实 ID 为 `poi_0` 到 `poi_66`;首页映射使用 `0`、`1`、`hall-1`、`exhibit-1` | POI 点击只能走临时 fallback,无法获得图片、说明、导航策略、收藏状态 | 用 `poiId` 或 `entityId` 建立真实映射,删除手写 `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_female`、`elevator`、`stairs`、`ticket_office`、`nursing_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,同时新增 `displayName`、`instanceNo`、`normalizedName` |
|
||||
| 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_51` 到 `poi_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 混用 | 拆分 `IndoorPOI` 与 `OutdoorMarker` |
|
||||
| `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 文件可以继续作为原始点位数据,但业务层需要派生规范实体:
|
||||
|
||||
```ts
|
||||
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 点击支持 `facility` 和 `entrance`,否则真实 1F 点位 61 个服务类点位无法交互。
|
||||
2. P0:用真实 POI 重建 1F `facilities` 和 `halls`,移除艺术馆设施/展厅对 1F 的覆盖。
|
||||
3. P1:建立 `poiId -> entityId` 映射,让地图、搜索、详情、路线共享同一实体。
|
||||
4. P1:新增设施分类字典,把 `女卫001`、`男卫002`、`电梯020`、`楼梯.001` 等归一到可筛选类别。
|
||||
5. P1:让 `floor_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.glb`、`f1-indoor.glb`、POI JSON、设施坐标来自同一版本 | 新增 `static/models/model-manifest.json` 或 `src/assets/data/model-manifest.json` |
|
||||
| P1 | 缺少坐标系/变换元数据 | `facilities.json.position {x,y}` 与 `f1-indoor-pois {x,y,z}` 可能来自不同模型或投影空间,未来 web 交互容易错位 | 为每组坐标声明 `sourceModel`、`coordinateSystem`、`unit`、`origin`、`scale`、`axisMapping` |
|
||||
| P1 | `Map3DManager` 运行时加载 `f1-indoor-pois.json`,但 `facilities.json` 坐标来自 `f1-floor.glb` | 运行态点位和业务设施点位可能使用两套坐标基准 | 明确 `f1-floor` 与 `f1-indoor` 的关系,建立统一转换或只让业务层引用同一基准 |
|
||||
| P2 | 模型部署目录策略不明确 | web 端和小程序端可能各自引用不同路径,造成缓存、版本和包体问题 | 约定 web 用 `public/models` 或 `static/models` 之一,并通过 manifest 管理 |
|
||||
|
||||
### 建议新增模型清单
|
||||
|
||||
```json
|
||||
{
|
||||
"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.glb`、`static/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/models` 和 `static/models` 的分工;如果 `public/models` 是 web 端专用副本,应写入 README/manifest,而不是简单删除。
|
||||
272
docs/GET_BUILDING_POLYGON.md
Normal file
272
docs/GET_BUILDING_POLYGON.md
Normal file
@@ -0,0 +1,272 @@
|
||||
# 获取建筑围栏坐标指南
|
||||
|
||||
## 方法概览
|
||||
|
||||
| 方法 | 准确度 | 难度 | 推荐度 |
|
||||
|------|--------|------|--------|
|
||||
| 腾讯地图坐标拾取器 | ⭐⭐⭐⭐⭐ | 简单 | ⭐⭐⭐⭐⭐ |
|
||||
| 卫星图手动标注 | ⭐⭐⭐⭐ | 简单 | ⭐⭐⭐⭐ |
|
||||
| 建筑平面图转换 | ⭐⭐⭐⭐⭐ | 中等 | ⭐⭐⭐⭐ |
|
||||
| 估算矩形围栏 | ⭐⭐ | 简单 | ⭐⭐ |
|
||||
|
||||
---
|
||||
|
||||
## 方法 1:腾讯地图坐标拾取器(推荐)
|
||||
|
||||
### 步骤
|
||||
|
||||
1. **打开坐标拾取器**
|
||||
- 访问:https://lbs.qq.com/getPoint/
|
||||
- 或使用:https://lbs.qq.com/tool/getpoint/
|
||||
|
||||
2. **定位到博物馆**
|
||||
- 搜索框输入:深圳自然博物馆
|
||||
- 或直接输入坐标:22.692763, 114.363487
|
||||
|
||||
3. **切换卫星图**
|
||||
- 点击右上角地图类型切换按钮
|
||||
- 选择"卫星图"模式
|
||||
- 放大到最大级别(可以看清建筑轮廓)
|
||||
|
||||
4. **标注建筑角点**
|
||||
- 沿着建筑外围,从西北角开始
|
||||
- 顺时针或逆时针依次点击每个角点
|
||||
- 记录每个点的坐标(纬度, 经度)
|
||||
|
||||
5. **复制坐标**
|
||||
- 将所有角点坐标记录下来
|
||||
- 按顺序排列(形成闭合多边形)
|
||||
|
||||
### 示例
|
||||
|
||||
假设标注了6个角点:
|
||||
|
||||
```javascript
|
||||
const polygons = ref([
|
||||
{
|
||||
points: [
|
||||
{ latitude: 22.693100, longitude: 114.363100 }, // 西北角
|
||||
{ latitude: 22.693100, longitude: 114.363500 }, // 北侧转角
|
||||
{ latitude: 22.693100, longitude: 114.363900 }, // 东北角
|
||||
{ latitude: 22.692400, longitude: 114.363900 }, // 东南角
|
||||
{ latitude: 22.692400, longitude: 114.363500 }, // 南侧转角
|
||||
{ latitude: 22.692400, longitude: 114.363100 }, // 西南角
|
||||
],
|
||||
strokeWidth: 3,
|
||||
strokeColor: '#E0E100',
|
||||
fillColor: '#E0E10020',
|
||||
zIndex: 1
|
||||
}
|
||||
])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 方法 2:使用 Google Earth / 百度地图
|
||||
|
||||
### Google Earth Pro(桌面版)
|
||||
|
||||
1. 下载安装 Google Earth Pro
|
||||
2. 搜索"深圳自然博物馆"
|
||||
3. 使用"添加多边形"工具
|
||||
4. 沿建筑外围绘制多边形
|
||||
5. 右键 → 属性 → 查看坐标
|
||||
6. 导出为 KML 文件,提取坐标
|
||||
|
||||
### 百度地图拾取坐标
|
||||
|
||||
1. 访问:https://api.map.baidu.com/lbsapi/getpoint/
|
||||
2. 搜索定位到博物馆
|
||||
3. 切换卫星图
|
||||
4. 依次点击建筑角点
|
||||
5. **注意**:百度地图使用 BD-09 坐标系,需要转换为 GCJ-02
|
||||
|
||||
---
|
||||
|
||||
## 方法 3:使用 API 脚本获取
|
||||
|
||||
### 运行脚本
|
||||
|
||||
```bash
|
||||
cd museum-guide-v4.0
|
||||
node scripts/get-building-polygon.js
|
||||
```
|
||||
|
||||
### 脚本功能
|
||||
|
||||
1. 调用腾讯地图 WebService API
|
||||
2. 搜索博物馆 POI 信息
|
||||
3. 尝试获取建筑轮廓数据
|
||||
4. 如果没有轮廓数据,计算估算的矩形围栏
|
||||
|
||||
### 调整建筑尺寸
|
||||
|
||||
如果使用估算方法,需要知道建筑的实际尺寸:
|
||||
|
||||
```javascript
|
||||
// 修改脚本中的参数
|
||||
calculateRectangle(
|
||||
22.692763, // 中心纬度
|
||||
114.363487, // 中心经度
|
||||
150, // 宽度(米)- 根据实际调整
|
||||
100 // 高度(米)- 根据实际调整
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 方法 4:从建筑平面图转换
|
||||
|
||||
如果有建筑平面图或 CAD 图纸:
|
||||
|
||||
### 步骤
|
||||
|
||||
1. **确定参考点**
|
||||
- 在平面图上标注一个已知坐标的点(如主入口)
|
||||
- 确定平面图的方向(正北方向)
|
||||
|
||||
2. **测量相对位置**
|
||||
- 测量每个角点相对于参考点的距离和方向
|
||||
- 单位:米
|
||||
|
||||
3. **计算坐标**
|
||||
```javascript
|
||||
// 纬度1度 ≈ 111km
|
||||
// 经度1度 ≈ 111km × cos(纬度)
|
||||
|
||||
const latPerMeter = 1 / 111000
|
||||
const lngPerMeter = 1 / (111000 * Math.cos(22.692763 * Math.PI / 180))
|
||||
|
||||
// 从参考点向北50米,向东30米
|
||||
const newLat = refLat + 50 * latPerMeter
|
||||
const newLng = refLng + 30 * lngPerMeter
|
||||
```
|
||||
|
||||
4. **验证坐标**
|
||||
- 在地图上标注计算出的坐标
|
||||
- 对比卫星图验证准确性
|
||||
|
||||
---
|
||||
|
||||
## 方法 5:实地测量(最准确)
|
||||
|
||||
使用 GPS 设备或手机 APP:
|
||||
|
||||
### 推荐 APP
|
||||
|
||||
- **奥维互动地图**(支持多种坐标系)
|
||||
- **两步路户外助手**
|
||||
- **GPS Test**(Android)
|
||||
|
||||
### 步骤
|
||||
|
||||
1. 到博物馆现场
|
||||
2. 打开 GPS APP
|
||||
3. 走到建筑每个角点
|
||||
4. 记录 GPS 坐标
|
||||
5. 确保使用 GCJ-02 坐标系(火星坐标)
|
||||
|
||||
---
|
||||
|
||||
## 坐标系转换
|
||||
|
||||
### 常见坐标系
|
||||
|
||||
- **WGS-84**:GPS 原始坐标,国际标准
|
||||
- **GCJ-02**:火星坐标,中国加密坐标(腾讯地图使用)
|
||||
- **BD-09**:百度坐标,百度地图专用
|
||||
|
||||
### 转换工具
|
||||
|
||||
- 在线转换:https://tool.lu/coordinate/
|
||||
- npm 包:`coordtransform`
|
||||
|
||||
```bash
|
||||
npm install coordtransform
|
||||
```
|
||||
|
||||
```javascript
|
||||
const coordtransform = require('coordtransform')
|
||||
|
||||
// WGS-84 转 GCJ-02
|
||||
const [lng, lat] = coordtransform.wgs84togcj02(114.363487, 22.692763)
|
||||
|
||||
// BD-09 转 GCJ-02
|
||||
const [lng2, lat2] = coordtransform.bd09togcj02(114.369487, 22.698763)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 验证围栏准确性
|
||||
|
||||
### 在地图上检查
|
||||
|
||||
1. 将坐标添加到 `TencentMap.vue`
|
||||
2. 运行项目查看地图
|
||||
3. 对比卫星图底图
|
||||
4. 调整不准确的点
|
||||
|
||||
### 计算围栏面积
|
||||
|
||||
```javascript
|
||||
// 使用 Shoelace 公式计算多边形面积
|
||||
function calculateArea(points) {
|
||||
let area = 0
|
||||
for (let i = 0; i < points.length; i++) {
|
||||
const j = (i + 1) % points.length
|
||||
area += points[i].longitude * points[j].latitude
|
||||
area -= points[j].longitude * points[i].latitude
|
||||
}
|
||||
area = Math.abs(area) / 2
|
||||
|
||||
// 转换为平方米(近似)
|
||||
const latPerMeter = 1 / 111000
|
||||
const lngPerMeter = 1 / (111000 * Math.cos(points[0].latitude * Math.PI / 180))
|
||||
const areaInSquareMeters = area / (latPerMeter * lngPerMeter)
|
||||
|
||||
return areaInSquareMeters
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: 为什么我的围栏位置偏移?
|
||||
|
||||
A: 可能的原因:
|
||||
1. 坐标系不匹配(检查是否为 GCJ-02)
|
||||
2. 纬度经度顺序错误(应为 latitude, longitude)
|
||||
3. 地图缩放级别太低,看不清细节
|
||||
|
||||
### Q: 如何绘制不规则建筑?
|
||||
|
||||
A: 增加更多角点,多边形支持任意数量的点:
|
||||
|
||||
```javascript
|
||||
points: [
|
||||
{ latitude: 22.693100, longitude: 114.363100 },
|
||||
{ latitude: 22.693100, longitude: 114.363300 },
|
||||
{ latitude: 22.693050, longitude: 114.363500 }, // 斜角
|
||||
{ latitude: 22.692900, longitude: 114.363700 }, // 弧形可用多个点近似
|
||||
// ... 更多点
|
||||
]
|
||||
```
|
||||
|
||||
### Q: 围栏太大或太小?
|
||||
|
||||
A: 检查坐标单位:
|
||||
- 纬度/经度差 0.0001 ≈ 11米/9米
|
||||
- 纬度/经度差 0.001 ≈ 110米/90米
|
||||
|
||||
---
|
||||
|
||||
## 推荐流程
|
||||
|
||||
1. ✅ **使用腾讯地图坐标拾取器**手动标注(5-10分钟)
|
||||
2. ✅ 将坐标复制到代码中
|
||||
3. ✅ 运行项目验证
|
||||
4. ✅ 微调不准确的点
|
||||
5. ✅ 完成!
|
||||
|
||||
这是最快速、最准确的方法。
|
||||
143
docs/MAP_COORDINATES_GUIDE.md
Normal file
143
docs/MAP_COORDINATES_GUIDE.md
Normal file
@@ -0,0 +1,143 @@
|
||||
# 深圳自然博物馆地图配置说明
|
||||
|
||||
## 地图中心坐标
|
||||
|
||||
当前使用的是示例坐标,需要替换为实际的深圳自然博物馆坐标。
|
||||
|
||||
### 如何获取实际坐标
|
||||
|
||||
1. **使用腾讯地图拾取坐标工具**
|
||||
- 访问:https://lbs.qq.com/getPoint/
|
||||
- 搜索"深圳自然博物馆"
|
||||
- 点击地图上的建筑位置
|
||||
- 复制经纬度坐标
|
||||
|
||||
2. **使用高德地图坐标拾取**
|
||||
- 访问:https://lbs.amap.com/tools/picker
|
||||
- 搜索并定位博物馆
|
||||
- 获取坐标(需转换为 GCJ-02 坐标系)
|
||||
|
||||
## 建筑外围标记配置
|
||||
|
||||
在 `TencentMap.vue` 中的 `polygons` 数组配置建筑轮廓:
|
||||
|
||||
```typescript
|
||||
const polygons = ref<Polygon[]>([
|
||||
{
|
||||
points: [
|
||||
{ latitude: 22.5433, longitude: 114.0577 }, // 西北角
|
||||
{ latitude: 22.5433, longitude: 114.0581 }, // 东北角
|
||||
{ latitude: 22.5429, longitude: 114.0581 }, // 东南角
|
||||
{ latitude: 22.5429, longitude: 114.0577 }, // 西南角
|
||||
],
|
||||
strokeWidth: 3,
|
||||
strokeColor: '#E0E100', // 黄色边框
|
||||
fillColor: '#E0E10020', // 半透明黄色填充
|
||||
zIndex: 1
|
||||
}
|
||||
])
|
||||
```
|
||||
|
||||
### 配置说明
|
||||
|
||||
- **points**: 建筑外围的坐标点数组(按顺时针或逆时针顺序)
|
||||
- **strokeWidth**: 边框宽度(像素)
|
||||
- **strokeColor**: 边框颜色(十六进制)
|
||||
- **fillColor**: 填充颜色(十六进制,最后两位是透明度)
|
||||
- **zIndex**: 层级(数值越大越在上层)
|
||||
|
||||
### 获取建筑轮廓坐标的方法
|
||||
|
||||
1. **手动标记**
|
||||
- 在腾讯地图拾取坐标工具中
|
||||
- 依次点击建筑的各个角点
|
||||
- 记录每个点的经纬度
|
||||
|
||||
2. **使用卫星图**
|
||||
- 在地图上切换到卫星视图
|
||||
- 更清晰地看到建筑轮廓
|
||||
- 标记关键点位
|
||||
|
||||
3. **简化轮廓**
|
||||
- 如果建筑形状复杂,可以简化为矩形或多边形
|
||||
- 只需标记主要的转角点
|
||||
|
||||
## 标记点配置
|
||||
|
||||
### 博物馆主标记
|
||||
|
||||
```typescript
|
||||
{
|
||||
id: 0,
|
||||
latitude: 22.5431,
|
||||
longitude: 114.0579,
|
||||
iconPath: '/static/icons/marker-museum.png',
|
||||
width: 40,
|
||||
height: 40,
|
||||
title: '深圳自然博物馆',
|
||||
callout: {
|
||||
content: '深圳自然博物馆',
|
||||
display: 'ALWAYS', // 始终显示
|
||||
bgColor: '#E0E100',
|
||||
color: '#000000'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 入口标记
|
||||
|
||||
```typescript
|
||||
{
|
||||
id: 1,
|
||||
latitude: 22.5429,
|
||||
longitude: 114.0579,
|
||||
iconPath: '/static/icons/marker-entrance.png',
|
||||
title: '主入口'
|
||||
}
|
||||
```
|
||||
|
||||
## 需要准备的图标
|
||||
|
||||
- `/static/icons/marker-museum.png` - 博物馆主标记(40x40px)
|
||||
- `/static/icons/marker-entrance.png` - 入口标记(30x30px)
|
||||
- `/static/icons/marker-hall.png` - 展厅标记(25x25px)
|
||||
- `/static/icons/marker-exhibit.png` - 展品标记(25x25px)
|
||||
|
||||
## 坐标系说明
|
||||
|
||||
- **GCJ-02**: 国测局坐标系(火星坐标系)
|
||||
- 腾讯地图、高德地图使用此坐标系
|
||||
- GPS 原始坐标需要转换
|
||||
|
||||
## 调试建议
|
||||
|
||||
1. 先设置地图中心点
|
||||
2. 调整缩放级别(scale: 18-20)
|
||||
3. 添加建筑外围多边形
|
||||
4. 微调多边形坐标点
|
||||
5. 添加内部标记点
|
||||
|
||||
## 示例:矩形建筑
|
||||
|
||||
```typescript
|
||||
// 假设建筑是一个矩形,长 100 米,宽 80 米
|
||||
const centerLat = 22.5431
|
||||
const centerLng = 114.0579
|
||||
|
||||
// 经纬度偏移量(约 1 度 ≈ 111 公里)
|
||||
const latOffset = 0.00045 // 约 50 米
|
||||
const lngOffset = 0.00036 // 约 40 米
|
||||
|
||||
const polygons = [{
|
||||
points: [
|
||||
{ latitude: centerLat + latOffset, longitude: centerLng - lngOffset },
|
||||
{ latitude: centerLat + latOffset, longitude: centerLng + lngOffset },
|
||||
{ latitude: centerLat - latOffset, longitude: centerLng + lngOffset },
|
||||
{ latitude: centerLat - latOffset, longitude: centerLng - lngOffset },
|
||||
],
|
||||
strokeWidth: 3,
|
||||
strokeColor: '#E0E100',
|
||||
fillColor: '#E0E10020',
|
||||
zIndex: 1
|
||||
}]
|
||||
```
|
||||
109
docs/MAP_MARKERS_GUIDE.md
Normal file
109
docs/MAP_MARKERS_GUIDE.md
Normal file
@@ -0,0 +1,109 @@
|
||||
# 地图标记图标说明
|
||||
|
||||
## 图标列表
|
||||
|
||||
### 用户定位标记
|
||||
- **文件**: `marker-user-location.svg`
|
||||
- **样式**: 黑色圆圈 + 黄色定位针 + 半透明外圈
|
||||
- **尺寸**: 40×40px
|
||||
- **用途**: 显示用户当前位置
|
||||
- **特点**:
|
||||
- 外圈半透明黑色(opacity: 0.2)
|
||||
- 内圈黑色,黄色边框
|
||||
- 中心黄色指针图标
|
||||
|
||||
### 博物馆主标记
|
||||
- **文件**: `marker-museum.svg`
|
||||
- **样式**: 黄色圆形 + 博物馆建筑图标
|
||||
- **尺寸**: 40×40px
|
||||
- **用途**: 标记博物馆主建筑位置
|
||||
- **特点**: 黄色背景,黑色建筑图标
|
||||
|
||||
### 入口标记
|
||||
- **文件**: `marker-entrance.svg`
|
||||
- **样式**: 黑色圆点 + 白色边框
|
||||
- **尺寸**: 30×30px
|
||||
- **用途**: 标记入口位置
|
||||
|
||||
### 展厅标记
|
||||
- **文件**: `marker-hall.svg`
|
||||
- **样式**: 红色圆点 + 白色边框
|
||||
- **尺寸**: 30×30px
|
||||
- **用途**: 标记展厅位置
|
||||
- **颜色**: #FF6B6B
|
||||
|
||||
### 展品标记
|
||||
- **文件**: `marker-exhibit.svg`
|
||||
- **样式**: 青色圆点 + 白色边框
|
||||
- **尺寸**: 30×30px
|
||||
- **用途**: 标记展品位置
|
||||
- **颜色**: #5ED0E4
|
||||
|
||||
### 设施标记
|
||||
- **文件**: `marker-facility.svg`
|
||||
- **样式**: 绿色圆点 + 白色边框
|
||||
- **尺寸**: 30×30px
|
||||
- **用途**: 标记设施位置(洗手间、咖啡厅等)
|
||||
- **颜色**: #4ECDC4
|
||||
|
||||
### 通用 POI 标记
|
||||
- **文件**: `marker-poi.svg`
|
||||
- **样式**: 青色圆点 + 白色边框
|
||||
- **尺寸**: 30×30px
|
||||
- **用途**: 通用兴趣点标记
|
||||
|
||||
## 标记 ID 规范
|
||||
|
||||
- **0**: 博物馆主标记
|
||||
- **1-99**: 入口标记
|
||||
- **100-199**: 展厅标记
|
||||
- **200-299**: 展品标记
|
||||
- **300-399**: 设施标记
|
||||
- **999**: 用户当前位置(动态添加)
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 添加标记
|
||||
|
||||
```typescript
|
||||
markers.value.push({
|
||||
id: 101,
|
||||
latitude: 22.692863,
|
||||
longitude: 114.363687,
|
||||
iconPath: '/static/icons/marker-hall.svg',
|
||||
width: 30,
|
||||
height: 30,
|
||||
title: '2号展厅',
|
||||
callout: {
|
||||
content: '2号展厅',
|
||||
display: 'BYCLICK',
|
||||
padding: 8,
|
||||
borderRadius: 4,
|
||||
bgColor: '#FF6B6B',
|
||||
color: '#FFFFFF',
|
||||
fontSize: 12
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### 用户定位
|
||||
|
||||
点击定位按钮后,会自动添加用户位置标记(ID: 999),使用 `marker-user-location.svg` 图标。
|
||||
|
||||
## 设计规范
|
||||
|
||||
- **圆点标记**: 直径 16px,白色边框 2px
|
||||
- **大标记**: 40×40px(用户位置、博物馆主标记)
|
||||
- **小标记**: 30×30px(其他所有标记)
|
||||
- **边框**: 白色,2px 宽度
|
||||
- **阴影**: 可选,用于增强立体感
|
||||
|
||||
## 颜色方案
|
||||
|
||||
| 类型 | 颜色代码 | 颜色名称 |
|
||||
|------|---------|---------|
|
||||
| 强调/当前位置 | #E0E100 | 黄色 |
|
||||
| 入口 | #333333 | 黑色 |
|
||||
| 展厅 | #FF6B6B | 红色 |
|
||||
| 展品 | #5ED0E4 | 青色 |
|
||||
| 设施 | #4ECDC4 | 绿色 |
|
||||
81
docs/MUSEUM_COORDINATES.md
Normal file
81
docs/MUSEUM_COORDINATES.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# 深圳自然博物馆地图配置
|
||||
|
||||
## 博物馆信息
|
||||
|
||||
- **名称**: 深圳自然博物馆
|
||||
- **坐标**: 22.692763, 114.363487
|
||||
- **POI ID**: 7043042949572197975
|
||||
- **地址**: 广东省深圳市坪山区
|
||||
|
||||
## 地图配置
|
||||
|
||||
### 中心点坐标
|
||||
|
||||
```typescript
|
||||
const mapCenter = {
|
||||
latitude: 22.692763,
|
||||
longitude: 114.363487
|
||||
}
|
||||
```
|
||||
|
||||
### 建筑外围多边形
|
||||
|
||||
建筑轮廓采用矩形标记(约 100m × 80m):
|
||||
|
||||
```typescript
|
||||
const polygons = [{
|
||||
points: [
|
||||
{ latitude: 22.693163, longitude: 114.363087 }, // 西北角
|
||||
{ latitude: 22.693163, longitude: 114.363887 }, // 东北角
|
||||
{ latitude: 22.692363, longitude: 114.363887 }, // 东南角
|
||||
{ latitude: 22.692363, longitude: 114.363087 }, // 西南角
|
||||
],
|
||||
strokeWidth: 3,
|
||||
strokeColor: '#E0E100',
|
||||
fillColor: '#E0E10020',
|
||||
zIndex: 1
|
||||
}]
|
||||
```
|
||||
|
||||
### 标记点配置
|
||||
|
||||
| ID | 名称 | 纬度 | 经度 | 类型 |
|
||||
|----|------|------|------|------|
|
||||
| 0 | 深圳自然博物馆 | 22.692763 | 114.363487 | 主标记 |
|
||||
| 1 | 主入口 | 22.692363 | 114.363487 | 入口 |
|
||||
| 2 | 1号展厅 | 22.692863 | 114.363687 | 展厅 |
|
||||
| 3 | 恐龙化石展区 | 22.692663 | 114.363287 | 展品 |
|
||||
|
||||
## 坐标偏移参考
|
||||
|
||||
在当前坐标系下:
|
||||
- 纬度 +0.0001 ≈ 北移 11 米
|
||||
- 经度 +0.0001 ≈ 东移 9 米
|
||||
- 纬度 +0.0004 ≈ 北移 44 米
|
||||
- 经度 +0.0004 ≈ 东移 36 米
|
||||
|
||||
## 调整建议
|
||||
|
||||
1. **建筑轮廓微调**
|
||||
- 使用腾讯地图卫星视图查看实际建筑形状
|
||||
- 根据实际轮廓调整多边形坐标点
|
||||
- 如果建筑不是矩形,可添加更多坐标点
|
||||
|
||||
2. **标记点位置**
|
||||
- 根据实际楼层平面图调整展厅位置
|
||||
- 入口位置应对应实际入口
|
||||
- 展品位置根据实际展陈布局设置
|
||||
|
||||
3. **缩放级别**
|
||||
- 当前设置为 19(较高缩放)
|
||||
- 可根据需要调整为 17-20 之间
|
||||
|
||||
## 腾讯地图 POI 信息
|
||||
|
||||
- **POI ID**: 7043042949572197975
|
||||
- 可用于调用腾讯地图 API 获取更多信息
|
||||
- 可用于路线规划和导航功能
|
||||
|
||||
## 更新日期
|
||||
|
||||
2026-05-21
|
||||
195
docs/QA/h5-business-flow-audit-2026-06-09.md
Normal file
195
docs/QA/h5-business-flow-audit-2026-06-09.md
Normal file
@@ -0,0 +1,195 @@
|
||||
# H5/小程序业务流程测试报告
|
||||
|
||||
日期:2026-06-09
|
||||
项目:深圳自然博物馆智能导览应用 - frontend-miniapp
|
||||
审计范围:导览、讲解、搜索、详情、设施导航、路线规划闭环
|
||||
|
||||
## 结论
|
||||
|
||||
Production audit:48/100,Blocked。H5 与微信小程序都能构建成功,但关键用户任务没有形成闭环:用户可以点击入口、跳转页面、看到局部状态变化,却无法稳定完成“找内容 -> 看详情/听讲解 -> 到达目的地/结束任务”的业务目标。
|
||||
|
||||
这不是单个 UI 问题,而是业务对象没有贯穿全链路:页面层大量使用硬编码 mock 数据,路由 ID 没有被详情页真实加载,地图 POI/搜索结果/讲解列表/详情页/路线页之间不是同一套数据。
|
||||
|
||||
## 使用的本项目 skills
|
||||
|
||||
本次只使用项目路径下的本地 skills,没有使用全局安装:
|
||||
|
||||
- `.agents/skills/ux-review/SKILL.md`:按可用性、状态反馈、错误/空态/成功态检查。
|
||||
- `.agents/skills/production-audit/SKILL.md`:按上线风险、证据、阻塞项给出分数。
|
||||
- `.agents/skills/user-flows-and-guided-paths/SKILL.md`:检查流程是否有明确起点、步骤、回退、完成态。
|
||||
- `.agents/skills/playwright-e2e-tester/SKILL.md`:整理应补的端到端测试用例。
|
||||
|
||||
## 验证结果
|
||||
|
||||
| 项目 | 结果 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `pnpm build:h5` | 通过 | 产物可构建,Sass legacy API 有弃用警告。 |
|
||||
| `pnpm build:mp-weixin` | 通过 | 微信小程序产物可构建,Sass legacy API 有弃用警告。 |
|
||||
| `pnpm type-check` | 失败 | 失败于 `vue-tsc@1.8.27` 与当前 TypeScript/Node 组合的工具链补丁:`Search string not found: "/supportedTSExtensions = .*(?=;)/"`。 |
|
||||
| 自动化 E2E | 未覆盖 | 未发现 `playwright.config.*`、`vitest.config.*` 或测试用例文件。 |
|
||||
| Git 基线 | 无提交 | 当前仓库 `No commits yet on master`,本报告基于当前工作区文件。 |
|
||||
|
||||
## 关键业务问题
|
||||
|
||||
### P0:自然馆产品壳与艺术馆数据混用
|
||||
|
||||
证据:
|
||||
|
||||
- `src/pages.json:52` 全局标题是“深圳自然博物馆”。
|
||||
- `src/assets/data/exhibits.json:4` 仍是“蒙娜丽莎”。
|
||||
- `src/assets/data/halls.json:6` 仍是“文艺复兴时期艺术作品展厅”。
|
||||
- `src/assets/data/routes.json:4` 仍是“经典艺术之旅”。
|
||||
- `src/assets/data/facilities.json:17`、`src/assets/data/facilities.json:30` 仍有“艺术咖啡厅”“艺术品商店”。
|
||||
|
||||
影响:用户在讲解、搜索、详情、路线里看到的对象不属于同一个博物馆业务域。即使页面跳转成功,也无法说明用户完成了自然馆导览任务。
|
||||
|
||||
建议:先统一一份自然馆业务数据契约,至少包含 `id/type/name/floor/hallId/audioUrl/position/routeTarget`,然后让讲解、搜索、详情、路线全部从同一数据源读取。
|
||||
|
||||
### P0:详情页接收 ID 但不加载对应业务数据
|
||||
|
||||
证据:
|
||||
|
||||
- `src/pages/exhibit/detail.vue:82` 读取 `options.id` 后只 `console.log`。
|
||||
- `src/pages/exhibit/detail.vue:68` 默认展品固定为“蒙娜丽莎”。
|
||||
- `src/pages/hall/detail.vue:72` 读取 `options.id` 后只 `console.log`。
|
||||
- `src/pages/hall/detail.vue:58`、`src/pages/hall/detail.vue:68` 展厅和展品列表固定写死。
|
||||
- `src/utils/dataLoader.ts:61`、`src/utils/dataLoader.ts:73` 已经有 `findExhibitById`、`findFacilityById`,但页面没有使用。
|
||||
|
||||
影响:搜索结果、地图 marker、讲解列表跳到详情页后,用户看到的不一定是刚才点的对象。流程在“详情确认”这一步断掉。
|
||||
|
||||
建议:详情页必须用路由参数查询统一数据源;查不到时给明确空态/返回路径,不能显示默认假数据。
|
||||
|
||||
### P0:讲解链路没有真实音频闭环
|
||||
|
||||
证据:
|
||||
|
||||
- `src/components/explain/ExplainList.vue:293` 至 `src/components/explain/ExplainList.vue:300` 多个展品 `hasAudio: true`,但 `audioUrl: ''`。
|
||||
- `src/pages/index/index.vue:377`、`src/pages/index/index.vue:426` 对空音频使用 `https://example.com/audio.mp3` 兜底。
|
||||
- `src/pages/exhibit/detail.vue:89` 的详情页播放按钮只切换 `isPlaying` 并打印日志。
|
||||
|
||||
影响:用户点击“讲解”或音频按钮后,可能进入不可控的外部示例音频,或只看到本地播放状态变化。用户无法确认“当前展品讲解已开始、可暂停、可结束、可回到展品”。
|
||||
|
||||
建议:去掉 `example.com` 兜底;无音频时显示“暂无讲解”;有音频时使用真实 `audioUrl`,并在列表、详情、底部播放器之间共享播放状态。
|
||||
|
||||
### P0:室内 3D/路线导航仍是演示态
|
||||
|
||||
证据:
|
||||
|
||||
- `src/components/navigation/GuideMapShell.vue:5` 至 `src/components/navigation/GuideMapShell.vue:8` 室内地图分支是 `/static/images/guide-indoor-3d-bg.png` 静态图。
|
||||
- `src/components/navigation/GuideMapShell.vue:11` 室外分支已使用原 `TencentMap`,但室内没有使用 `ThreeMap`。
|
||||
- `src/pages/route/detail.vue:156` 路线固定指向“1F 南侧卫生间”。
|
||||
- `src/pages/route/detail.vue:358` 开始导航只是把 `navigationState` 改成 `navigating`。
|
||||
- `src/pages/route/detail.vue:377` 返回室内继续也只是改状态。
|
||||
|
||||
影响:用户从设施详情点击“开始导航”后,看起来进入了路线页,但没有真实路径、定位、楼层切换、到达判定,也没有和 3D 模型或地图 POI 绑定。
|
||||
|
||||
建议:将路线页目标、起点、路径段、楼层、地图渲染层统一绑定;室内模式接入 `ThreeMap` 或明确降级为 2D 平面图,不能用静态设计图冒充可导航地图。
|
||||
|
||||
### P1:室外 TencentMap 恢复了,但 marker 交互不闭环
|
||||
|
||||
证据:
|
||||
|
||||
- `src/components/navigation/GuideMapShell.vue:11` 当前室外地图使用 `TencentMap`,这是正确方向。
|
||||
- `src/components/map/TencentMap.vue:239` marker 点击先 `emit('markerClick')`。
|
||||
- `src/components/map/TencentMap.vue:244` 至 `src/components/map/TencentMap.vue:250` 同一个点击又立即 `navigateTo`。
|
||||
- `src/pages/index/index.vue:232` 至 `src/pages/index/index.vue:282` 首页准备了 marker 详情、导航、讲解、收藏等处理函数,但 `GuideMapShell` 没有把 `TencentMap` 的 marker 事件继续暴露给首页。
|
||||
|
||||
影响:marker 点击到底应该打开底部卡片,还是直接跳详情页,当前没有统一。用户无法在地图上完成“看点位 -> 选择讲解/导航/收藏”的预期动作。
|
||||
|
||||
建议:`TencentMap` 只负责发出 marker 事件;由 `GuideMapShell`/页面决定打开 sheet、跳详情或开始导航。避免组件内部自行跳转。
|
||||
|
||||
### P1:搜索页不是综合搜索,关键词没有真正驱动结果
|
||||
|
||||
证据:
|
||||
|
||||
- `src/pages/search/index.vue:85` 搜索页使用本地设施数组。
|
||||
- `src/pages/search/index.vue:112` 至 `src/pages/search/index.vue:119` 只按筛选项过滤设施。
|
||||
- `src/pages/search/index.vue:123` `all` 模式固定显示 6 条,但实际设施数组只有 3 条。
|
||||
- `src/pages/search/index.vue:133` 搜索框点击只打印“保持搜索结果页”。
|
||||
- `src/utils/search.ts:70` 已有 `searchAll`,但搜索页没有接入。
|
||||
|
||||
影响:用户从首页或设施详情带关键词进入搜索页后,看到的是固定设施列表,不是围绕关键词的展品/展厅/设施结果。搜索任务没有“查找 -> 确认 -> 进入详情/导航”的闭环。
|
||||
|
||||
建议:搜索页接入 `loadExhibits/loadHalls/loadFacilities + searchAll`,按类型展示结果,并根据 `type` 跳到对应详情页。
|
||||
|
||||
### P1:“讲解”不是独立页面,而是首页 tab,但缺少独立业务边界
|
||||
|
||||
证据:
|
||||
|
||||
- `src/pages.json:2` 至 `src/pages.json:42` 注册页面只有首页、搜索、展品/展厅/设施详情、路线详情。
|
||||
- `src/pages.json:61` `tabBar.list` 为空。
|
||||
- `src/pages/index/index.vue:127` 至 `src/pages/index/index.vue:128` 首页只有 `导览` 和 `讲解` 两个内容 tab。
|
||||
- `src/pages/index/index.vue:81` 讲解分支渲染 `ExplainList`。
|
||||
|
||||
结论:原有“讲解”能力没有完全消失,但它不是独立页面,而是被内嵌为首页 tab。当前点击“讲解”不会进入室内模型;它进入 `ExplainList`。真正的问题是讲解 tab 内的数据、音频、详情页没有连成闭环。
|
||||
|
||||
建议:如果产品需要“讲解”作为一级业务,应明确它是首页 tab 还是独立页面;然后补齐分享/返回/深链/播放状态保存规则。
|
||||
|
||||
### P1:导航与操作按钮多为 toast/log/返回上一页
|
||||
|
||||
证据:
|
||||
|
||||
- `src/pages/exhibit/detail.vue:94` 至 `src/pages/exhibit/detail.vue:96` 展品详情“导航”只是 `navigateBack()`。
|
||||
- `src/pages/hall/detail.vue:84` 至 `src/pages/hall/detail.vue:86` 展厅详情“导航到展厅”只是 `navigateBack()`。
|
||||
- `src/pages/facility/detail.vue:73` “选择起点”只是 toast。
|
||||
- `src/pages/route/detail.vue:420` 工具按钮主要打印日志或本地切换状态。
|
||||
|
||||
影响:用户点击关键按钮后没有进入下一步任务,也没有明确失败原因。界面有按钮,但业务没有提交、没有完成、没有恢复路径。
|
||||
|
||||
建议:每个主按钮必须有确定结果:进入路线页、打开起点选择、保存收藏、启动音频、到达完成页或显示可恢复错误。
|
||||
|
||||
## 用户流程闭环检查
|
||||
|
||||
| 流程 | 当前状态 | 断点 | 闭环建议 |
|
||||
| --- | --- | --- | --- |
|
||||
| 导览首页 -> 室外地图 -> 点 marker -> 详情/导航/讲解 | 未闭环 | marker 组件内部直接跳转,首页 sheet 逻辑未接上;ID 与详情数据不一致。 | marker 只发事件,页面统一打开 POI sheet;sheet 操作分别进入详情、路线、音频。 |
|
||||
| 导览首页 -> 室内 3D -> 选 POI -> 路线 | 未闭环 | 室内是静态图,未接 `ThreeMap`、POI、路径。 | 接入真实室内地图/3D 场景;POI ID 与路线目标一致。 |
|
||||
| 搜索关键词 -> 结果 -> 详情 -> 导航 | 未闭环 | 搜索页不使用关键词做综合搜索;详情页不加载 ID;详情导航返回上一页。 | 搜索接统一数据源;详情按 ID 渲染;导航按钮带目标进入路线页。 |
|
||||
| 讲解 -> 筛选/搜索 -> 展品 -> 播放音频 -> 结束/返回 | 未闭环 | `activeFilter` 对数据组织影响弱;音频 URL 为空却标记可播放;详情页播放是假状态。 | 按展厅/主题真实分组;无音频禁用播放;播放器跨列表/详情共享状态。 |
|
||||
| 设施详情 -> 选择起点 -> 开始导航 -> 到达 | 未闭环 | 选择起点没有输入结果;路线页固定目标;开始导航只切状态。 | 起点选择写入 route query/store;路线页按起终点生成路径;提供到达/结束态。 |
|
||||
| 路线中 -> 查看室外地图 -> 返回室内继续 | 部分演示 | 暂停/恢复只改 `navigationState`,未保留地图层、楼层、进度。 | 保存 route session;室外/室内切换只换展示层,不丢路径和当前步骤。 |
|
||||
|
||||
## 建议补充的 E2E 用例
|
||||
|
||||
按照 `playwright-e2e-tester` skill,本项目至少需要以下端到端用例,作为业务闭环验收:
|
||||
|
||||
1. 点击首页“讲解”后,应显示讲解列表,不应加载室内 3D/静态室内地图。
|
||||
2. 首页“导览”室外模式应渲染 `TencentMap` 容器,并能点击 marker 打开 POI 操作面板。
|
||||
3. 搜索“卫生间”应只展示匹配设施;点击结果进入对应设施详情;点击“开始导航”进入路线页并保留目标 ID。
|
||||
4. 讲解列表中 `audioUrl` 为空的展品应显示“暂无讲解”或禁用播放,不应请求 `example.com`。
|
||||
5. 点击自然馆展品讲解,应进入同一个展品详情,并能播放同一个音频对象。
|
||||
6. 路线页从 planning -> navigating -> paused -> navigating -> arrived 应保留目标、楼层、路径步骤。
|
||||
7. 详情页传入不存在的 ID 时,应显示空态与返回路径,不应显示默认“蒙娜丽莎”。
|
||||
|
||||
## 修复优先级
|
||||
|
||||
1. 建立统一自然馆数据模型,替换艺术馆 mock 数据。
|
||||
2. 让详情页、搜索页、讲解页全部接入 `dataLoader`/`searchAll`,消除硬编码默认对象。
|
||||
3. 移除 `https://example.com/audio.mp3`,补真实音频状态和无音频状态。
|
||||
4. 拆清 `TencentMap` 责任:地图只发事件,页面负责业务动作。
|
||||
5. 路线页接入真实目标、起点和路径状态;室内地图不要再用静态设计图冒充导航。
|
||||
6. 修复 `vue-tsc` 工具链版本,让类型检查成为有效质量门。
|
||||
7. 增加 Playwright 冒烟用例覆盖“导览、讲解、搜索、详情、路线”五条主链路。
|
||||
|
||||
## Evidence checked
|
||||
|
||||
- `src/pages.json`
|
||||
- `src/pages/index/index.vue`
|
||||
- `src/components/navigation/GuideMapShell.vue`
|
||||
- `src/components/map/TencentMap.vue`
|
||||
- `src/components/map/ThreeMap.vue`
|
||||
- `src/components/explain/ExplainList.vue`
|
||||
- `src/components/search/SearchPanel.vue`
|
||||
- `src/components/audio/AudioPlayer.vue`
|
||||
- `src/pages/search/index.vue`
|
||||
- `src/pages/exhibit/detail.vue`
|
||||
- `src/pages/hall/detail.vue`
|
||||
- `src/pages/facility/detail.vue`
|
||||
- `src/pages/route/detail.vue`
|
||||
- `src/assets/data/exhibits.json`
|
||||
- `src/assets/data/halls.json`
|
||||
- `src/assets/data/facilities.json`
|
||||
- `src/assets/data/routes.json`
|
||||
- `src/utils/dataLoader.ts`
|
||||
- `src/utils/search.ts`
|
||||
- `package.json`
|
||||
146
docs/QA/user-flow-map-2026-06-09.md
Normal file
146
docs/QA/user-flow-map-2026-06-09.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# 用户使用流程图
|
||||
|
||||
日期:2026-06-09
|
||||
范围:导览、讲解、搜索、详情、路线导航
|
||||
|
||||
## 当前用户流(含断点)
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["用户打开小程序/H5"] --> B["首页"]
|
||||
B --> C{"选择一级内容"}
|
||||
|
||||
C -->|"导览"| D["导览页地图"]
|
||||
D --> E{"地图模式"}
|
||||
E -->|"室外"| F["TencentMap 室外地图"]
|
||||
E -->|"室内 3D"| G["室内静态设计图"]
|
||||
|
||||
F --> H["点击 marker"]
|
||||
H --> H1["组件内部直接跳详情"]
|
||||
H --> H2["首页预期打开 POI 操作卡片"]
|
||||
H2 -. "事件未接通" .-> X1["断点:无法稳定选择详情/导航/讲解"]
|
||||
|
||||
G -. "未接 ThreeMap/POI/路径" .-> X2["断点:室内导航只是展示图"]
|
||||
|
||||
D --> I["点击搜索"]
|
||||
I --> J["搜索页"]
|
||||
J --> J1["固定设施列表"]
|
||||
J1 -. "关键词未驱动综合搜索" .-> X3["断点:搜索结果与用户意图不一致"]
|
||||
J1 --> K["设施详情"]
|
||||
K --> K1["选择起点"]
|
||||
K1 -. "只 toast" .-> X4["断点:起点没有写入路线"]
|
||||
K --> L["开始导航"]
|
||||
L --> M["路线详情"]
|
||||
M --> M1["固定目标/本地 navigationState"]
|
||||
M1 -. "无真实路径/定位/到达判定" .-> X5["断点:导航无法完成"]
|
||||
|
||||
C -->|"讲解"| N["首页讲解 Tab"]
|
||||
N --> O["讲解列表"]
|
||||
O --> P{"用户操作"}
|
||||
P -->|"搜索/筛选"| P1["本地 mock 列表"]
|
||||
P1 -. "筛选未形成真实分组" .-> X6["断点:讲解发现路径不稳定"]
|
||||
P -->|"点击展品"| Q["展品详情"]
|
||||
Q --> Q1["默认硬编码展品"]
|
||||
Q1 -. "路由 ID 未加载真实数据" .-> X7["断点:详情不是刚点击的对象"]
|
||||
P -->|"播放音频"| R["底部播放器"]
|
||||
R --> R1["audioUrl 为空时使用 example.com"]
|
||||
R1 -. "无真实音频/无不可用状态" .-> X8["断点:讲解播放无法验收"]
|
||||
|
||||
Q --> S["详情页导航"]
|
||||
S -. "navigateBack" .-> X9["断点:详情无法发起路线"]
|
||||
```
|
||||
|
||||
## 目标闭环用户流
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["用户打开小程序/H5"] --> B["首页"]
|
||||
B --> C{"用户目标"}
|
||||
|
||||
C -->|"我要找位置/设施"| D["导览"]
|
||||
D --> D1{"选择地图层"}
|
||||
D1 -->|"室外"| D2["TencentMap 室外地图"]
|
||||
D1 -->|"室内"| D3["ThreeMap 或真实室内平面图"]
|
||||
D2 --> E["点击 POI"]
|
||||
D3 --> E
|
||||
E --> F["POI 操作卡片"]
|
||||
F -->|"看详情"| G["对应详情页"]
|
||||
F -->|"到这里"| H["选择起点"]
|
||||
F -->|"听讲解"| I["打开对应讲解音频"]
|
||||
|
||||
C -->|"我要搜索"| J["搜索页"]
|
||||
J --> J1["输入关键词"]
|
||||
J1 --> J2["综合搜索:展品/展厅/设施"]
|
||||
J2 --> J3{"选择结果类型"}
|
||||
J3 -->|"展品"| G1["展品详情"]
|
||||
J3 -->|"展厅"| G2["展厅详情"]
|
||||
J3 -->|"设施"| G3["设施详情"]
|
||||
G1 --> G
|
||||
G2 --> G
|
||||
G3 --> G
|
||||
|
||||
C -->|"我要听讲解"| K["讲解"]
|
||||
K --> K1["按展厅/主题分组"]
|
||||
K1 --> K2["选择展品"]
|
||||
K2 --> K3{"音频是否可用"}
|
||||
K3 -->|"可用"| I
|
||||
K3 -->|"不可用"| K4["显示暂无讲解"]
|
||||
I --> I1["播放/暂停/进度/结束"]
|
||||
I1 --> I2["回到展品详情或讲解列表"]
|
||||
|
||||
G --> G4{"详情页主操作"}
|
||||
G4 -->|"开始导航"| H
|
||||
G4 -->|"播放讲解"| I
|
||||
G4 -->|"收藏/分享"| G5["保存状态并反馈"]
|
||||
|
||||
H --> H1["确认当前位置或手动选择起点"]
|
||||
H1 --> H2["生成起点到目标路径"]
|
||||
H2 --> H3["路线规划页"]
|
||||
H3 --> H4["开始导航"]
|
||||
H4 --> H5["导航中:楼层/步骤/距离/方向"]
|
||||
H5 --> H6{"用户中途操作"}
|
||||
H6 -->|"查看室外"| H7["切换室外地图层并保留路线"]
|
||||
H7 --> H5
|
||||
H6 -->|"暂停/继续"| H8["保留当前进度"]
|
||||
H8 --> H5
|
||||
H6 -->|"到达"| H9["到达完成页"]
|
||||
H9 --> H10["下一步:继续游览/返回首页/听该点讲解"]
|
||||
```
|
||||
|
||||
## 主流程闭环标准
|
||||
|
||||
| 流程 | 起点 | 必要中间态 | 完成态 |
|
||||
| --- | --- | --- | --- |
|
||||
| 导览找点 | 首页导览 | 地图层、POI 卡片、详情或路线选择 | 到达 POI,或返回地图继续浏览 |
|
||||
| 搜索找内容 | 搜索入口 | 关键词、综合结果、类型详情 | 进入详情,或发起导航/播放讲解 |
|
||||
| 讲解收听 | 首页讲解 | 分组/搜索、展品、音频可用性判断 | 播放结束,返回展品或讲解列表 |
|
||||
| 设施导航 | 设施详情 | 起点确认、路径生成、导航中状态 | 到达完成页,有下一步动作 |
|
||||
| 详情转导航 | 展品/展厅/设施详情 | 目标 ID、起点、路线规划 | 到达目标,不是简单返回上一页 |
|
||||
|
||||
## 页面与数据关系
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
DS["统一自然馆数据源"] --> S["搜索页"]
|
||||
DS --> E["讲解列表"]
|
||||
DS --> D["详情页"]
|
||||
DS --> M["地图 POI"]
|
||||
DS --> R["路线规划"]
|
||||
|
||||
S -->|"result.type + result.id"| D
|
||||
E -->|"exhibit.id"| D
|
||||
M -->|"poi.id + poi.type"| D
|
||||
D -->|"target.id + target.type"| R
|
||||
R -->|"routeSession"| M
|
||||
E -->|"audioUrl"| P["播放器"]
|
||||
D -->|"audioUrl"| P
|
||||
```
|
||||
|
||||
## 落地顺序
|
||||
|
||||
1. 统一自然馆数据源和 ID 规则。
|
||||
2. 搜索页、讲解页、详情页全部按统一数据源渲染。
|
||||
3. 地图 marker 只发 POI 事件,由页面统一打开操作卡片。
|
||||
4. 详情页主按钮明确进入路线页或播放器。
|
||||
5. 路线页保存 `routeSession`,覆盖起点、目标、路径、楼层、当前步骤和完成态。
|
||||
|
||||
87
docs/TENCENT_MAP_GUIDE.md
Normal file
87
docs/TENCENT_MAP_GUIDE.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# 腾讯地图集成说明
|
||||
|
||||
## 配置步骤
|
||||
|
||||
### 1. 获取腾讯地图 Key
|
||||
|
||||
1. 访问 [腾讯位置服务](https://lbs.qq.com/)
|
||||
2. 注册并登录账号
|
||||
3. 进入控制台 -> 应用管理 -> 我的应用
|
||||
4. 创建应用并添加 Key
|
||||
5. 选择产品类型:
|
||||
- **H5**: WebServiceAPI
|
||||
- **微信小程序**: 微信小程序
|
||||
- **App**: 移动应用
|
||||
|
||||
### 2. 配置 Key
|
||||
|
||||
在 `src/manifest.json` 中配置:
|
||||
|
||||
```json
|
||||
{
|
||||
"h5": {
|
||||
"sdkConfigs": {
|
||||
"maps": {
|
||||
"qqmap": {
|
||||
"key": "YOUR_TENCENT_MAP_KEY"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mp-weixin": {
|
||||
"permission": {
|
||||
"scope.userLocation": {
|
||||
"desc": "您的位置信息将用于地图导航"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 微信小程序额外配置
|
||||
|
||||
在微信小程序后台配置:
|
||||
1. 设置 -> 开发设置 -> 服务器域名
|
||||
2. 添加 request 合法域名:`https://apis.map.qq.com`
|
||||
|
||||
## 使用说明
|
||||
|
||||
uni-app 已内置地图组件,无需额外安装插件。直接使用 `<map>` 组件即可。
|
||||
|
||||
### 基本用法
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<map
|
||||
:latitude="latitude"
|
||||
:longitude="longitude"
|
||||
:markers="markers"
|
||||
@markertap="handleMarkerTap"
|
||||
/>
|
||||
</template>
|
||||
```
|
||||
|
||||
## 功能特性
|
||||
|
||||
- ✅ 地图显示(腾讯地图)
|
||||
- ✅ 标记点(展厅、展品、设施、当前位置)
|
||||
- ✅ 点击标记点跳转详情
|
||||
- ✅ 楼层切换
|
||||
- ✅ 定位功能
|
||||
- ✅ 地图缩放
|
||||
- ✅ 地图拖拽
|
||||
|
||||
## 图标资源清单
|
||||
|
||||
需要准备以下图标(建议 PNG 格式,透明背景):
|
||||
|
||||
- `/static/icons/marker-location.png` - 当前位置(30x30px)
|
||||
- `/static/icons/marker-hall.png` - 展厅(25x25px)
|
||||
- `/static/icons/marker-exhibit.png` - 展品(25x25px)
|
||||
- `/static/icons/marker-facility.png` - 设施(25x25px)
|
||||
- `/static/icons/location.png` - 定位按钮图标(24x24px)
|
||||
|
||||
## 参考文档
|
||||
|
||||
- [腾讯位置服务官网](https://lbs.qq.com/)
|
||||
- [uni-app 地图组件文档](https://uniapp.dcloud.net.cn/component/map.html)
|
||||
669
docs/UX/ux-ui-audit-2026-05-28.md
Normal file
669
docs/UX/ux-ui-audit-2026-05-28.md
Normal file
@@ -0,0 +1,669 @@
|
||||
# frontend-miniapp 用户体验与界面审查报告
|
||||
|
||||
日期:2026-05-28
|
||||
分支:`analysis/ux-ui-audit-2026-05-28`
|
||||
项目范围:`museum-guide-v4.0/frontend-miniapp`
|
||||
审查对象:uni-app / Vue 3 小程序与 H5 导览前端,包括地图、讲解、搜索、详情页、路线、设施、音频和 3D 地图模块。
|
||||
|
||||
## 1. 执行摘要
|
||||
|
||||
### 1.1 总体判断
|
||||
|
||||
当前项目已经具备“导览原型”的主要界面部件:2D 腾讯地图、Three.js 3D 室内地图、顶部导览/讲解切换、搜索框、设施筛选、讲解抽屉、音频播放器、展品/展厅/设施/路线详情页。
|
||||
|
||||
但从真实到馆任务看,它还没有形成可完整测试的用户体验闭环。最关键的问题不是视觉细节,而是入口、数据、状态和操作结果之间没有打通:
|
||||
|
||||
- 用户能看到搜索框,但搜索结果体系分散且首页搜索只 `console.log`。
|
||||
- 用户能点击地图点位,但 `TencentMap.vue` 同时触发底部详情浮层和页面跳转。
|
||||
- 用户能看到路线详情页,但没有路线入口,“开始导览”只是 `uni.navigateBack()`。
|
||||
- 用户能看到音频按钮,但不同入口各自维护状态,且首页回退到 `https://example.com/audio.mp3`。
|
||||
- 用户能进入 3D 地图,但首页传入空 POI 数组,`ThreeMap.vue` 不会回退默认点位。
|
||||
- 项目标题是深圳自然博物馆,但核心数据仍是“蒙娜丽莎”“星空”“经典艺术之旅”等艺术馆 mock 内容。
|
||||
- 无障碍语义、键盘焦点、读屏标签和颜色对比度基础不足。
|
||||
|
||||
### 1.2 最高优先级建议
|
||||
|
||||
| 优先级 | 关键发现 | 用户影响 | 建议 |
|
||||
| --- | --- | --- | --- |
|
||||
| P0 | `pages.json` 的 `tabBar.list` 为空,`BottomTabBar` 未接入 | 用户找不到路线、服务、我的等一级任务 | 重建一级导航:地图、讲解、路线、服务、我的 |
|
||||
| P0 | 地图 marker 点击既打开浮层又跳详情页 | 用户还没选择行动就被带离地图 | marker 点击只打开浮层,按钮再触发详情/导航/音频 |
|
||||
| P0 | `AreaSelector` emit 与首页监听不匹配 | 设施筛选无法稳定驱动地图 | 统一为 `change(typeId)` 并过滤地图/列表 |
|
||||
| P0 | 搜索、路线、音频、收藏大量占位 | 用户测试会卡在功能断点 | 先完成可测试闭环,再做视觉精修 |
|
||||
| P0 | 自然馆数据缺失,艺术馆 mock 混入 | 用户画像和任务无法真实验证 | 替换自然博物馆 seed data |
|
||||
| P0 | 无障碍和色彩基础不足 | 老年、低视力、视障用户不可用 | 建立语义按钮、图标标签、高对比 token |
|
||||
| P1 | 视觉层级和底部浮层互相竞争 | 地图、抽屉、播放器会遮挡 | 定义 z-index 和底部避让规则 |
|
||||
| P2 | 竞品已具备路线、音频、多语言、无障碍、AR/AI/客流 | 功能广度落后 | 分阶段补齐官方导览生态能力 |
|
||||
|
||||
### 1.3 推荐实施策略
|
||||
|
||||
不要先大面积重做视觉。建议用三条竖切片把产品打通:
|
||||
|
||||
1. 设施导航:搜索/筛选卫生间或电梯,地图定位,点击“到这里”,出现路线状态。
|
||||
2. 展品讲解:搜索“恐龙/化石”,进入展品详情,播放真实音频,播放器跨页保留。
|
||||
3. 推荐路线:从一级入口进入路线列表,选择亲子/镇馆/无障碍路线,点击开始后回到地图。
|
||||
|
||||
这三条链路打通后,再开展第一轮真实用户测试。
|
||||
|
||||
## 2. 审查方法与证据范围
|
||||
|
||||
### 2.1 本地源码审查
|
||||
|
||||
重点审查文件:
|
||||
|
||||
| 模块 | 文件 |
|
||||
| --- | --- |
|
||||
| 路由与导航 | `src/pages.json`、`src/pages/index/index.vue`、`src/components/navigation/TopTabBar.vue`、`src/components/navigation/BottomTabBar.vue` |
|
||||
| 地图 | `src/components/map/TencentMap.vue`、`src/components/map/ThreeMap.vue`、`src/components/map/MarkerDetailSheet.vue`、`src/services/map/Map3DManager.ts` |
|
||||
| 搜索 | `src/components/search/SearchBar.vue`、`src/components/search/SearchPanel.vue`、`src/pages/search/index.vue`、`src/utils/search.ts` |
|
||||
| 讲解与音频 | `src/components/explain/ExplainList.vue`、`src/components/audio/AudioPlayer.vue`、`src/components/audio/FloatingAudioButton.vue` |
|
||||
| 详情页 | `src/pages/exhibit/detail.vue`、`src/pages/hall/detail.vue`、`src/pages/facility/detail.vue`、`src/pages/route/detail.vue` |
|
||||
| 数据 | `src/assets/data/exhibits.json`、`halls.json`、`facilities.json`、`routes.json` |
|
||||
| 视觉 token | `src/App.vue`、`src/styles/variables.scss` |
|
||||
|
||||
### 2.2 竞品资料来源
|
||||
|
||||
官方资料与页面:
|
||||
|
||||
- 故宫博物院导览页:https://www.dpm.org.cn/Visit.html
|
||||
- “数字故宫”小程序 2.0 官方发布稿:https://www.dpm.org.cn/classify_detail/257034.html
|
||||
- 上海自然博物馆 App 下载页:https://www.snhm.org.cn/cgfw/appDown.htm
|
||||
- 上海自然博物馆楼层导览:https://nao.snhm.org.cn/foreign/cszl/index.htm
|
||||
- 上海自然博物馆虚拟漫游:https://nao.snhm.org.cn/foreign/cszl/virtualRoaming.htm
|
||||
- British Museum Audio app:https://www.britishmuseum.org/visit/audio-app
|
||||
- MoMA Audio / Bloomberg Connects guide:https://www.moma.org/audio/
|
||||
- The Met Plan Your Visit / Digital Guide:https://www.metmuseum.org/plan-your-visit
|
||||
- The Met Audio Guide:https://www.metmuseum.org/audio-guide
|
||||
|
||||
## 3. 核心用户测试场景设计
|
||||
|
||||
### 3.1 用户画像 A:首次访客
|
||||
|
||||
画像:
|
||||
|
||||
- 年龄 20-45 岁。
|
||||
- 第一次到馆,对展馆楼层、展厅名称和服务设施不了解。
|
||||
- 目标是“快速开始参观,不迷路”。
|
||||
|
||||
关键任务 A1:找到目标展品或展区。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 打开小程序,搜索或浏览“恐龙/化石/生命演化”相关内容,进入一个展品详情 |
|
||||
| 成功标准 | 3 分钟内找到目标;不超过 2 次误点;能说出展品所在楼层/展厅 |
|
||||
| 预期行为 | 先找搜索框或地图点位,然后进入详情,最后返回地图继续参观 |
|
||||
| 当前风险 | 首页搜索只日志输出;数据仍是艺术馆 mock;详情页没有真实加载 id 数据 |
|
||||
|
||||
关键任务 A2:从地图点位了解“我点到的是什么”。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 点击地图上的一个展厅/展品点位,查看信息后选择“查看详情” |
|
||||
| 成功标准 | 点击 marker 后停留在地图,浮层信息清晰;用户自主选择下一步 |
|
||||
| 预期行为 | 点位先展开底部 sheet,再选择导航、详情、讲解或收藏 |
|
||||
| 当前风险 | `TencentMap.vue` 点击 marker 后同时 emit 和 `navigateTo`,流程冲突 |
|
||||
|
||||
关键任务 A3:找到出口或服务台。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 在首页找到“出口/服务中心”,点击开始导航 |
|
||||
| 成功标准 | 45 秒内找到;导航状态明确;能返回地图 |
|
||||
| 预期行为 | 用户会找“服务”“设施”“地图上的按钮” |
|
||||
| 当前风险 | 设施入口隐藏在横向标签中;导航动作多为 toast 或 `navigateBack()` |
|
||||
|
||||
### 3.2 用户画像 B:家庭游客
|
||||
|
||||
画像:
|
||||
|
||||
- 家长带 6-12 岁儿童。
|
||||
- 注意力分散,需要短平快的路线和互动反馈。
|
||||
- 目标是找到孩子感兴趣的内容,减少走冤枉路。
|
||||
|
||||
关键任务 B1:选择亲子路线。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 找到适合 60 分钟的亲子路线,查看站点并开始导览 |
|
||||
| 成功标准 | 60 秒内发现路线入口;路线时长和站点可理解;开始后地图显示第一站 |
|
||||
| 预期行为 | 用户优先找“路线”“推荐”“亲子”而不是手动搜索每个展品 |
|
||||
| 当前风险 | 路线详情存在但无一级入口;`route/detail.vue` 开始导览只是返回 |
|
||||
|
||||
关键任务 B2:播放儿童友好讲解。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 从讲解列表或展品详情播放一条适合儿童的音频 |
|
||||
| 成功标准 | 音频 10 秒内开始;标题和当前展品对应;切页后播放器仍存在 |
|
||||
| 预期行为 | 用户会点击耳机/播放图标,期望自动开始 |
|
||||
| 当前风险 | 音频状态分散;无儿童标签;无真实音频 URL 时请求 example.com |
|
||||
|
||||
关键任务 B3:完成一个小任务或打卡。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 找到一个“寻宝/打卡/问答”互动入口并完成一项 |
|
||||
| 成功标准 | 入口可发现;反馈明确;儿童能理解完成状态 |
|
||||
| 预期行为 | 家庭用户会被“任务”“徽章”“找一找”吸引 |
|
||||
| 当前风险 | 当前没有互动任务体系,上海自然博物馆 App 已提供寻宝游戏方向参考 |
|
||||
|
||||
### 3.3 用户画像 C:资深爱好者
|
||||
|
||||
画像:
|
||||
|
||||
- 自然科学爱好者、摄影/标本/古生物爱好者。
|
||||
- 愿意花 2-4 小时深度参观。
|
||||
- 目标是按主题系统浏览并收藏内容。
|
||||
|
||||
关键任务 C1:按主题浏览展品。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 在讲解页按主题筛选,如古生物、矿物、生态、植物 |
|
||||
| 成功标准 | 用户能理解主题分类;列表内容匹配主题;可进入详情 |
|
||||
| 预期行为 | 从“讲解”或“路线”进入主题内容 |
|
||||
| 当前风险 | `ExplainList.vue` 的“按展厅/按主题”只切 activeFilter,未真正重组数据 |
|
||||
|
||||
关键任务 C2:收藏并形成个人清单。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 收藏 3 个展品,稍后从“我的”或收藏页找回 |
|
||||
| 成功标准 | 收藏状态可见;刷新或切页后保留;能批量查看 |
|
||||
| 预期行为 | 用户点击爱心后期待保存到个人清单 |
|
||||
| 当前风险 | 收藏是组件局部状态,无持久化和“我的”入口 |
|
||||
|
||||
关键任务 C3:在 3D 地图中理解空间关系。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 进入 3D 室内地图,查看某楼层展厅和点位关系 |
|
||||
| 成功标准 | 5 秒内出现可用模型或骨架;有 POI;可切换楼层 |
|
||||
| 预期行为 | 用户会探索模型并点击点位 |
|
||||
| 当前风险 | 首页传入空 `poiList`,3D 默认点位不会出现;3D 与路线/详情未连接 |
|
||||
|
||||
### 3.4 用户画像 D:学生与研学团队
|
||||
|
||||
画像:
|
||||
|
||||
- 中小学生、大学生或老师带队。
|
||||
- 有明确学习目标,需要时间管理、知识点和团队路线。
|
||||
- 目标是完成主题学习和记录。
|
||||
|
||||
关键任务 D1:按研学主题规划路线。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 选择“生命演化 90 分钟”或“地球矿物 60 分钟”路线 |
|
||||
| 成功标准 | 路线有学习目标、站点、预计时长;可开始导航 |
|
||||
| 预期行为 | 老师会先看路线目标,再看站点顺序 |
|
||||
| 当前风险 | `routes.json` 是艺术路线,且路线没有地图状态 |
|
||||
|
||||
关键任务 D2:获取展品详细信息。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 进入某展品详情,查看介绍、年代、位置、讲解 |
|
||||
| 成功标准 | 关键信息首屏可见;说明适合学习记录;有引用或延伸知识 |
|
||||
| 预期行为 | 学生会截图、收藏、返回列表继续看 |
|
||||
| 当前风险 | 展品详情是固定 mock,没有按 id 加载,内容和自然馆不匹配 |
|
||||
|
||||
关键任务 D3:完成小组集合点导航。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 找到集合点、服务台或出口并导航 |
|
||||
| 成功标准 | 30 秒内找到,地图反馈明确 |
|
||||
| 预期行为 | 用户会搜索“出口/服务台/电梯” |
|
||||
| 当前风险 | 设施搜索和导航未闭环 |
|
||||
|
||||
### 3.5 用户画像 E:老年与无障碍需求用户
|
||||
|
||||
画像:
|
||||
|
||||
- 老年游客、低视力用户、视障用户、行动不便用户。
|
||||
- 对复杂手势和小图标不敏感或不可用。
|
||||
- 目标是独立完成找设施、听讲解、少走楼梯。
|
||||
|
||||
关键任务 E1:找到无障碍电梯和卫生间。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 选择无障碍设施,找到电梯或无障碍卫生间 |
|
||||
| 成功标准 | 读屏能读出入口;目标点击区域不小于 44px;地图或列表明确反馈 |
|
||||
| 预期行为 | 用户更依赖文字和清晰按钮,而不是图标猜测 |
|
||||
| 当前风险 | 大量 emoji 和 `view @tap`;缺少 aria-label、focus、role |
|
||||
|
||||
关键任务 E2:使用语音讲解。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 进入展品详情或讲解页,播放、暂停、关闭音频 |
|
||||
| 成功标准 | 读屏能读出播放状态;按钮可键盘触发;错误可理解 |
|
||||
| 预期行为 | 用户需要稳定的“播放/暂停/关闭”文字反馈 |
|
||||
| 当前风险 | 播放按钮缺少语义状态,进度条不可访问 |
|
||||
|
||||
关键任务 E3:选择少楼梯路线。
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 任务 | 选择“无障碍优先”路线并开始导览 |
|
||||
| 成功标准 | 路线避开楼梯;明确提示电梯、坡道、休息区 |
|
||||
| 预期行为 | 用户会寻找“无障碍”“电梯优先”设置 |
|
||||
| 当前风险 | 路线数据没有无障碍属性 |
|
||||
|
||||
## 4. UX 交互逻辑系统分析
|
||||
|
||||
### 4.1 信息架构
|
||||
|
||||
当前 IA 示意:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["首页 pages/index"] --> B["顶部 TopTabBar"]
|
||||
B --> C["导览 guide"]
|
||||
B --> D["讲解 explain"]
|
||||
C --> E["地图 + 搜索 + 设施筛选"]
|
||||
C --> F["点位详情 sheet"]
|
||||
D --> G["讲解抽屉 + 搜索"]
|
||||
E --> H["展品/展厅/设施详情页"]
|
||||
G --> H
|
||||
H --> I["导航/收藏/音频占位动作"]
|
||||
J["路线详情页"] -. "无稳定入口" .-> A
|
||||
```
|
||||
|
||||
问题:
|
||||
|
||||
| 问题 | 证据 | 影响 | 建议 |
|
||||
| --- | --- | --- | --- |
|
||||
| 一级导航缺失 | `pages.json` 的 `tabBar.list` 为空;`BottomTabBar.vue` 未接入首页 | 用户只能看到“导览/讲解”,路线、服务、我的缺位 | 建立 5 个一级入口:地图、讲解、路线、服务、我的 |
|
||||
| 路线入口过深或不存在 | 仅有 `pages/route/detail.vue`,无列表页和首页入口 | 时间敏感用户无法开始路线 | 新增 `route/index` 和首页/底部 tab 入口 |
|
||||
| 内容分类不匹配 | `exhibits.json`、`halls.json`、`routes.json` 是艺术馆内容 | 自然馆测试失真 | 替换自然科学 taxonomy 和 seed data |
|
||||
| 搜索 IA 重复 | 搜索页、SearchPanel、ExplainList 内各有 mock 数据 | 用户从不同入口得到不同结果 | 统一搜索服务和结果动作 |
|
||||
| 服务信息缺位 | 没有开放时间、预约、票务、交通、临展、服务须知入口 | 到馆前/馆内服务链路断裂 | 新增服务页,整合官方服务能力 |
|
||||
|
||||
建议 IA:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["底部主导航"] --> M["地图"]
|
||||
A --> N["讲解"]
|
||||
A --> R["路线"]
|
||||
A --> S["服务"]
|
||||
A --> U["我的"]
|
||||
M --> M1["2D/3D 地图"]
|
||||
M --> M2["楼层/设施筛选"]
|
||||
M --> M3["点位详情"]
|
||||
N --> N1["按展厅"]
|
||||
N --> N2["按主题"]
|
||||
N --> N3["当前播放"]
|
||||
R --> R1["亲子路线"]
|
||||
R --> R2["镇馆路线"]
|
||||
R --> R3["无障碍路线"]
|
||||
S --> S1["开放时间/预约"]
|
||||
S --> S2["卫生间/电梯/出口"]
|
||||
U --> U1["收藏"]
|
||||
U --> U2["历史"]
|
||||
U --> U3["无障碍偏好"]
|
||||
```
|
||||
|
||||
### 4.2 交互流程
|
||||
|
||||
关键断点示意:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A["点击地图点位"] --> B["父组件打开 MarkerDetailSheet"]
|
||||
A --> C["TencentMap 内部 navigateTo"]
|
||||
B --> D["用户本应选择行动"]
|
||||
C --> E["页面已跳走"]
|
||||
D -. "被中断" .-> E
|
||||
```
|
||||
|
||||
主要问题:
|
||||
|
||||
| 流程 | 当前问题 | 建议 |
|
||||
| --- | --- | --- |
|
||||
| 地图点位 | `TencentMap.vue` marker 点击同时 emit 和跳页 | marker 点击只打开 sheet,sheet 按钮触发详情/导航 |
|
||||
| 设施筛选 | `AreaSelector` emits `change`,父组件监听 `area-click`、`floor-change` | 统一事件合约,筛选后更新地图点位和结果列表 |
|
||||
| 3D 地图 | `poiList` 空数组传入后不回退默认 POI | 改为 `props.pois?.length ? props.pois : defaultPOIs`,再接真实数据 |
|
||||
| 搜索 | 首页 `handleSearch` 只日志输出;搜索组件重复 mock | 一套搜索服务,多入口复用 |
|
||||
| 音频 | 详情页只切换 `isPlaying`;首页 fallback 到 example.com | 统一音频 store,禁用无音频项,支持加载/错误/重试 |
|
||||
| 路线 | `handleStartRoute` 只是返回 | 设置导航状态,回地图展示路线进度 |
|
||||
| 收藏 | 组件局部 ref,无“我的” | 持久化收藏,增加收藏入口 |
|
||||
|
||||
操作步骤数量评估:
|
||||
|
||||
| 任务 | 理想步骤 | 当前可能步骤 | 问题 |
|
||||
| --- | ---: | ---: | --- |
|
||||
| 找卫生间并导航 | 3:服务/筛选 -> 选择卫生间 -> 到这里 | 5+,且可能无结果 | 入口、筛选、导航未闭环 |
|
||||
| 播放展品讲解 | 2:展品 -> 播放 | 3-5,且可能是假 URL | 音频状态分散 |
|
||||
| 开始推荐路线 | 3:路线 -> 选路线 -> 开始 | 无稳定入口 | IA 缺口 |
|
||||
| 查看点位详情 | 2:点 marker -> 查看详情 | 1,但被自动跳页 | 缺少确认和行动选择 |
|
||||
|
||||
### 4.3 认知负荷
|
||||
|
||||
| 负荷来源 | 表现 | 用户后果 | 改进 |
|
||||
| --- | --- | --- | --- |
|
||||
| 功能命名抽象 | “导览/讲解”重叠 | 用户不确定去哪找路线、设施、音频 | 改为任务型一级导航 |
|
||||
| 控件过多且叠加 | 顶部 tab、搜索、设施、楼层、地图按钮、抽屉、播放器 | 首屏决策复杂 | 分组并减少默认可见控件 |
|
||||
| 状态不可见 | 收藏、路线、音频、筛选状态本地化 | 用户不知道操作是否生效 | 全局状态条和明确反馈 |
|
||||
| 手势学习成本 | 抽屉拖拽、地图拖拽、浮层关闭同时存在 | 用户误触或不知道如何关闭 | 增加显性按钮,手势作为增强 |
|
||||
| 图标语义不稳定 | emoji 用于设施、导航、收藏 | 读屏和跨端展示不可控 | SVG 图标 + 文字 label |
|
||||
| 内容可信度低 | 自然馆里出现艺术名作 | 用户信任下降 | 换真实自然馆内容 |
|
||||
|
||||
## 5. UI 展示逻辑审查
|
||||
|
||||
### 5.1 当前首页层级示意
|
||||
|
||||
```text
|
||||
┌──────────────────────────┐
|
||||
│ 顶部 TopTabBar: 导览/讲解 │ z=1001
|
||||
├──────────────────────────┤
|
||||
│ 搜索栏 │ z=1001
|
||||
├──────────────────────────┤
|
||||
│ 设施横向筛选 │ z=1001
|
||||
│ │
|
||||
│ 地图/3D模型 │ base
|
||||
│ 楼层按钮/定位按钮 │ map-control
|
||||
│ │
|
||||
├──────────────────────────┤
|
||||
│ Marker Sheet / 讲解抽屉 │ z=500 / 100
|
||||
├──────────────────────────┤
|
||||
│ 音频播放器 │ z=1000
|
||||
└──────────────────────────┘
|
||||
```
|
||||
|
||||
问题:顶部工具层和底部播放器层级接近,底部 sheet、讲解抽屉和音频条缺少互斥或避让规则。
|
||||
|
||||
### 5.2 视觉层次
|
||||
|
||||
问题:
|
||||
|
||||
- 主任务入口不突出,顶部只有两个文字 tab,缺少地图/路线/服务等核心任务权重。
|
||||
- 详情页 hero 固定 450px,小屏首屏几乎只剩图片,标题和位置下沉。
|
||||
- `MarkerDetailSheet` 的标题、位置、导航、音频、收藏都在 280px 内挤压。
|
||||
- 3D 地图加载态视觉强,但失败态和回退态弱。
|
||||
- 地图控件右侧堆叠,缺少任务分组。
|
||||
|
||||
建议:
|
||||
|
||||
- 一级导航使用底部 tab 或平台原生 tab,地图页内部再用 segmented control。
|
||||
- 展品详情首屏优先级:标题、展厅/楼层、播放、导航,再是大图。
|
||||
- 底部 sheet 两档:摘要态 180-240px,全屏态承载详细信息。
|
||||
- 地图控件按“定位/缩放”“楼层”“模式”分区。
|
||||
|
||||
### 5.3 色彩系统
|
||||
|
||||
当前主色:
|
||||
|
||||
- `--museum-accent: #E0E100`
|
||||
- `--museum-poi-marker: #5ED0E4`
|
||||
- 多处硬编码 `#E0E100`。
|
||||
|
||||
对比度风险:
|
||||
|
||||
| 组合 | 对比度 | 结论 |
|
||||
| --- | ---: | --- |
|
||||
| `#E0E100` / 白色 | 约 1.41:1 | 不适合白底小图形、边框、细状态 |
|
||||
| `#E0E100` / `#262421` | 约 11.01:1 | 适合作为深色文字背景 |
|
||||
| `#5ED0E4` / 白色 | 约 1.81:1 | 白底可见性不足 |
|
||||
| `#999999` / 白色 | 约 2.85:1 | 不适合正文 |
|
||||
|
||||
问题:
|
||||
|
||||
- 同一个黄色承担品牌、选中态、路径、地图建筑边界、音频、加载、按钮等过多语义。
|
||||
- 缺少功能色:成功、警告、错误、信息、拥挤度、无障碍。
|
||||
- 地图上浅色点位和浅色路径在复杂背景上不稳定。
|
||||
|
||||
建议:
|
||||
|
||||
- 保留黄色作为品牌背景和大面积 CTA,不作为白底细边框。
|
||||
- 增加语义色 token:
|
||||
- `--color-info: #1463D9`
|
||||
- `--color-success: #1B7F3A`
|
||||
- `--color-warning: #9A5B00`
|
||||
- `--color-danger: #C62828`
|
||||
- `--color-accessible: #005A9C`
|
||||
- 地图点位采用深色底、白描边、类型图标和文字缩写。
|
||||
|
||||
### 5.4 空间布局
|
||||
|
||||
问题:
|
||||
|
||||
- 大量固定高度:`100vh`、`450px` hero、`50vh` 抽屉、`46px` 控件。
|
||||
- `AreaSelector.vue` 的展开面板 `top: 100%`,在 fixed overlay 内可能落在视口外。
|
||||
- 设施标签固定 68px,长词如“无障碍设施”容易拥挤。
|
||||
- 抽屉和播放器都在底部,没有全局占位变量。
|
||||
|
||||
建议:
|
||||
|
||||
- 详情图使用 `height: min(42vh, 320px)` 思路。
|
||||
- 抽屉使用 `bottom: 0` 和明确 `max-height`,不要依赖 `top: 100%`。
|
||||
- 设施标签改为内容自适应,常用设施用快捷按钮。
|
||||
- 定义 `--bottom-player-height`,所有底部浮层避让。
|
||||
|
||||
### 5.5 响应式设计
|
||||
|
||||
风险:
|
||||
|
||||
| 视口 | 风险 | 建议验证 |
|
||||
| --- | --- | --- |
|
||||
| 375x667 小屏 | 顶部 tab + 搜索 + 筛选占用地图过多 | 首屏是否还能看到当前位置和地图点位 |
|
||||
| 390x844 常规手机 | 抽屉、播放器、marker sheet 互相遮挡 | 播放音频时打开 marker sheet |
|
||||
| 430x932 大屏手机 | 控件分散但仍偏移动端 | 检查底部操作区拇指可达 |
|
||||
| 768x1024 平板 | 列表过窄,地图空旷 | 讲解列表可改侧栏 |
|
||||
| 横屏 | 100vh 和底部栏遮挡严重 | 改为侧边工具栏或紧凑布局 |
|
||||
|
||||
建议:
|
||||
|
||||
- 增加 H5 视觉回归,至少覆盖上述 5 个视口。
|
||||
- 平板/H5 使用地图 + 侧栏双栏布局。
|
||||
- 小屏默认折叠非必要筛选,仅保留搜索和“最近设施”。
|
||||
|
||||
### 5.6 无障碍性
|
||||
|
||||
问题:
|
||||
|
||||
- 核心控件是 `view @tap`,H5 下缺少 button 语义。
|
||||
- 未发现 `aria-label`、`aria-live`、`role="dialog"`、`aria-pressed`。
|
||||
- emoji 图标用于卫生间、收藏、导航、播放等核心功能。
|
||||
- 播放器进度条不可键盘操作,读屏无法知道当前时间。
|
||||
- 抽屉打开后没有焦点陷阱,背景地图仍可被误触。
|
||||
|
||||
建议:
|
||||
|
||||
- 抽象 `AppButton`、`IconButton`,H5 输出语义 button,小程序端映射为可点击 view。
|
||||
- 所有图标按钮必须具备文字 label 或 `aria-label`。
|
||||
- 弹层用 `role="dialog"`,关闭按钮明确,打开时聚焦标题或第一个操作。
|
||||
- 音频状态用 `aria-live="polite"`。
|
||||
- 增加“大字/高对比/减少动画/无障碍路线优先”设置。
|
||||
|
||||
## 6. 竞品对比分析
|
||||
|
||||
### 6.1 竞品选择
|
||||
|
||||
本次选取 5 个官方移动端/数字导览生态:
|
||||
|
||||
1. 故宫博物院“数字故宫”小程序与官方导览页。
|
||||
2. 上海自然博物馆 App/H5 楼层导览/虚拟漫游。
|
||||
3. British Museum Audio app。
|
||||
4. MoMA Audio + Bloomberg Connects digital guide。
|
||||
5. The Met Audio Guide / Digital Guide / interactive map。
|
||||
|
||||
### 6.2 核心功能差异
|
||||
|
||||
| 功能 | 当前项目 | 故宫 | 上海自然博物馆 | British Museum | MoMA | The Met | 我们缺失 |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| 一级导航 | 仅导览/讲解 | 导览、展览、探索、票务等 | 常设展览、参观服务等 | Visit 下含 audio app/map/accessibility | Visit 下含 map/audio/accessibility | Plan Visit 下含 audio/map/accessibility | 任务型主导航 |
|
||||
| 官方路线 | mock 路线,无入口 | LBS 推荐路线、定制路线 | App 提供参观路线 | self-guided tours | self-guided tours | highlights / collection tours | 路线入口和开始导览 |
|
||||
| 地图 | 2D/3D 原型 | 精确路线、AR 实景导航 | 楼层导览 | interactive map | interactive museum map | interactive map | 地图与路线/服务打通 |
|
||||
| 音频 | 组件存在,未闭环 | 官方语音讲解 | 实时学习/导览生态 | 250 highlights、65 gallery intros、多语言 | 分主题音频、kids、verbal descriptions | 展览/藏品音频 playlists | 真实音频、分类、多语言、儿童/无障碍版本 |
|
||||
| 收藏 | 局部状态 | 未作为本次重点 | 未作为本次重点 | favourites | digital guide 支持探索内容 | digital guide/audio guide | 持久化收藏和“我的” |
|
||||
| 互动 | 无 | AI 助手、AR 瑞兽 | 寻宝游戏、AR 展品复原 | self-guided tours | highlights / exhibitions | featured tours | 亲子任务、AR、AI |
|
||||
| 客流 | 无 | 舒适度指数 | 限流提示 | 无官方页面重点 | 无官方页面重点 | 访问计划信息 | 客流/拥挤度 |
|
||||
| 无障碍 | 基础缺失 | 读屏、无障碍路线/设施 | 页面有基础服务,App 未见完整无障碍描述 | BSL、audio descriptive guide | verbal descriptions | accessibility guide | 读屏、无障碍路线、描述音频 |
|
||||
| 离线/预下载 | 无 | 未见明确离线 | 建议到馆前下载 App | 建议到馆前下载 audio tours | Bloomberg Connects app | Digital guide/app store | 到馆前下载/缓存策略 |
|
||||
|
||||
### 6.3 交互设计亮点
|
||||
|
||||
| 竞品 | 亮点 | 可借鉴点 |
|
||||
| --- | --- | --- |
|
||||
| 故宫 | 将路线、语音讲解、AR 导航、舒适度指数、AI 助手、无障碍路线整合为到馆闭环 | 把“地图”升级为路线和服务中枢,不只是展示平面图 |
|
||||
| 上海自然博物馆 | 楼层导览和虚拟漫游围绕自然科学主题,如起源之谜、生命长河、演化之道 | 当前项目应采用自然馆主题 taxonomy,而不是通用展品列表 |
|
||||
| British Museum | 音频 app 有多语言、主题 tour、250 件重点藏品、收藏、互动地图、BSL 和描述音频 | 音频应按主题、语言、人群和无障碍类型组织 |
|
||||
| MoMA | Audio 页面按 collection、kids、verbal descriptions 等分组,并接入 Bloomberg Connects | 讲解不只是列表,应有人群化入口,如儿童、描述音频、展览专题 |
|
||||
| The Met | Plan Visit 聚合票务、地图、音频、无障碍、家庭访问;Audio Guide 支持 stop number 和 playlists | 到馆前信息和到馆中导览应在一条链路里 |
|
||||
|
||||
### 6.4 技术实现优势对比
|
||||
|
||||
| 方向 | 竞品优势 | 当前差距 | 建议 |
|
||||
| --- | --- | --- | --- |
|
||||
| 内容分发 | British Museum / MoMA / The Met 使用成熟的音频和导览内容体系 | 当前音频 URL、内容分类、详情加载均未成熟 | 建立内容模型和 CMS/API 接口 |
|
||||
| 定位与路线 | 故宫 LBS 路线和 AR 导航 | 当前路径是模拟,详情导航只返回 | 先做静态路线状态,再接真实室内定位 |
|
||||
| 预下载 | British Museum 建议到馆前下载音频 | 当前没有缓存策略 | H5/小程序缓存地图、音频元数据、轻量图片 |
|
||||
| 多语言 | British Museum、The Met、MoMA 支持多语言或 Bloomberg Connects 多语言能力 | 当前只有中文 | 中期增加中英双语,长期多语言 |
|
||||
| 无障碍 | 故宫、British Museum、MoMA、The Met 都有可访问内容或服务入口 | 当前语义和内容均缺失 | 建立 a11y 组件规范和无障碍路线数据 |
|
||||
| 性能 | 竞品多数使用轻量列表/音频/地图,3D 不作为首屏基础依赖 | 当前 3D GLB 可能成为性能风险 | 默认 2D,3D 按需加载,低端机降级 |
|
||||
|
||||
### 6.5 按优先级的竞品借鉴建议
|
||||
|
||||
P0:
|
||||
|
||||
- 借鉴 The Met / MoMA 的“Visit/Map/Audio/Accessibility”任务入口,重建主导航。
|
||||
- 借鉴 British Museum 的音频内容模型:主题 tour、重点对象、收藏、地图信息。
|
||||
- 借鉴上海自然博物馆的自然科学主题命名,替换艺术馆 mock。
|
||||
|
||||
P1:
|
||||
|
||||
- 借鉴故宫路线闭环:路线推荐、语音讲解、地图导航联动。
|
||||
- 借鉴 MoMA 的 kids / verbal descriptions 分组,建立儿童和无障碍讲解入口。
|
||||
- 借鉴 The Met 的计划访问页面,把开放时间、票务、地图、音频、无障碍聚合。
|
||||
|
||||
P2:
|
||||
|
||||
- 借鉴故宫舒适度指数,增加人工或实时客流状态。
|
||||
- 借鉴上海自然博物馆寻宝和 AR 展品复原,做亲子互动任务。
|
||||
- 借鉴故宫 AI 助手,但限制在官方知识库和地图数据内,避免编造。
|
||||
|
||||
## 7. 分阶段优化计划
|
||||
|
||||
### 7.1 短期,1-2 周:可测试版本
|
||||
|
||||
目标:修复 P0 阻塞,让 5 类用户任务能被真实测试。
|
||||
|
||||
| 编号 | 改进项 | 涉及模块 | 工作量 |
|
||||
| --- | --- | --- | --- |
|
||||
| S1 | 建立主导航:地图、讲解、路线、服务、我的 | `pages.json`、导航组件、首页 | 3-5 人日 |
|
||||
| S2 | 修复 marker 点击冲突 | `TencentMap.vue`、`MarkerDetailSheet.vue` | 1-2 人日 |
|
||||
| S3 | 修复设施筛选事件和展开面板 | `AreaSelector.vue`、`index.vue` | 2-3 人日 |
|
||||
| S4 | 统一搜索服务和结果动作 | `SearchPanel`、`ExplainList`、`search/index`、`utils/search.ts` | 4-6 人日 |
|
||||
| S5 | 替换自然馆 seed data | data JSON、详情页加载 | 3-5 人日 |
|
||||
| S6 | 统一音频播放器,去掉假 URL | `AudioPlayer`、详情页、讲解列表 | 4-6 人日 |
|
||||
| S7 | 路线入口和开始导览闭环 | 路线列表、路线详情、地图状态 | 5-7 人日 |
|
||||
| S8 | P0 无障碍和对比度修复 | 基础按钮、图标、色彩 token | 4-6 人日 |
|
||||
|
||||
短期验收:
|
||||
|
||||
- 5 个用户画像至少各 1 条任务可完整执行。
|
||||
- 地图点位、搜索、设施、音频、路线不再只停留在 toast 或 console。
|
||||
- 读屏能识别核心按钮。
|
||||
|
||||
### 7.2 中期,3-6 周:体验一致性与内容体系
|
||||
|
||||
目标:降低认知负荷,提高导览效率,支撑第二轮用户测试。
|
||||
|
||||
| 编号 | 改进项 | 说明 | 工作量 |
|
||||
| --- | --- | --- | --- |
|
||||
| M1 | 全局状态模型 | 地图、路线、音频、收藏、搜索历史 | 5-8 人日 |
|
||||
| M2 | 视觉层级和 z-index token | 顶栏、地图控件、sheet、播放器、modal | 2-3 人日 |
|
||||
| M3 | 响应式专项 | 小屏、常规手机、平板、横屏 | 5-7 人日 |
|
||||
| M4 | 内容分类体系 | 展厅、主题、展品、路线、设施 taxonomy | 5-8 人日 |
|
||||
| M5 | 真实加载/空态/错误态 | 3D、音频、搜索、定位、路线 | 4-6 人日 |
|
||||
| M6 | 收藏和我的 | 收藏、历史、设置、无障碍偏好 | 4-6 人日 |
|
||||
| M7 | 多语言基础 | 中英字段、语言切换框架 | 5-8 人日 |
|
||||
|
||||
中期验收:
|
||||
|
||||
- SUS 目标 75+。
|
||||
- 设施查找 30 秒内。
|
||||
- 搜索结果一致性 100%。
|
||||
- 关键视口无明显遮挡。
|
||||
|
||||
### 7.3 长期,7-12 周:官方导览生态和差异化
|
||||
|
||||
目标:补齐竞品能力,形成 3D + 自然科学 + 亲子/研学差异化。
|
||||
|
||||
| 编号 | 改进项 | 说明 | 工作量 |
|
||||
| --- | --- | --- | --- |
|
||||
| L1 | 服务与票务入口 | 开放时间、预约、票务、交通、临展 | 5-8 人日 |
|
||||
| L2 | 无障碍路线 | 电梯优先、少楼梯、休息区、无障碍卫生间 | 8-12 人日 |
|
||||
| L3 | 客流舒适度 | 先人工运营,后接实时数据 | 8-15 人日 |
|
||||
| L4 | 亲子寻宝/研学任务 | 打卡、问答、奖励、路线 | 10-15 人日 |
|
||||
| L5 | 3D 地图产品化 | POI、路线、楼层剖切、性能降级 | 12-20 人日 |
|
||||
| L6 | AR 展品复原 | 古生物/化石复原场景 | 15-30 人日 |
|
||||
| L7 | AI 导览助手 | 官方知识库、路线推荐、服务问答 | 15-25 人日 |
|
||||
|
||||
长期验收:
|
||||
|
||||
- 亲子路线、无障碍路线、深度主题路线均可测试。
|
||||
- 3D 不只是模型展示,而能完成找展品/找设施/走路线。
|
||||
- AI 回答有来源边界,不编造展品和场馆信息。
|
||||
|
||||
## 8. 工作量与资源需求
|
||||
|
||||
### 8.1 角色配置
|
||||
|
||||
| 阶段 | 前端 | UX/UI | 内容/策展 | 后端/API | 3D/图形 | QA | 备注 |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: | --- |
|
||||
| 短期 | 1-2 人 | 0.5 人 | 0.5 人 | 0-0.5 人 | 0.2 人 | 0.5 人 | 以本地 seed data 为主 |
|
||||
| 中期 | 1-2 人 | 1 人 | 1 人 | 0.5-1 人 | 0.5 人 | 0.5-1 人 | 建立状态、内容和响应式体系 |
|
||||
| 长期 | 2 人 | 1 人 | 1-2 人 | 1-2 人 | 1 人 | 1 人 | 涉及客流、AR、AI、3D 性能 |
|
||||
|
||||
### 8.2 粗略工期
|
||||
|
||||
| 阶段 | 工期 | 人日估算 |
|
||||
| --- | --- | ---: |
|
||||
| 短期 P0 | 1-2 周 | 26-40 人日 |
|
||||
| 中期 P1 | 3-6 周 | 30-46 人日 |
|
||||
| 长期 P2/P3 | 7-12 周 | 73-125 人日 |
|
||||
|
||||
### 8.3 关键依赖
|
||||
|
||||
- 自然馆真实内容 taxonomy 和 seed data。
|
||||
- 展厅、展品、设施、路线的统一 ID。
|
||||
- 音频资源和版权状态。
|
||||
- 室内点位坐标和无障碍设施数据。
|
||||
- 是否接入实时客流、定位、AR 或 AI 后端服务。
|
||||
|
||||
## 9. 用户测试计划
|
||||
|
||||
### 9.1 测试轮次
|
||||
|
||||
| 轮次 | 时间点 | 样本 | 目标 |
|
||||
| --- | --- | --- | --- |
|
||||
| 第 1 轮 | 短期 P0 完成后 | 8-10 人 | 验证核心任务是否可执行 |
|
||||
| 第 2 轮 | 中期 P1 完成后 | 15-20 人 | 验证 IA、响应式、无障碍基础 |
|
||||
| 第 3 轮 | 长期能力上线后 | 25+ 人 | 验证亲子、研学、无障碍和 3D 差异化 |
|
||||
|
||||
### 9.2 指标
|
||||
|
||||
| 指标 | P0 目标 | P1 目标 | P2/P3 目标 |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| 核心任务完成率 | 80% | 90% | 95% |
|
||||
| 找设施用时 | 45 秒内 | 30 秒内 | 20 秒内 |
|
||||
| 路线入口发现率 | 70% | 90% | 95% |
|
||||
| 音频播放成功率 | 90% | 95% | 98% |
|
||||
| SUS | 68+ | 75+ | 80+ |
|
||||
| 读屏核心按钮可识别率 | 80% | 95% | 98% |
|
||||
|
||||
## 10. 结论
|
||||
|
||||
当前项目最需要的不是再增加一个视觉模块,而是把已经存在的部件连接成真实任务:
|
||||
|
||||
1. 信息架构从“导览/讲解”改为“地图/讲解/路线/服务/我的”。
|
||||
2. 地图点位先确认,再由用户选择导航、详情、音频或收藏。
|
||||
3. 搜索、音频、路线、收藏都要统一状态和统一数据源。
|
||||
4. 先替换自然博物馆内容,再做用户测试。
|
||||
5. 先满足老年、儿童、首次访客的基础可用性,再上 AR、AI、客流、3D 深化。
|
||||
|
||||
建议下一步直接以“设施导航”和“展品讲解”两条竖切片启动 P0,实现后用 8-10 名用户做第一轮可用性测试。
|
||||
Reference in New Issue
Block a user