sync: d8d-dev 新增 Phase VD-3 视觉差异自动修复 + VISUAL-FIX 修复类别 #12
@@ -51,6 +51,11 @@
|
||||
| 20 | API route handler 无 try-catch 包裹,导致未处理异常直接返回原始 500 且无日志 | Bug(健壮性) | AUTO-FIX | Admin 提现审批 PUT 返回 500 但状态仍更新(异常被吞) |
|
||||
| 21 | uni-app 页面使用 `onMounted` 获取数据,但该页面是 `uni.navigateBack()` 的返回目标,导致回退时数据不刷新 | Bug(数据陈旧) | AUTO-FIX | 提现后返回收益页余额未刷新(onMounted 不再触发) |
|
||||
| **99** | **以上都不匹配的任何 FAIL** | **默认: Bug** | **AUTO-FIX** | **兜底规则,确保无遗漏** |
|
||||
| **V1** | 页面主题/配色与原型不一致(深色→浅色、主色调偏差) | 视觉差异 | VISUAL-FIX | 原型深色主题但实际浅色;按钮颜色不一致 |
|
||||
| **V2** | 页面布局结构与原型不同(顶部导航↔侧边栏、网格↔列表、卡片↔表格) | 视觉差异 | VISUAL-FIX | 原型顶部水平导航但实际左侧边栏;原型卡片网格但实际列表 |
|
||||
| **V3** | 品牌标识与原型不同(Logo 图标、标题文字、副标题) | 视觉差异 | VISUAL-FIX | 原型闪电图标+"VividSpark"但实际 "V" 字母+"Welcome back" |
|
||||
| **V4** | 原型存在的 UI 组件在实际页面中缺失(Remember me、FAQ、过滤器、标签页等) | 视觉差异 | VISUAL-FIX | 原型有 FAQ 区域但实际缺失;原型有 Remember me 但实际无 |
|
||||
| **V5** | 按钮/输入框/卡片样式与原型不一致(padding、圆角、边框、字号等) | 视觉差异 | VISUAL-FIX | 原型圆角 16px 但实际 8px;原型按钮 padding 16/32 但实际 12/24 |
|
||||
|
||||
### "可接受"严格限定(⛔ 仅以下 2 种,其余一律必须修复)
|
||||
|
||||
@@ -557,5 +562,6 @@ GATE-CHECK:
|
||||
| `validation-mode.md` | AUTO-FIX/AUTO-IMPLEMENT 分支 → `Read fully and follow: ./auto-fix-engine.md` |
|
||||
| `phase-04-test.md` | Phase 4.5 AUTO-FIX 循环 → 引用第 4 节修复流程 |
|
||||
| `phase-05-review.md` | 质量关卡 FAIL 处理 → 引用第 2 节分类标准 |
|
||||
| `visual-diff-mode.md` | Phase VD-3 逐页修复 → VISUAL-FIX (V1-V5) 分类引用 |
|
||||
| `e2e-testing.md` | 步骤 9.5 判定规则 → 引用第 2 节分类标准 |
|
||||
| `iron-laws.md` | 检测即阻断规则 → 引用第 2 节分类标准 + 第 5 节 GATE-CHECK |
|
||||
|
||||
643
.claude/skills/d8d-dev/visual-diff-mode.md
Normal file
643
.claude/skills/d8d-dev/visual-diff-mode.md
Normal file
@@ -0,0 +1,643 @@
|
||||
# 原型对比验证模式(Visual Diff Mode)
|
||||
|
||||
> **定位**:在回归验证和旅程验证之后,将实际页面实现与原型 HTML 页面做逐页视觉对比,发现布局偏差、组件遗漏、交互方式差异等视觉问题。
|
||||
>
|
||||
> **与其他模式的关系**:
|
||||
> - 回归验证模式 → 检查功能点存在且正确(类比单元测试)
|
||||
> - 旅程验证模式 → 检查用户流程完整性(类比 E2E 测试)
|
||||
> - **原型对比验证模式** → 检查视觉还原度(类比视觉回归测试)
|
||||
>
|
||||
> **触发时机**:
|
||||
> - 旅程验证模式完成后建议进入
|
||||
> - 手动触发:`/d8d-dev visual-diff` 或 `/d8d-dev visual-diff epic-3`
|
||||
> - 流水线自动触发:每个 Epic 完成后(可配置)
|
||||
|
||||
---
|
||||
|
||||
## 前置条件
|
||||
|
||||
```
|
||||
检查清单(任一不满足 → 报错并终止):
|
||||
├── prototype/ 目录存在且含 pages/ 子目录
|
||||
├── prototype/server.js 存在(原型预览服务)
|
||||
├── pipeline-context.md 存在(含实际应用 URL 和凭据)
|
||||
├── pm2 服务运行中(实际应用可访问)
|
||||
└── 至少有一个 Epic 的 Story 已 verified
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心流程
|
||||
|
||||
```
|
||||
Phase VD-0: 准备
|
||||
├── 发现原型页面 → 建立页面清单
|
||||
├── 读取 pipeline-context.md → 获取实际应用 URL
|
||||
├── 启动原型服务 → node prototype/server.js (port 8080)
|
||||
└── 构建页面映射表(原型页面 ↔ 实际路由)
|
||||
|
||||
Phase VD-1: 逐页对比循环
|
||||
对每个映射页面:
|
||||
├── A. 截取原型页面截图
|
||||
├── B. 截取实际页面截图
|
||||
├── C. UI 差异对比(三层对比法)
|
||||
└── D. 差异分级 + 记录
|
||||
|
||||
Phase VD-2: 汇总报告
|
||||
├── 生成 visual-diff-report.md
|
||||
└── 输出差异统计和修复建议
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase VD-0: 准备
|
||||
|
||||
### 0.1 发现原型页面
|
||||
|
||||
```bash
|
||||
# 列出所有原型页面
|
||||
find prototype/pages -name "*.html" | sort
|
||||
```
|
||||
|
||||
从输出中提取页面清单,分类为 frontend 和 admin。
|
||||
|
||||
### 0.2 读取实际应用信息
|
||||
|
||||
读取 `_bmad-output/implementation-artifacts/pipeline-context.md` 获取:
|
||||
- 实际应用 URL(API_URL, ADMIN_URL)
|
||||
- 认证凭据
|
||||
- 已实现的路由
|
||||
|
||||
### 0.3 启动原型服务
|
||||
|
||||
```bash
|
||||
# 检查 8080 端口是否已被占用
|
||||
lsof -i :8080 || true
|
||||
|
||||
# 启动原型服务(后台运行)
|
||||
cd prototype && node server.js &
|
||||
# 验证服务可用
|
||||
curl -sf --max-time 5 http://localhost:8080/ && echo "OK"
|
||||
```
|
||||
|
||||
如果 8080 端口被占用,使用其他端口并记录。
|
||||
|
||||
### 0.4 构建页面映射表
|
||||
|
||||
**自动映射规则**:
|
||||
|
||||
```
|
||||
对每个原型页面 prototype/pages/{group}/{name}.html:
|
||||
1. 提取 group (app/admin) 和 name
|
||||
2. 在实际路由中查找匹配:
|
||||
- name=login → /login 或 /admin/login
|
||||
- name=dashboard → / 或 /dashboard
|
||||
- name=register → /register
|
||||
- 其他 → /{name} 或 /admin/{name}
|
||||
3. 验证实际路由可访问(curl 检查非 404)
|
||||
4. 不可访问的页面标记为 skipped
|
||||
```
|
||||
|
||||
**映射输出格式**(记录到 pipeline-state.yaml):
|
||||
|
||||
```yaml
|
||||
visual_diff_mapping:
|
||||
- prototype: "pages/app/login.html"
|
||||
actual_route: "/login"
|
||||
group: "frontend"
|
||||
status: "active" # active / skipped / error
|
||||
|
||||
- prototype: "pages/app/dashboard.html"
|
||||
actual_route: "/"
|
||||
group: "frontend"
|
||||
status: "active"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase VD-1: 逐页对比循环
|
||||
|
||||
对映射表中每个 `status: active` 的页面执行以下流程。
|
||||
|
||||
### 1.0 创建截图目录
|
||||
|
||||
```bash
|
||||
mkdir -p tests/e2e/screenshots/visual-diff
|
||||
```
|
||||
|
||||
### 1.A 截取原型页面截图
|
||||
|
||||
```
|
||||
1. browser_navigate → http://localhost:8080/pages/{group}/{name}.html
|
||||
2. browser_resize → 1440x900 (桌面端) 或 375x812 (移动端)
|
||||
3. browser_wait_for → time=2 (等待页面渲染)
|
||||
4. browser_take_screenshot(fullPage=false)
|
||||
→ tests/e2e/screenshots/visual-diff/{name}-prototype-viewport.png
|
||||
5. browser_take_screenshot(fullPage=true)
|
||||
→ tests/e2e/screenshots/visual-diff/{name}-prototype-full.png
|
||||
```
|
||||
|
||||
### 1.B 截取实际页面截图
|
||||
|
||||
```
|
||||
1. browser_navigate → {实际 URL}{route}
|
||||
2. browser_resize → 同上视口(必须与原型一致)
|
||||
3. 处理认证:
|
||||
- 如果页面需要登录 → 从 pipeline-context.md 读取凭据
|
||||
- browser_navigate → 登录页 → 填写凭据 → 提交 → 等待跳转
|
||||
- 如果已登录(直接访问无跳转)→ 继续
|
||||
4. browser_wait_for → time=3 (等待数据加载)
|
||||
5. browser_take_screenshot(fullPage=false)
|
||||
→ tests/e2e/screenshots/visual-diff/{name}-actual-viewport.png
|
||||
6. browser_take_screenshot(fullPage=true)
|
||||
→ tests/e2e/screenshots/visual-diff/{name}-actual-full.png
|
||||
```
|
||||
|
||||
### 1.C 三层对比法
|
||||
|
||||
**判断页面长度**:
|
||||
|
||||
```javascript
|
||||
// browser_evaluate
|
||||
() => {
|
||||
return {
|
||||
pageHeight: document.documentElement.scrollHeight,
|
||||
viewportHeight: window.innerHeight,
|
||||
isLongPage: document.documentElement.scrollHeight > window.innerHeight * 1.5
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**如果 isLongPage === false(短页面)**:
|
||||
|
||||
```
|
||||
直接对比首屏:
|
||||
ui_diff_check(
|
||||
expected_image_source = "{name}-prototype-viewport.png",
|
||||
actual_image_source = "{name}-actual-viewport.png",
|
||||
prompt = "对比这两张截图:第一张是设计原型,第二张是实际实现。列出所有视觉差异,包括布局结构、组件排列、颜色、间距、字体、图标等。按严重程度排序。"
|
||||
)
|
||||
```
|
||||
|
||||
**如果 isLongPage === true(长页面)**:
|
||||
|
||||
执行三层对比法:
|
||||
|
||||
#### 层 1:首屏对比(viewport 截图)
|
||||
|
||||
```
|
||||
ui_diff_check(
|
||||
expected_image_source = "{name}-prototype-viewport.png",
|
||||
actual_image_source = "{name}-actual-viewport.png",
|
||||
prompt = "对比这两张首屏截图:第一张是设计原型,第二张是实际实现。首屏是最重要的视觉区域。列出所有差异,按严重程度排序。"
|
||||
)
|
||||
```
|
||||
|
||||
#### 层 2:全页面对比(fullPage 截图)
|
||||
|
||||
```
|
||||
ui_diff_check(
|
||||
expected_image_source = "{name}-prototype-full.png",
|
||||
actual_image_source = "{name}-actual-full.png",
|
||||
prompt = "对比这两张完整页面截图:第一张是设计原型,第二张是实际实现。注意页面可能很长,重点关注各区域的布局和组件差异。"
|
||||
)
|
||||
```
|
||||
|
||||
#### 层 3:差异区域精确定位(仅当层 1 或层 2 发现差异时执行)
|
||||
|
||||
```
|
||||
对原型和实际页面分别执行分段截图:
|
||||
1. 计算分段数量 = ceil(pageHeight / viewportHeight)
|
||||
2. 对每一段:
|
||||
a. browser_evaluate → window.scrollTo(0, segmentIndex * viewportHeight * 0.8)
|
||||
// 20% 重叠避免切割区域遗漏
|
||||
b. browser_wait_for → time=1
|
||||
c. browser_take_screenshot(fullPage=false)
|
||||
→ {name}-prototype-section-{N}.png
|
||||
→ {name}-actual-section-{N}.png
|
||||
3. 逐段 ui_diff_check 对比
|
||||
```
|
||||
|
||||
**原型页面也需要 scroll**:原型是静态 HTML,需要同样执行 scroll + 截图。
|
||||
|
||||
### 1.D 差异分级
|
||||
|
||||
每页对比完成后,将差异分级:
|
||||
|
||||
| 级别 | 标准 | 示例 |
|
||||
|------|------|------|
|
||||
| 🔴 严重 | 布局结构不同、关键组件缺失、交互方式不同 | 原型有两列布局实际一列、缺少侧边栏、用标签页代替下拉菜单 |
|
||||
| 🟡 中等 | 颜色/间距偏差、图标不一致、文字样式差异、非核心组件缺失 | 卡片圆角不一致、间距差 8px+、图标风格不同 |
|
||||
| 🟢 轻微 | 微小像素差异、动画效果差异、可接受的响应式适配差异 | 1-2px 偏移、hover 效果不同、字体渲染差异 |
|
||||
|
||||
### 1.E 即时写入 Context(关键!)
|
||||
|
||||
**每完成一个页面的 ui_diff_check 后,必须立即将结果写入 `pipeline-context.md`,防止上下文压缩导致结果丢失。**
|
||||
|
||||
```
|
||||
流程:
|
||||
1. ui_diff_check 返回差异结果
|
||||
2. 立即编辑 pipeline-context.md,在 "原型对比验证结果" 部分更新该页面的差异摘要
|
||||
3. 格式:#### N/11 {页面名} — 严重程度 🔴/🟡/🟢/✅
|
||||
4. 列出关键差异(精简为 3-7 条)
|
||||
5. 继续下一个页面
|
||||
```
|
||||
|
||||
**为什么必须即时写入?**
|
||||
- 原型对比流程涉及 11 个页面的截图+对比,对话上下文可能在中途被压缩
|
||||
- 如果不在每页完成后即时持久化,已完成的对比结果会丢失
|
||||
- `pipeline-context.md` 是上下文压缩后的恢复锚点
|
||||
|
||||
**context 中的记录格式示例**:
|
||||
|
||||
```markdown
|
||||
## 原型对比验证结果 (Visual Diff)
|
||||
|
||||
### 全局问题(所有页面共通)
|
||||
- 🔴 问题描述...
|
||||
|
||||
### 逐页结果
|
||||
|
||||
#### 1/11 Login — 严重 🔴
|
||||
- 原型: pages/app/login.html → 实际: /login
|
||||
- 🔴 差异1
|
||||
- 🔴 差异2
|
||||
- 🟡 差异3
|
||||
|
||||
#### 2/11 Register — 严重 🔴
|
||||
- ...
|
||||
```
|
||||
|
||||
**差异记录格式(pipeline-state.yaml)**:
|
||||
|
||||
```yaml
|
||||
visual_diff_results:
|
||||
dashboard:
|
||||
prototype_page: "pages/app/dashboard.html"
|
||||
actual_route: "/"
|
||||
severity: moderate # critical / moderate / minor / match
|
||||
viewport_compared: true
|
||||
fullpage_compared: true
|
||||
sections_compared: 3
|
||||
differences:
|
||||
- severity: critical
|
||||
location: "首屏左侧"
|
||||
description: "侧边栏缺失,原型有固定侧边栏导航"
|
||||
section: 1
|
||||
- severity: moderate
|
||||
location: "首屏中部"
|
||||
description: "上传区域卡片圆角:原型 16px,实际 8px"
|
||||
section: 1
|
||||
- severity: minor
|
||||
location: "第2段"
|
||||
description: "卡片间距略宽:原型 16px,实际 24px"
|
||||
section: 2
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase VD-2: 汇总报告
|
||||
|
||||
### 2.1 生成报告
|
||||
|
||||
生成 `tests/e2e/screenshots/visual-diff/visual-diff-report.md`:
|
||||
|
||||
```markdown
|
||||
# Visual Diff Report
|
||||
|
||||
生成时间: {timestamp}
|
||||
对比页面数: {total_pages}
|
||||
|
||||
## Summary
|
||||
|
||||
| 级别 | 数量 |
|
||||
|------|------|
|
||||
| 🔴 严重 | {critical_count} |
|
||||
| 🟡 中等 | {moderate_count} |
|
||||
| 🟢 轻微 | {minor_count} |
|
||||
| ✅ 匹配 | {match_count} |
|
||||
|
||||
## 严重差异(需修复)
|
||||
|
||||
### 🔴 {page_name}
|
||||
- 原型截图: `visual-diff/{name}-prototype-viewport.png`
|
||||
- 实际截图: `visual-diff/{name}-actual-viewport.png`
|
||||
- 差异:
|
||||
1. {具体差异描述}
|
||||
2. {具体差异描述}
|
||||
- 修复建议: {auto-fix 建议}
|
||||
|
||||
## 中等差异(建议修复)
|
||||
|
||||
### 🟡 {page_name}
|
||||
...
|
||||
|
||||
## 轻微差异(可接受)
|
||||
|
||||
### 🟢 {page_name}
|
||||
...
|
||||
|
||||
## 完全匹配
|
||||
|
||||
### ✅ {page_name}
|
||||
```
|
||||
|
||||
### 2.2 更新 pipeline-state.yaml
|
||||
|
||||
```yaml
|
||||
visual_diff:
|
||||
status: completed # completed / partial / failed
|
||||
total_pages: 11
|
||||
compared_pages: 10
|
||||
skipped_pages: 1
|
||||
critical_count: 0
|
||||
moderate_count: 3
|
||||
minor_count: 5
|
||||
match_count: 2
|
||||
report_path: "tests/e2e/screenshots/visual-diff/visual-diff-report.md"
|
||||
timestamp: "2026-04-08T10:30:00Z"
|
||||
```
|
||||
|
||||
### 2.3 输出结论
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════
|
||||
Visual Diff Report 完成
|
||||
═══════════════════════════════════════════
|
||||
总页面: 10 对比, 1 跳过
|
||||
🔴 严重: 0 → 无需修复
|
||||
🟡 中等: 3 → 建议修复
|
||||
🟢 轻微: 5 → 可接受
|
||||
✅ 匹配: 2
|
||||
|
||||
报告: tests/e2e/screenshots/visual-diff/visual-diff-report.md
|
||||
═══════════════════════════════════════════
|
||||
```
|
||||
|
||||
### 2.4 修复决策
|
||||
|
||||
```
|
||||
VD-2 报告完成后:
|
||||
├── 🔴 严重差异 > 0 → 自动进入 Phase VD-3 全量修复
|
||||
└── ✅ 无严重差异 → 流程结束
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase VD-3: 全量自动修复
|
||||
|
||||
> **定位**:在 Phase VD-2 发现严重差异后,自动修复所有视觉差异,使实际页面还原原型设计。以原型 HTML 为 Source of Truth,重写 UI 层。
|
||||
>
|
||||
> **核心原则**:
|
||||
> - 先全局后逐页:全局修复(主题、导航、品牌)先做,避免逐页修复被全局问题干扰
|
||||
> - 保留后端逻辑:只改 UI 层(React 组件 + CSS),不动 API 路由和数据库
|
||||
> - 以原型为基准:直接从原型 HTML 提取设计 token 和组件结构
|
||||
> - 修复后必须验证:重新截图 + ui_diff_check 确认还原度
|
||||
> - 全程零确认、全自动
|
||||
|
||||
### 3.1 全局修复(先修复影响所有页面的共性问题)
|
||||
|
||||
从 pipeline-context.md 的"原型对比验证结果"中提取全局问题,按优先级修复:
|
||||
|
||||
```
|
||||
全局问题按优先级:
|
||||
P0: 主题系统(深色/浅色主题 — 影响 app 组页面)
|
||||
P0: 品牌标识(图标 + 标题 — 影响所有页面)
|
||||
P1: 管理后台导航结构(顶部水平导航 — 影响 admin 组页面)
|
||||
P1: 通用组件样式(按钮 padding/圆角、输入框样式)
|
||||
```
|
||||
|
||||
#### 3.1.1 主题修复
|
||||
|
||||
```
|
||||
1. 读取原型 HTML(如 pages/app/login.html),提取:
|
||||
- 页面背景色(如 #000000)
|
||||
- 卡片/容器背景色(如 #1E1E1E)
|
||||
- 文字颜色(如 #FFFFFF)
|
||||
- 主色调(如 #FF8400)
|
||||
- 边框颜色(如 #333333)
|
||||
|
||||
2. 修改全局样式文件:
|
||||
- globals.css / tailwind.config.ts
|
||||
- 定义 CSS 变量或 Tailwind theme extend
|
||||
|
||||
3. 修改布局组件:
|
||||
- 背景色 class 对齐
|
||||
- 确保所有 app 组页面使用新主题
|
||||
```
|
||||
|
||||
#### 3.1.2 品牌标识修复
|
||||
|
||||
```
|
||||
1. 从原型提取品牌元素:
|
||||
- 图标(如 FontAwesome fa-bolt 闪电图标)
|
||||
- 标题文字(如 "VividSpark")
|
||||
- 副标题文字(如页面特有描述)
|
||||
|
||||
2. 定位品牌组件文件,替换:
|
||||
- Logo 组件(图标 + 文字)
|
||||
- 页面标题区域
|
||||
```
|
||||
|
||||
#### 3.1.3 管理后台导航修复
|
||||
|
||||
```
|
||||
1. 从原型 admin 页面提取导航结构:
|
||||
- 位置:顶部水平导航栏
|
||||
- 菜单项:用户管理、内容审核、平台配置、数据分析、系统设置
|
||||
- 右侧:管理员邮箱 + 登出按钮
|
||||
|
||||
2. 修改 admin 布局组件:
|
||||
- 从左侧边栏 → 顶部水平导航
|
||||
- 调整所有 admin 页面布局适配
|
||||
```
|
||||
|
||||
#### 3.1.4 全局修复完成后即时写入 context
|
||||
|
||||
```
|
||||
编辑 pipeline-context.md,在"原型对比验证结果"下添加:
|
||||
|
||||
### 全局修复记录
|
||||
- ✅/⚠️ 主题修复:{结果摘要}
|
||||
- ✅/⚠️ 品牌标识修复:{结果摘要}
|
||||
- ✅/⚠️ 导航结构修复:{结果摘要}
|
||||
```
|
||||
|
||||
### 3.2 逐页修复循环
|
||||
|
||||
对 Phase VD-2 报告中每个有差异的页面,执行以下流程:
|
||||
|
||||
```
|
||||
对每个有差异的页面(按严重程度排序,🔴 优先):
|
||||
├── Step A: 解析原型 HTML
|
||||
├── Step B: 定位并重写实际源码
|
||||
├── Step C: 重新截图验证
|
||||
└── 即时写入 context(每页完成后)
|
||||
```
|
||||
|
||||
#### Step A: 解析原型 HTML
|
||||
|
||||
```
|
||||
读取 prototype/pages/{group}/{name}.html,提取:
|
||||
|
||||
1. 设计 Token:
|
||||
- 颜色:背景色、卡片色、文字色、主色调、边框色
|
||||
- 字体:font-family、font-size、font-weight
|
||||
- 间距:padding、margin、gap
|
||||
- 圆角:border-radius
|
||||
- 阴影:box-shadow
|
||||
|
||||
2. 组件列表:
|
||||
- 表单字段(类型、标签、占位符、图标)
|
||||
- 按钮(文字、颜色、大小、圆角)
|
||||
- 卡片(布局、内容结构)
|
||||
- 表格(列定义、操作按钮)
|
||||
- 特殊组件(标签页、进度条、图表区域)
|
||||
|
||||
3. 文案:
|
||||
- 页面标题、副标题
|
||||
- 占位符文字
|
||||
- 按钮文字
|
||||
- 链接文字
|
||||
|
||||
4. 布局结构:
|
||||
- grid/flex 布局
|
||||
- 列数/行数
|
||||
- 组件排列顺序
|
||||
```
|
||||
|
||||
#### Step B: 定位并重写实际源码
|
||||
|
||||
```
|
||||
1. 路由 → 源码文件映射:
|
||||
/login → src/app/(auth)/login/page.tsx
|
||||
/register → src/app/(auth)/register/page.tsx
|
||||
/dashboard → src/app/(creator)/dashboard/page.tsx(或 src/app/page.tsx)
|
||||
/publish → src/app/(creator)/publish/page.tsx
|
||||
/pricing → src/app/(creator)/pricing/page.tsx
|
||||
/settings → src/app/(creator)/settings/page.tsx
|
||||
/admin/login → src/app/admin/login/page.tsx
|
||||
/admin/users → src/app/admin/users/page.tsx
|
||||
/admin/moderation → src/app/admin/moderation/page.tsx
|
||||
/admin/analytics → src/app/admin/analytics/page.tsx
|
||||
/admin/platforms → src/app/admin/platforms/page.tsx
|
||||
/admin/settings → src/app/admin/settings/page.tsx
|
||||
|
||||
通用组件:
|
||||
侧边栏 → src/components/layout/sidebar.tsx
|
||||
头部导航 → src/components/layout/header.tsx(或 admin-header.tsx)
|
||||
|
||||
2. 以原型为 Source of Truth,对齐:
|
||||
a. 组件结构:补全缺失组件(如 Remember me、FAQ、标签页、过滤器)
|
||||
b. 布局结构:对齐网格列数、卡片 vs 列表等
|
||||
c. 样式 class:Tailwind class 对齐原型视觉
|
||||
d. 文案:品牌标题、占位符、按钮文字
|
||||
e. 数据展示:如原型用图表,引入 chart 库并实现
|
||||
|
||||
3. 关键约束:
|
||||
- 保留后端逻辑不变(API 调用、数据处理)
|
||||
- 只修改 JSX 结构和 Tailwind class
|
||||
- 新增的 UI 组件使用项目已有的设计系统组件
|
||||
```
|
||||
|
||||
#### Step C: 重新截图验证
|
||||
|
||||
```
|
||||
1. 重跑 Phase VD-1 的截图流程:
|
||||
a. 截取修复后的实际页面截图
|
||||
→ tests/e2e/screenshots/visual-diff/{name}-fixed-viewport.png
|
||||
b. ui_diff_check 对比(修复后 vs 原型)
|
||||
|
||||
2. 结果判定:
|
||||
- PASS(无 🔴/🟡)→ 标记 ✅ fixed
|
||||
- FAIL → 调整修复策略,重试(最多 2 次)
|
||||
- 仍 FAIL → 标记 ⚠️ needs-manual-fix,记录原因
|
||||
|
||||
3. 每页修复完成后即时写入 pipeline-context.md:
|
||||
#### N/11 {页面名} — ✅ fixed / ⚠️ needs-manual-fix
|
||||
- 修复内容: {具体修复了什么}
|
||||
- 验证结果: {ui_diff_check 摘要}
|
||||
```
|
||||
|
||||
### 3.3 修复后二次对比(全量验证)
|
||||
|
||||
```
|
||||
全局 + 逐页修复完成后:
|
||||
1. 对所有 11 页重跑 Phase VD-1 截图 + ui_diff_check
|
||||
2. 生成修复前后对比:
|
||||
- 修复前: visual-diff/{name}-actual-viewport.png
|
||||
- 修复后: visual-diff/{name}-fixed-viewport.png
|
||||
3. 更新 visual-diff-report.md(添加修复结果列)
|
||||
4. 更新 pipeline-state.yaml visual_diff 部分
|
||||
```
|
||||
|
||||
### 3.4 最终报告
|
||||
|
||||
```yaml
|
||||
visual_diff:
|
||||
status: completed # completed / partial / failed
|
||||
total_pages: 11
|
||||
compared_pages: 11
|
||||
fixed_pages: 8 # 新增
|
||||
manual_fix_needed: 3 # 新增
|
||||
critical_count: 0 # 修复后的数值
|
||||
moderate_count: 1
|
||||
minor_count: 5
|
||||
match_count: 5
|
||||
report_path: "tests/e2e/screenshots/visual-diff/visual-diff-report.md"
|
||||
fix_report_path: "tests/e2e/screenshots/visual-diff/visual-diff-fix-report.md"
|
||||
timestamp: "2026-04-08T12:00:00Z"
|
||||
```
|
||||
|
||||
输出结论:
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════
|
||||
Visual Diff Report + 自动修复 完成
|
||||
═══════════════════════════════════════════════
|
||||
总页面: 11 对比, 0 跳过
|
||||
✅ 已修复: 8
|
||||
⚠️ 需手动修复: 3(见报告)
|
||||
|
||||
修复前: 🔴 11 🟡 0 🟢 0 ✅ 0
|
||||
修复后: 🔴 0 🟡 1 🟢 5 ✅ 5
|
||||
|
||||
报告: tests/e2e/screenshots/visual-diff/visual-diff-report.md
|
||||
修复报告: tests/e2e/screenshots/visual-diff/visual-diff-fix-report.md
|
||||
═══════════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 视口配置
|
||||
|
||||
| 目标 | 宽度 | 高度 | 用途 |
|
||||
|------|------|------|------|
|
||||
| 桌面端(管理后台) | 1440 | 900 | admin 组页面 |
|
||||
| 桌面端(前端) | 1440 | 900 | app 组页面(如有移动端原型则用移动视口) |
|
||||
| 移动端 | 375 | 812 | 移动端原型(如有 mobile 目录) |
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
|---------|---------|
|
||||
| 原型服务启动失败 | 检查端口占用,尝试其他端口,报告错误 |
|
||||
| 实际页面无法访问 | 标记该页面为 error,继续下一个 |
|
||||
| 实际页面需要认证且登录失败 | 标记该页面为 error,记录认证错误 |
|
||||
| ui_diff_check 超时 | 降级为仅 analyze_image 语义分析 |
|
||||
| 截图文件过大 | fullPage 截图限制最大 8000px 高度 |
|
||||
| 原型页面无对应实际路由 | 标记为 skipped,记录在报告中 |
|
||||
|
||||
---
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **视口必须一致**:原型和实际页面使用完全相同的视口尺寸截图
|
||||
- **数据状态差异**:原型是静态设计,实际页面有真实数据。对比时忽略因数据内容不同导致的差异(如文字内容、图片内容),只关注布局和组件差异
|
||||
- **认证页面**:login/register 页面不需要登录即可访问,直接截图对比
|
||||
- **原型静态特性**:原型没有动画和过渡效果,实际页面可能有,这些差异标记为 🟢 轻微
|
||||
- **自动修复**:Phase VD-2 发现严重差异后自动进入 Phase VD-3 全量修复,全程零确认
|
||||
- **保留后端逻辑**:修复只改 UI 层(React 组件 + CSS),不动 API 路由和数据库
|
||||
- **重试上限**:每页最多修复重试 2 次,仍失败则标记为需手动修复
|
||||
@@ -87,18 +87,19 @@
|
||||
| **单 Epic 模式** | 执行指定 Epic 的所有 Story | 按模块开发 |
|
||||
| **回归验证模式** | 不做实现,逐 Story 验证功能点存在且正确 | 代码已实现需回归验证(类比:单元测试) |
|
||||
| **旅程验证模式** | 专用用户旅程定义+验证(跨页面完整流程) | 跨 Story/Epic 的用户体验验证(类比:E2E 测试) |
|
||||
| **原型对比验证模式** | 截取原型和实际页面截图,使用 ui_diff_check + analyze_image 对比差异 | Epic 完成后的视觉还原度检查(类比:视觉回归测试) |
|
||||
|
||||
## 模式选择与流转
|
||||
|
||||
### 三种核心模式职责对比
|
||||
|
||||
| 维度 | 完整模式 | 回归验证模式 | 旅程验证模式 |
|
||||
|------|---------|------------|------------|
|
||||
| 粒度 | 全项目 | 逐 Story | 跨 Story/Epic |
|
||||
| 目标 | 实现代码 | 验证功能点存在且正确 | 验证用户能完成目标 |
|
||||
| 类比 | 开发 | 单元测试 | 集成测试/E2E |
|
||||
| 入口 | pages.json 自然入口 | 直接 navigate 到目标页面 | 自然入口 |
|
||||
| 断言 | N/A | API 返回 200 + 页面渲染 | 数据状态变化 |
|
||||
| 维度 | 完整模式 | 回归验证模式 | 旅程验证模式 | 原型对比验证模式 |
|
||||
|------|---------|------------|------------|------------|
|
||||
| 粒度 | 全项目 | 逐 Story | 跨 Story/Epic | 逐页面 |
|
||||
| 目标 | 实现代码 | 验证功能点存在且正确 | 验证用户能完成目标 | 验证视觉还原度 |
|
||||
| 类比 | 开发 | 单元测试 | 集成测试/E2E | 视觉回归测试 |
|
||||
| 入口 | pages.json 自然入口 | 直接 navigate 到目标页面 | 自然入口 | 原型页面 ↔ 实际路由映射 |
|
||||
| 断言 | N/A | API 返回 200 + 页面渲染 | 数据状态变化 | ui_diff_check 差异分级 |
|
||||
|
||||
### 自动选择逻辑(用户未指定模式时)
|
||||
|
||||
@@ -112,6 +113,12 @@
|
||||
├── status: in_progress → 续跑模式(从中断点恢复)
|
||||
├── status: completed 且 story_results 全部 verified →
|
||||
│ 询问: "Story 功能验证已通过。是否进入旅程验证模式?"
|
||||
├── status: completed 且 journey 验证已通过 且 prototype/ 存在 →
|
||||
│ 询问: "旅程验证已通过,检测到原型页面。是否进入原型对比验证模式?"
|
||||
├── visual_diff.status: completed 且 critical_count > 0 且 无 fix_report_path →
|
||||
│ 自动进入原型对比验证模式 Phase VD-3(视觉差异修复)
|
||||
├── visual_diff.status: completed 且 fix_report_path 存在 →
|
||||
│ 询问: "视觉差异修复已完成。查看修复报告 or 重新验证?"
|
||||
├── status: completed 且存在 unverified stories →
|
||||
│ 询问: "有 N 个 Story 未验证。建议先回归验证。"
|
||||
│ → 回归验证模式
|
||||
@@ -125,10 +132,15 @@
|
||||
```
|
||||
完整模式/续跑模式 完成 → 建议进入回归验证模式
|
||||
回归验证模式 完成(全部 PASS)→ 建议进入旅程验证模式
|
||||
旅程验证模式 完成 → 输出最终报告
|
||||
旅程验证模式 完成 → 建议进入原型对比验证模式
|
||||
原型对比验证模式 完成 →
|
||||
├── 🔴 严重差异 > 0 → 自动进入 Phase VD-3 全量修复 → 修复后输出最终报告
|
||||
└── ✅ 无严重差异 → 输出最终报告(含视觉差异报告)
|
||||
|
||||
⛔ 不得跳过回归验证直接进入旅程验证。
|
||||
功能不存在时测旅程无意义(用户点不到不存在的东西)。
|
||||
⛔ 不得跳过旅程验证直接进入原型对比验证。
|
||||
页面功能不正确时做视觉对比无意义(功能错了再像也没用)。
|
||||
```
|
||||
|
||||
### 用户指定模式时
|
||||
@@ -168,6 +180,12 @@ Read fully and follow: ./validation-mode.md
|
||||
Read fully and follow: ./journey-mode.md
|
||||
```
|
||||
|
||||
### 原型对比验证模式
|
||||
|
||||
```
|
||||
Read fully and follow: ./visual-diff-mode.md
|
||||
```
|
||||
|
||||
### 仅测试模式 / 仅审查模式
|
||||
|
||||
直接读取对应 Story 的 phase-04-test.md 或 phase-05-review.md 中的相关部分。
|
||||
|
||||
Reference in New Issue
Block a user