完成40%

This commit is contained in:
rain
2026-07-14 17:36:39 +08:00
parent 1015e60ff7
commit 8c98936da5
151 changed files with 5132 additions and 351 deletions
@@ -0,0 +1,198 @@
# G01 无家谱状态合并实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:executing-plans` to 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 条已注册路由为新的页面契约的静态测试。
- [x] **Step 1: 写失败的合约测试**
`tests/g01-empty-state-contract.ps1` 断言:
```powershell
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。
- [x] **Step 2: 运行测试确认失败**
Run: `powershell -ExecutionPolicy Bypass -File tests/g01-empty-state-contract.ps1`
Expected: FAIL,指出 G02 仍在路由表中,且 G01 尚未拥有 `forceEmptyState` 和最终 `g01-empty-panel.png`
- [x] **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.png` to `static/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` 展示带“创建我的家谱”和“搜索并申请加入”动作的空状态。
- [x] **Step 1: 实现最小路由状态所有权**
在 G01 里引入 `forceEmptyState`,在 `onLoad``onShow` 中同步当前页面 `options.state`(H5 时从 hash 查询串读取)。只用它定义:
```js
const hasGenealogies = computed(() => !forceEmptyState.value && list.value.length > 0)
```
默认路由不携带 `state=empty`,因此继续走现有已验收列表分支。
- [x] **Step 2: 替换 G01 的旧 CSS 空状态表面**
仅替换 `v-else` 空状态内容为:
```vue
<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()`
- [x] **Step 3: 移除独立 G02 入口**
`pages.json` 删除 `pages/genealogy/g02-empty-genealogies`,删除 `pages/genealogy/g02-empty-genealogies.vue`,并将最终位图重命名为 `g01-empty-panel.png`。不保留 G02 兼容路由或重定向。
- [x] **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 列表、空状态、创建跳转和搜索跳转的运行时证据。
- [x] **Step 1: 写运行时测试**
测试在同一浏览器中依序验证:
```js
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')
```
- [x] **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 入口和准确的交接记录。
- [x] **Step 1: 截图并做同图对比审视**
在 360×800 截默认 G01 和 `state=empty`,在 412×915 截空状态;把迁移前 `route-audit/G01-360x800.png` 与迁移后默认图并排为一张对比图。使用图像查看确认默认态没有发生可见改动,并确认空状态不出现透明黑角、裁切或 CSS 伪造表面。
- [x] **Step 2: 清除过期 G02 资料**
`rg` 确认没有其余活跃引用后,删除仅属于独立 G02 的路由实现、测试、计划、设计记录和旧截图。保留路线审计里的总览截图,避免抹除先前审计证据。
- [x] **Step 3: 更新真实状态**
文档统一为:已注册路由 57 条;G01 默认列表仍已验收;G01 `state=empty` 已实现和截图验证、等待用户对新增状态的审美确认;下一项合并仍是 G04→G03,尚未开始。
- [x] **Step 4: 完成回归验证**
Run:
```powershell
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 警告但无空白错误。