sloth-d2c-mcp 1.0.4-beta77 → 1.0.4-beta79
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -68
- package/cli/run.js +20 -0
- package/dist/build/core/prompt-builder.js +94 -0
- package/dist/build/index.js +44 -14
- package/dist/build/server.js +332 -4
- package/dist/build/utils/file-manager.js +128 -6
- package/dist/interceptor-web/dist/build-report.json +7 -7
- package/dist/interceptor-web/dist/detail.html +1 -1
- package/dist/interceptor-web/dist/index.html +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -1,100 +1,83 @@
|
|
|
1
|
-
|
|
1
|
+
# Sloth D2C MCP
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## 简介
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Sloth D2C 设计稿转代码工具,包括 Sloth D2C 设计稿转代码 Figma 插件及 Sloth D2C MCP 工具。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Sloth D2C 设计稿转代码插件,面向前端开发与设计团队的智能化工具,支持设计稿快速转前端代码,并通过协同 MCP 工具,写入生产级前端代码;同时支持文本/图片+Prompt输入AI,生成目标风格页面并转译至Figma节点。
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Sloth D2C MCP 工具,获取插件推送的转码数据,通过拦截页面配置框架选择、转换倍率、颜色格式、图片存储、提示词编辑等基础设置,同时支持圈选分组、组件映射、模块标记等高级设置,以生成提示词指导 Agent 生成目标代码并写入。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## 核心能力
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* 窗口始终保持在最前面
|
|
16
|
-
* 支持快捷键操作
|
|
13
|
+
<!-- ### 节点清洗 -->
|
|
14
|
+
<!-- 待补充 -->
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
### 效果预览及源码调整
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
* `nodeId`: 节点ID (可选)
|
|
22
|
-
* `depth`: 遍历深度 (可选)
|
|
18
|
+
插件支持生成代码页面预览,同时支持源码二次编辑。在插件转码后,提供代码编辑器编辑源码,实时预览效果。
|
|
23
19
|
|
|
24
|
-
###
|
|
20
|
+
### AI 生成页面
|
|
25
21
|
|
|
26
|
-
|
|
22
|
+
插件支持文本/图片+Prompt 输入 AI,生成目标风格页面代码并预览。同时支持转译至成 Figma 节点并插入 Figma 设计稿。
|
|
27
23
|
|
|
28
|
-
|
|
24
|
+
### 自研 MCP 拦截器
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
* 兼容性更好
|
|
32
|
-
* 无需额外的桌面应用
|
|
26
|
+
设计了创新的 MCP 拦截器。利用 await 挂起 MCP 的核心请求,为用户创造了一个交互窗口。通过配置拦截及数据推送突破 RESTful API 限制,最大化还原度。
|
|
33
27
|
|
|
34
|
-
|
|
28
|
+
### 支持多种框架
|
|
35
29
|
|
|
36
|
-
|
|
37
|
-
* `nodeId`: 节点ID (可选)
|
|
38
|
-
* `depth`: 遍历深度 (可选)
|
|
30
|
+
MCP 默认支持 React、Vue 代码生成,系统内置提示词默认配置。同时支持新增自定义框架,配置自定义框架生成提示词。
|
|
39
31
|
|
|
40
|
-
|
|
32
|
+
### 多种图片存储方式
|
|
41
33
|
|
|
42
|
-
|
|
34
|
+
支持图片本地存储、OSS 存储及自定义图片上传方式。
|
|
43
35
|
|
|
44
|
-
|
|
36
|
+
### 圈选分组与采样
|
|
45
37
|
|
|
46
|
-
|
|
38
|
+
支持圈选分组与智能采样,圈选分组功能允许你在设计稿预览页中手动划分代码结构区域,每个区域分别在不同的采用请求流程进行代码生成,提高转码效率和准确性。
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
"method": "tools/call",
|
|
51
|
-
"params": {
|
|
52
|
-
"name": "d2c_figma_intercept_web",
|
|
53
|
-
"arguments": {
|
|
54
|
-
"fileKey": "your-figma-file-key",
|
|
55
|
-
"nodeId": "optional-node-id"
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
```
|
|
40
|
+
### 组件映射
|
|
60
41
|
|
|
61
|
-
|
|
42
|
+
从项目中选择组件文件,将项目中的组件映射对应圈选元素,生成代码时直接引用对应组件。
|
|
62
43
|
|
|
63
|
-
|
|
64
|
-
* 网页服务器: 端口3002
|
|
65
|
-
* Tauri回调服务器: 动态端口 (从3001开始)
|
|
44
|
+
### 模块标记
|
|
66
45
|
|
|
67
|
-
|
|
46
|
+
对圈选后的模块进行标记,方便其他设计稿类似模块的直接复用,无需重复生成。
|
|
68
47
|
|
|
69
|
-
|
|
70
|
-
# 安装依赖
|
|
71
|
-
npm install
|
|
48
|
+
## 安装 MCP
|
|
72
49
|
|
|
73
|
-
|
|
74
|
-
|
|
50
|
+
```bash
|
|
51
|
+
# 使用 pnpm(推荐)
|
|
52
|
+
pnpm install sloth-d2c-mcp -g
|
|
75
53
|
|
|
76
|
-
#
|
|
77
|
-
npm
|
|
54
|
+
# 或使用 npm
|
|
55
|
+
npm install sloth-d2c-mcp -g
|
|
78
56
|
|
|
79
|
-
#
|
|
80
|
-
|
|
57
|
+
# 验证安装
|
|
58
|
+
sloth
|
|
81
59
|
```
|
|
82
60
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
61
|
+
## 配置 MCP
|
|
62
|
+
|
|
63
|
+
**TME-Continue**
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
- name: sloth-d2c-mcp
|
|
67
|
+
command: sloth
|
|
68
|
+
connectionTimeout: 3000000
|
|
69
|
+
args:
|
|
70
|
+
- --stdio
|
|
94
71
|
```
|
|
95
72
|
|
|
96
|
-
|
|
97
|
-
|
|
73
|
+
**Copilot**
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
"d2c-cli": {
|
|
77
|
+
"type": "stdio",
|
|
78
|
+
"command": "sloth",
|
|
79
|
+
"args": ["--stdio"]
|
|
80
|
+
}
|
|
98
81
|
```
|
|
99
82
|
|
|
100
|
-
|
|
83
|
+
> **提示**:推荐使用 Claude AI 模型。若需转码长设计稿,请开启 MCP 采样功能以优化转码策略(TME-Continue 和 Copilot 均支持)。
|
package/cli/run.js
CHANGED
|
@@ -93,6 +93,26 @@ if (args[0] === 'config') {
|
|
|
93
93
|
process.env.SLOTH_COMMAND = 'framework';
|
|
94
94
|
// 传递子命令参数
|
|
95
95
|
process.env.SLOTH_FRAMEWORK_ARGS = JSON.stringify(args.slice(1));
|
|
96
|
+
} else if (args[0] === 'run') {
|
|
97
|
+
// run 命令:后台运行 sloth --stdio
|
|
98
|
+
const { spawn } = await import('node:child_process');
|
|
99
|
+
const { fileURLToPath } = await import('node:url');
|
|
100
|
+
|
|
101
|
+
// 获取当前脚本路径(兼容 Node.js 18)
|
|
102
|
+
const scriptPath = fileURLToPath(import.meta.url);
|
|
103
|
+
|
|
104
|
+
// 后台启动子进程
|
|
105
|
+
const child = spawn(process.execPath, [scriptPath, '--stdio'], {
|
|
106
|
+
detached: true,
|
|
107
|
+
stdio: 'ignore',
|
|
108
|
+
env: { ...process.env, NODE_ENV: 'cli' }
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// 解除父进程对子进程的引用,允许父进程退出
|
|
112
|
+
child.unref();
|
|
113
|
+
|
|
114
|
+
console.log(`[sloth] 已在后台启动,PID: ${child.pid}`);
|
|
115
|
+
process.exit(0);
|
|
96
116
|
} else {
|
|
97
117
|
// 设置环境变量为CLI模式
|
|
98
118
|
process.env.NODE_ENV = "cli";
|
|
@@ -209,3 +209,97 @@ export function buildPlaceholderPrompt(placeholders) {
|
|
|
209
209
|
prompt += '\n将 HTML 标签转换为真实组件调用,但不需要添加对应的 import 语句,保持其在布局中的位置。\n';
|
|
210
210
|
return prompt;
|
|
211
211
|
}
|
|
212
|
+
/**
|
|
213
|
+
* 构建完整的 AI 代码修改提示词
|
|
214
|
+
* 用于用户确认变更后,生成可直接发送给 AI 的完整提示词
|
|
215
|
+
* @param confirmedChanges 用户确认的变更点列表
|
|
216
|
+
* @param options 配置选项
|
|
217
|
+
* @returns 完整的 AI 提示词
|
|
218
|
+
*/
|
|
219
|
+
export function buildFullUpdatePromptForAI(confirmedChanges, options = {}) {
|
|
220
|
+
const { fileKey, nodeId, htmlDiff } = options;
|
|
221
|
+
if (!confirmedChanges || confirmedChanges.length === 0) {
|
|
222
|
+
return '没有需要修改的变更点。';
|
|
223
|
+
}
|
|
224
|
+
const typeLabels = {
|
|
225
|
+
layout: '布局变更',
|
|
226
|
+
style: '样式变更',
|
|
227
|
+
content: '内容变更',
|
|
228
|
+
structure: '结构变更',
|
|
229
|
+
};
|
|
230
|
+
let prompt = `# 设计稿变更 - 代码修改任务
|
|
231
|
+
|
|
232
|
+
## 任务背景
|
|
233
|
+
|
|
234
|
+
用户的 UI 设计稿发生了变更,需要根据以下变更点修改现有代码。这是一个**增量修改任务**,不是全新创建。
|
|
235
|
+
|
|
236
|
+
## 前置要求
|
|
237
|
+
|
|
238
|
+
**请先确认当前上下文中是否包含需要修改的代码。**
|
|
239
|
+
|
|
240
|
+
如果当前上下文中没有相关代码,请让用户:
|
|
241
|
+
1. 提供需要修改的代码文件路径,以便读取
|
|
242
|
+
2. 或直接粘贴需要修改的代码内容
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## 变更信息
|
|
247
|
+
|
|
248
|
+
`;
|
|
249
|
+
// 添加设计稿信息(如果有)
|
|
250
|
+
if (fileKey) {
|
|
251
|
+
prompt += `- **设计稿标识**: ${fileKey}${nodeId ? ` / ${nodeId}` : ''}\n`;
|
|
252
|
+
}
|
|
253
|
+
prompt += `- **变更数量**: ${confirmedChanges.length} 个\n\n`;
|
|
254
|
+
// 变更点详情
|
|
255
|
+
prompt += `## 变更点详情\n\n`;
|
|
256
|
+
confirmedChanges.forEach((change, index) => {
|
|
257
|
+
prompt += `### ${index + 1}. ${change.title}\n\n`;
|
|
258
|
+
prompt += `- **类型**: ${typeLabels[change.type] || change.type}\n`;
|
|
259
|
+
prompt += `- **描述**: ${change.description}\n`;
|
|
260
|
+
prompt += `- **建议操作**: ${change.suggestedAction}\n`;
|
|
261
|
+
if (change.userPrompt) {
|
|
262
|
+
prompt += `- **用户补充**: ${change.userPrompt}\n`;
|
|
263
|
+
}
|
|
264
|
+
prompt += `\n`;
|
|
265
|
+
});
|
|
266
|
+
// 添加 HTML Diff(如果有)
|
|
267
|
+
if (htmlDiff && htmlDiff.trim()) {
|
|
268
|
+
prompt += `## 设计稿 HTML Diff
|
|
269
|
+
|
|
270
|
+
以下是新旧设计稿的 HTML 差异,可帮助你精确定位需要修改的样式和布局:
|
|
271
|
+
|
|
272
|
+
\`\`\`diff
|
|
273
|
+
${htmlDiff}
|
|
274
|
+
\`\`\`
|
|
275
|
+
|
|
276
|
+
**说明**:
|
|
277
|
+
- \`---\` 开头的行表示被删除的内容(旧设计稿)
|
|
278
|
+
- \`+++\` 开头的行表示新增的内容(新设计稿)
|
|
279
|
+
- HTML 使用 Tailwind CSS 类名
|
|
280
|
+
|
|
281
|
+
`;
|
|
282
|
+
}
|
|
283
|
+
// 修改指南
|
|
284
|
+
prompt += `## 修改要求
|
|
285
|
+
|
|
286
|
+
### 核心原则
|
|
287
|
+
|
|
288
|
+
1. **基于现有实现**: 分析当前项目的技术栈和代码实现方式,在此基础上进行修改
|
|
289
|
+
2. **最小化变更**: 只修改与变更点相关的代码,保持其他部分不变
|
|
290
|
+
3. **保持一致性**: 遵循现有代码的命名规范、代码风格和架构模式
|
|
291
|
+
4. **增量修改**: 优先通过修改现有代码实现,避免大规模重构
|
|
292
|
+
|
|
293
|
+
### 修改流程
|
|
294
|
+
|
|
295
|
+
1. **分析现有代码**: 理解当前代码的技术栈、组件结构、样式方案
|
|
296
|
+
2. **定位修改位置**: 根据变更点找到需要修改的具体代码位置
|
|
297
|
+
3. **实施修改**: 按照现有代码风格进行修改
|
|
298
|
+
4. **验证完整性**: 确保修改后代码可正常运行
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
**请开始分析代码并执行修改。如果需要更多信息或代码上下文,请告诉我。**
|
|
303
|
+
`;
|
|
304
|
+
return prompt;
|
|
305
|
+
}
|
package/dist/build/index.js
CHANGED
|
@@ -13,7 +13,7 @@ import { updateImageMapIfNeeded } from './utils/update.js';
|
|
|
13
13
|
import { Logger } from './utils/logger.js';
|
|
14
14
|
import { getAvailablePort, saveImageFile, replaceImageSrc } from './utils/utils.js';
|
|
15
15
|
import { processSampling, buildNestingStructure } from './core/sampling.js';
|
|
16
|
-
import { buildComponentMappingPrompt, buildPlaceholderPrompt } from './core/prompt-builder.js';
|
|
16
|
+
import { buildComponentMappingPrompt, buildFullUpdatePromptForAI, buildPlaceholderPrompt } from './core/prompt-builder.js';
|
|
17
17
|
// @ts-ignore
|
|
18
18
|
import * as flatted from 'flatted';
|
|
19
19
|
import { promises as fs } from 'fs';
|
|
@@ -77,11 +77,16 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
77
77
|
nodeId: z.string().optional().describe('The ID of the node to fetch, often found as URL parameter node-id=<nodeId>, always use if provided'),
|
|
78
78
|
depth: z.number().optional().describe('How many levels deep to traverse the node tree, only use if explicitly requested by the user'),
|
|
79
79
|
local: z.boolean().optional().describe('Whether to use local data cache, default is false'),
|
|
80
|
+
update: z
|
|
81
|
+
.boolean()
|
|
82
|
+
.optional()
|
|
83
|
+
.default(false)
|
|
84
|
+
.describe('Set to true only when user explicitly wants to modify/update previously generated code. Default is false (create new code).'),
|
|
80
85
|
}, async (args) => {
|
|
81
86
|
try {
|
|
82
87
|
trackToolCall('d2c_figma');
|
|
83
88
|
Logger.log(`收到工具调用参数:`, JSON.stringify(args, null, 2));
|
|
84
|
-
const { fileKey, nodeId, depth, local } = args;
|
|
89
|
+
const { fileKey, nodeId, depth, local, update = false } = args;
|
|
85
90
|
let config = await configManager.load();
|
|
86
91
|
let hasLaunchWebview = false;
|
|
87
92
|
// 检测 VSCode 扩展是否可用
|
|
@@ -99,19 +104,21 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
99
104
|
Logger.log('获取根目录时出错:', error);
|
|
100
105
|
}
|
|
101
106
|
await startListening();
|
|
102
|
-
|
|
103
|
-
|
|
107
|
+
let userConfirmedChanges;
|
|
108
|
+
let userHtmlDiff; // 存储 HTML diff 文本
|
|
109
|
+
// 没有配置figmaApiKey,非数据推送模式,无法预览,直接唤起配置页面
|
|
110
|
+
if (!config.mcp?.figmaApiKey && !local) {
|
|
104
111
|
hasLaunchWebview = true;
|
|
105
112
|
let configDataString;
|
|
106
113
|
if (isVSCodePluginAvailable) {
|
|
107
114
|
// 优先使用 VSCode 扩展
|
|
108
115
|
Logger.log('使用 VSCode 扩展获取用户输入');
|
|
109
|
-
configDataString = await getUserInputFromVSCode({ fileKey: fileKey, nodeId: nodeId });
|
|
116
|
+
configDataString = await getUserInputFromVSCode({ fileKey: fileKey, nodeId: nodeId, mode: update ? 'update' : 'create' });
|
|
110
117
|
}
|
|
111
118
|
else {
|
|
112
119
|
// 降级到网页浏览器
|
|
113
120
|
Logger.log('VSCode 扩展不可用,降级到网页浏览器');
|
|
114
|
-
configDataString = await getUserInput({ fileKey: fileKey, nodeId: nodeId });
|
|
121
|
+
configDataString = await getUserInput({ fileKey: fileKey, nodeId: nodeId, mode: update ? 'update' : 'create' });
|
|
115
122
|
}
|
|
116
123
|
console.log('getting configDataString', configDataString);
|
|
117
124
|
if (!configDataString || configDataString.trim() === '') {
|
|
@@ -119,7 +126,7 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
119
126
|
}
|
|
120
127
|
else {
|
|
121
128
|
const configData = JSON.parse(configDataString);
|
|
122
|
-
const { mcp, groupsData, ...rest } = configData;
|
|
129
|
+
const { mcp, groupsData, confirmedChanges, htmlDiff, ...rest } = configData;
|
|
123
130
|
config = {
|
|
124
131
|
...config,
|
|
125
132
|
mcp,
|
|
@@ -128,6 +135,8 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
128
135
|
[fileKey]: rest,
|
|
129
136
|
},
|
|
130
137
|
};
|
|
138
|
+
userConfirmedChanges = confirmedChanges;
|
|
139
|
+
userHtmlDiff = htmlDiff; // 保存 HTML diff
|
|
131
140
|
mcpServer.setConfig(config.mcp);
|
|
132
141
|
configManager.save(config);
|
|
133
142
|
if (rest) {
|
|
@@ -160,12 +169,12 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
160
169
|
await fileManager.saveFile(fileKey, nodeId, 'nodeList.json', flatted.stringify(d2cNodeList));
|
|
161
170
|
await fileManager.saveFile(fileKey, nodeId, 'imageMap.json', flatted.stringify(imageMap));
|
|
162
171
|
// 保存figma绝对定位代码
|
|
163
|
-
await fileManager.
|
|
172
|
+
await fileManager.saveAbsoluteHtml(fileKey, nodeId, absoluteHtml);
|
|
164
173
|
}
|
|
165
174
|
else {
|
|
166
175
|
d2cNodeList = flatted.parse(await fileManager.loadFile(fileKey, nodeId, 'nodeList.json'));
|
|
167
176
|
imageMap = flatted.parse(await fileManager.loadFile(fileKey, nodeId, 'imageMap.json'));
|
|
168
|
-
absoluteHtml = await fileManager.
|
|
177
|
+
absoluteHtml = await fileManager.loadAbsoluteHtml(fileKey, nodeId);
|
|
169
178
|
console.log('cache load data');
|
|
170
179
|
}
|
|
171
180
|
console.log('d2cNodeList', d2cNodeList);
|
|
@@ -177,10 +186,10 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
177
186
|
Logger.log(`收到网页工具调用参数:`, JSON.stringify(args, null, 2));
|
|
178
187
|
let configDataString;
|
|
179
188
|
if (isVSCodePluginAvailable) {
|
|
180
|
-
configDataString = await getUserInputFromVSCode({ fileKey: fileKey, nodeId: nodeId });
|
|
189
|
+
configDataString = await getUserInputFromVSCode({ fileKey: fileKey, nodeId: nodeId, mode: update ? 'update' : 'create' });
|
|
181
190
|
}
|
|
182
191
|
else {
|
|
183
|
-
configDataString = await getUserInput({ fileKey: fileKey, nodeId: nodeId });
|
|
192
|
+
configDataString = await getUserInput({ fileKey: fileKey, nodeId: nodeId, mode: update ? 'update' : 'create' });
|
|
184
193
|
}
|
|
185
194
|
console.log('收到网页提交数据', configDataString);
|
|
186
195
|
if (!configDataString || configDataString.trim() === '') {
|
|
@@ -188,7 +197,9 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
188
197
|
}
|
|
189
198
|
else {
|
|
190
199
|
const configData = JSON.parse(configDataString);
|
|
191
|
-
const { mcp, groupsData, ...rest } = configData;
|
|
200
|
+
const { mcp, groupsData, confirmedChanges, htmlDiff, ...rest } = configData;
|
|
201
|
+
userConfirmedChanges = confirmedChanges;
|
|
202
|
+
userHtmlDiff = htmlDiff; // 保存 HTML diff
|
|
192
203
|
// 保存旧配置用于比较
|
|
193
204
|
const oldFileConfig = config.fileConfigs?.[fileKey] || defaultConfigData;
|
|
194
205
|
config = {
|
|
@@ -227,6 +238,22 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
227
238
|
}
|
|
228
239
|
}
|
|
229
240
|
}
|
|
241
|
+
// Update 模式:直接返回提示词,不需要复杂的采样逻辑
|
|
242
|
+
if (update) {
|
|
243
|
+
// 保存图片文件
|
|
244
|
+
saveImageFile({ imageMap, root });
|
|
245
|
+
Logger.log(`Update 模式: 收到已构建的提示词,直接返回`);
|
|
246
|
+
Logger.log(`Update 模式: 变更点数量 - ${userConfirmedChanges?.length || 0} 个`);
|
|
247
|
+
Logger.log(`Update 模式: HTML Diff 长度 - ${userHtmlDiff?.length || 0} 字符`);
|
|
248
|
+
return {
|
|
249
|
+
content: [
|
|
250
|
+
{
|
|
251
|
+
type: 'text',
|
|
252
|
+
text: buildFullUpdatePromptForAI(userConfirmedChanges, { htmlDiff: userHtmlDiff }),
|
|
253
|
+
},
|
|
254
|
+
],
|
|
255
|
+
};
|
|
256
|
+
}
|
|
230
257
|
// 从 fileManager 按 nodeId 加载 groupsData 和 promptSetting
|
|
231
258
|
const groupsData = await fileManager.loadGroupsData(fileKey, nodeId);
|
|
232
259
|
const savedPromptSetting = await fileManager.loadPromptSetting(fileKey, nodeId);
|
|
@@ -385,10 +412,10 @@ mcpServer.tool('d2c_figma', 'Convert Figma Design File to Code', {
|
|
|
385
412
|
const markedComponents = [];
|
|
386
413
|
if (groupsData && groupsData.length > 0) {
|
|
387
414
|
groupsData.forEach((group) => {
|
|
388
|
-
if (group.marked && group.screenshot
|
|
415
|
+
if (group.marked && group.screenshot && group.name) {
|
|
389
416
|
markedComponents.push({
|
|
390
417
|
name: group.name,
|
|
391
|
-
signature: group.screenshot
|
|
418
|
+
signature: group.screenshot,
|
|
392
419
|
});
|
|
393
420
|
}
|
|
394
421
|
});
|
|
@@ -520,6 +547,9 @@ mcpServer.tool('mark_components', 'Mark and save components to project component
|
|
|
520
547
|
super: comp.super,
|
|
521
548
|
description: comp.description,
|
|
522
549
|
};
|
|
550
|
+
if (comp.signature) {
|
|
551
|
+
storedComponent.signature = comp.signature;
|
|
552
|
+
}
|
|
523
553
|
if (existingIndex !== undefined) {
|
|
524
554
|
// 更新已存在的组件(保留原始导入时间)
|
|
525
555
|
const originalImportedAt = existingComponents[existingIndex].importedAt;
|