Review changes batch 6 of 6

This commit is contained in:
2026-07-20 06:52:33 +08:00
parent db97d3da27
commit 5a31a75da0
160 changed files with 9206 additions and 572 deletions
@@ -0,0 +1,216 @@
# N01 消息中心基准页 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将 N01 重做为 N 系列消息中心视觉基准,并完成列表、已读、全部已读、加载、空、失败和审核跳转的 H5 审批状态。
**Architecture:** `pages/notification/n01-message-center.vue` 单独拥有本地演示数据、状态与交互;项目现有 `PageHeader``AppButton``AppLoading``AppToast``ModulePageBackground` 继续作为公共组件。N01 使用本模块独立的透明位图线框,不再引用家谱申请业务卡片。
**Tech Stack:** uni-app、Vue 3 `<script setup>`、SCSS、PowerShell 契约测试、Node CDP 运行时冒烟。
## Global Constraints
- 只处理 N01,不对接接口,不修改 N02 或其他模块页面。
- 不使用子代理或 worktree。
- 不执行 `git add``commit``push``reset``checkout`
- 保留当前全部已修改、未跟踪和忽略文件。
- 所有 Toast、Loading 和按钮使用项目自定义组件。
- 每次只向用户展示一个状态;用户全部明确“通过”后才标记 N01 为 `[x]`
- Android/HBuilderX 仍未验证,H5 截图只作为内部候选证据。
---
### Task 1: 锁定 N01 独立页面契约
**Files:**
- Create: `tests/n01-module-baseline-contract.ps1`
- Modify: `pages/notification/n01-message-center.vue`
**Interfaces:**
- Consumes: `AppButton``AppLoading``AppToast``ModulePageBackground``PageHeader`
- Produces: 可由 `?state=loading|empty|error` 复现的 N01 页面,以及 `.notice-state--list``.notice-state--loading``.notice-state--empty``.notice-state--error` DOM 状态类。
- [ ] **Step 1: 写入失败契约**
```powershell
$source = Get-Content 'pages/notification/n01-message-center.vue' -Raw -Encoding UTF8
$required = @(
'n01-notice-card.png', 'AppLoading', 'AppToast',
'notice-state--loading', 'notice-state--list',
'notice-state--empty', 'notice-state--error',
'未读', '已读', '全部已读', '前往入谱审核'
)
foreach ($token in $required) {
if (-not $source.Contains($token)) { throw "N01 missing contract token: $token" }
}
if ($source.Contains('application-status-card.png')) {
throw 'N01 must not reuse the genealogy application card'
}
Write-Output 'N01-MODULE-BASELINE-CONTRACT PASS'
```
- [ ] **Step 2: 运行契约并确认 RED**
Run: `powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/n01-module-baseline-contract.ps1`
Expected: FAIL,至少指出缺少 `n01-notice-card.png` 或仍引用 `application-status-card.png`
- [ ] **Step 3: 只添加后续实现所需状态类和资产引用,保持测试继续驱动页面实现**
将根节点状态类补齐为:
```vue
<view class="notice-page" :class="`notice-state--${noticeState}`">
```
资产引用统一为:
```vue
<image src="/static/assets/modules/notification/transparent/n01-notice-card.png" mode="scaleToFill" />
```
### Task 2: 制作 N01 透明消息线框资产
**Files:**
- Create: `static/assets/modules/notification/transparent/n01-notice-card.png`
- Preserve: `tmp/imagegen/` 下的生成源图与后处理证据。
**Interfaces:**
- Produces: 约 3:1 比例、四角透明、无文字无底色的古金色消息卡线框 PNG。
- [ ] **Step 1: 用内置 ImageGen 生成可抠色源图**
Prompt:
```text
Use case: ui-mockup
Asset type: scalable message-list card frame for a Chinese genealogy mobile app
Primary request: a restrained traditional Chinese archival card border made only from thin antique-gold linework
Style/medium: refined Song/Yuan inspired ornamental line art, visually consistent with the existing R01 transparent person card
Composition/framing: wide horizontal 3:1 frame, symmetrical corners, quiet center, generous inner text area
Scene/backdrop: perfectly flat solid #00ff00 chroma-key background inside and outside the border
Constraints: no fill panel, no paper texture, no white background, no red marks, no bell icon, no text, no badge, no shadow, no watermark; do not use #00ff00 in the ornament
```
- [ ] **Step 2: 使用 imagegen 技能自带抠色脚本输出透明 PNG**
Run:
```powershell
& 'C:\Users\Rain\AppData\Local\Python\bin\python.exe' 'C:\Users\Rain\.codex\skills\.system\imagegen\scripts\remove_chroma_key.py' --input 'tmp/imagegen/n01-notice-card-chroma.png' --out 'static/assets/modules/notification/transparent/n01-notice-card.png' --auto-key border --soft-matte --transparent-threshold 12 --opaque-threshold 220 --despill
```
- [ ] **Step 3: 检查资产透明度和边缘**
Run:
```powershell
& 'C:\Users\Rain\AppData\Local\Python\bin\python.exe' -c "from PIL import Image; p='static/assets/modules/notification/transparent/n01-notice-card.png'; im=Image.open(p); assert im.mode=='RGBA'; a=im.getchannel('A'); assert a.getpixel((0,0))==0; assert a.getbbox(); print('N01-ASSET-ALPHA PASS', im.size)"
```
Expected: `N01-ASSET-ALPHA PASS`
### Task 3: 实现 N01 列表与审批状态
**Files:**
- Modify: `pages/notification/n01-message-center.vue`
- Test: `tests/n01-module-baseline-contract.ps1`
**Interfaces:**
- `readNotice(item)`:把单条 `item.unread` 设为 `false`
- `markAllRead()`:把全部消息设为已读,并显示“已全部标记为已读”自定义 Toast。
- `restoreList()`:把错误态恢复为列表态。
- `toReview()`:保留 `/pages/genealogy/g10-application-review?genealogyId=...` 路由。
- [ ] **Step 1: 将模板整理为四个明确分支**
```vue
<AppLoading v-if="noticeState === 'loading'" text="正在整理消息" description="请稍候,正在同步家谱申请与家族提醒。" />
<view v-else-if="noticeState === 'list'" class="notice-list">...</view>
<view v-else class="notice-state-card">...</view>
```
列表卡片需使用以下文字层级:
```vue
<text class="notice-card__status" :class="{'is-unread': item.unread}">{{ item.unread ? '未读提醒' : '已读' }} · {{ item.time }}</text>
<text class="notice-card__title">{{ item.title }}</text>
<text class="notice-card__summary">{{ item.content }}</text>
```
- [ ] **Step 2: 统一空态与失败态操作**
```vue
<AppButton
block
:type="noticeState === 'error' ? 'secondary' : 'primary'"
:label="noticeState === 'error' ? '重新查看' : '前往入谱审核'"
@click="noticeState === 'error' ? restoreList() : toReview()"
/>
```
- [ ] **Step 3: 让卡片自适应内容并移除白底来源**
```scss
.notice-content { padding: 24rpx 28rpx 100rpx; }
.notice-list { display: flex; flex-direction: column; gap: 18rpx; }
.notice-card { position: relative; min-height: 220rpx; }
.notice-card__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.notice-card__copy { position: relative; z-index: 1; padding: 34rpx 44rpx; }
.notice-card__status { color: $ink-muted; }
.notice-card__status.is-unread { color: $brand-red; font-weight: 700; }
.notice-card__title { margin-top: 8rpx; color: $ink; font-family: STKaiti, KaiTi, serif; font-weight: 700; }
.notice-review-action { margin: 30rpx auto 0; }
```
- [ ] **Step 4: 运行聚焦契约并确认 GREEN**
Run: `powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/n01-module-baseline-contract.ps1`
Expected: `N01-MODULE-BASELINE-CONTRACT PASS`
### Task 4: 运行时验证并进入逐状态审批
**Files:**
- Create: `docs/design/screens/runtime/2026-07-19/n01-review/*.png`
- Modify only after all explicit approvals: `docs/验收规划.md`
**Interfaces:**
- Consumes: 单个现有 Chrome 项目标签页和调试端口 9222。
- Produces: 412×915 的逐状态审批画面,以及四档响应式内部证据。
- [ ] **Step 1: 运行静态和运行时检查**
Run:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/n01-module-baseline-contract.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tests/root-pages-visual-contract.ps1
node tests/root-pages-runtime-smoke.js
node tests/module-series-responsive-runtime-smoke.js
git diff --check
```
Expected: 所有测试输出 `PASS``git diff --check` 退出码为 0,允许已有行尾提示。
- [ ] **Step 2: 复用同一标签页显示 412×915 正常列表态**
Run:
```powershell
node scripts/capture-chrome-page.js 'http://localhost:5173/#/pages/notification/n01-message-center' '.notice-state--list' 'docs/design/screens/runtime/2026-07-19/n01-review/01-list-412x915.png' 412 915
```
Inspect: 打开保存的截图,确认没有白底块、裁切、错误页面或半加载内容,再等待用户审批。
- [ ] **Step 3: 按顺序展示其余状态**
顺序:单条已读 → 全部已读 Toast → 加载 → 空 → 失败 → 审核跳转。每次只显示一个状态并等待用户确认。
- [ ] **Step 4: 内部检查四档尺寸**
尺寸:`320×568``360×640``360×800``412×915`。发现问题只返工 N01;未发现问题不逐档打断用户。
- [ ] **Step 5: 所有状态明确通过后更新审批记录**
仅把 `docs/验收规划.md` 的 N01 行从 `[~]` 改为 `[x]`,随后重新运行 Task 4 Step 1 的全部验证。