Created
March 20, 2026 13:57
-
-
Save sang4lv/4064abd377a0ae27511d9b22d84dbff8 to your computer and use it in GitHub Desktop.
make-it-happen-skill
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| 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