Skip to content

Instantly share code, notes, and snippets.

@sang4lv
Created March 20, 2026 13:57
Show Gist options
  • Select an option

  • Save sang4lv/4064abd377a0ae27511d9b22d84dbff8 to your computer and use it in GitHub Desktop.

Select an option

Save sang4lv/4064abd377a0ae27511d9b22d84dbff8 to your computer and use it in GitHub Desktop.
make-it-happen-skill
---
name: make-it-happen
description: 基于 Figma 设计稿端到端实功能——涵盖业务需求梳理、API 集成、状态管理、错误处理、订阅检查、i18n、视觉还原和组件映射。当用户提供 Figma URL、提到"实现设计"、"从 Figma 构建",或需要根据 Figma 规范开发前端功能时触发。需要 Figma MCP 服务器连接。
metadata:
mcp-server: figma
filePattern: "apps/**/*.tsx"
---
# 基于 Figma 实现设计
基于 Figma 设计稿的端到端功能实现指南。Figma 只告诉你"长什么样"——业务规则、API 合约、错误状态、权限逻辑、边界情况都不在设计稿里。本 skill 通过结构化的需求梳理流程,在写代码之前补齐所有缺失的上下文。
---
## 第一阶段:Brainstorming — 建立完整产品理解
**必须调用 `superpowers:brainstorming` skill 来驱动整个第一阶段。**
Figma 设计稿只告诉你"长什么样"——用户路径、业务规则、边界情况、API 合约、状态管理都不在设计稿里。在写任何代码之前,必须通过 brainstorming 建立完整的产品图景。
Brainstorming 过程中会依次完成以下信息采集,但所有信息都服务于一个目标:**知道所有的产品路径,这样代码才能写对。**
### 信息采集(在 brainstorming 中完成)
**收集参考资料:**
- Linear issue(用 `get_issue` + `list_comments` 获取——评论里通常有 Figma 链接、设计决策和团队讨论)
- PRD 或设计文档(如有)
- 后端设计文档(API 合约、数据模型变更)
- 相关 Figma URL(如尚未提供)
**阅读现有代码:**
- `apps/youweb/src/apis/{feature}.ts` — 已有 API 调用
- `apps/youweb/src/hooks/` — 可能相关的 hooks
- `apps/youweb/src/components/{feature}/` — 正在修改的已有组件
- `packages/ui/src/components/` — 可用的 UI 基础组件
**获取 Figma 设计:**
- 解析 URL → `get_design_context(fileKey, nodeId)` → `get_screenshot(fileKey, nodeId)`
- 如果结果太大:先 `get_metadata` → 定位子节点 → 单独获取
- 为设计中的每个页面/状态截图留作参考
### Brainstorming 必须覆盖的维度
**用户故事与产品路径:**
- 谁是用户?他们为什么需要这个功能?
- 用户的主流程是什么?(Happy path,从入口到完成)
- 有哪些替代路径?(不同的入口、不同的操作顺序)
- 用户在什么上下文下使用这个功能?(刚打开页面?工作中途?移动端?)
- 用户完成后会去做什么?(导航到哪里?期望看到什么反馈?)
**功能完整性审查:**
- Figma 画了哪些页面/状态?有没有缺失的状态(空态、错误态、首次使用态)?
- 设计中有没有隐含的交互没有画出来?(hover 效果、键盘导航、拖拽)
- 该功能与系统中其他功能的关系?(共享数据?联动 UI?导航跳转?)
- 是否涉及数据迁移或向后兼容?(旧数据格式、旧 API 调用方)
**数据与 API:**
- 该功能调用哪些 API 端点?是否已存在?
- 请求/响应的数据结构是什么?(检查 `@repo/api` 生成的类型)
- 涉及数据的创建、更新还是删除?有什么校验规则?
- API 出错时怎么处理?(通用 toast?自定义错误状态?重试?)
**权限与门控:**
- 谁可以使用该功能?(所有用户?仅付费用户?特定套餐?)
- 该操作是否消耗 Credits?
- 是否需要 Feature Flag 控制?
**状态与交互:**
- 用户交互后哪些状态会变化?(本地状态?Jotai atom 全局状态?)
- 是否需要乐观更新?
- 哪些其他组件会响应这个状态变化?
- 用户中途离开页面会怎样?
**边界情况与防御性思考:**
- 数据为空时怎么显示?
- 数据极多时怎么处理?(分页?虚拟滚动?截断?)
- 文本过长时怎么处理?(truncate?tooltip?换行?)
- 网络错误时怎么处理?(重试?toast?内联错误?)
- 并发操作怎么处理?(两个 tab 同时编辑?乐观更新冲突?)
- 权限不足时怎么处理?(隐藏入口?禁用按钮?提示升级?)
- 移动端行为?(响应式?独立 UI?不支持?)
**技术决策:**
- 状态放在哪里?(本地 useState?Jotai atom?URL params?)
- 需要哪些 API?已有的够用吗?需要后端配合新增吗?
- 能复用哪些已有组件?需要新建哪些?
- 有没有性能风险?(大列表渲染、频繁 re-render、大体积组件)
### Brainstorming 产出
1. 完整的用户路径列表(主路径 + 所有分支路径)
2. 每个路径的预期行为描述
3. 已识别的边界情况及其处理方案
4. API 依赖清单(已有 / 需新增)
5. 技术决策要点
6. 需要用户确认的开放问题
### 产出:实现设计文档
Brainstorming 的最终产出是一份实现设计文档(新建或更新已有文档)。这不是一个单独的阶段——它是 brainstorming 的自然结果。文档保存在 `apps/youweb/docs/feature/{feature-name}.md`。
如果用户已经提供了设计文档,brainstorming 应该审查并补充缺失的内容,而非从头写。
### 文档结构
```markdown
# [功能名称] — 实现设计
## 概述
一段话:该功能做什么、为什么做、关键用户流程。
## API 依赖
- 列出每个端点:方法、路径、请求/响应结构
- 标注尚未实现的端点(需要后端配合)
- 注明使用哪些 `@repo/api` 类型
## 业务规则
- 校验规则(必填、可选、限制)
- 权限规则(谁能做什么)
- Credits/订阅门控(如有)
- 边界情况处理(空状态、错误、加载、溢出)
## 状态设计
- 本地状态(什么、在哪、初始值)
- 全局状态(Jotai atoms——复用现有的还是新建)
- 数据流(哪个组件拥有状态、谁读取)
## 组件拆解
每个组件:
- 名称和文件路径
- 渲染内容(Figma 元素 → @repo/ui 组件映射)
- Props 接口
- 关键交互和状态变化
## Figma → Code 映射
- 具体 Figma 元素 → 项目组件
- 颜色映射(Figma hex → Tailwind token)
- 与 Figma 的偏差(附理由说明)
## i18n 翻译键
- 列出所需的新翻译键
- 命名空间:`Domain.{feature}`
## Visual QA 对比清单
每个需要视觉验收的场景,列出:
| 场景 | 操作路径 | Figma 节点 | 对比区域 | 忽略项 |
|---|---|---|---|---|
| [场景名] | [如何到达该页面/状态] | [fileKey:nodeId] | [要对比的 UI 区域] | [动态数据、背景内容等] |
示例:
| 场景 | 操作路径 | Figma 节点 | 对比区域 | 忽略项 |
|---|---|---|---|---|
| 创建 dialog | /boards → Tasks tab → New | 655:6573 | dialog 本体 | 表单内的测试数据 |
| Schedule picker | 打开 dialog → 点 Schedule 下拉 | 877:5847 | popover 内容 | Next run 时间(动态) |
| 空状态 | /boards → Tasks tab(无数据时) | 652:12453 | 整个表格区域 | 无 |
| 任务列表 | /boards → Tasks tab(有数据时) | 652:12453 | 表格行样式 | 任务名称、时间等数据内容 |
**为什么需要这张表**:
- Visual QA agent 需要知道比什么、在哪比、忽略什么
- 页面中的动态数据(用户名、时间、任务名)与 Figma 不同,必须排除
- 对比区域限定到具体组件(dialog/popover/table),不是整个页面
- 操作路径告诉 agent 如何用 Claude in Chrome 导航到目标状态
## 实现顺序
编号列表,每步可独立验证:
1. API 层(如需新端点)
2. 核心组件 A
3. 核心组件 B
4. 集成和状态串联
5. 边界情况和打磨
```
### 获得用户确认
将设计文档提交给用户审阅。用户确认前不开始写代码。如果用户指出遗漏或错误,更新文档后再次确认。
---
## 第二阶段:逐步实现
### 进度追踪
实现开始前,**必须使用 TaskCreate 为设计文档中"实现顺序"里的每一步创建 task**。每个 task 应包含:
- `subject`:实现步骤的简要描述
- `description`:该步骤的具体内容 + 完成后需要验证的测试清单
**测试清单**——每个 task 的 description 中必须包含该步骤对应的验证项:
```markdown
## 实现内容
- [具体要做什么]
## 完成后验证
- [ ] 类型检查通过(npx tsc --noEmit)
- [ ] [该步骤涉及的用户故事 1] 可正常走通
- [ ] [该步骤涉及的用户故事 2] 可正常走通
- [ ] [相关的 UI 状态] 显示正确(默认态/hover/disabled/空态/错误态)
- [ ] [相关的边界情况] 已处理
- [ ] i18n:新增文案已添加翻译
```
示例:
```
TaskCreate:
subject: "Schedule Picker 组件"
description: |
## 实现内容
Popover + Interval/Once CapsuleTabs + 条件字段 + 时间选择器 + Next run 预览
## 完成后验证
- [ ] tsc --noEmit 无新错误
- [ ] Interval 模式:选择 hour/day/week/month 各单位,条件字段正确显示/隐藏
- [ ] Week 模式:可多选星期,pill 选中态正确(黑底白字)
- [ ] Month 模式:可多选日期(1-31)
- [ ] Once 模式:日期选择器禁止过去日期,今天时过滤过去时间
- [ ] 时间选择器:双列滚动,自动滚到当前选中项
- [ ] Next run 预览文案正确
- [ ] Trigger 按钮摘要文案随选择实时更新
```
### 执行流程
按 task 顺序逐步执行。每完成一个 task:
1. 编写代码
2. 逐项检查该 task 的验证清单
3. 类型检查通过(`npx tsc --noEmit` 检查变更文件)
4. 将 task 标记为 completed
5. 进入下一个 task
### 代码规范参考
完整参考见 `apps/youweb/docs/figma/design-system-rules.md`,要点如下:
**导入顺序:**
```typescript
// React → 第三方 → @repo → @/ 本地 → 相对路径
import { useState, useCallback } from 'react'
import { ChevronDown } from 'lucide-react'
import { cn } from '@repo/ui/lib/utils'
import { Popover, PopoverContent, PopoverTrigger } from '@repo/ui/components/ui/popover'
import { useTranslation } from '@/hooks/useTranslation'
```
**API 调用:**
```typescript
import { apiClient, callAPI } from '@/utils/callHTTP'
// youweb 统一使用 snake_case API
const result = await callAPI(apiClient.featureApi.doSomething(params))
```
**i18n——所有可见文案:**
```typescript
const { t } = useTranslation('Domain.featureName')
// 使用 /i18n skill 在 18 种语言中添加翻译
```
**状态管理:**
```typescript
import { useAtomValue, useSetAtom } from 'jotai'
```
**错误处理:** `callAPI` 自动处理 toast + Sentry。员工调试信息用 `<EmployeeOnly>` 包裹。
**组件映射:** 完整对照表见 design-system-rules.md。
**Token 映射:** 禁止硬编码颜色,使用 Tailwind token(详见 design-system-rules.md)。
**图标:** lucide-react + @youmindinc/youicon + iconfont。禁止安装新的图标库。
---
## 静态资源处理
### 图片和文件类资源
上传到 S3,通过 CDN 访问:
- **S3 Bucket**: `youmind-product-files-public`
- **上传路径**: `s3://youmind-product-files-public/assets/{文件名}`
- **CDN 域名**: `https://cdn.gooo.ai/assets/{文件名}`
- **上传方式**: 使用项目内置的 **s3-uploader MCP server**(`.claude/mcp-servers/s3-uploader/`):
```
mcp__s3-uploader__upload_file(filePath: "/path/to/file.png", customName: "assets/my-image.png")
```
代码中使用:
```typescript
const imageUrl = 'https://cdn.gooo.ai/assets/your-image.png'
// 或通过 CdnImage / CfImage 组件
```
### 自定义图标(非 Lucide)
项目使用 **iconfont** 方案管理自定义图标:
**架构:**
1. 设计师在 iconfont 平台(iconfont.cn)上传/管理 SVG 图标
2. 导出为 Symbol JS 文件(`iconfont_icons.js`)
3. 上传到 S3:`s3://youmind-product-files-public/assets/iconfont_icons.js`
4. 前端通过 `<Script>` 全局加载:`https://cdn.gooo.ai/assets/iconfont_icons.js`
5. 组件通过 `<use xlinkHref="#iconId">` 引用
**使用方式:**
```typescript
import { IconFontBase } from '@repo/ui/components/icons/iconfont-base'
// 直接使用
<IconFontBase iconId="icon-xxx" size={20} />
// 或封装为独立组件
export const IconFlash = (props: IconFontBaseProps) => (
<IconFontBase iconId="icon-flash" {...props} />
)
```
**新增自定义图标的流程:**
1. 从 Figma 导出 SVG
2. 上传到 iconfont.cn 项目(由设计师操作,或用 CLI 工具)
3. 重新生成并上传 `iconfont_icons.js` 到 S3
4. 在代码中通过 `iconId` 引用
**注意:** 如果 Figma 中的图标在 lucide-react 中有对应的,优先用 lucide。只有 lucide 没有的才走 iconfont 流程。
### 图标优先级
1. **lucide-react** — 通用 UI 图标(优先使用)
2. **@youmindinc/youicon** — Board/品牌图标
3. **iconfont (IconFontBase)** — 自定义设计图标
4. **packages/ui/src/components/icons/** — 内联 SVG 组件(特殊场景)
禁止安装新的图标库(如 react-icons、heroicons 等)。
---
### 动效与交互打磨
Figma 设计稿不包含动效规范。以下是项目已有的动效模式——实现时必须主动补齐,让界面从"能用"变成"好用"。
### 核心原则
1. **有意图的动效**:每个动画必须服务于信息传递(出现、消失、状态变化),而非装饰
2. **一致性**:同类交互使用相同的时长和缓动,用户才能建立预期
3. **性能优先**:只动 `transform` 和 `opacity`,避免触发 layout reflow
### 项目动效库
| 库 | 用途 | 何时使用 |
|---|---|---|
| **Tailwind transition classes** | 简单状态变化(hover、focus、颜色/透明度) | 默认首选 |
| **tailwindcss-animate** | Radix UI 组件的 open/close 动画 | Popover、Dialog、Dropdown 等 |
| **framer-motion** | 复杂编排(列表 stagger、页面切换、拖拽、布局动画) | 需要 spring 物理或多步编排时 |
| **CSS @keyframes** | 循环动画(loading、shimmer、pulse) | 不依赖状态的持续动画 |
### 标准时长与缓动
| 场景 | 时长 | 缓动 | Tailwind 类 |
|---|---|---|---|
| Hover 反馈(背景色、透明度) | 150ms | ease | `transition-colors duration-150` |
| 状态切换(展开/折叠、tab 切换) | 200ms | ease-in-out | `transition-all duration-200` |
| Popover/Dropdown 出现 | 200ms | ease-out | Radix `data-[state=open]:animate-in` |
| Dialog 出现 | 300ms | ease-out + scale | `fadeAndScaleIn 0.3s ease-in-out` |
| Dialog 消失 | 100ms | ease-in + scale | `fadeAndScaleOut 0.1s ease-in-out` |
| 弹性回弹(toast pop、badge 出现) | 300ms | cubic-bezier(0.34, 1.56, 0.64, 1) | easeOutBack |
| 页面级过渡 | spring | stiffness: 300, damping: 30 | framer-motion spring |
| 列表 stagger | 0.1s 间隔 | ease-out | framer-motion staggerChildren |
| Loading shimmer | 2.5s | linear infinite | `animate-[loading-shimmer_2.5s_linear_infinite]` |
### 必须添加动效的场景
#### 1. Popover / Dialog / Dropdown
Radix UI 组件已内置 `data-[state=open/closed]` 动画。如果自建 modal:
```tsx
// 出现:scale 0.9→1 + opacity 0→1,300ms
// 消失:scale 1→0.9 + opacity 1→0,100ms(快进慢出)
// 遮罩:opacity 0→0.3,200ms
```
#### 2. 列表项出现(表格行、卡片列表)
新数据加载后,行应有 stagger fade-in:
```tsx
import { motion, AnimatePresence } from 'framer-motion'
// 容器
<motion.div variants={{ show: { transition: { staggerChildren: 0.05 } } }}>
{items.map(item => (
<motion.div
key={item.id}
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
/>
))}
</motion.div>
```
#### 3. Hover 微交互
所有可交互元素必须有 hover 反馈:
```
// 按钮/图标按钮
hover:bg-new-select transition-colors // 背景色变化
hover:opacity-80 transition-opacity // 透明度变化
// 卡片/行
hover:bg-new-select/50 transition-colors // 浅色背景
// 图标按钮
hover:scale-105 transition-transform // 轻微放大(谨慎使用)
```
#### 4. Toggle / Switch
状态切换应有平滑过渡,Radix Switch 已内置。自建 toggle:
```css
transition: background-color 200ms ease-in-out, transform 200ms ease-in-out;
```
#### 5. Loading 状态
| 场景 | 方案 |
|---|---|
| 页面/区块首次加载 | Skeleton 骨架屏(`@repo/ui Skeleton` 组件) |
| 按钮提交中 | `<Loader2 className="animate-spin" />` 替换按钮文案 |
| 内容流式加载 | Loading shimmer(`loading-shimmer.css`) |
| AI 生成中 | Blinking cursor(`blinking-cursor.module.css`) |
| 长时间后台任务 | 三点脉冲(`SimpleLoading` 组件) |
#### 6. 空状态 → 有数据
从空状态首次出现数据时,内容应 fade + slide-up 进入:
```tsx
<motion.div
initial={{ opacity: 0, y: 12 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3, ease: 'easeOut' }}
>
```
#### 7. 删除/消失
元素被删除时,应 fade-out + 高度收缩(不能突然消失):
```tsx
<AnimatePresence>
{visible && (
<motion.div
exit={{ opacity: 0, height: 0, marginBottom: 0 }}
transition={{ duration: 0.2, ease: 'easeInOut' }}
/>
)}
</AnimatePresence>
```
### 禁止事项
- ❌ **不要**用 `transition-all` 在大容器上——会触发所有属性的 transition,包括 `height`/`width`
- ❌ **不要**在滚动容器内添加弹性动画——会引起性能问题
- ❌ **不要**使用超过 500ms 的 UI 过渡——用户会感觉卡顿
- ❌ **不要**安装新的动画库(不用 react-spring、anime.js 等)——用 framer-motion + CSS
- ❌ **不要**给每个元素都加动画——重点放在状态变化和首次出现
### 动效验证清单
- [ ] Popover/Dialog 有 open/close 动画
- [ ] 列表数据加载后有 stagger 出现效果
- [ ] 所有可交互元素有 hover 反馈
- [ ] 按钮提交中有 loading 态
- [ ] 删除操作有 fade-out 过渡
- [ ] 空状态 → 有数据有过渡动画
- [ ] 没有 jank/闪烁(检查 will-change 和 transform 使用)
---
## 第三阶段:验证
所有实现 task 完成后,**并行启动两个独立 agent**:
| Agent | 职责 | 工具 | 能否改代码 |
|---|---|---|---|
| **业务逻辑审查** | 对照设计文档 + 验证清单,读代码核实每条业务规则 | Read, Grep, Glob | ✅ 发现缺失直接修复 |
| **Visual QA** | 对照 Figma 截图,用 Claude in Chrome 验收 UI,发现差异直接修复 | Claude in Chrome, Figma MCP, Edit | ✅ 用 implement-design skill 修复 |
两个 agent 不冲突:一个只读写代码,一个独占浏览器。
**每个 agent 完成后必须返回结构化报告:**
```markdown
## [Agent 名称] 验证报告
### 发现的问题
1. [问题描述] — ✅ 已修复 / ⚠️ 需人工处理
2. ...
### 修复清单
- [文件路径]: [修改描述]
- ...
### 未能修复的问题(如有)
- [原因说明]
### 结论
✅ 全部通过 / ⚠️ 有 N 项需人工处理 / ❌ 有严重问题
```
主 agent 收到两份报告后,汇总结果。如果都是 ✅,进入提交流程。如果有未修复项,主 agent 处理后做最终 tsc 检查。
以下是通用验证清单(agent 之外,主 agent 自查):
### 视觉对齐
- [ ] 布局与 Figma 截图一致
- [ ] 颜色使用 Tailwind token
- [ ] 暗黑模式正常(CSS 变量自动切换)
- [ ] 交互状态(hover、active、disabled、focus)
### 动效与交互
- [ ] Popover/Dialog/Dropdown 有 open/close 动画
- [ ] 列表数据加载后有 stagger 出现效果
- [ ] 所有可交互元素有 hover 反馈(背景色或透明度变化)
- [ ] 按钮提交中有 loading spinner
- [ ] 删除操作有 fade-out 过渡
- [ ] 空状态 → 有数据时有过渡动画
- [ ] Toggle/Switch 有平滑状态切换
- [ ] 无 jank/闪烁(只动 transform + opacity)
### 功能完整性
- [ ] API 调用的请求/响应结构正确
- [ ] 所有业务规则已实现
- [ ] 错误状态已处理
- [ ] 加载状态已实现
- [ ] 空状态已实现
- [ ] 订阅门控已实现(如适用)
### 业务逻辑独立审查
**使用 Agent tool 启动一个独立的审查 agent**,把设计文档、实现摘要、以及第二阶段每个 task 的验证清单一起交给它,让它用全新视角逐项核实。
准备审查输入:
1. 设计文档路径
2. 变更文件列表(`git diff --name-only` 的输出)
3. **第二阶段所有 task 的验证清单**——从 TaskList 中提取每个 completed task 的 description 中的"完成后验证"部分,汇总为一份完整清单
```
Agent(
description: "审查业务逻辑完整性",
prompt: """
你是一个业务逻辑审查员。你的任务是独立验证实现是否完整。
## 输入
设计文档路径: {design_doc_path}
变更文件列表:
{changed_files}
## 实现阶段的验证清单(需要你逐项核实)
{aggregated_task_checklists}
## 审查要求
1. 先读取设计文档,理解所有业务规则、用户路径和边界情况
2. 然后逐项核实上面的验证清单——读取对应的代码文件,确认每一项是否真的实现了
3. 额外检查:设计文档中有没有验证清单没覆盖到的场景?
对于每一项,给出:✅ 已实现 / ⚠️ 部分实现(说明缺失) / ❌ 未实现
如果发现缺失或错误,直接修复代码。
最后输出结构化报告:
## 业务逻辑审查报告
### 发现的问题(逐项列出,标注是否已修复)
### 修复清单(文件路径 + 修改描述)
### 未能修复的问题(如有,说明原因)
### 结论(✅ 全部通过 / ⚠️ 有 N 项需人工处理 / ❌ 有严重问题)
""",
subagent_type: "general-purpose"
)
```
**关键**:
- 这个 agent 只拿到设计文档路径、变更文件列表和验证清单——不继承当前实现上下文,避免"已实现"的惯性思维
- 它会独立读取设计文档和代码文件来交叉验证每一项
- 验证清单来自第二阶段的 task,确保不遗漏任何步骤
- 如果审查发现缺失,它会直接修复代码
### Visual QA Agent(视觉验收 + 修复)
**使用 Agent tool 启动一个独立的视觉验收 agent**,给它 Figma 截图信息和页面 URL,让它用 Claude in Chrome 打开实际页面,截图对比,逐项报告差异。
准备输入:
1. 第一阶段获取的 Figma 截图(fileKey + nodeId 列表,agent 可以自己调 Figma MCP 获取)
2. dev server URL(端口从 `.env.preview.local` 读取)
3. 需要验证的页面路径和交互场景列表
```
Agent(
description: "Visual QA 视觉验收",
prompt: """
你是一个视觉验收工程师。你的任务是对比 Figma 设计稿和实际实现的 UI,确保 1:1 视觉还原。
先调用 figma:implement-design skill 获取 Figma 到代码的精确还原标准,然后用它来评判每个差异是否可接受。
## 输入
Figma 文件: {figma_file_key}
需要对比的 Figma 节点:
{figma_node_list}
Dev server: http://localhost:{port}
需要验证的页面和场景:
{pages_and_scenarios}
## 验收流程
对于每个场景:
1. 用 Figma MCP 获取设计截图(get_screenshot)
2. 用 Claude in Chrome 打开对应页面,截图
- 先 ToolSearch 加载 mcp__claude-in-chrome__tabs_context_mcp
- 创建 tab → 导航到目标 URL
- 如果需要登录 → 停下来报告,请用户协助
3. 逐像素对比,报告差异
## 检查项(每个场景都要检查)
**布局**:元素位置、间距、对齐是否与 Figma 一致
**尺寸**:宽高、padding、margin 是否匹配(用 javascript_tool 获取 computedStyle)
**颜色**:背景色、文字色、边框色是否使用正确的 token
**字体**:字号、字重、行高是否匹配
**圆角**:border-radius 是否匹配
**阴影**:box-shadow 是否匹配
**交互状态**:hover(用 computer 移动鼠标)、disabled、focus 状态是否正确
**暗黑模式**:切换后颜色是否正确
## 输出格式
对于每个场景:
- 场景名称
- ✅ 匹配 / ⚠️ 有差异(列出具体差异 + 截图对比描述)/ ❌ 严重不匹配
- 差异详情:哪个元素、什么属性、Figma 值 vs 实际值
发现差异后,用 figma:implement-design skill 直接修复代码。每次修复后等待至少 5 秒让 HMR 完成,再重新验证。
所有场景验收完后,回放所有产品路径,确认修复没有破坏其他场景。
最后输出结构化报告:
## Visual QA 验收报告
### 发现的差异(逐项列出,标注是否已修复)
### 修复清单(文件路径 + 修改描述)
### 未能修复的问题(如有,说明原因)
### 结论(✅ 全部通过 / ⚠️ 有 N 项需人工处理 / ❌ 有严重问题)
""",
subagent_type: "general-purpose"
)
```
**关键**:
- 这个 agent 能同时使用 Figma MCP 和 Claude in Chrome——一边看设计稿一边看实际页面
- 用 `javascript_tool` 获取精确的 computed style 值,不是靠目测
- 检查暗黑模式需要切换 theme 后再截图
**⚠️ 只能有一个 Visual QA agent(验收 + 修复一体):**
- Claude in Chrome 的 `computer` 工具操作的是浏览器窗口焦点,多个 agent 同时操作会冲突
- 因此用一个 agent 完成完整的验收-修复循环:
1. 对比 Figma 截图和实际页面,发现差异
2. 用 `figma:implement-design` skill 直接修复代码,达到 1:1 还原
3. 等待至少 5 秒让 HMR 完成
4. 重新截图验证修复结果
5. 进入下一个场景
- 所有场景验收完后,**回放所有产品路径**,确认修复没有破坏其他场景
- 业务逻辑审查 agent 可以与 Visual QA agent **并行**运行(它只读代码,不碰浏览器)
### 浏览器实机验证参考(Claude in Chrome)
项目配置了 **Claude in Chrome** 插件(`mcp__claude-in-chrome__*`),这是主要的浏览器自动化工具。它能读取页面内容、导航、截图、点击、填写表单、执行 JS——足以完成所有 UI 验证。
**⚠️ 重要**:使用任何 `mcp__claude-in-chrome__*` 工具前,必须先用 `ToolSearch` 加载对应工具的 schema。
**前置条件:**
- dev server 已启动(`pnpm dev` 或 `pnpm dev:fe-only`)
- youweb 默认端口为 `2000`,但在 worktree 中端口可能不同——**必须从 `.env.preview.local` 读取实际端口**:
```bash
grep 'PORT' .env.preview.local # 查找 youweb 端口
```
- **登录**:如果打开页面后发现未登录(重定向到登录页),**不要自动导航到 dev-login**,而是提示用户手动登录或协助完成登录
**验证流程:**
1. **确认端口 & 获取当前 tab 状态**
```bash
grep 'PORT' .env.preview.local # 确认 youweb 端口
```
```
ToolSearch("select:mcp__claude-in-chrome__tabs_context_mcp")
mcp__claude-in-chrome__tabs_context_mcp → 获取已有 tab 和浏览器状态
```
2. **打开目标页面**
```
mcp__claude-in-chrome__tabs_create_mcp → 创建新 tab
mcp__claude-in-chrome__navigate → 导航到 http://localhost:{port}/{path}
```
如果页面重定向到登录页 → **停下来,请用户手动登录后再继续验证**
3. **查看页面 & 截图**
```
mcp__claude-in-chrome__read_page → 读取页面 DOM 结构和可见文本
mcp__claude-in-chrome__get_page_text → 获取纯文本内容(验证文案/i18n)
mcp__claude-in-chrome__upload_image → 截图上传(可用于对比)
```
4. **交互验证(模拟用户操作)**
```
mcp__claude-in-chrome__computer → 点击、移动鼠标(验证 hover 态、按钮、tab 切换)
mcp__claude-in-chrome__form_input → 填写输入框、选择下拉
mcp__claude-in-chrome__find → 在页面中查找特定元素/文本
```
5. **调试 UI 差异(执行 JS)**
```
mcp__claude-in-chrome__javascript_tool → 执行任意 JS,获取 computed styles、元素尺寸等
```
当发现 UI 与 Figma 不匹配时:
```javascript
// 获取元素的 computed style
const el = document.querySelector('.my-element');
const styles = getComputedStyle(el);
JSON.stringify({
width: styles.width,
height: styles.height,
padding: styles.padding,
margin: styles.margin,
color: styles.color,
backgroundColor: styles.backgroundColor,
borderRadius: styles.borderRadius,
fontSize: styles.fontSize,
fontWeight: styles.fontWeight,
});
// 检查 CSS 变量
getComputedStyle(document.documentElement).getPropertyValue('--token-name');
// 检查元素是否存在
document.querySelectorAll('[data-testid="my-component"]').length;
```
6. **检查控制台错误**
```
mcp__claude-in-chrome__read_console_messages → 读取控制台输出,检查 JS 错误
```
使用 `pattern` 参数过滤特定日志,避免被大量无关输出干扰。
7. **对比 Figma**
- 将浏览器截图与 Figma 截图(第一阶段获取的)逐像素对比
- 检查:间距、字号、颜色、圆角、阴影、对齐
- 检查:hover 态、空态、加载态、错误态
**验证清单:**
- [ ] 默认状态截图与 Figma 一致
- [ ] 暗黑模式截图正常(切换 theme 后再截图)
- [ ] 空状态页面截图正确
- [ ] 表单填写后截图(校验状态、已选项展示)
- [ ] Popover/Dialog 打开状态截图
- [ ] 控制台无报错(`read_console_messages`)
- [ ] 所有可见文案正确(`get_page_text` 检查 i18n)
### 代码质量
- [ ] i18n:无硬编码的用户可见文案
- [ ] 复用了 @repo/ui 组件
- [ ] 类型安全(`npx tsc --noEmit`)
- [ ] 遵循现有代码模式
---
## 适用范围
**适用于:** youweb(Rsbuild + React 18)基于 Figma 的功能实现
**不适用于:** youadmin、youhome、youapi 后端、无 UI 的纯逻辑变更
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment