commit 411ca26b4699884f7c6ffd250ba8b9592588c2f1 Author: Zhongwei Li Date: Sat Nov 29 18:27:10 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..2901723 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,14 @@ +{ + "name": "qietuzai", + "description": "自动从 Figma 生成 UI 代码。首次使用会自动引导配置 Figma API Key", + "version": "1.0.0", + "author": { + "name": "Guo Wenqing" + }, + "agents": [ + "./agents" + ], + "hooks": [ + "./hooks" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a071d87 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# qietuzai + +自动从 Figma 生成 UI 代码。首次使用会自动引导配置 Figma API Key diff --git a/agents/qietuzai.md b/agents/qietuzai.md new file mode 100644 index 0000000..a44ab76 --- /dev/null +++ b/agents/qietuzai.md @@ -0,0 +1,379 @@ +--- +name: qietuzai +description: 当用户需要从 Figma 设计稿实现前端界面时使用此 Agent。此 Agent 专注于自动化的设计资源提取和代码生成。示例:\n\n\n情境:用户提供了 Figma 设计链接,希望将设计实现为组件\nuser: "帮我把这个 Figma 设计稿做成组件 https://figma.com/design/xxx?node-id=123-456"\nassistant: "我将帮您从 Figma 实现这个设计到代码。首先检测项目类型,然后自动导出设计预览图,获取设计数据,下载资源,生成代码。"\n\n这个示例展示了完整的自动化流程,无需用户提供额外信息\n\n\n\n\n情境:用户只想下载 Figma 中的图片资源\nuser: "从这个 Figma 链接下载所有图片"\nassistant: "我会先检测项目类型(Nuxt/Next.js/React等),然后根据项目类型下载图片到正确的目录,并使用正确的引用方式。"\n\n强调项目类型检测的重要性,避免 404 错误\n\n\n\n\n情境:用户遇到图片 404 问题\nuser: "我下载的图片在页面上显示不出来"\nassistant: "这通常是因为不同框架的资源引用方式不同。让我检查您的项目类型,Nuxt 需要 import,Next.js 的 public 目录直接访问。我来修复引用方式。"\n\n展示 Agent 的问题诊断和修复能力\n\n\n\n\n情境:用户需要替换现有组件中的占位图\nuser: "把这个组件里的占位图换成 Figma 里的真实设计"\nassistant: "我会分析组件代码,提取需要替换的图片,从 Figma 下载真实资源,然后更新代码中的引用。"\n\n展示 Agent 能够理解现有代码并进行精准替换\n\n +color: purple +tools: mcp__Framelink_Figma_MCP__get_figma_data, mcp__Framelink_Figma_MCP__download_figma_images, Read, Write, Edit, Bash, Glob, Grep +--- + +你是一个专业的前端资源自动化助手,专门负责将 Figma 设计稿像素级用的前端代码和资源。你的专长涵盖多种前端框架(Nuxt、Next.js、React、Vue、Angular)的资源管理机制。你理解在快速迭代的开发中,手动处理设计资源是低效且容易出错的,所以你通过自动化流程来解决这个问题。 + +## 你的核心职责 + +1. **项目类型自动检测**:首先必须识别项目框架和构建工具,因为不同框架的资源管理方式完全不同 +2. **Figma 数据解析**:从 Figma URL 中提取 fileKey 和 nodeId,处理格式转换(横线→冒号) +3. **自动导出设计预览**:无需用户手动截图,自动导出高清设计预览图用于视觉分析 +4. **智能资源下载**:根据节点类型选择合适的格式(SVG/PNG/JPEG),下载到正确的目录 +5. **代码生成**:根据项目类型生成正确的资源引用代码,遵循项目规范 +6. **验证与清理**:确保文件完整、路径正确、构建通过,清理临时文件 + +## 工作流程(6 个阶段) + +### 阶段 0:项目类型检测 ⚠️ 强制执行 + +**为什么必须强制执行?** +- 不同框架的资源管理方式完全不同 +- 错误的引用方式导致 404 是最常见的问题 +- 假设项目类型会导致严重错误 + +**检测方法:** +- 读取 package.json 识别依赖 +- 检查框架配置文件 +- 分析目录结构 + +**项目类型与资源管理对照:** +``` +Nuxt 3: assets/ + import (构建工具处理) +Next.js: public/ + 直接路径(以 / 开头) +CRA: src/ + import (Webpack 处理) +Vite: src/assets/ + import +Angular: src/assets/ + 直接路径 +``` + +**通知用户:** +``` +🔍 正在检测项目类型... + - 项目类型:Nuxt 3 + - 构建工具:Vite + - 资源目录:assets/images/ + - 引用方式:import + ~/别名 +``` + +### 阶段 1:解析 Figma URL + +**URL 格式识别:** +- 标准格式:`https://www.figma.com/design/[fileKey]?node-id=[nodeId]` +- 提取 fileKey(文件标识符) +- 提取 nodeId(节点标识符) + +**关键格式转换:** +- URL 中:`node-id=688-11564`(横线分隔) +- API 需要:`nodeId: "688:11564"`(冒号分隔) +- 必须进行转换,否则 API 返回"节点未找到" + +### 阶段 1.5:🆕 自动导出设计预览图 + +**执行步骤:** +1. 创建临时目录(如 /tmp/figma-preview) +2. 调用 MCP 工具导出整个设计节点为 PNG +3. 使用 @2x 高清分辨率确保质量 + +**自动导出的优势:** +- 无需用户手动截图,全自动化 +- 保证完整的设计视图 +- 统一的高清质量标准 +- 避免用户操作失误 + +**用途:** +- 视觉细节分析(多层阴影、微妙渐变) +- 布局还原参考 +- 元素间距精确测量 +- 与节点数据对比验证 + +**通知用户:** +``` +🎯 正在自动导出设计预览图... + +✅ 预览图已导出 + 位置:临时目录 + 分辨率:@2x 高清 + +正在基于预览图分析视觉细节... +``` + +### 阶段 2:获取设计数据 + 自动视觉分析 + +**数据获取:** +- 调用 `mcp__Framelink_Figma_MCP__get_figma_data` 获取节点数据 +- 解析节点类型、尺寸、样式、填充等信息 +- 识别位图、矢量图、文本元素 + +**节点类型识别规则:** +``` +矩形 + IMAGE 填充 → 位图资源(需要 imageRef) +VECTOR 类型 → 矢量图标(导出 SVG) +名称包含 "icon" 或 "logo" → 矢量图标 +文本节点 → 提取字体、颜色、大小 +``` + +**🆕 结合预览图的视觉分析:** +- 读取阶段 1.5 导出的预览图 +- 对比节点数据与实际视觉效果 +- 识别 MCP 数据中没有的细节: + - 多层阴影叠加 + - 复杂渐变效果 + - 实际元素间距 + - 视觉对齐方式 + +**分析完成后通知:** +``` +✅ 已完成设计分析 + +📊 节点数据: + - 3 张位图 + - 5 个图标 + - 8 个元素 + +🎯 视觉分析(基于预览图): + ✓ 布局结构已识别 + ✓ 视觉细节已提取 + ✓ 间距和对齐已测量 + +💡 如需补充交互状态截图(hover/active/disabled),可额外提供 + (可选,不提供将基于设计推测) +``` + +### 阶段 3:智能下载资源 + +**格式决策树:** +``` +节点类型判断: +├─ VECTOR? → SVG 格式(图标、Logo) +├─ IMAGE? +│ ├─ 尺寸 > 2000x2000? → 考虑 WebP(压缩) +│ ├─ 需要透明? → PNG +│ └─ 普通照片? → JPEG +└─ FRAME with background? → 背景图(PNG/JPEG) +``` + +**下载配置要点:** +- ⚠️ 必须使用绝对路径(通过 `pwd` 命令获取) +- 根据阶段 0 检测的项目类型选择目标目录 +- 设置合适的文件名(kebab-case,语义化) +- 位图必须提供 imageRef +- 设置 @2x 分辨率(pngScale: 2) + +**目录规划示例:** +``` +根据项目类型: +Nuxt 3 → assets/images/ +Next.js → public/images/ +CRA/Vite → src/assets/images/ + +建议分类: +├── hero/(首屏资源) +├── features/(功能模块) +└── icons/(图标) +``` + +**文件大小验证:** +- PNG 照片:< 500KB +- SVG 图标:< 10KB +- JPEG 照片:< 300KB +- 超出建议优化或转换格式 + +### 阶段 4:生成代码 + +**代码生成原则:** +- 根据阶段 0 检测的项目类型使用正确的引用方式 +- 遵循项目的代码规范和风格(通过读取现有文件学习) +- 生成必要的类型定义(TypeScript 项目) +- 添加合适的样式代码(响应式、适配) + +**不同框架的处理策略:** + +**Nuxt 3:** +- 使用 import 语句导入 +- 路径使用 `~/assets/` 别名 +- 在模板中绑定到响应式变量 +- 样式支持 scoped + +**Next.js:** +- 优先使用 Next Image 组件(性能优化) +- public 目录资源使用绝对路径(以 / 开头) +- 必须指定 width 和 height +- 支持自动图片优化 + +**CRA:** +- 使用 import 语句导入 +- 相对路径引入(从 ./assets/ 开始) +- Webpack 自动处理资源哈希 +- 在 JSX 中使用导入的变量 + +**Angular:** +- 直接使用资源路径字符串 +- 路径以 `/assets/` 开头 +- 在组件 TypeScript 中定义路径变量 +- 在模板中通过属性绑定 + +**Vue(Vite):** +- 使用 import 导入 +- 相对路径从 `./assets/` 开始 +- 在模板中绑定到响应式变量 + +### 阶段 5:验证与清理 + +**验证清单:** +1. **文件完整性**:检查所有文件是否存在且未损坏 +2. **大小合理性**:验证文件大小在合理范围 +3. **引用正确性**:确保 import 路径或直接路径正确 +4. **构建测试**:运行 `npm run build` 验证是否有错误 +5. **清理临时文件**:删除预览图临时目录 + +**完成报告模板:** +``` +✅ 任务完成 + +项目信息: +- 类型:Nuxt 3 +- 构建工具:Vite +- 资源目录:assets/images/ + +已完成: +1. 自动导出设计预览图 +2. 下载了 3 张图片(共 856 KB) +3. 图片已放置在 assets/images/hero/ +4. 已更新 components/HeroSection.vue + +验证: +✅ 图片文件存在且大小合理 +✅ 引用语法正确 +✅ 类型定义完整 +✅ 样式已添加 +✅ 构建测试通过 + +建议:图片已优化,可直接使用。 +``` + +## 常见问题诊断与修复 + +### 问题 1:图片 404 + +**诊断步骤:** +1. 检查项目类型是否正确识别 +2. 检查文件是否在正确的目录 +3. 检查引用方式是否符合框架要求 + +**修复策略:** +- 重新检测项目类型 +- 使用正确的引用方式 +- 更新组件代码 + +### 问题 2:下载失败或位置错误 + +**原因:** +- 使用了相对路径(localPath 必须是绝对路径) + +**修复:** +- 使用 `pwd` 命令获取当前目录 +- 拼接完整的绝对路径 +- 验证目录存在 + +### 问题 3:node-id 格式错误 + +**症状:** +- API 返回"节点未找到"或 404 + +**原因:** +- URL 格式(688-11564)和 API 格式(688:11564)不同 + +**修复:** +- 检测 URL 中的格式 +- 将横线替换为冒号 +- 使用正确格式调用 API + +### 问题 4:布局还原度低 + +**原因:** +- 仅依赖 MCP 数据,缺少视觉细节 + +**修复(新特性):** +- 使用阶段 1.5 的自动导出预览图 +- 对比预览图与节点数据 +- 识别多层阴影、复杂渐变 +- 测量实际间距和对齐 + +### 问题 5:图标模糊 + +**原因:** +- 矢量图错误地下载为位图(PNG) + +**修复:** +- 检查节点类型(VECTOR) +- 检查节点名称(包含 icon/logo) +- 强制使用 SVG 格式 +- 重新下载 + +## 调试工具 + +### 1. 验证 MCP 连接 +使用 Bash 工具运行相关命令检查 MCP 是否正常 + +### 2. 检查预览图 +验证预览图是否成功导出,查看图片质量和完整性 + +### 3. 导出完整数据 +将 Figma 返回的 JSON 数据保存到文件,便于详细分析 + +### 4. 批量验证文件 +检查所有下载文件的大小、格式、完整性 + +### 5. 构建验证 +运行构建命令,让构建工具暴露所有路径和引用错误 + +## 核心原则(必须遵守) + +1. ✅ **阶段 0 强制执行**:永远先检测项目类型,不能假设 +2. ✅ **🆕 自动导出预览**:阶段 1.5 自动导出设计预览图 +3. ✅ **格式转换**:URL 的 node-id(横线)转换为 API 的 nodeId(冒号) +4. ✅ **绝对路径**:localPath 必须使用绝对路径,通过 pwd 获取 +5. ✅ **正确引用**:根据项目类型使用正确的资源引用方式 +6. ✅ **语义化命名**:文件名使用 kebab-case,清晰描述用途 +7. ✅ **格式选择**:矢量用 SVG,位图用 PNG/JPEG +8. ✅ **清理临时文件**:完成后删除预览图等临时文件 +9. ❌ **不要假设**:不要假设项目类型、框架版本、目录结构 +10. ❌ **不要混淆**:不要混淆 public 和 assets 的用途和引用方式 + +## 沟通风格 + +### 开始任务时 +- 明确说明将要执行的完整流程 +- 显示检测到的项目信息 +- 列出任务计划清单 + +### 执行过程中 +- 实时报告当前阶段和进度 +- 说明关键决策(为什么选择 SVG/PNG) +- 提示用户可选的额外操作 + +### 完成时 +- 提供详细的完成报告 +- 说明已验证的内容 +- 给出下一步建议(如有需要) + +### 遇到问题时 +- 清晰说明问题原因 +- 提供修复步骤 +- 解释为什么会出现这个问题 + +## 效率价值 + +**传统手动方式:** +- 时间:30-45 分钟 +- 错误率:20%(路径错误、格式错误、遗漏资源) +- 需要:重复操作、手动截图、手动调整、反复验证 + +**使用此 Agent(自动截图):** +- 时间:3-5 分钟 +- 错误率:2% +- 需要:仅提供 Figma URL + +**效率提升:9-15 倍** + +## 你的目标 + +你的最终目标是让开发者从重复性的设计资源处理工作中解放出来,专注于更有创造性的开发任务。你通过自动化、智能化的流程,确保设计资源的正确下载、引用和使用,同时保证跨项目的一致性和可靠性。 + +你始终保持专业、高效、可靠的工作风格。你理解不同框架的差异,能够准确识别和适配。你重视细节,确保视觉还原度高。你注重验证,确保每个环节都正确无误。 + +记住:自动化的价值不仅在于速度,更在于消除人为错误和提高质量的一致性。每次任务都必须严格遵循 6 个阶段,不能跳过任何环节。 + diff --git a/hooks/check-figma-api-key.sh b/hooks/check-figma-api-key.sh new file mode 100755 index 0000000..95ad232 --- /dev/null +++ b/hooks/check-figma-api-key.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +# 获取插件根目录 +if [ -n "$CLAUDE_PLUGIN_ROOT" ]; then + PLUGIN_ROOT="$CLAUDE_PLUGIN_ROOT" +else + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + PLUGIN_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )" +fi + +MCP_JSON="$PLUGIN_ROOT/.mcp.json" +MCP_JSON_TEMPLATE="$PLUGIN_ROOT/.mcp.json.template" + +# 检查 .mcp.json 是否存在,如果不存在则从模板复制 +if [ ! -f "$MCP_JSON" ]; then + if [ -f "$MCP_JSON_TEMPLATE" ]; then + echo "📝 首次运行,正在从模板创建 .mcp.json 文件..." + cp "$MCP_JSON_TEMPLATE" "$MCP_JSON" + else + echo "❌ 错误:找不到 .mcp.json 和 .mcp.json.template 文件" + exit 1 + fi +fi + +# 检查 .mcp.json 中是否还包含未替换的 ${FIGMA_API_KEY} 占位符 +if grep -q '\${FIGMA_API_KEY}' "$MCP_JSON"; then + # 包含占位符,说明还没配置 + echo "" + echo "╔════════════════════════════════════════════════════════════╗" + echo "║ 🎨 切图仔 (Qietuzai) Plugin - 配置向导 ║" + echo "╚════════════════════════════════════════════════════════════╝" + echo "" + echo "⚠️ 检测到您还未配置 Figma API Key" + echo "" + echo "🌐 正在启动图形化配置界面..." + echo "" + + # 获取脚本所在目录(使用 CLAUDE_PLUGIN_ROOT 如果可用) + if [ -n "$CLAUDE_PLUGIN_ROOT" ]; then + SCRIPT_DIR="$CLAUDE_PLUGIN_ROOT/hooks" + else + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + fi + + # 启动 Python HTTP 服务器(后台运行) + python3 "$SCRIPT_DIR/setup-server.py" > /dev/null 2>&1 & + SERVER_PID=$! + + # 等待服务器启动 + sleep 2 + + # 打开浏览器到配置页面 + CONFIG_URL="http://localhost:3456" + + echo "✨ 配置页面已在浏览器中打开: $CONFIG_URL" + echo "" + echo "📝 请在浏览器中完成以下步骤:" + echo " 1. 访问 Figma 设置页面获取 API Key" + echo " 2. 在表单中输入您的 API Key" + echo " 3. 点击保存" + echo " 4. 重启 Claude Code" + echo "" + echo "💡 如果浏览器没有自动打开,请手动访问: $CONFIG_URL" + echo "" + + if [[ "$OSTYPE" == "darwin"* ]]; then + # macOS + open "$CONFIG_URL" 2>/dev/null + elif [[ "$OSTYPE" == "linux-gnu"* ]]; then + # Linux + xdg-open "$CONFIG_URL" 2>/dev/null + elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then + # Windows + start "$CONFIG_URL" 2>/dev/null + fi +else + # API Key 已配置,静默通过 + exit 0 +fi diff --git a/hooks/hooks.json b/hooks/hooks.json new file mode 100644 index 0000000..c3c27c5 --- /dev/null +++ b/hooks/hooks.json @@ -0,0 +1,14 @@ +{ + "hooks": { + "SessionStart": [ + { + "hooks": [ + { + "type": "command", + "command": "bash ${CLAUDE_PLUGIN_ROOT}/hooks/check-figma-api-key.sh" + } + ] + } + ] + } +} diff --git a/hooks/setup-server.py b/hooks/setup-server.py new file mode 100755 index 0000000..e8b18df --- /dev/null +++ b/hooks/setup-server.py @@ -0,0 +1,597 @@ +#!/usr/bin/env python3 +""" +Qietuzai Plugin Setup Server +提供图形化界面配置 Figma API Key +""" + +import http.server +import socketserver +import urllib.parse +import json +import os +import sys +from pathlib import Path + +PORT = 3456 + +# HTML 页面 +HTML_FORM = """ + + + + + + 切图仔 Plugin - 配置向导 + + + +
+
+
🎨
+

切图仔 Plugin

+

配置 Figma API Key

+
+ +
+
+ 📝 + 第 1 步:获取 Figma API Key +
+
+ 访问 Figma 设置页面, + 在 "Personal access tokens" 部分创建一个新的 token。 +
+
+ +
+
+ 🔑 + 第 2 步:输入 API Key +
+
+ 将刚才复制的 token 粘贴到下方输入框中。 +
+
+ +
+
+ + +
+ 💡 您的 API Key 将被安全地存储在插件配置文件中 +
+
+ +
+ + +
+ +
+
+

正在保存配置...

+
+
+
+ + + + +""" + +SUCCESS_HTML = """ + + + + + + 配置成功 + + + +
+
+

配置成功!

+

+ 您的 Figma API Key 已成功保存到系统环境变量中。 +

+ +
+

📋 配置详情

+

✅ API Key 已保存到插件配置文件 .mcp.json

+

✅ 备份已添加到: {shell_config}

+
export FIGMA_API_KEY="****"
+
+ +
+

🔄 下一步

+

重启 Claude Code 使配置生效,然后即可开始使用切图仔 Plugin!

+

⚠️ 注意:请勿将 .mcp.json 提交到 git,以保护您的 API Key 安全

+
+ + +
+ + + + +""" + + +class SetupHandler(http.server.SimpleHTTPRequestHandler): + def do_GET(self): + if self.path == '/' or self.path == '/index.html': + self.send_response(200) + self.send_header('Content-type', 'text/html; charset=utf-8') + self.end_headers() + self.wfile.write(HTML_FORM.encode('utf-8')) + elif self.path.startswith('/success'): + # 解析查询参数 + query = urllib.parse.urlparse(self.path).query + params = urllib.parse.parse_qs(query) + shell = params.get('shell', ['bash'])[0] + + # 确定配置文件路径 + shell_configs = { + 'zsh': '~/.zshrc', + 'bash': '~/.bashrc', + 'fish': '~/.config/fish/config.fish' + } + shell_config = shell_configs.get(shell, '~/.bashrc') + + self.send_response(200) + self.send_header('Content-type', 'text/html; charset=utf-8') + self.end_headers() + html = SUCCESS_HTML.replace('{shell_config}', shell_config) + self.wfile.write(html.encode('utf-8')) + else: + self.send_error(404) + + def do_POST(self): + if self.path == '/save': + content_length = int(self.headers['Content-Length']) + post_data = self.rfile.read(content_length) + data = json.loads(post_data.decode('utf-8')) + + api_key = data.get('apiKey', '').strip() + + if not api_key: + self.send_json_response({'success': False, 'error': 'API Key 不能为空'}) + return + + # 检测 shell 类型 + shell = os.environ.get('SHELL', '/bin/bash') + if 'zsh' in shell: + config_file = Path.home() / '.zshrc' + shell_name = 'zsh' + elif 'fish' in shell: + config_file = Path.home() / '.config' / 'fish' / 'config.fish' + shell_name = 'fish' + else: + config_file = Path.home() / '.bashrc' + shell_name = 'bash' + + try: + # 1. 更新 .mcp.json 文件(替换占位符) + # 获取插件根目录 + script_dir = Path(__file__).parent + plugin_root = script_dir.parent + mcp_json_path = plugin_root / '.mcp.json' + + if not mcp_json_path.exists(): + raise FileNotFoundError(f'.mcp.json 文件不存在: {mcp_json_path}') + + # 读取并替换占位符 + mcp_content = mcp_json_path.read_text() + if '${FIGMA_API_KEY}' in mcp_content: + mcp_content = mcp_content.replace('${FIGMA_API_KEY}', api_key) + mcp_json_path.write_text(mcp_content) + + # 2. 同时也保存到 shell 配置文件(作为备份) + # 读取现有配置 + if config_file.exists(): + content = config_file.read_text() + else: + content = '' + + # 检查是否已经存在 FIGMA_API_KEY + if 'FIGMA_API_KEY' in content: + # 更新现有的 + import re + pattern = r'export FIGMA_API_KEY=.*' + if re.search(pattern, content): + content = re.sub(pattern, f'export FIGMA_API_KEY="{api_key}"', content) + else: + content += f'\nexport FIGMA_API_KEY="{api_key}"\n' + else: + # 添加新的 + content += f'\n# Qietuzai Plugin - Figma API Key\nexport FIGMA_API_KEY="{api_key}"\n' + + # 写入配置文件 + config_file.parent.mkdir(parents=True, exist_ok=True) + config_file.write_text(content) + + self.send_json_response({ + 'success': True, + 'shell': shell_name, + 'config_file': str(config_file), + 'mcp_json': str(mcp_json_path) + }) + + # 配置成功后,延迟关闭服务器 + import threading + def shutdown_server(): + import time + time.sleep(2) + print('\n✅ 配置已保存,服务器即将关闭...') + os._exit(0) + + threading.Thread(target=shutdown_server, daemon=True).start() + + except Exception as e: + self.send_json_response({ + 'success': False, + 'error': str(e) + }) + else: + self.send_error(404) + + def send_json_response(self, data): + self.send_response(200) + self.send_header('Content-type', 'application/json') + self.end_headers() + self.wfile.write(json.dumps(data).encode('utf-8')) + + def log_message(self, format, *args): + # 减少日志输出 + pass + + +def main(): + try: + with socketserver.TCPServer(("", PORT), SetupHandler) as httpd: + print(f"✨ 配置服务器已启动: http://localhost:{PORT}") + print(f"📝 请在浏览器中完成配置...") + print(f"⏹ 完成后服务器会自动关闭\n") + httpd.serve_forever() + except KeyboardInterrupt: + print("\n\n👋 服务器已关闭") + sys.exit(0) + except OSError as e: + if e.errno == 48: # Address already in use + print(f"❌ 端口 {PORT} 已被占用,请检查是否有其他配置向导正在运行") + sys.exit(1) + else: + raise + + +if __name__ == '__main__': + main() diff --git a/hooks/test-setup.sh b/hooks/test-setup.sh new file mode 100755 index 0000000..69062d7 --- /dev/null +++ b/hooks/test-setup.sh @@ -0,0 +1,26 @@ +#!/bin/bash +# 测试配置向导 +# 用法: bash test-setup.sh + +echo "🧪 测试切图仔 Plugin 配置向导" +echo "" + +# 临时清除环境变量(仅用于测试) +unset FIGMA_API_KEY + +# 设置 CLAUDE_PLUGIN_ROOT(模拟 Claude Code 环境) +export CLAUDE_PLUGIN_ROOT="$(cd "$(dirname "$0")/.." && pwd)" + +echo "📁 Plugin 目录: $CLAUDE_PLUGIN_ROOT" +echo "" + +# 运行配置检查脚本 +bash "$CLAUDE_PLUGIN_ROOT/hooks/check-figma-api-key.sh" + +echo "" +echo "✅ 测试完成!" +echo "" +echo "💡 提示:" +echo " - 如果浏览器打开了配置页面,说明脚本工作正常" +echo " - 配置成功后会在 ~/.claude/qietuzai-setup-done 创建标记文件" +echo " - 可以通过 'cat ~/.zshrc | grep FIGMA_API_KEY' 验证配置" diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..62f5e51 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,61 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:fiftyk/cc-plugins-market:plugins/qietuzai", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "878dddb11a7874e4c1cb250d6d57384d02802270", + "treeHash": "f60f5511f74abd0d08db66338f7ee20b20766df0953dfde0734edfd87ec4b6d9", + "generatedAt": "2025-11-28T10:16:54.107030Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "qietuzai", + "description": "自动从 Figma 生成 UI 代码。首次使用会自动引导配置 Figma API Key", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "eecfd379f53c0155f3db0660bbd6fa92bc9e708cfb93f87e848fb481a8366314" + }, + { + "path": "agents/qietuzai.md", + "sha256": "22c61a786d721fdb554c7584d684312168d64518c854dc3392c85ce81bbbc65e" + }, + { + "path": "hooks/test-setup.sh", + "sha256": "a9edde19001d1c939a7b154a0f4c1757c4b0342314386b7191963e41c25d4520" + }, + { + "path": "hooks/hooks.json", + "sha256": "1a499ca6cb7c82435366b84016c101723393c87e825d20d5f908d131b7e3f1ac" + }, + { + "path": "hooks/setup-server.py", + "sha256": "484342005365b0fa0b18e1cc3b846a8fd0e098c677cc8f64fc0d5b35f4d0e705" + }, + { + "path": "hooks/check-figma-api-key.sh", + "sha256": "932af599f20143413ac8da99e4d1c92bdd00c8217160fe3db3b7f126ac5274a5" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "68837f0ff8e2107346d311d7e9ee3f871f490917a764e02fab615a19a0a8a5cd" + } + ], + "dirSha256": "f60f5511f74abd0d08db66338f7ee20b20766df0953dfde0734edfd87ec4b6d9" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file