Files
frontend-miniapp/docs/QA/h5-business-flow-audit-2026-06-09.md
lyf 8fed715235
Some checks failed
CI / verify (push) Has been cancelled
chore: sync latest project updates
2026-07-03 14:42:38 +08:00

196 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# H5/小程序业务流程测试报告
日期2026-06-09
项目:深圳自然博物馆智能导览应用 - frontend-miniapp
审计范围:导览、讲解、搜索、详情、设施导航、路线规划闭环
## 结论
Production audit48/100Blocked。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 sheetsheet 操作分别进入详情、路线、音频。 |
| 导览首页 -> 馆内 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`