Files
jiapuapp/docs/superpowers/plans/2026-07-19-n01-message-center-baseline.md
T
2026-07-20 06:52:33 +08:00

217 lines
9.0 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.
# 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 的全部验证。