@szc-ft/mcp-szcd-client 0.24.0 → 0.25.0

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.
Files changed (31) hide show
  1. package/agents/build.js +22 -12
  2. package/agents/opencode-extension/agents/szcd-component-expert.md +92 -48
  3. package/agents/qwen-extension/agents/szcd-component-expert.md +92 -48
  4. package/agents/src/szcd-component-expert.md +92 -48
  5. package/agents/src/tools.json +1 -1
  6. package/agents/szcd-component-expert.md +92 -48
  7. package/agents/szcd-component-expert.qoder.md +93 -49
  8. package/agents/szcd-component-expert.trae.md +92 -48
  9. package/opencode-extension/agents/szcd-component-expert.md +92 -48
  10. package/opencode-extension/skills/local-api-tool/SKILL.md +164 -60
  11. package/opencode-extension/skills/local-api-tool/scripts/extract_swagger.py +477 -0
  12. package/opencode-extension/skills/szcd-component-helper/SKILL.md +7 -4
  13. package/opencode-extension/skills/szcd-design-to-code/SKILL.md +95 -24
  14. package/package.json +1 -1
  15. package/qwen-extension/agents/szcd-component-expert.md +92 -48
  16. package/qwen-extension/qwen-extension.json +1 -1
  17. package/qwen-extension/skills/local-api-tool/SKILL.md +164 -60
  18. package/qwen-extension/skills/local-api-tool/scripts/extract_swagger.py +477 -0
  19. package/qwen-extension/skills/szcd-component-helper/SKILL.md +7 -4
  20. package/qwen-extension/skills/szcd-design-to-code/SKILL.md +95 -24
  21. package/scripts/lib/claude-code.js +1 -1
  22. package/scripts/lib/common.js +44 -0
  23. package/scripts/lib/opencode.js +1 -1
  24. package/scripts/lib/qoder.js +1 -1
  25. package/scripts/lib/trae-cli.js +1 -1
  26. package/scripts/lib/trae-ide.js +1 -1
  27. package/scripts/postinstall.js +1 -0
  28. package/standard-skill/local-api-tool/SKILL.md +164 -60
  29. package/standard-skill/local-api-tool/scripts/extract_swagger.py +477 -0
  30. package/standard-skill/szcd-component-helper/SKILL.md +7 -4
  31. package/standard-skill/szcd-design-to-code/SKILL.md +95 -24
@@ -55,29 +55,32 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
55
55
 
56
56
  ### 步骤2.5:Sketch 文件解析(有 .sketch 文件时执行)
57
57
 
58
- **核心原则**:写代码之前必须拿到所有 `text` 和 `rectangle` 节点的完整样式 Token,禁止凭节点名猜测颜色/字号/背景色。`getMultipleNodeInfo` 支持任意数量 ID(内部自动分片),比逐个 `getNodeInfo` 快 10 倍以上。
58
+ **核心原则**:写代码之前必须拿到所有 `text`、`rectangle`、`group` 节点的完整样式 Token + 父子层级,禁止凭节点名猜测颜色/字号/背景色,禁止用 x 坐标平面判定元素归属。`queryNodes.type` 接受数组、`getMultipleNodeInfo` 内部自动分片,比逐个 `getNodeInfo` 快 10 倍以上。
59
59
 
60
- **工具调用顺序(优化后,4 次主调用)**:
60
+ **工具调用顺序(sketch-mcp-server ≥ v1.5.0,4 次主调用)**:
61
61
 
62
62
  1. `mcp__sketch-mcp-server__loadSketchByPath` — 加载文件(内部自动解压并保存目录,供后续 extractBitmaps 使用)
63
63
  2. `mcp__sketch-mcp-server__listPages` — 获取页面列表
64
64
  3. `mcp__sketch-mcp-server__queryNodes`(pageId, type="artboard")— 获取画板列表,确定目标画板
65
- 4. `mcp__sketch-mcp-server__getPageStructure`(pageId, mode="ids")**替代旧的 getPageStructure + getNodesSummary 组合**
66
- - 一次返回按类型分组的全量 ID:`{ text: [...], rectangle: [...], bitmap: [...], shapePath: [...] }`
67
- - 可选 `typeFilter` 参数限制返回类型
65
+ 4. `mcp__sketch-mcp-server__getPageStructure`(pageId, mode="tree")— **先看完整层级关系**,识别顶层 group 分区(如 LeftTree 区/Query+Table 区/信息栏区/标题栏区)
66
+ - 再用 `mode="ids"` 拿到按类型分组的全量 ID:`{ text: [...], rectangle: [...], group: [...], bitmap: [...], shapePath: [...] }`
68
67
  - 同时返回 `summary`(各类型统计)和 `totalIds`(总数)
69
- 5. `mcp__sketch-mcp-server__getMultipleNodeInfo`([所有 text + rectangle ID])— **支持任意数量 ID,内部自动分批处理**
70
- - 关键字段:`style.fills[0].color.hex`(背景色)、`text.color`(文字色)、`style.fontSize`、`style.fontWeight`
68
+ 5. `mcp__sketch-mcp-server__getMultipleNodeInfo`([**所有 text + rectangle + group ID 同批提交**])— **支持任意数量 ID,内部自动分批处理**
69
+ - 关键字段:`style.fills[0].color.hex`(背景色)、`text.color`(文字色)、`style.fontSize`、`style.fontWeight`、`style.borders[0]`、`style.shadows`
70
+ - **`parent: { id, name, type }`**(v1.5.0+ 新增)— 元素归属判定的核心字段,**始终用 parent 走 group 父子关系,禁止用 x/y 坐标判定归属**
71
+ - **禁止只取 text 类型**:会遗漏 rectangle/group 容器的渐变背景、边框、阴影;信息栏/卡片类区块必须连容器一起拉
71
72
  - 无需手动分批,传入全部 ID 即可(内部按 100 个一批自动处理)
72
73
 
73
- **与旧策略的差异**:
74
- - 旧策略:`getPageStructure`(可能截断) + `getNodesSummary` + 手动分批 `getMultipleNodeInfo`
75
- - 新策略:`getPageStructure(mode="ids")`(轻量全量 ID) + `getMultipleNodeInfo`(自动分片)
76
- - 调用次数:旧 6 次 4 次(含 loadSketch + listPages 合并)
74
+ **替代方案(更短,3 次主调用)**:当只关心特定类型节点时,可用 `queryNodes` 一次性拿数组类型:
75
+ ```
76
+ queryNodes({ pageId, type: ["text", "rectangle", "group"], limit: 500 })
77
+ 返回这三类节点的 ID 列表,跳过 getPageStructure(mode="ids") 步骤
78
+ ```
79
+ 适用场景:已通过 `getPageStructure(mode="tree")` 看清分区,只想批量获取关键 token 节点时。
77
80
 
78
81
  **步骤 2.5 产出物**(**只产出数据,不做组件映射**):
79
82
  - 按类型分组的全量节点 ID 列表
80
- - text/rectangle 节点的完整样式 Token
83
+ - text/rectangle/group 节点的完整样式 Token + parent 父子关系
81
84
  - bitmap ID 列表(传给步骤 2.5.1)
82
85
  - shapePath 节点名列表(传给步骤 2.5.1)
83
86
 
@@ -92,21 +95,55 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
92
95
  1. `mcp__sketch-mcp-server__extractBitmaps`(bitmapIds)— 从 .sketch 解压目录提取 bitmap PNG 资源
93
96
  - 返回 `{ bitmaps: [{ nodeId, name, base64, mimeType, size, fileName }] }`
94
97
  - 位图资源用于 CSS `background-image` 引用
95
- 2. `mcp__sketch-mcp-server__matchIconFromName`(nodeNames, library="newFont")— 匹配 iconfont 图标库
96
- - 输入 shapePath 节点名列表(如 `["表 icon", "文件 icon"]`)
97
- - 匹配策略:节点名关键词 拼音匹配图标列表
98
+ 2. `mcp__sketch-mcp-server__matchIconFromName`(nodeNames, library="newFont")— 匹配 iconfont 图标库(v1.5.0+ 评分制)
99
+ - 输入 shapePath 节点名列表(如 `["表 icon", "新建文件夹", "编组11备份"]`)
100
+ - **评分机制**:compoundIcons 强映射 +100、keyword 精确 +20、keyword 包含 +10、semanticTag +3
101
+ - 每个 nodeName 返回 **Top-3 候选**(按分数降序),让你做最终选择
98
102
  - 返回格式:
99
103
  ```json
100
104
  {
101
- "matchedIcons": [
102
- { "nodeName": "表 icon", "iconType": "icon-biao", "library": "newFont" }
105
+ "results": [
106
+ {
107
+ "nodeName": "新建文件夹",
108
+ "top3": [
109
+ { "source": "compound", "score": 104, "antdIcon": "FolderAddOutlined", "matchedBy": "文件夹|目录|folder + 新增|添加|add|plus|新建|create", "rationale": "..." },
110
+ { "source": "compound", "score": 104, "antdIcon": "FileAddOutlined" },
111
+ { "source": "compound", "score": 102, "antdIcon": "FolderOutlined" }
112
+ ],
113
+ "bestMatch": { "source": "compound", "antdIcon": "FolderAddOutlined" }
114
+ }
103
115
  ],
104
- "unmatched": ["菜单icon"],
105
- "recommendFallback": { "菜单icon": "antd MenuOutlined" },
106
- "matchRate": "80.0%"
116
+ "matchedIcons": [...], // Top-1 兼容旧字段
117
+ "unmatched": ["编组11备份"], // 无关键词信号的节点
118
+ "recommendFallback": { "编组11备份": "antd QuestionOutlined" },
119
+ "matchRate": "66.7%"
107
120
  }
108
121
  ```
109
122
 
123
+ **⚠️ 图标语义优先级(v1.5.0 已内置 compoundIcons,多数场景自动命中)**:
124
+
125
+ 实战教训:Sketch 中"编组11备份"实际是 folder-plus 图标,旧版被误判为通用 PlusOutlined(优先命中"新增"关键词吃掉了 folder 语义)。v1.5.0 评分制 + compoundIcons 强映射已修复该类问题。
126
+
127
+ **判定流程**:
128
+ 1. **优先看 `bestMatch.source`**:`compound` 表示触发了复合词强映射,可直接采用 `antdIcon`
129
+ 2. **看 Top-3 是否有合适的候选**:分数接近的候选都值得考虑
130
+ 3. **`unmatched` 节点(如"编组11备份"无关键词信号)**:必须看节点 `parent.name` 和兄弟节点上下文兜底
131
+ - 例:parent 是 LeftTree 标题区 → 多半是文件夹/分类操作图标 → `FolderAddOutlined` / `FolderOpenOutlined`
132
+ - 例:parent 是 Query 操作栏 → 多半是表单动作图标 → `SearchOutlined` / `PlusOutlined`
133
+
134
+ **参考表(内置 compoundIcons 已覆盖;列出供 unmatched 兜底参考)**:
135
+
136
+ | Sketch 节点上下文 | 期望 antd 图标 | 反例(不要选) |
137
+ |---|---|---|
138
+ | 文件夹+新增/添加 | `FolderAddOutlined` | PlusOutlined |
139
+ | 文件+新增 | `FileAddOutlined` | PlusOutlined |
140
+ | 用户+新增 | `UserAddOutlined` | PlusOutlined |
141
+ | 文件夹+打开 | `FolderOpenOutlined` | FolderOutlined |
142
+ | 编辑+笔 | `EditOutlined` | FormOutlined |
143
+ | 设置+齿轮 | `SettingOutlined` | ToolOutlined |
144
+
145
+ **操作流程**:matchIconFromName 返回 unmatched 或 fallback 为通用 `PlusOutlined/EditOutlined` 时,**先看节点 parent group 的名称/兄弟节点**,按上表选语义更精确的复合图标。
146
+
110
147
  **步骤 2.5.1 产出物**:
111
148
  - bitmap base64 资源列表 → 用于代码中的 CSS background-image
112
149
  - IconfontWapper 代码片段(`<IconfontWapper assets="newFont" type="icon-biao" />`)
@@ -128,15 +165,36 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
128
165
  - 新做法:直接传入全部 ID(如 200 个)→ 内部自动按 100 个一批处理 → 返回合并结果
129
166
  - 返回结构不变:`{ nodes: [...], total, requested, batches }`
130
167
 
131
- **经验3:text 节点是颜色/DOM 映射的两级索引**
168
+ **经验3:元素归属必须走 group 父子关系,禁止 x 坐标平面判定**
169
+
170
+ 实战教训:`'主题'text(x=272,y=149)` 被错误识别为内容区块标题,实际是左侧树标题(与树节点同 x=272 列)。同列坐标不代表同区域。
171
+
172
+ 正确做法:
173
+ - 步骤 2.5 第 4 步先 `mode="tree"` 看顶层 group 分区(通常 2-5 个,对应 LeftTree区/Query+Table区/信息栏区/标题栏区)
174
+ - `getMultipleNodeInfo`/`getNodeInfo` v1.5.0+ **自动返回** `parent: { id, name, type }` 字段,按 parent 归属到具体分区即可
175
+ - "主题"这类标题文本,先看 `parent.name` 是否带 "LeftTree" / "树" 等容器关键字,不要看 x 坐标
176
+ - 坐标仅作为同 parent 内子元素排序兜底使用
177
+
178
+ **经验4:信息栏/卡片容器必须先取 group 再取子元素**
179
+
180
+ 实战教训:步骤 2.5 仅提取 text 节点导致信息栏容器样式遗漏(渐变背景 #f3faff→#f8fdff、边框 #e9f5ff、图标编组)。
181
+
182
+ 正确做法:
183
+ - 看到画板里有 `编组N`/`infoCard`/`statBox` 等 group 节点,必须连 group 自身和内部 rectangle 一起拉 `getMultipleNodeInfo`
184
+ - group 节点的 `style.fills` 才是渐变背景、`style.borders` 才是边框
185
+ - 子图标若为 group(rectangle + shapePath),rectangle 是圆形/方形背景,shapePath 是矢量图标
186
+
187
+ **经验5:text 节点是颜色/DOM 映射的两级索引**
132
188
  每个 text 节点同时关联两种上下文,**必须同批拉取**:
133
189
  - 自身样式:`fontSize`、`fontWeight`、`text.color`
134
190
  - 所属 group 父级 rectangle 样式:`bg`、`border`、`radius`、`shadow`
135
191
 
136
192
  错误做法:先查 text 拿自身样式 → 再根据 parent ID 单独查 rectangle(多走一步)
137
- 正确做法:构造查询列表时,**把同一 group 内的 text + rectangle 节点 ID 合并提交**
193
+ 正确做法:
194
+ - 用 `queryNodes({ pageId, type: ["text", "rectangle", "group"], limit: 500 })` 一次拿三类节点的 ID
195
+ - 再用 `getMultipleNodeInfo([...全部ID])` 同批提交,每个节点返回的 `parent` 字段直接告诉你归属关系,无需二次查询
138
196
 
139
- **经验4:图表区样式提取有规律可循**
197
+ **经验6:图表区样式提取有规律可循**
140
198
 
141
199
  | 图表子元素 | 对应 Sketch 节点类型 | 关键样式字段 |
142
200
  |---|---|---|
@@ -151,7 +209,7 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
151
209
 
152
210
  识别出图表后,**图例色块**应归入 ECharts `legend` 配置(不要用 div 硬编码),**柱体色**映射到 `series.itemStyle.color`。
153
211
 
154
- **经验5:矢量图形用 matchIconFromName 自动匹配,无需手动解压**
212
+ **经验7:矢量图形用 matchIconFromName 自动匹配,无需手动解压**
155
213
  - `shapePath` / `shapeGroup` 在 sketch 节点中占比可能高达 46.8%,但 `renderNodeAsBase64` 不支持渲染
156
214
  - **新方案**:`matchIconFromName(shapePathNames)` 自动查询 iconfont 库 → 返回匹配结果
157
215
  - bitmap 用 `extractBitmaps(bitmapIds)` 自动提取 PNG 资源
@@ -206,6 +264,19 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
206
264
  | 柱状对比图 | `Bar` |
207
265
  | 饼图/环形图 | `Pie` |
208
266
 
267
+ ### ⚠️ TemplateMode 槽位传参铁律(高频踩坑)
268
+
269
+ **LeftContent / Query / PageContent 三个槽位都接收单个 ReactNode,禁止传数组**:
270
+
271
+ | ❌ 错误 | ✅ 正确 | 后果 |
272
+ |---|---|---|
273
+ | `LeftContent={[<LeftTree/>]}` | `LeftContent={<LeftTree/>}` | 数组会触发多余 tab 渲染 |
274
+ | `LeftContent={[<LeftTree/>, <Filter/>]}` | `LeftContent={<><LeftTree/><Filter/></>}` 或包一层 div | 同上 |
275
+ | `Query={[<Query/>]}` | `Query={<Query/>}` | 同上 |
276
+ | `PageContent={[<TableOrList/>]}` | `PageContent={<TableOrList/>}` | 同上 |
277
+
278
+ **判定方法**:Sketch 中只要某个分区是"单棵树/单个查询面板/单个表格",对应槽位就传单个组件实例。需要多个并列时用 Fragment `<>...</>` 或容器 div 包裹,**不要用数组**。
279
+
209
280
  **长尾场景走语义搜索**(不进文档,避免膨胀):
210
281
  - 数据可视化长尾:`Radar` / `Gauge` / `Funnel`(用 `Line/Bar/Pie` 之外的图表)
211
282
  - 表格子类型长尾:`DragSortTable`(拖拽排序)、`steps` 步骤条表单
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@szc-ft/mcp-szcd-client",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "MCP client for szcd component library - auto-configures AI coding tools with MCP server, skills, agents and commands",
5
5
  "keywords": [
6
6
  "mcp",
@@ -66,11 +66,11 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
66
66
 
67
67
  ### 步骤2.5:Sketch 文件解析(条件执行)
68
68
 
69
- **当用户提供 .sketch 设计文件时**,使用 `sketch-mcp-server`(独立 MCP Server,stdio 模式)解析,直接提取结构化数据,结合组件库架构推理组件方案,无需经过视觉模型和 `map_design_data`。
69
+ **当用户提供 .sketch 设计文件时**,使用 `sketch-mcp-server`(独立 MCP Server,stdio 模式,**v1.5.0+**)解析,直接提取结构化数据,结合组件库架构推理组件方案,无需经过视觉模型和 `map_design_data`。
70
70
 
71
- **核心原则**:写代码前必须先 `getMultipleNodeInfo` 拉取所有 `text` 和 `rectangle` 节点的完整样式 Token(`style.fills[0].color.hex`、`text.color`、`style.fontSize`),禁止凭节点名猜测颜色和样式。一次批量查询(50-100 ID)比逐个 `getNodeInfo` 10 倍以上,且不会遗漏。
71
+ **核心原则**:写代码前必须先 `getMultipleNodeInfo` 拉取所有 `text`、`rectangle`、`group` 节点的完整样式 Token + 父子归属。`queryNodes.type` 接受数组(一次拿三类)、`getMultipleNodeInfo` 内部自动分片、每个节点自动返回 `parent: {id,name,type}`,禁止凭节点名猜测样式,禁止用 x 坐标判定元素归属。
72
72
 
73
- **工作流(6步深度探查,像素级还原)**:
73
+ **工作流(4 步,sketch-mcp-server v1.5.0+)**:
74
74
 
75
75
  1. **加载文件**:
76
76
  - `loadSketchByPath` 加载 .sketch 文件
@@ -78,42 +78,42 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
78
78
  - `queryNodes`(pageId, type="artboard")获取画板列表
79
79
  - 根据画板名称选择目标页面
80
80
 
81
- 2. **获取完整节点树**:
82
- - `getPageStructure`(pageId)**或** `getDocumentStructure`(includeDetails=true)— 拿到完整节点树 + 所有节点 ID
83
- - 必须 `includeDetails=true`,否则拿不到初始样式
84
- - 拿到所有节点 ID 列表,为下一步分组做准备
85
-
86
- 3. **按类型分组统计**:
87
- - `getPageStructure`(pageId, mode="summary", groupBy="type")— 按类型分组,统计 text/rectangle/group 各多少个
88
- - 识别组件模式:
89
- - `group(rectangle + text)` = 标签组件(如状态徽章)
90
- - `group(text + text + rectangle...)` = 表单项
91
- - `group(text 列表 + 边框)` = 表格行
92
- - 决定下一批 `getMultipleNodeInfo` 的目标节点范围(所有 type=text + type=rectangle)
93
-
94
- 4. **批量拉取样式 Token**:
95
- - `getMultipleNodeInfo`([id1, id2, ...])— 每次 ≤ 100 个节点
81
+ 2. **获取分区结构**:
82
+ - `getPageStructure`(pageId, mode="tree", maxDepth=3)— 看顶层 group 分区(通常 2-5 个,对应 LeftTree区/Query+Table区/信息栏区/标题栏区)
83
+ - 记下每个分区根 group 的 id 和 name,后续按 `parent` 字段归属元素
84
+
85
+ 3. **批量获取目标节点 ID**:
86
+ - 推荐:`queryNodes({ pageId, type: ["text", "rectangle", "group"], limit: 500 })` — **type 数组**一次拿三类节点的 ID
87
+ - 备选:`getPageStructure(pageId, mode="ids")` 返回按类型分组的全量 ID `{ text: [...], rectangle: [...], group: [...], bitmap: [...], shapePath: [...] }`
88
+ - 顺手记下 bitmap/shapePath 节点列表,传给步骤 2.5.1
89
+
90
+ 4. **批量拉取样式 Token + 父子归属**:
91
+ - `getMultipleNodeInfo`([id1, id2, ...])— 传入全部 ID,**内部自动按 100 个一批分片**,无需手动拆分
92
+ - **同批必须包含 text + rectangle + group 三类节点 ID**(漏 group 会丢失渐变背景/边框/阴影)
96
93
  - 关键字段提取:
97
- - 背景色:`style.fills[0].color.hex`
94
+ - 背景色:`style.fills[0].color.hex`(含 group 容器的渐变)
98
95
  - 文字色:`text.color`(部分版本在 `style.fills[0].color`)
99
96
  - 字号:`style.fontSize`
100
97
  - 字重:`style.fontWeight`
101
98
  - 边框:`style.borders[0].color.hex` + `thickness`
99
+ - 阴影:`style.shadows`
100
+ - **父子归属**:`parent: { id, name, type }` ← v1.5.0+ 自动返回,元素归属判定唯一可信来源
102
101
  - **禁止**逐个 `getNodeInfo` 探查
103
102
 
104
103
  **步骤 2.5 产出物**(**只产出数据,不做组件映射**):
105
- - Sketch 节点结构 + 全量节点 ID 列表
106
- - text/rectangle 节点的完整样式 Token
104
+ - Sketch 顶层分区结构(步骤 2 tree)
105
+ - text/rectangle/group 节点的完整样式 Token + parent 父子关系
107
106
  - 图表区结构规律识别结果
107
+ - bitmap ID 列表 + shapePath 节点名列表(传给步骤 2.5.1)
108
108
 
109
109
  组件候选列表推理**不**在步骤 2.5 内部完成,**统一在主流程步骤 3.5 中结合步骤 1 的 `templatePatterns` 推理**。
110
110
 
111
- **Sketch → szcd 工作流(结构化直传 + 样式 Token,无需视觉模型)**:
111
+ **Sketch → szcd 工作流(v1.5.0+)**:
112
112
  ```
113
- .sketch → loadSketchByPath → listPages → queryNodes(pageId, type=artboard)
114
- → getPageStructure(includeDetails=true) / getDocumentStructure(includeDetails=true)
115
- getPageStructure(pageId, mode="summary", groupBy="type")
116
- → getMultipleNodeInfo([所有text+rectangle节点ID]) 步骤 2.5 结束
113
+ .sketch → loadSketchByPath → listPages → queryNodes(pageId, type="artboard")
114
+ → getPageStructure(pageId, mode="tree", maxDepth=3) ← 拿分区
115
+ queryNodes(pageId, type=["text","rectangle","group"]) ← 拿全量 ID(数组类型)
116
+ → getMultipleNodeInfo([全部 ID]) 自动分片,含 parent 字段
117
117
  → [进入主流程步骤 3.5 统一推理]
118
118
  ```
119
119
 
@@ -121,16 +121,17 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
121
121
 
122
122
  | 步骤 | 第一次做错的 | 应该做的 |
123
123
  |------|------------|---------|
124
- | 结构获取 | `getDocumentStructure(includeDetails=false)` 只有名称和位置 | `includeDetails=true` `getPageStructure`,拿到初始样式 |
125
- | 样式提取 | 没做 | `getMultipleNodeInfo` 批量拉取所有 type=text 和 type=rectangle 节点 |
126
- | 组件识别 | 凭节点名猜测(如看到 "tag" 节点就写 `<Tag>`) | `getPageStructure(pageId, mode="summary", groupBy="type")` 统计类型分布,识别 text+rectangle 组合 → 标签组件 |
127
- | 颜色提取 | 跳过 | 对每个 rectangle(背景)+ text(文字)取 `style.fills[0].color.hex` + `text.color` |
124
+ | 分区识别 | 直接拉所有节点详情,靠 x/y 反推分区 | `getPageStructure(mode="tree", maxDepth=3)` 先看顶层 group 分布 |
125
+ | 节点收集 | 分两次调用 queryNodes text 和 rectangle | `queryNodes(type=["text","rectangle","group"])` 一次拿三类 |
126
+ | 样式提取 | 没做 | `getMultipleNodeInfo([全部 ID])` 内部自动分片,**单次调用** |
127
+ | 元素归属 | x/y 坐标判定("x=272 列都是同区域") | `getMultipleNodeInfo` 返回的 `parent.id/name` 字段 |
128
+ | 颜色提取 | 跳过 group 只取 text/rectangle | 同批提交 group ID,从 `style.fills` 取渐变背景 |
128
129
 
129
- **实战经验沉淀(重要,4 条核心收获)**:
130
+ **实战经验沉淀(重要)**:
130
131
 
131
132
  **收获 1:首轮 `getMultipleNodeInfo` 必须全量拉取,不能挑**
132
133
  - 错误做法:先查 7 个顶层容器,再根据需要分批补漏(结果补了 7 轮 ≈ 108 个节点)
133
- - 正确做法:`getPageStructure(pageId)` 一次性拿全量 ID → `getMultipleNodeInfo(全部 text + 全部 rectangle 节点 ID)`,≤100 个/批,**2 批搞定**
134
+ - 正确做法:`queryNodes(type=["text","rectangle","group"])` 一次性拿全量 ID → `getMultipleNodeInfo([全部 ID])`,**单次调用**(内部自动分片)
134
135
 
135
136
  **收获 2:text 节点是颜色/DOM 映射的两级索引**
136
137
  每个 text 节点同时关联两种上下文,**必须同批拉取**:
@@ -138,9 +139,28 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
138
139
  - 所属 group 父级 rectangle 样式:`bg`、`border`、`radius`、`shadow`
139
140
 
140
141
  错误做法:先查 text 拿自身样式 → 再根据 parent ID 单独查 rectangle(多走一步)
141
- 正确做法:构造查询列表时,**把同一 group 内的 text + rectangle 节点 ID 合并提交**
142
+ 正确做法:用 `queryNodes(type=["text","rectangle","group"])` 一次拿三类 ID,`getMultipleNodeInfo` 返回的 `parent` 字段直接告诉你归属关系
143
+
144
+ **收获 3:元素归属必须走 group 父子关系,禁止 x 坐标平面判定**
145
+
146
+ 实战教训:`'主题'text(x=272,y=149)` 被错误识别为内容区块标题,实际是左侧树标题(与树节点同 x=272 列)。同列坐标不代表同区域。
147
+
148
+ 正确做法:
149
+ - 步骤 2 拿到完整节点树后,先识别顶层 group 分区(通常 2-5 个,对应 LeftTree区/Query+Table区/信息栏区/标题栏区)
150
+ - `getMultipleNodeInfo` v1.5.0+ **自动返回** `parent: { id, name, type }` 字段,按 parent 归属到具体分区
151
+ - "主题"这类标题文本,先看 `parent.name` 是否带 "LeftTree" / "树" / "PageContent" 等容器关键字,不要看 x 坐标
152
+ - 坐标仅作为同 parent 内子元素排序兜底使用
142
153
 
143
- **收获 3:图表区样式提取有规律可循**
154
+ **收获 4:信息栏/卡片容器必须先取 group 再取子元素**
155
+
156
+ 实战教训:仅提取 text 节点导致信息栏容器样式遗漏(渐变背景 #f3faff→#f8fdff、边框 #e9f5ff、图标编组)。
157
+
158
+ 正确做法:
159
+ - 看到画板里有 `编组N`/`infoCard`/`statBox` 等 group 节点,必须连 group 自身和内部 rectangle 一起拉 `getMultipleNodeInfo`
160
+ - group 节点的 `style.fills` 才是渐变背景、`style.borders` 才是边框
161
+ - 子图标若为 group(rectangle + shapePath),rectangle 是圆形/方形背景,shapePath 是矢量图标
162
+
163
+ **收获 5:图表区样式提取有规律可循**
144
164
 
145
165
  | 图表子元素 | 对应 Sketch 节点类型 | 关键样式字段 |
146
166
  |---|---|---|
@@ -155,23 +175,34 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
155
175
 
156
176
  识别出图表后,**图例色块**应归入 ECharts `legend` 配置(不要用 div 硬编码),**柱体色**映射到 `series.itemStyle.color`。
157
177
 
158
- **收获 4:矢量图形是工具链盲区(兜底方案)**
159
- - `shapePath` / `shapeGroup` 在 sketch 节点中占比可能高达 46.8%(实战中 434/926),但 `renderNodeAsBase64` 不支持渲染
160
- - 解压 `.sketch`(zip 格式)只能提取 `bitmap` 中内嵌的 PNG/PDF(实战中可能仅 2 张,常是侧边栏 Logo)
161
- - **兜底方案**:① 用解压提取的 PNG/PDF 资源;② 无资源时用 antd `@ant-design/icons` 同语义图标替代;③ 在代码注释中标注"⚠️ 矢量图标用 antd 图标替代,原始 Sketch 为 shapePath"
178
+ **收获 6:矢量图形 + 图标语义优先级(v1.5.0 已内置 compoundIcons)**
179
+ - `shapePath` / `shapeGroup` 在 sketch 节点中占比可能高达 46.8%,`renderNodeAsBase64` 不支持渲染
180
+ - 解压 `.sketch` 只能提取 `bitmap` 中内嵌的 PNG/PDF(常仅几张,通常是 Logo)
181
+ - **`matchIconFromName` v1.5.0+ 评分制**:每个 nodeName 返回 Top-3 候选,complex 词组合(如"文件夹+新增")自动命中 `FolderAddOutlined`(compound score 100+),不会被"新增"单独 +20 分压制
182
+ - 优先看 `bestMatch.source === "compound"`:表示已强映射,直接采用 `antdIcon`
183
+ - `unmatched`(无关键词信号,如"编组11备份")必须看节点 `parent.name` 和兄弟节点上下文兜底
184
+
185
+ **参考表(内置 compoundIcons 已覆盖;列出供 unmatched 兜底参考)**:
162
186
 
163
- **提示**:
187
+ | Sketch 节点上下文 | 期望 antd 图标 | 反例(不要选) |
188
+ |---|---|---|
189
+ | 文件夹+新增/添加 | `FolderAddOutlined` | PlusOutlined |
190
+ | 文件+新增 | `FileAddOutlined` | PlusOutlined |
191
+ | 用户+新增 | `UserAddOutlined` | PlusOutlined |
192
+ | 文件夹+打开 | `FolderOpenOutlined` | FolderOutlined |
193
+ | 编辑+笔 | `EditOutlined` | FormOutlined |
194
+ | 设置+齿轮 | `SettingOutlined` | ToolOutlined |
195
+
196
+ - **兜底方案**:① 用 `extractBitmaps` 提取的 PNG/PDF 资源;② `matchIconFromName` 的 Top-1(若 source=compound);③ unmatched 时按 parent 上下文 + 上表选 antd `@ant-design/icons` 复合图标;④ 在代码注释中标注"⚠️ 矢量图标用 antd 图标替代,原始 Sketch 为 shapePath"
197
+
198
+ **提示(sketch-mcp-server v1.5.0+)**:
164
199
  - 大型 .sketch 文件先 `queryNodes(pageId, type="artboard")` 锁定目标画板,避免一次性加载整个文档
165
- - `getPageStructure(pageId, mode="summary")` token 节省关键:先按类型分组统计,再决定要查哪些节点 ID
166
- - 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部自动分批),无需手动拆分
200
+ - `queryNodes(pageId, type=["text","rectangle","group"])` 一次拿三类节点 ID(type 字段支持数组),跳过 `getPageStructure(mode="ids")` 单独调用
201
+ - `getPageStructure(pageId, mode="tree", maxDepth=2-3)` 用于看分区层级;`mode="summary"` 用于按类型统计概况
202
+ - 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段,元素归属直接走 parent,禁止用 x/y 坐标
203
+ - `matchIconFromName` 评分制返回 Top-3 + `bestMatch.source === "compound"` 强映射,shapePath 节点优先走它
167
204
  - 仅当结构化样式数据仍不足(如复杂渐变、阴影)时,才回退到 `renderNodeAsBase64` + `analyze_design_image`
168
- - 如果 sketch-mcp-server 工具不可用,提示用户安装:`npm install -g sketch-mcp-server`
169
-
170
- **提示**:
171
- - 大型 .sketch 文件用 `getPageStructure(maxDepth=1-2)` 即可获取布局概况,避免深层递归超时
172
- - `queryNodes(pageId, type="artboard")` 优先于 `getPageStructure`,更轻量
173
- - 仅当结构化数据不足以判断视觉细节(颜色、间距、字体)时,才回退到 `renderNodeAsBase64` + `analyze_design_image`
174
- - 如果 sketch-mcp-server 工具不可用,提示用户安装:`npm install -g sketch-mcp-server`
205
+ - 如果 sketch-mcp-server 工具不可用,提示用户安装:`npm install -g @szc-ft/sketch-mcp-server`
175
206
 
176
207
  ### 步骤3:分析设计稿(条件执行)
177
208
 
@@ -240,6 +271,19 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
240
271
  | 可编辑表格(单元格直接输入) | `TableOrList(componentType="EditableProTable")` | 可编辑表格特征 |
241
272
  | 卡片列表(非表格式数据卡片) | `TableOrList(componentType="ProList")` | 卡片布局特征 |
242
273
 
274
+ #### ⚠️ TemplateMode 槽位传参铁律(高频踩坑)
275
+
276
+ **LeftContent / Query / PageContent 三个槽位都接收单个 ReactNode,禁止传数组**:
277
+
278
+ | ❌ 错误 | ✅ 正确 | 后果 |
279
+ |---|---|---|
280
+ | `LeftContent={[<LeftTree/>]}` | `LeftContent={<LeftTree/>}` | 数组会触发多余 tab 渲染 |
281
+ | `LeftContent={[<LeftTree/>, <Filter/>]}` | `LeftContent={<><LeftTree/><Filter/></>}` 或包一层 div | 同上 |
282
+ | `Query={[<Query/>]}` | `Query={<Query/>}` | 同上 |
283
+ | `PageContent={[<TableOrList/>]}` | `PageContent={<TableOrList/>}` | 同上 |
284
+
285
+ **判定方法**:Sketch 中只要某个分区是"单棵树/单个查询面板/单个表格",对应槽位就传单个组件实例。需要多个并列时用 Fragment `<>...</>` 或容器 div 包裹,**不要用数组**。
286
+
243
287
  **长尾场景走语义搜索**(不进文档,避免膨胀):
244
288
 
245
289
  *数据可视化长尾*:`Radar`(雷达图)、`Gauge`(仪表盘)、`Funnel`(漏斗图)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "szcd-component-helper",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "szcd 组件库 MCP 助手 — 查询组件信息、匹配需求、生成代码",
5
5
  "mcpServers": {
6
6
  "szcd-component-helper": {