10 KiB
G01 无家谱状态合并实施计划
For agentic workers: REQUIRED SUB-SKILL: Use
superpowers:executing-plansto implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Goal: 删除独立的 G02 页面路由,让“无家谱”成为 G01 在 ?state=empty 下可复现、可验证的页面状态,同时保持 G01 默认已验收列表画面不变。
Architecture: pages/genealogy/g01-my-genealogies.vue 是“我的家谱”状态的唯一所有者:默认路由继续读取现有示例家谱数据,state=empty 只覆盖 hasGenealogies 的演示状态。G01 的空状态使用已生成的完整位图面板和现有按钮位图;G02 路由、专属实现、测试与已失效的专属交接材料删除。
Tech Stack: uni-app Vue 3、Vue Composition API、PowerShell 合约测试、Chrome DevTools 截图脚本、Node.js 运行时冒烟测试。
Global Constraints
- 不修改 G01 默认“已有家谱”状态的可见效果,也不修改已验收的 A01、A02、A04、A05、A06。
- 可审计路由/视觉结构改动必须先有最小失败契约测试;行为验证必须覆盖默认与空状态。
- 空状态完整面板、按钮边框和装饰面使用位图资产,不以 CSS 伪造。
- 不执行
git add、git commit、git push、git reset或 worktree 操作。 - 仅删除本项目此前为独立 G02 创建、且在迁移后无引用的文件;保留最终位图并改为 G01 所属名称。
Task 1: 建立 G01 空状态与路由收敛契约
Files:
- Create:
tests/g01-empty-state-contract.ps1 - Modify:
tests/full-page-visual-contract.ps1 - Test:
tests/g01-empty-state-contract.ps1
Interfaces:
-
Consumes:
pages.json路由注册、pages/genealogy/g01-my-genealogies.vue、static/assets/modules/genealogy/opaque/g01-empty-panel.png。 -
Produces: 证明 G01 是唯一入口、
state=empty是唯一空状态开关、并且 57 条已注册路由为新的页面契约的静态测试。 -
Step 1: 写失败的合约测试
在 tests/g01-empty-state-contract.ps1 断言:
Assert-True ($pages.paths -contains 'pages/genealogy/g01-my-genealogies') 'G01 route missing'
Assert-True (-not ($pages.paths -contains 'pages/genealogy/g02-empty-genealogies')) 'G02 route must be removed'
Assert-Match $g01Source 'forceEmptyState' 'G01 must own the explicit empty state'
Assert-Match $g01Source 'state.*empty' 'G01 must parse state=empty'
Assert-Match $g01Source 'g01-empty-panel\.png' 'G01 must use its final raster empty panel'
Assert-Match $g01Source 'empty-create-action' 'G01 must expose create action in empty state'
Assert-Match $g01Source 'empty-search-action' 'G01 must expose search action in empty state'
Assert-NoCssSurface $g01Source 'empty-panel'
Assert-NoCssSurface $g01Source 'empty-create-action'
Assert-NoCssSurface $g01Source 'empty-search-action'
并在 tests/full-page-visual-contract.ps1 中把期望页面数和完整清单收敛为 57 条,移除 G02。
- Step 2: 运行测试确认失败
Run: powershell -ExecutionPolicy Bypass -File tests/g01-empty-state-contract.ps1
Expected: FAIL,指出 G02 仍在路由表中,且 G01 尚未拥有 forceEmptyState 和最终 g01-empty-panel.png。
- Step 3: 记录失败原因
失败不是视觉问题:现有 pages.json 将 G02 作为第二个页面注册,且现有 G01 空分支没有 URL 状态开关。这证明需要迁移所有权,而不是额外保留一个“空状态页面”。
Task 2: 将空状态实现迁移到 G01
Files:
- Modify:
pages/genealogy/g01-my-genealogies.vue - Modify:
pages.json - Move:
static/assets/modules/genealogy/opaque/g02-empty-panel-v2.pngtostatic/assets/modules/genealogy/opaque/g01-empty-panel.png - Test:
tests/g01-empty-state-contract.ps1
Interfaces:
-
Consumes:
state=empty路由参数和现有 G01 的createGenealogy()、applyToJoin()。 -
Produces: 默认 G01 保持有家谱;
/pages/genealogy/g01-my-genealogies?state=empty展示带“创建我的家谱”和“搜索并申请加入”动作的空状态。 -
Step 1: 实现最小路由状态所有权
在 G01 里引入 forceEmptyState,在 onLoad 和 onShow 中同步当前页面 options.state(H5 时从 hash 查询串读取)。只用它定义:
const hasGenealogies = computed(() => !forceEmptyState.value && list.value.length > 0)
默认路由不携带 state=empty,因此继续走现有已验收列表分支。
- Step 2: 替换 G01 的旧 CSS 空状态表面
仅替换 v-else 空状态内容为:
<view v-else class="genealogy-empty-state">
<view class="empty-panel">
<image class="empty-panel-skin" src="/static/assets/modules/genealogy/opaque/g01-empty-panel.png" mode="aspectFill" />
<view class="empty-panel-content">
<!-- 印章、标题、说明、分隔纹、创建与搜索动作 -->
</view>
</view>
</view>
按钮皮肤继续引用现有 a01-primary-button.png 与 a01-secondary-button.png。使用 empty-create-action、empty-search-action 等新类名,不能改动现有列表中 .create-action 的已验收样式;这两个动作分别继续调用 createGenealogy() 与 applyToJoin()。
- Step 3: 移除独立 G02 入口
从 pages.json 删除 pages/genealogy/g02-empty-genealogies,删除 pages/genealogy/g02-empty-genealogies.vue,并将最终位图重命名为 g01-empty-panel.png。不保留 G02 兼容路由或重定向。
- Step 4: 运行静态契约确认通过
Run: powershell -ExecutionPolicy Bypass -File tests/g01-empty-state-contract.ps1
Expected: PASS,且 powershell -ExecutionPolicy Bypass -File tests/full-page-visual-contract.ps1 输出 57 条路由清单通过。
Task 3: 验证真实页面状态与动作
Files:
- Create:
tests/g01-empty-state-runtime-smoke.js - Test:
tests/g01-empty-state-runtime-smoke.js
Interfaces:
-
Consumes: Chrome DevTools
http://localhost:9222与开发服务器http://localhost:5173。 -
Produces: 默认 G01 列表、空状态、创建跳转和搜索跳转的运行时证据。
-
Step 1: 写运行时测试
测试在同一浏览器中依序验证:
await open('/#/pages/genealogy/g01-my-genealogies?state=empty')
await waitFor('.genealogy-empty-state .empty-create-action')
await click('.empty-create-action')
assertPath('/pages/genealogy/g03-create-genealogy')
await open('/#/pages/genealogy/g01-my-genealogies?state=empty')
await click('.empty-search-action')
assertPath('/pages/genealogy/g06-search-genealogies')
await open('/#/pages/genealogy/g01-my-genealogies')
assertExists('.current-slip')
assertMissing('.genealogy-empty-state')
- Step 2: 运行运行时测试确认通过
Run: node tests/g01-empty-state-runtime-smoke.js http://localhost:5173
Expected: PASS,证明两个空状态动作可用,且不带参数的 G01 仍为默认列表。
Task 4: 截图审视、清理与交接同步
Files:
- Modify:
docs/交接记录.md - Modify:
docs/规划.md - Modify:
docs/design/P00_页面结构与资产清单.md - Modify:
docs/design/2026-07-14_页面与状态合并审计.md - Delete:
tests/g02-empty-genealogies-contract.ps1 - Delete:
tests/g02-empty-genealogies-runtime-smoke.js - Delete:
docs/design/G02_无家谱空状态_设计记录.md - Delete:
docs/superpowers/specs/2026-07-14-g02-empty-genealogies-design.md - Delete:
docs/superpowers/plans/2026-07-14-g02-empty-genealogies.md - Delete:
docs/design/screens/runtime/2026-07-14/G02-before-360x800.png - Delete:
docs/design/screens/runtime/2026-07-14/G02-before-412x915.png - Delete:
docs/design/screens/runtime/2026-07-14/G02-after-360x800.png - Delete:
docs/design/screens/runtime/2026-07-14/G02-after-412x915.png - Delete:
docs/design/screens/runtime/2026-07-14/G01-G02-comparison-360x800.png - Create:
docs/design/screens/runtime/2026-07-14/G01-empty-after-360x800.png - Create:
docs/design/screens/runtime/2026-07-14/G01-empty-after-412x915.png - Create:
docs/design/screens/runtime/2026-07-14/G01-default-after-360x800.png - Create:
docs/design/screens/runtime/2026-07-14/G01-default-before-after-360x800.png
Interfaces:
-
Consumes: G01 的两种可达状态、迁移后的 57 路由契约、审计前的
route-audit/G01-360x800.png。 -
Produces: 同一视口的默认态前后对比、空状态截图、无过期 G02 入口和准确的交接记录。
-
Step 1: 截图并做同图对比审视
在 360×800 截默认 G01 和 state=empty,在 412×915 截空状态;把迁移前 route-audit/G01-360x800.png 与迁移后默认图并排为一张对比图。使用图像查看确认默认态没有发生可见改动,并确认空状态不出现透明黑角、裁切或 CSS 伪造表面。
- Step 2: 清除过期 G02 资料
在 rg 确认没有其余活跃引用后,删除仅属于独立 G02 的路由实现、测试、计划、设计记录和旧截图。保留路线审计里的总览截图,避免抹除先前审计证据。
- Step 3: 更新真实状态
文档统一为:已注册路由 57 条;G01 默认列表仍已验收;G01 state=empty 已实现和截图验证、等待用户对新增状态的审美确认;下一项合并仍是 G04→G03,尚未开始。
- Step 4: 完成回归验证
Run:
powershell -ExecutionPolicy Bypass -File tests/g01-empty-state-contract.ps1
node tests/g01-empty-state-runtime-smoke.js http://localhost:5173
powershell -ExecutionPolicy Bypass -File tests/full-page-visual-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/visual-asset-compliance.ps1
powershell -ExecutionPolicy Bypass -File tests/a01-landing-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/a02-login-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/a04-forgot-password-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/a05-register-contract.ps1
powershell -ExecutionPolicy Bypass -File tests/a06-auth-status-contract.ps1
git diff --check
Expected: 全部通过;git diff --check 允许 CRLF 警告但无空白错误。