---
description: F2C - 设计稿转 Vue 组件。触发：用户提供 Figma 片段 ID，要求生成/还原组件。
alwaysApply: false
---

# F2C - Figma to Component

该规则用于将 Figma 设计稿转换为 Vue 组件：

**当用户提供 Figma 片段 ID 时：**

- 调用 `fetch-html-fragment` 获取设计数据
- 生成 `index.vue` + `Example.vue`
- 遵循 **@modules/components.mdc** 组件规范

**当设计稿中存在切图时：**

- 读取并解析本地切图文件判断用途（禁止读取文件名理解用途）
- 按 `{业务前缀}-{用途}-{描述}.png` 重命名（kebab-case）
- 组件专属 → `{ComponentName}/assets/`
- 多组件共享 → `src/assets/img/{business}/`

**当设计稿中存在重复结构时：**

- 拆分子组件 + `v-for`
- Props 化列表数据

---

## ⚠️ 核心约束：忠于设计稿

| 允许 ✅                     | 禁止 ❌                  |
| --------------------------- | ------------------------ |
| 设计稿中明确存在的元素/交互 | 自行添加"改进"功能或效果 |
| 按规范补充 Props 类型定义   | 添加设计稿未体现的 Props |
| 缺失切图用占位符 + TODO     | 自行设计替代图标/图片    |
| 复用现有公共组件            | 为"优化"而新增组件       |

> 💡 如需优化：完成还原后，在单独 commit 中提出建议。

---

## 📥 输入 → 📤 输出

**输入**：Figma 片段 ID + 目标目录（绝对路径）

**输出**：

```
{ComponentName}/
├── index.vue       # 主组件
├── Example.vue     # 使用示例
├── components/     # 子组件（如有）
└── assets/         # 组件专属切图（如有）
```

---

## 🔧 工具链

| 阶段     | 工具                       | 产物       |
| -------- | -------------------------- | ---------- |
| 数据获取 | `fetch-html-fragment`      | 组件数据   |
| 组件生成 | `save-vue-component`       | Vue 组件   |
| 文档生成 | `get-docs-path`            | 文档路径   |
| 文档生成 | `generate-component-doc`   | Markdown   |
| 上传     | `save-component-to-server` | 服务器记录 |

---

## 🔄 执行流程

### 阶段 1: 准备

**目录信息设置**：

```typescript
const baseDir = "/absolute/path/to/workspace";
const componentDir = `${baseDir}/components`;
```

> ⚠️ **重要**：开始执行前，先将所有相对路径转换为绝对路径。

**必做**：读取 @foundation/project.mdc 获取技术栈、公共组件清单、响应式配置。

---

### 阶段 2: 数据获取

```typescript
const { name, needId, image, html, cutImages } = await fetchHtmlFragment(
  fragmentId
);
```

**设计稿理解优先级**：

| 优先级 | 来源         | 用途     |
| ------ | ------------ | -------- |
| 1️⃣     | designImage  | 以此为准 |
| 2️⃣     | cutImages    | 辅助理解 |
| 3️⃣     | htmlFragment | 仅供参考 |

---

### 阶段 3: 复用检查（引用+源码双验证）

**扫描优先级**：

| 优先级 | 来源                      | 示例                             |
| ------ | ------------------------- | -------------------------------- |
| 1️⃣     | UI 库组件                 | `<van-button>`                   |
| 2️⃣     | 公共组件                  | `<Avatar>`                       |
| 3️⃣     | 公共 CSS 类/公共 CSS 文件 | `.flex-row-center flip-icon-rtl` |
| 4️⃣     | 子组件拆分                | `./components/...`               |
| 5️⃣     | 新写代码                  | 最后选择                         |

#### 3.1 发现可复用资源

从设计稿中识别可能复用的 UI 元素。

#### 3.2 查找项目引用

**自动执行查询**：

```bash
# 组件引用
grep -rn "import.*ComponentName" src/
grep -rn "<ComponentName" src/

# CSS类引用
grep -rn "class.*className" src/
```

**提取信息**：

- 引用文件的代码片段（上下文 5-10 行）
- 实际使用的 Props 配置组合
- 样式类的搭配使用方式

#### 3.3 读取源码定义

**对于公共组件**：

- 定位组件文件（index.vue / index.ts）
- 提取 Props/Emits/Slots 完整定义
- 关注类型约束、默认值
- 识别注释中的 @warn/@example 标记

**对于 CSS 类**：

- 定位样式文件（全局 less/css）
- 读取完整样式规则
- 检查副作用（定位、z-index、依赖结构）

#### 3.4 交叉验证

验证项目案例的正确性：

- ✅ 案例用法符合源码定义
- ⚠️ 标注案例中的非标准用法
- 💡 识别源码支持但案例未用的能力

#### 3.5 用户确认

**展示格式**：

- 📂 **源码定义**：API 列表、类型约束、使用限制
- 🔍 **项目实战**：X 处引用、代码片段、正确性标注
- 📊 **团队规律**：统计分析的使用模式
- 🎯 **推荐用法**：基于案例调整的代码、对比说明

> ⚠️ 等待用户确认后再继续

---

**📖 示例参考**

<details>
<summary>Avatar组件检查流程</summary>

**源码**: Props 包含 src/size/shape/border，@warn 数字会转 px  
**引用**: 3 处，66%用 string+rem  
**推荐**: `<Avatar :src="user.avatar" size="0.8rem" :border="true" />`

</details>

<details>
<summary>CSS类检查流程</summary>

**源码**: .ellipsis 需配合 max-width (@warn 标记)  
**引用**: 5 处，100%都配合了 maxWidth  
**推荐**: `<div class="name ellipsis" :style="{maxWidth:'2rem'}">{{text}}</div>`

</details>

---

### 阶段 4: 设计分析

#### 4.1 切图处理

**切图理解规则**：

- ❌ **禁止**读取切图名称来理解切图的作用
- ✅ **必须**读取并解析本地切图文件，根据切图内容和设计图内容相结合判断用途
- ✅ **必须**根据理解的切图内容信息和用途重命名本地切图（kebab-case）
- ✅ **必须**确认切图在设计图中的位置（需要反复确认）

**切图命名规范**：

```
{业务前缀}-{用途}-{描述}.{ext}

示例：
- game-icon-coin.png
- user-avatar-default.png
- btn-bg-primary.png
```

#### 4.2 布局分析

**符号化语法**：

- 【A B】→ 横向（row）
- 【A + B】→ 纵向（column）
- 【A 【B + C】】→ 嵌套
- 【A 0.32rem B】→ 带间距标注

**间距测量**（F2C 特有）：

设计稿常用绝对定位，转 flex + gap 前必须测量间距：

```
1. 测量相邻元素间距 → 标注到符号化结构
2. 判断间距一致性 → 决定是否需要 DOM 嵌套
```

| 间距情况   | DOM 策略                 |
| ---------- | ------------------------ |
| 全部一致   | 平铺，统一 `gap`         |
| 部分不一致 | 嵌套分组，各组独立 `gap` |

> 📋 **分组决策原则**详见 @modules/components.mdc

#### 4.3 占位符策略

| 场景              | 处理方式                   |
| ----------------- | -------------------------- |
| 本地切图缺失      | 占位 div + emoji + TODO    |
| 远程图片（Props） | backgroundImage + 默认状态 |
| 动态文字          | 默认占位值                 |

```vue
<!-- 本地切图缺失 -->
<div class="xxx__placeholder" :style="{ width, height }">🏆</div>
<!-- ⚠️ TODO: 切图 - 描述 | 尺寸 | 路径 -->

<!-- 远程图片 -->
<div
  class="xxx__avatar"
  :style="{ backgroundImage: src ? `url(${src})` : 'none' }"
>
  <span v-if="!src">👤</span>
</div>
```

> 📋 **布局规范**详见 @modules/components.mdc - Flex + Gap 布局

**必做**：输出布局方案供用户确认

```markdown
📐 布局分析结果：

**间距测量**：
【头像 0.32rem 名字 0.32rem 金币 0.64rem 排名】
↑ 一致 ────────↑ ↑ 不一致 → 需分组

**分组方案**：
【【头像 名字】0.64rem【金币 排名】】
↑ gap:0.32rem ↑ gap:0.64rem

**DOM 树**：
根容器 (row, gap: 0.64rem)
├── 用户组 (row, gap: 0.32rem) → .item**user
└── 数据组 (row, gap: 0.64rem) → .item**stats

是否按此方案生成？(可调整嵌套/间距)
```

> ⚠️ 等待用户确认后再进入代码生成阶段

---

### 阶段 5: 组件生成

#### 5.1 代码生成优先级

- ✅ **优先**生成静态页面代码
- ✅ **然后**加上逻辑交互（逻辑交互以静态页面代码为基础）
- ❌ **禁止**交互逻辑代码影响布局，需保证布局正确
- ✅ 修正 HTML 片段与设计图不一致的地方
- ✅ 转换为 Vue 3 Composition API 风格

#### 5.2 图片处理规则

- ✅ 使用 JavaScript `import` 导入切图
- ✅ 使用相对路径（基于 `index.vue` 位置计算）
- ❌ **禁止**直接在 HTML 中写图片路径

```vue
<script setup lang="ts">
// ✅ 正确：使用 import 导入
import coinIcon from "./assets/game-icon-coin.png";
</script>

<template>
  <!-- ✅ 正确 -->
  <img :src="coinIcon" alt="金币" />

  <!-- ❌ 错误：禁止直接写路径 -->
  <img src="./assets/game-icon-coin.png" alt="金币" />
</template>
```

#### 5.3 布局规则

- 优先使用 Flexbox / Grid 布局
- 非必要不使用绝对定位

#### 5.4 子组件拆分决策

| 条件               | 决策                  |
| ------------------ | --------------------- |
| 相同 UI 模式 ≥2 次 | ✅ 拆分子组件 + v-for |
| 仅 1 次            | ❌ 直接写在主组件     |

#### 5.5 Example.vue 规则

```vue
<template>
  <div class="example">
    <!-- 基础用法 -->
    <ComponentName />
    <!-- Props 变体 -->
    <ComponentName size="sm" />
    <!-- 事件演示 -->
    <ComponentName @click="handleClick" />
  </div>
</template>

<script setup lang="ts">
import ComponentName from "./index.vue";
const handleClick = () => console.log("clicked");
</script>
```

**文档样式规范**：

- ✅ 标题使用 h3 及以下（禁用 h1、h2）
- ✅ 只需分段标题，不需总标题
- ✅ 使用 VitePress 默认亮色主题
- ❌ 禁止生成 props 说明（由文档工具自动生成）

#### 5.6 工具调用

```typescript
await saveVueComponent({
  componentName,
  componentDir,
  indexVueCode,
  exampleVueCode,
});
```

**验证步骤**：检查所有切图相对路径是否正确，如有错误立即修正。

> 📋 **组件规范**详见 @modules/components.mdc - 设计策略、BEM 命名、Props 策略

---

### 阶段 6: 文档生成（可选）

```typescript
const { docsPath } = await getDocsPath();
await generateComponentDoc({ targetIndexVuePath, docsDir: docsPath, props });
```

> ⚠️ **注意**：不要修改 `getDocsPath` 返回的路径，直接使用。

---

### 阶段 7: 上传服务器

> ⚠️ **人工确认点**

#### 7.1 展示待上传信息

```markdown
📦 待上传：${componentName}
📋 需求 ID：${needId}
📁 组件目录：${componentDir}/${componentName}
📁 文档目录：${docsPath}

生成的文件列表：

- `index.vue`（组件代码）
- `Example.vue`（范例代码）
- 文档 Markdown 文件（如已生成）
```

#### 7.2 预览确认

- ⚠️ **特别提示**：请用户先进行组件的效果预览
- ⚠️ 确保组件代码的样式和功能符合预期
- ⚠️ 组件效果 OK 后，再让 AI 执行上传操作

```markdown
⏸️ 请先预览组件效果，确认样式和功能符合预期后再上传。

确认上传？(是/yes/确认)
```

#### 7.3 执行上传

```typescript
if (userConfirmed) {
  await saveComponentToServer({
    name,
    needId,
    componentDirPath,
    docDirPath,
    framework: "vue3",
  });
}
```

---

## ✅ 检查清单

### 环境

- ✅ 所有路径已转换为绝对路径

### 忠于设计稿

- ✅ 所有元素均来自设计稿
- ✅ 布局与设计稿一致
- ❌ 禁止添加设计稿不存在的功能/效果

### 数据与复用

- ✅ 已扫描可复用组件/类
- ✅ 已查找项目引用并读取源码定义
- ✅ 已交叉验证案例正确性
- ✅ 已展示源码+实战双重依据
- ✅ 已标注团队使用规律
- ✅ 已获得用户确认
- ❌ 禁止只看案例不验证源码
- ❌ 禁止只看源码不参考实战
- ❌ 禁止不检查直接开发

### 切图处理

- ✅ 已读取切图文件内容理解用途（非文件名）
- ✅ 切图已按 `{业务前缀}-{用途}-{描述}.png` 重命名
- ✅ 已确认切图在设计图中的位置

### 布局与组件

- ✅ 已用符号化语法分析布局
- ✅ 缺失内容用占位符 + TODO
- ✅ 重复模式已拆分子组件
- ✅ 图片使用 JS `import` 导入
- ❌ 禁止 Props/Emits 缺少类型定义
- ❌ 禁止组件样式不使用 scoped
- ❌ 禁止交互逻辑影响布局

### 工具使用

- ✅ 工具参数使用绝对路径
- ✅ 用户已预览确认组件效果
- ❌ 禁止未经用户确认自动上传

---

## 📚 规范引用

| 规范                    | 用途                               |
| ----------------------- | ---------------------------------- |
| @foundation/project.mdc | 项目配置、公共组件清单、响应式配置 |
| @modules/components.mdc | Props/Emits、BEM、布局策略         |
| @foundation/naming.mdc  | 文件/切图命名                      |
| @foundation/style.mdc   | 样式规范                           |
