chore: initialize frontend miniapp repository
This commit is contained in:
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`,覆盖起点、目标、路径、楼层、当前步骤和完成态。
|
||||
|
||||
Reference in New Issue
Block a user