@szc-ft/mcp-szcd-client 0.25.0 → 0.27.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 (26) hide show
  1. package/agents/opencode-extension/agents/szcd-component-expert.md +160 -40
  2. package/agents/qwen-extension/agents/szcd-component-expert.md +160 -40
  3. package/agents/src/szcd-component-expert.md +187 -40
  4. package/agents/src/tools.json +2 -2
  5. package/agents/szcd-component-expert.md +160 -40
  6. package/agents/szcd-component-expert.qoder.md +186 -41
  7. package/agents/szcd-component-expert.trae.md +185 -40
  8. package/opencode-extension/agents/szcd-component-expert.md +160 -40
  9. package/opencode-extension/skills/local-api-tool/SKILL.md +160 -28
  10. package/opencode-extension/skills/local-api-tool/scripts/extract-swagger.mjs +625 -0
  11. package/opencode-extension/skills/local-api-tool/scripts/extract_swagger.py +125 -9
  12. package/opencode-extension/skills/szcd-component-helper/SKILL.md +12 -13
  13. package/opencode-extension/skills/szcd-design-to-code/SKILL.md +250 -28
  14. package/package.json +1 -1
  15. package/qwen-extension/agents/szcd-component-expert.md +160 -40
  16. package/qwen-extension/qwen-extension.json +1 -1
  17. package/qwen-extension/skills/local-api-tool/SKILL.md +160 -28
  18. package/qwen-extension/skills/local-api-tool/scripts/extract-swagger.mjs +625 -0
  19. package/qwen-extension/skills/local-api-tool/scripts/extract_swagger.py +125 -9
  20. package/qwen-extension/skills/szcd-component-helper/SKILL.md +12 -13
  21. package/qwen-extension/skills/szcd-design-to-code/SKILL.md +250 -28
  22. package/standard-skill/local-api-tool/SKILL.md +160 -28
  23. package/standard-skill/local-api-tool/scripts/extract-swagger.mjs +625 -0
  24. package/standard-skill/local-api-tool/scripts/extract_swagger.py +125 -9
  25. package/standard-skill/szcd-component-helper/SKILL.md +12 -13
  26. package/standard-skill/szcd-design-to-code/SKILL.md +251 -28
@@ -42,7 +42,7 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
42
42
  **在正式开始之前,获取项目架构全局视图,同时验证 MCP 连接。**
43
43
 
44
44
  执行动作:
45
- 1. 调用 `get_architecture_overview`(detail="summary")获取7层架构图、模板组合模式、推荐使用顺序和 LLM 映射错误提示
45
+ 1. 调用 `get_architecture_overview`(detail="full")一次性获取:7 层架构图、模板组合模式、推荐使用顺序、LLM 映射错误提示,**以及 `componentSummary`(全量组件 + 设计元信息:layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)+ `styleMapping`(节点样式映射)+ `assetExtraction`(图标/位图/图表色提取规则)**——这些是步骤 3.5 推理组件候选和步骤 5 样式注入的核心依据
46
46
  2. 如果连接失败,**立即停止并返回错误信息**,告知用户需要先配置 MCP 服务器
47
47
  3. 如果成功,根据返回的 `templatePatterns` 初步判断用户需求匹配哪个模板
48
48
 
@@ -131,6 +131,27 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
131
131
  | 元素归属 | 凭 x/y 坐标判定("x=272 列都是同区域") | 看 `getMultipleNodeInfo` 返回的 `parent.id/name` 字段 |
132
132
  | 颜色提取 | 跳过 group 只取 text/rectangle | 同批提交 group ID,从 `style.fills` 取渐变背景 |
133
133
 
134
+ #### getMultipleNodeInfo 返回字段契约(sketch-mcp-server ≥ v1.6.1)
135
+
136
+ | 字段 | 适用类型 | 用途 |
137
+ |------|----------|------|
138
+ | `position:{x,y}` + `size:{width,height}` | 全部 | 步骤 2.6 表 1/2/3/4 的坐标推理 |
139
+ | `parent:{id,name,type}` | 全部(顶层除外) | 步骤 2.6 表 1 大区归属、Pass 2 质检 |
140
+ | `style.fills[].{color,gradient}` | rectangle / group / text | 表 5 样式映射 |
141
+ | `style.borders[].{color,thickness}` | rectangle / group | 表 5 样式映射 |
142
+ | `style.shadows[]` | rectangle / group | 表 5 样式映射 |
143
+ | `text.attributes[0].attributes.{fontFamily,fontSize,color,lineHeight}` | text | 字号/字重/颜色(fontFamily 编码字重,如 PingFangSC-Semibold → 600) |
144
+ | `children:[id]` | group / artboard | 推断容器子节点集合(与 parent 反向印证) |
145
+ | `isVisualContainer:bool` | group / artboard | true = 该 group 自身带 fills/borders/shadows,必须作为 UI 容器渲染(不是纯图层分组) |
146
+ | `shape.cornerRadius` | rectangle / oval | 圆角 |
147
+
148
+ **字段缺失自检**(任一项失败 → sketch-mcp-server 版本过旧,升级到 ≥ v1.6.1 后重跑):
149
+
150
+ - [ ] 任取一个 text 节点,`parent.id` 非空 ✅
151
+ - [ ] 任取一个 group 节点,`isVisualContainer` 类型是 boolean、`children` 是数组 ✅
152
+ - [ ] 任取一个 rectangle 节点,`style.fills` 数组存在(即使为空也要是 `[]` 不能 undefined) ✅
153
+ - [ ] 任取一个 text 节点,`text.attributes[0].attributes.fontFamily` 可读出(编码字重) ✅
154
+
134
155
  **实战经验沉淀(重要)**:
135
156
 
136
157
  **收获 1:首轮 `getMultipleNodeInfo` 必须全量拉取,不能挑**
@@ -145,15 +166,20 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
145
166
  错误做法:先查 text 拿自身样式 → 再根据 parent ID 单独查 rectangle(多走一步)
146
167
  正确做法:用 `queryNodes(type=["text","rectangle","group"])` 一次拿三类 ID,`getMultipleNodeInfo` 返回的 `parent` 字段直接告诉你归属关系
147
168
 
148
- **收获 3:元素归属必须走 group 父子关系,禁止 x 坐标平面判定**
169
+ **收获 3:归属判定走 x+y+parent 三轴联合,禁止单轴定论(坐标和 parent 互为纠错器)**
149
170
 
150
- 实战教训:`'主题'text(x=272,y=149)` 被错误识别为内容区块标题,实际是左侧树标题(与树节点同 x=272 列)。同列坐标不代表同区域。
171
+ 实战教训:
172
+ - 反例 A:`'主题'text(x=272,y=149)` 单看 x 在右侧内容区列,但 `parent.name=leftTreeHeader` 强语义 → 归左树(情形 C:parent 修正坐标)
173
+ - 反例 B(反馈 #11):`'段码含义'text(x=300,y=257)` 坐标落在 `渐变容器(x=240..960, y=189..297)` 内,但 parent 是兄弟编组 `cataMain` → 视觉上属于渐变容器内(情形 B:图层拆开,按坐标渲染)
151
174
 
152
175
  正确做法:
153
- - 步骤 2 拿到完整节点树后,先识别顶层 group 分区(通常 2-5 个,对应 LeftTree区/Query+Table区/信息栏区/标题栏区)
154
- - `getMultipleNodeInfo` v1.5.0+ **自动返回** `parent: { id, name, type }` 字段,按 parent 归属到具体分区
155
- - "主题"这类标题文本,先看 `parent.name` 是否带 "LeftTree" / "树" / "PageContent" 等容器关键字,不要看 x 坐标
156
- - 坐标仅作为同 parent 内子元素排序兜底使用
176
+ - 步骤 2.5 4 步先 `mode="tree"` 看顶层 group 分区(通常 2-5 个)
177
+ - 步骤 2.6 做双向校验:Pass 1 坐标推假设 Pass 2 parent 质检 四类情形 A/B/C/D 处理
178
+ - 大区归属:`parent.name` `LeftTree/树/PageContent/sidebar/cataMain` 等强语义关键字时优先于 x 分布
179
+ - 容器归属:必须 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]`,单轴判定无效
180
+ - 跨分区不比 y;同分区内按 y 升序;同行(y 差<8px)按 x 升序
181
+
182
+ 详细决策矩阵见步骤 2.6。
157
183
 
158
184
  **收获 4:信息栏/卡片容器必须先取 group 再取子元素**
159
185
 
@@ -199,14 +225,129 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
199
225
 
200
226
  - **兜底方案**:① 用 `extractBitmaps` 提取的 PNG/PDF 资源;② `matchIconFromName` 的 Top-1(若 source=compound);③ unmatched 时按 parent 上下文 + 上表选 antd `@ant-design/icons` 复合图标;④ 在代码注释中标注"⚠️ 矢量图标用 antd 图标替代,原始 Sketch 为 shapePath"
201
227
 
202
- **提示(sketch-mcp-server v1.5.0+)**:
228
+ **收获 8:rectangle 的 fill/border 必须以内联样式或精确选择器落到 DOM,禁止借用通用 CSS class**
229
+
230
+ 实战教训(反馈 #11):5 个段码视觉块的颜色(#f2f8fd/#f5ffed/#fffbe6/#f5f6f7)完整地从 rectangle 节点拿到了,但代码却用了 `.beforebg{background:#ebf0ff}` 这种与设计稿无对应关系的通用 class,导致 5 个块颜色全错。
231
+
232
+ 正确做法:
233
+ - 步骤 2.6 的样式映射表(表 5)必须为每个"颜色块"列出 rectangle 数据 → 内联 style 的对应关系
234
+ - 写代码时直接用 `<div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}>`
235
+ - 若必须用 CSS class,类名要能反向追到 Sketch 节点(如 `.segmentBlock-blue` 而非 `.beforebg`),且 class 内容必须**精确等于** rectangle 的 fill/border
236
+ - 反例排查:写完代码后 grep 一下 CSS class 名,出现 `.bg1/.box2/.before*` 这类无语义类名、且颜色和设计稿对不上 → 几乎确定是凭空兜底
237
+
238
+ ### 步骤2.6:布局推理(必做,写代码前的最后一道关)
239
+
240
+ ⚠️ 这一步专治"数据全拿到却放错位置"。反馈 #11 的 5 处错位全部由跳过此步骤导致。
241
+
242
+ **核心思路**:x+y 坐标先画"视觉假设",parent 字段做质检纠错。两套信号**互为纠错器**,不是单方向"谁优先"。
243
+
244
+ **输入**:步骤 2.5 产出的 `text + rectangle + group` 节点全量数据(含 `position.{x,y}`、`size.{width,height}`、`parent.{id,name,type}`、`style`、`isVisualContainer`)
245
+
246
+ #### Pass 1:坐标推假设(产出 5 张表)
247
+
248
+ 每张表都必须输出,即使某类节点为空也要写"无"。
249
+
250
+ ##### 表 1:分区识别表(x+y+parent 联合,定大区)
251
+
252
+ ```
253
+ | 节点 name | x | y | parent.name | 推断分区 | 决策依据 |
254
+ |----------------|-----|-----|------------------|--------------|-------------------------|
255
+ | 主题(text) | 272 | 149 | leftTreeHeader | 左树标题区 | parent 强语义压过 x 列 |
256
+ | 段码定义(text) | 320 | 200 | cataMain | 右侧内容-顶部 | parent 含 PageContent 类语义 |
257
+ ```
258
+
259
+ 判定流程:
260
+ 1. 按 x 把画板切成 1-3 列(x<300 → 左区、x≥300 → 右区,或按设计稿实际边界)
261
+ 2. 用 `parent.name` 校验:含 `LeftTree/树/sidebar/cataMain/PageContent/header/footer` 等关键字时以 parent 为准
262
+ 3. 冲突时遵循"收获 3"的 A/B/C/D 矩阵(见下方 Pass 2)
263
+
264
+ → 此表输出**布局类型**:UpDown(单列)/ LeftRight(双列)/ LeftMiddleRight(三列)
265
+
266
+ ##### 表 2:纵向顺序表(同分区内按 y)
267
+
268
+ ```
269
+ | 分区 | 节点 | y | 推断角色 |
270
+ |------------|---------------|-----|-------------------|
271
+ | 右侧内容区 | 段码定义 | 200 | 卡片 1 |
272
+ | 右侧内容区 | Tabs | 420 | Tabs(type=card) |
273
+ | 右侧内容区 | 配置说明 | 478 | 卡片 2(Tabs 下方) |
274
+ ```
275
+
276
+ 铁律:**同分区内**渲染顺序按 y 升序。跨分区不比 y(左树第 100 行 y 和右内容区第 1 行 y 没有可比性)。
277
+
278
+ ##### 表 3:横向排列表(同行按 x,y 差<8px 视为同行)
279
+
280
+ ```
281
+ | 分区/容器 | 节点 | x | y | 推断角色 |
282
+ |-----------------|--------------|-----|-----|-------------------------|
283
+ | Query 操作栏 | 名称输入框 | 320 | 50 | Form.Item col-span=6 |
284
+ | Query 操作栏 | 状态下拉 | 540 | 50 | Form.Item col-span=6 |
285
+ | Query 操作栏 | 查询按钮 | 980 | 50 | 操作按钮(右对齐) |
286
+ ```
287
+
288
+ 判定流程:
289
+ 1. y 差<8px 识别同一行
290
+ 2. 同行按 x 升序排
291
+ 3. 计算 x 间距推算 antd Col span(24 栅格)或 flex
292
+ 4. 最右元素若 `x + width` 接近容器右边界 → 右对齐(justify-content: flex-end)
293
+
294
+ ##### 表 4:容器归属表(x+y 双轴边界检测)
295
+
296
+ 仅对 `isVisualContainer === true` 的 group 和带 fill/border 的 rectangle 做检测。
297
+
298
+ ```
299
+ | 容器 | x..x+w | y..y+h | 落入子元素 |
300
+ |------------------|----------|----------|----------------------------------|
301
+ | 渐变容器(group) | 240..960 | 189..297 | 段码含义(x=300,y=257) ✅ |
302
+ | 段码块-蓝(rect) | 320..420 | 320..360 | (无子节点,仅样式) |
303
+ ```
304
+
305
+ 判定式:子元素 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]` → 渲染在容器内部。**单轴判定无效**。
306
+
307
+ ##### 表 5:样式映射表(rectangle/group fill → UI 组件内联样式)
308
+
309
+ ```
310
+ | Sketch 节点 | 数据来源 | bg/border | 映射到代码 |
311
+ |----------------------|--------------------------|--------------------------|-----------------------------------------------------------|
312
+ | 段码块-蓝(rectangle) | style.fills[0]/borders[0]| bg #f2f8fd / b #d9eafb | <div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}> |
313
+ | 渐变容器(group) | style.fills[0].gradient | linear #f3faff→#f8fdff | <div style={{background:'linear-gradient(180deg,#f3faff,#f8fdff)'}}> |
314
+ | Tab 激活态 | rect bg #fff border #0079f7 | bg #fff / b #0079f7 | Tabs type="card" + .segmentTabs .ant-tabs-tab-active 覆盖 |
315
+ ```
316
+
317
+ 铁律(见收获 8):rectangle 的 fill/border 必须以**内联样式**或精确选择器落到代码,**禁止**用 `.beforebg{background:#ebf0ff}` 这类与设计稿无对应关系的 CSS class。
318
+
319
+ #### Pass 2:parent 质检(按 A/B/C/D 矩阵处理冲突)
320
+
321
+ 逐行扫表 1,对照 parent 字段:
322
+
323
+ | 情形 | 坐标判定 | parent 判定 | 处理 |
324
+ |------|----------|-------------|------|
325
+ | A | 在容器 X 内 | parent 链含 X | ✅ 双向一致,直接采用 |
326
+ | B | 在容器 X 内 | parent 是兄弟节点 Y | ⚠️ **视觉容器优先**(设计师把图层拆开了)→ 按坐标渲染到 X 内 |
327
+ | C | 不在容器 X 内 | parent.name 强语义 = X | ⚠️ **parent 优先**(绝对定位/溢出布局)→ 按 parent 归属,加 `position:absolute` 标注 |
328
+ | D | 双向都不落 | parent 是顶层 | 独立元素,按坐标走纵向顺序 |
329
+
330
+ 输出**最终归属表**:在表 1 末尾追加 `情形(A/B/C/D)` 列。
331
+
332
+ #### Pass 3:自检清单(写代码前必跑)
333
+
334
+ - [ ] 表 1 是否按 x 分布判定了布局类型(UpDown / LeftRight / LeftMiddleRight)?
335
+ - [ ] 表 2 同分区内是否按 y 排序,没有跨分区比 y?
336
+ - [ ] 表 3 同行元素(y 差<8px)是否按 x 排序,计算了栅格 span 或右对齐?
337
+ - [ ] 表 4 容器归属是否做了 x+y 双轴检测,不是只看一轴?
338
+ - [ ] 表 5 所有"颜色块/卡片/渐变"样式都来自 rectangle/group 的 style.fills/borders,没有出现凭空 CSS class?
339
+ - [ ] Pass 2 冲突行是否标了 A/B/C/D 情形和决策依据?
340
+
341
+ 任一项 ❌ → 回 Pass 1 补;禁止跳到步骤 3 前未输出全部 5 张表 + 最终归属表。
342
+
343
+ **提示(sketch-mcp-server v1.6.1+)**:
203
344
  - 大型 .sketch 文件先 `queryNodes(pageId, type="artboard")` 锁定目标画板,避免一次性加载整个文档
204
345
  - `queryNodes(pageId, type=["text","rectangle","group"])` 一次拿三类节点 ID(type 字段支持数组),跳过 `getPageStructure(mode="ids")` 单独调用
205
346
  - `getPageStructure(pageId, mode="tree", maxDepth=2-3)` 用于看分区层级;`mode="summary"` 用于按类型统计概况
206
- - 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段,元素归属直接走 parent,禁止用 x/y 坐标
347
+ - 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段 + group/artboard 额外有 `children` 和 `isVisualContainer` —— 步骤 2.6 的双向校验同时用 parent x/y,不是只挑一个
207
348
  - `matchIconFromName` 评分制返回 Top-3 + `bestMatch.source === "compound"` 强映射,shapePath 节点优先走它
208
349
  - 仅当结构化样式数据仍不足(如复杂渐变、阴影)时,才回退到 `renderNodeAsBase64` + `analyze_design_image`
209
- - 如果 sketch-mcp-server 工具不可用,提示用户安装:`npm install -g @szc-ft/sketch-mcp-server`
350
+ - 如果 sketch-mcp-server 工具不可用或版本 < v1.6.1(parent / isVisualContainer 字段缺失),提示用户升级:`npm install -g @szc-ft/sketch-mcp-server@latest`
210
351
 
211
352
  ### 步骤3:分析设计稿(条件执行)
212
353
 
@@ -229,6 +370,7 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
229
370
 
230
371
  **输入**:
231
372
  - 步骤 1 的 `get_architecture_overview` 返回的 `templatePatterns`(TreeQueryTable / QueryTabsTables / LeftRight / UpDown)
373
+ - 步骤 1 的 `componentSummary`:全量组件 + 设计元信息(layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)—— **推理组件候选的权威目录,长尾场景按 layoutRole / useCases / sketchSignals 直接反查**
232
374
  - 步骤 1 的 `llmMappingHints.commonMistakes`(避免 LLM 常见映射错误)
233
375
  - 步骤 2.5 的 Sketch 节点结构 + 样式 Token
234
376
  - 或步骤 3 的图片分析描述
@@ -242,38 +384,15 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
242
384
  - ❌ 在步骤 3 内部推理组件候选列表(应只产出图片描述)
243
385
  - ❌ 跳过此环节直接调 `get_component_full_profile`(必须先有候选列表)
244
386
 
245
- **推理时使用映射规则**(**此表为本步骤专用,仅含核心高频场景**):
387
+ **推理依据**:步骤 1 返回的 `componentSummary` 是组件候选的权威目录(由组件库源码动态生成),每项含 `layoutRole` / `variantProps` / `useCases` / `sketchSignals`(图表层)。按以下顺序反查:
246
388
 
247
- *页面级布局*:
248
- | Sketch 特征 | 推断结果 | 依据 |
249
- |---|---|---|
250
- | 画板名称(如 "4.1-编目审核-待办") | `pageName` | 直接使用 |
251
- | 左右分区布局 | `TemplateMode(templateTpye="LeftRight")` | 区域分布 |
252
- | 上下分区布局 | `TemplateMode(templateTpye="TopBottom")` | 区域分布 |
253
- | 标签页(Tabs) + 每个 Tab 内有表格 | `QueryTabsTables` 或 `TemplateMode` + Tabs | templatePatterns.QueryTabsTables |
254
-
255
- *区域级组件*:
256
- | Sketch 特征 | 推断结果 | 依据 |
257
- |---|---|---|
258
- | 左侧窄区域 + 树形图层 | `LeftTree` 组件 | templatePatterns.TreeQueryTable |
259
- | 顶部输入框/下拉框/日期选择器 | `Query` 组件 | 搜索区域特征 |
260
- | 中间表头 + 数据行图层 | `TableOrList` 组件 | 表格区域特征 |
261
- | 弹窗/抽屉图层 | `ModelOrDrawer` 组件 | 弹窗交互特征 |
262
- | 页面标题 + 返回箭头 | `TitleAndBack` 组件 | 标题栏特征 |
263
- | 详情展示区域(只读字段) | `FormItemOrDetailItem(type="detail")` | 详情区特征 |
264
-
265
- *数据可视化(核心 3 类)*:
266
- | Sketch 特征 | 推断结果 | 依据 |
267
- |---|---|---|
268
- | 折线趋势图/时间序列图 | `Line` | ECharts 层图表组件 |
269
- | 柱状对比图/条形图 | `Bar` | ECharts 层图表组件 |
270
- | 饼图/环形图/占比图 | `Pie` | ECharts 层图表组件 |
389
+ 1. **画板名称** → 直接作为 `pageName`
390
+ 2. **大区切分** `componentSummary.other` `layoutRole === '页面定位'` 的组件(如 TemplateMode),结合 `variantProps.templateType`(LeftRight / TopBottom)和 `templatePatterns`(TreeQueryTable / QueryTabsTables)选模板
391
+ 3. **区域容器** → `layoutRole === '区域容器'` 的组件(LeftTree / Query / TableOrList / ModelOrDrawer / TitleAndBack / FormItemOrDetailItem 等),按 `useCases` 描述匹配 Sketch 区域语义
392
+ 4. **图表组件** `componentSummary.echarts[*].sketchSignals` 反查 `chartType`,锁定 Line / Bar / Pie / Scatter 等
393
+ 5. **变体选择** 同一组件的子类型(如 TableOrList 的 ProTable / ProList / EditableProTable)查 `variantProps` 配合 useCases
271
394
 
272
- *表格子类型(核心 2 类)*:
273
- | Sketch 特征 | 推断结果 | 依据 |
274
- |---|---|---|
275
- | 可编辑表格(单元格直接输入) | `TableOrList(componentType="EditableProTable")` | 可编辑表格特征 |
276
- | 卡片列表(非表格式数据卡片) | `TableOrList(componentType="ProList")` | 卡片布局特征 |
395
+ 不要硬编码任何「Sketch 特征 → 组件」对照表——`componentSummary` 是唯一可信源,硬编码表会和服务端动态扫描结果漂移。
277
396
 
278
397
  #### ⚠️ TemplateMode 槽位传参铁律(高频踩坑)
279
398
 
@@ -332,6 +451,7 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
332
451
  - ProTable/ProForm 等使用 valueType 配置列/字段类型
333
452
  - 复合组件配合 TemplateMode 使用实现标准页面布局
334
453
 
454
+
335
455
  **交互节点**:代码生成后,主动询问用户是否需要调整:
336
456
  - "代码已生成,是否需要调整样式或交互细节?"
337
457
  - "是否需要补充表单校验规则?"
@@ -38,7 +38,7 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
38
38
  **在正式开始之前,获取项目架构全局视图,同时验证 MCP 连接。**
39
39
 
40
40
  执行动作:
41
- 1. 调用 `get_architecture_overview`(detail="summary")获取7层架构图、模板组合模式、推荐使用顺序和 LLM 映射错误提示
41
+ 1. 调用 `get_architecture_overview`(detail="full")一次性获取:7 层架构图、模板组合模式、推荐使用顺序、LLM 映射错误提示,**以及 `componentSummary`(全量组件 + 设计元信息:layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)+ `styleMapping`(节点样式映射)+ `assetExtraction`(图标/位图/图表色提取规则)**——这些是步骤 3.5 推理组件候选和步骤 5 样式注入的核心依据
42
42
  2. 如果连接失败,**立即停止并返回错误信息**,告知用户需要先配置 MCP 服务器
43
43
  3. 如果成功,根据返回的 `templatePatterns` 初步判断用户需求匹配哪个模板
44
44
 
@@ -127,6 +127,27 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
127
127
  | 元素归属 | 凭 x/y 坐标判定("x=272 列都是同区域") | 看 `getMultipleNodeInfo` 返回的 `parent.id/name` 字段 |
128
128
  | 颜色提取 | 跳过 group 只取 text/rectangle | 同批提交 group ID,从 `style.fills` 取渐变背景 |
129
129
 
130
+ #### getMultipleNodeInfo 返回字段契约(sketch-mcp-server ≥ v1.6.1)
131
+
132
+ | 字段 | 适用类型 | 用途 |
133
+ |------|----------|------|
134
+ | `position:{x,y}` + `size:{width,height}` | 全部 | 步骤 2.6 表 1/2/3/4 的坐标推理 |
135
+ | `parent:{id,name,type}` | 全部(顶层除外) | 步骤 2.6 表 1 大区归属、Pass 2 质检 |
136
+ | `style.fills[].{color,gradient}` | rectangle / group / text | 表 5 样式映射 |
137
+ | `style.borders[].{color,thickness}` | rectangle / group | 表 5 样式映射 |
138
+ | `style.shadows[]` | rectangle / group | 表 5 样式映射 |
139
+ | `text.attributes[0].attributes.{fontFamily,fontSize,color,lineHeight}` | text | 字号/字重/颜色(fontFamily 编码字重,如 PingFangSC-Semibold → 600) |
140
+ | `children:[id]` | group / artboard | 推断容器子节点集合(与 parent 反向印证) |
141
+ | `isVisualContainer:bool` | group / artboard | true = 该 group 自身带 fills/borders/shadows,必须作为 UI 容器渲染(不是纯图层分组) |
142
+ | `shape.cornerRadius` | rectangle / oval | 圆角 |
143
+
144
+ **字段缺失自检**(任一项失败 → sketch-mcp-server 版本过旧,升级到 ≥ v1.6.1 后重跑):
145
+
146
+ - [ ] 任取一个 text 节点,`parent.id` 非空 ✅
147
+ - [ ] 任取一个 group 节点,`isVisualContainer` 类型是 boolean、`children` 是数组 ✅
148
+ - [ ] 任取一个 rectangle 节点,`style.fills` 数组存在(即使为空也要是 `[]` 不能 undefined) ✅
149
+ - [ ] 任取一个 text 节点,`text.attributes[0].attributes.fontFamily` 可读出(编码字重) ✅
150
+
130
151
  **实战经验沉淀(重要)**:
131
152
 
132
153
  **收获 1:首轮 `getMultipleNodeInfo` 必须全量拉取,不能挑**
@@ -141,15 +162,20 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
141
162
  错误做法:先查 text 拿自身样式 → 再根据 parent ID 单独查 rectangle(多走一步)
142
163
  正确做法:用 `queryNodes(type=["text","rectangle","group"])` 一次拿三类 ID,`getMultipleNodeInfo` 返回的 `parent` 字段直接告诉你归属关系
143
164
 
144
- **收获 3:元素归属必须走 group 父子关系,禁止 x 坐标平面判定**
165
+ **收获 3:归属判定走 x+y+parent 三轴联合,禁止单轴定论(坐标和 parent 互为纠错器)**
145
166
 
146
- 实战教训:`'主题'text(x=272,y=149)` 被错误识别为内容区块标题,实际是左侧树标题(与树节点同 x=272 列)。同列坐标不代表同区域。
167
+ 实战教训:
168
+ - 反例 A:`'主题'text(x=272,y=149)` 单看 x 在右侧内容区列,但 `parent.name=leftTreeHeader` 强语义 → 归左树(情形 C:parent 修正坐标)
169
+ - 反例 B(反馈 #11):`'段码含义'text(x=300,y=257)` 坐标落在 `渐变容器(x=240..960, y=189..297)` 内,但 parent 是兄弟编组 `cataMain` → 视觉上属于渐变容器内(情形 B:图层拆开,按坐标渲染)
147
170
 
148
171
  正确做法:
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 内子元素排序兜底使用
172
+ - 步骤 2.5 4 步先 `mode="tree"` 看顶层 group 分区(通常 2-5 个)
173
+ - 步骤 2.6 做双向校验:Pass 1 坐标推假设 Pass 2 parent 质检 四类情形 A/B/C/D 处理
174
+ - 大区归属:`parent.name` `LeftTree/树/PageContent/sidebar/cataMain` 等强语义关键字时优先于 x 分布
175
+ - 容器归属:必须 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]`,单轴判定无效
176
+ - 跨分区不比 y;同分区内按 y 升序;同行(y 差<8px)按 x 升序
177
+
178
+ 详细决策矩阵见步骤 2.6。
153
179
 
154
180
  **收获 4:信息栏/卡片容器必须先取 group 再取子元素**
155
181
 
@@ -195,14 +221,129 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
195
221
 
196
222
  - **兜底方案**:① 用 `extractBitmaps` 提取的 PNG/PDF 资源;② `matchIconFromName` 的 Top-1(若 source=compound);③ unmatched 时按 parent 上下文 + 上表选 antd `@ant-design/icons` 复合图标;④ 在代码注释中标注"⚠️ 矢量图标用 antd 图标替代,原始 Sketch 为 shapePath"
197
223
 
198
- **提示(sketch-mcp-server v1.5.0+)**:
224
+ **收获 8:rectangle 的 fill/border 必须以内联样式或精确选择器落到 DOM,禁止借用通用 CSS class**
225
+
226
+ 实战教训(反馈 #11):5 个段码视觉块的颜色(#f2f8fd/#f5ffed/#fffbe6/#f5f6f7)完整地从 rectangle 节点拿到了,但代码却用了 `.beforebg{background:#ebf0ff}` 这种与设计稿无对应关系的通用 class,导致 5 个块颜色全错。
227
+
228
+ 正确做法:
229
+ - 步骤 2.6 的样式映射表(表 5)必须为每个"颜色块"列出 rectangle 数据 → 内联 style 的对应关系
230
+ - 写代码时直接用 `<div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}>`
231
+ - 若必须用 CSS class,类名要能反向追到 Sketch 节点(如 `.segmentBlock-blue` 而非 `.beforebg`),且 class 内容必须**精确等于** rectangle 的 fill/border
232
+ - 反例排查:写完代码后 grep 一下 CSS class 名,出现 `.bg1/.box2/.before*` 这类无语义类名、且颜色和设计稿对不上 → 几乎确定是凭空兜底
233
+
234
+ ### 步骤2.6:布局推理(必做,写代码前的最后一道关)
235
+
236
+ ⚠️ 这一步专治"数据全拿到却放错位置"。反馈 #11 的 5 处错位全部由跳过此步骤导致。
237
+
238
+ **核心思路**:x+y 坐标先画"视觉假设",parent 字段做质检纠错。两套信号**互为纠错器**,不是单方向"谁优先"。
239
+
240
+ **输入**:步骤 2.5 产出的 `text + rectangle + group` 节点全量数据(含 `position.{x,y}`、`size.{width,height}`、`parent.{id,name,type}`、`style`、`isVisualContainer`)
241
+
242
+ #### Pass 1:坐标推假设(产出 5 张表)
243
+
244
+ 每张表都必须输出,即使某类节点为空也要写"无"。
245
+
246
+ ##### 表 1:分区识别表(x+y+parent 联合,定大区)
247
+
248
+ ```
249
+ | 节点 name | x | y | parent.name | 推断分区 | 决策依据 |
250
+ |----------------|-----|-----|------------------|--------------|-------------------------|
251
+ | 主题(text) | 272 | 149 | leftTreeHeader | 左树标题区 | parent 强语义压过 x 列 |
252
+ | 段码定义(text) | 320 | 200 | cataMain | 右侧内容-顶部 | parent 含 PageContent 类语义 |
253
+ ```
254
+
255
+ 判定流程:
256
+ 1. 按 x 把画板切成 1-3 列(x<300 → 左区、x≥300 → 右区,或按设计稿实际边界)
257
+ 2. 用 `parent.name` 校验:含 `LeftTree/树/sidebar/cataMain/PageContent/header/footer` 等关键字时以 parent 为准
258
+ 3. 冲突时遵循"收获 3"的 A/B/C/D 矩阵(见下方 Pass 2)
259
+
260
+ → 此表输出**布局类型**:UpDown(单列)/ LeftRight(双列)/ LeftMiddleRight(三列)
261
+
262
+ ##### 表 2:纵向顺序表(同分区内按 y)
263
+
264
+ ```
265
+ | 分区 | 节点 | y | 推断角色 |
266
+ |------------|---------------|-----|-------------------|
267
+ | 右侧内容区 | 段码定义 | 200 | 卡片 1 |
268
+ | 右侧内容区 | Tabs | 420 | Tabs(type=card) |
269
+ | 右侧内容区 | 配置说明 | 478 | 卡片 2(Tabs 下方) |
270
+ ```
271
+
272
+ 铁律:**同分区内**渲染顺序按 y 升序。跨分区不比 y(左树第 100 行 y 和右内容区第 1 行 y 没有可比性)。
273
+
274
+ ##### 表 3:横向排列表(同行按 x,y 差<8px 视为同行)
275
+
276
+ ```
277
+ | 分区/容器 | 节点 | x | y | 推断角色 |
278
+ |-----------------|--------------|-----|-----|-------------------------|
279
+ | Query 操作栏 | 名称输入框 | 320 | 50 | Form.Item col-span=6 |
280
+ | Query 操作栏 | 状态下拉 | 540 | 50 | Form.Item col-span=6 |
281
+ | Query 操作栏 | 查询按钮 | 980 | 50 | 操作按钮(右对齐) |
282
+ ```
283
+
284
+ 判定流程:
285
+ 1. y 差<8px 识别同一行
286
+ 2. 同行按 x 升序排
287
+ 3. 计算 x 间距推算 antd Col span(24 栅格)或 flex
288
+ 4. 最右元素若 `x + width` 接近容器右边界 → 右对齐(justify-content: flex-end)
289
+
290
+ ##### 表 4:容器归属表(x+y 双轴边界检测)
291
+
292
+ 仅对 `isVisualContainer === true` 的 group 和带 fill/border 的 rectangle 做检测。
293
+
294
+ ```
295
+ | 容器 | x..x+w | y..y+h | 落入子元素 |
296
+ |------------------|----------|----------|----------------------------------|
297
+ | 渐变容器(group) | 240..960 | 189..297 | 段码含义(x=300,y=257) ✅ |
298
+ | 段码块-蓝(rect) | 320..420 | 320..360 | (无子节点,仅样式) |
299
+ ```
300
+
301
+ 判定式:子元素 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]` → 渲染在容器内部。**单轴判定无效**。
302
+
303
+ ##### 表 5:样式映射表(rectangle/group fill → UI 组件内联样式)
304
+
305
+ ```
306
+ | Sketch 节点 | 数据来源 | bg/border | 映射到代码 |
307
+ |----------------------|--------------------------|--------------------------|-----------------------------------------------------------|
308
+ | 段码块-蓝(rectangle) | style.fills[0]/borders[0]| bg #f2f8fd / b #d9eafb | <div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}> |
309
+ | 渐变容器(group) | style.fills[0].gradient | linear #f3faff→#f8fdff | <div style={{background:'linear-gradient(180deg,#f3faff,#f8fdff)'}}> |
310
+ | Tab 激活态 | rect bg #fff border #0079f7 | bg #fff / b #0079f7 | Tabs type="card" + .segmentTabs .ant-tabs-tab-active 覆盖 |
311
+ ```
312
+
313
+ 铁律(见收获 8):rectangle 的 fill/border 必须以**内联样式**或精确选择器落到代码,**禁止**用 `.beforebg{background:#ebf0ff}` 这类与设计稿无对应关系的 CSS class。
314
+
315
+ #### Pass 2:parent 质检(按 A/B/C/D 矩阵处理冲突)
316
+
317
+ 逐行扫表 1,对照 parent 字段:
318
+
319
+ | 情形 | 坐标判定 | parent 判定 | 处理 |
320
+ |------|----------|-------------|------|
321
+ | A | 在容器 X 内 | parent 链含 X | ✅ 双向一致,直接采用 |
322
+ | B | 在容器 X 内 | parent 是兄弟节点 Y | ⚠️ **视觉容器优先**(设计师把图层拆开了)→ 按坐标渲染到 X 内 |
323
+ | C | 不在容器 X 内 | parent.name 强语义 = X | ⚠️ **parent 优先**(绝对定位/溢出布局)→ 按 parent 归属,加 `position:absolute` 标注 |
324
+ | D | 双向都不落 | parent 是顶层 | 独立元素,按坐标走纵向顺序 |
325
+
326
+ 输出**最终归属表**:在表 1 末尾追加 `情形(A/B/C/D)` 列。
327
+
328
+ #### Pass 3:自检清单(写代码前必跑)
329
+
330
+ - [ ] 表 1 是否按 x 分布判定了布局类型(UpDown / LeftRight / LeftMiddleRight)?
331
+ - [ ] 表 2 同分区内是否按 y 排序,没有跨分区比 y?
332
+ - [ ] 表 3 同行元素(y 差<8px)是否按 x 排序,计算了栅格 span 或右对齐?
333
+ - [ ] 表 4 容器归属是否做了 x+y 双轴检测,不是只看一轴?
334
+ - [ ] 表 5 所有"颜色块/卡片/渐变"样式都来自 rectangle/group 的 style.fills/borders,没有出现凭空 CSS class?
335
+ - [ ] Pass 2 冲突行是否标了 A/B/C/D 情形和决策依据?
336
+
337
+ 任一项 ❌ → 回 Pass 1 补;禁止跳到步骤 3 前未输出全部 5 张表 + 最终归属表。
338
+
339
+ **提示(sketch-mcp-server v1.6.1+)**:
199
340
  - 大型 .sketch 文件先 `queryNodes(pageId, type="artboard")` 锁定目标画板,避免一次性加载整个文档
200
341
  - `queryNodes(pageId, type=["text","rectangle","group"])` 一次拿三类节点 ID(type 字段支持数组),跳过 `getPageStructure(mode="ids")` 单独调用
201
342
  - `getPageStructure(pageId, mode="tree", maxDepth=2-3)` 用于看分区层级;`mode="summary"` 用于按类型统计概况
202
- - 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段,元素归属直接走 parent,禁止用 x/y 坐标
343
+ - 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段 + group/artboard 额外有 `children` 和 `isVisualContainer` —— 步骤 2.6 的双向校验同时用 parent x/y,不是只挑一个
203
344
  - `matchIconFromName` 评分制返回 Top-3 + `bestMatch.source === "compound"` 强映射,shapePath 节点优先走它
204
345
  - 仅当结构化样式数据仍不足(如复杂渐变、阴影)时,才回退到 `renderNodeAsBase64` + `analyze_design_image`
205
- - 如果 sketch-mcp-server 工具不可用,提示用户安装:`npm install -g @szc-ft/sketch-mcp-server`
346
+ - 如果 sketch-mcp-server 工具不可用或版本 < v1.6.1(parent / isVisualContainer 字段缺失),提示用户升级:`npm install -g @szc-ft/sketch-mcp-server@latest`
206
347
 
207
348
  ### 步骤3:分析设计稿(条件执行)
208
349
 
@@ -225,6 +366,7 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
225
366
 
226
367
  **输入**:
227
368
  - 步骤 1 的 `get_architecture_overview` 返回的 `templatePatterns`(TreeQueryTable / QueryTabsTables / LeftRight / UpDown)
369
+ - 步骤 1 的 `componentSummary`:全量组件 + 设计元信息(layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)—— **推理组件候选的权威目录,长尾场景按 layoutRole / useCases / sketchSignals 直接反查**
228
370
  - 步骤 1 的 `llmMappingHints.commonMistakes`(避免 LLM 常见映射错误)
229
371
  - 步骤 2.5 的 Sketch 节点结构 + 样式 Token
230
372
  - 或步骤 3 的图片分析描述
@@ -238,38 +380,15 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
238
380
  - ❌ 在步骤 3 内部推理组件候选列表(应只产出图片描述)
239
381
  - ❌ 跳过此环节直接调 `get_component_full_profile`(必须先有候选列表)
240
382
 
241
- **推理时使用映射规则**(**此表为本步骤专用,仅含核心高频场景**):
383
+ **推理依据**:步骤 1 返回的 `componentSummary` 是组件候选的权威目录(由组件库源码动态生成),每项含 `layoutRole` / `variantProps` / `useCases` / `sketchSignals`(图表层)。按以下顺序反查:
242
384
 
243
- *页面级布局*:
244
- | Sketch 特征 | 推断结果 | 依据 |
245
- |---|---|---|
246
- | 画板名称(如 "4.1-编目审核-待办") | `pageName` | 直接使用 |
247
- | 左右分区布局 | `TemplateMode(templateTpye="LeftRight")` | 区域分布 |
248
- | 上下分区布局 | `TemplateMode(templateTpye="TopBottom")` | 区域分布 |
249
- | 标签页(Tabs) + 每个 Tab 内有表格 | `QueryTabsTables` 或 `TemplateMode` + Tabs | templatePatterns.QueryTabsTables |
250
-
251
- *区域级组件*:
252
- | Sketch 特征 | 推断结果 | 依据 |
253
- |---|---|---|
254
- | 左侧窄区域 + 树形图层 | `LeftTree` 组件 | templatePatterns.TreeQueryTable |
255
- | 顶部输入框/下拉框/日期选择器 | `Query` 组件 | 搜索区域特征 |
256
- | 中间表头 + 数据行图层 | `TableOrList` 组件 | 表格区域特征 |
257
- | 弹窗/抽屉图层 | `ModelOrDrawer` 组件 | 弹窗交互特征 |
258
- | 页面标题 + 返回箭头 | `TitleAndBack` 组件 | 标题栏特征 |
259
- | 详情展示区域(只读字段) | `FormItemOrDetailItem(type="detail")` | 详情区特征 |
260
-
261
- *数据可视化(核心 3 类)*:
262
- | Sketch 特征 | 推断结果 | 依据 |
263
- |---|---|---|
264
- | 折线趋势图/时间序列图 | `Line` | ECharts 层图表组件 |
265
- | 柱状对比图/条形图 | `Bar` | ECharts 层图表组件 |
266
- | 饼图/环形图/占比图 | `Pie` | ECharts 层图表组件 |
385
+ 1. **画板名称** → 直接作为 `pageName`
386
+ 2. **大区切分** `componentSummary.other` `layoutRole === '页面定位'` 的组件(如 TemplateMode),结合 `variantProps.templateType`(LeftRight / TopBottom)和 `templatePatterns`(TreeQueryTable / QueryTabsTables)选模板
387
+ 3. **区域容器** → `layoutRole === '区域容器'` 的组件(LeftTree / Query / TableOrList / ModelOrDrawer / TitleAndBack / FormItemOrDetailItem 等),按 `useCases` 描述匹配 Sketch 区域语义
388
+ 4. **图表组件** `componentSummary.echarts[*].sketchSignals` 反查 `chartType`,锁定 Line / Bar / Pie / Scatter 等
389
+ 5. **变体选择** 同一组件的子类型(如 TableOrList 的 ProTable / ProList / EditableProTable)查 `variantProps` 配合 useCases
267
390
 
268
- *表格子类型(核心 2 类)*:
269
- | Sketch 特征 | 推断结果 | 依据 |
270
- |---|---|---|
271
- | 可编辑表格(单元格直接输入) | `TableOrList(componentType="EditableProTable")` | 可编辑表格特征 |
272
- | 卡片列表(非表格式数据卡片) | `TableOrList(componentType="ProList")` | 卡片布局特征 |
391
+ 不要硬编码任何「Sketch 特征 → 组件」对照表——`componentSummary` 是唯一可信源,硬编码表会和服务端动态扫描结果漂移。
273
392
 
274
393
  #### ⚠️ TemplateMode 槽位传参铁律(高频踩坑)
275
394
 
@@ -328,6 +447,7 @@ szcd 是基于 Ant Design 5.27 封装的企业级 React 组件库,采用分层
328
447
  - ProTable/ProForm 等使用 valueType 配置列/字段类型
329
448
  - 复合组件配合 TemplateMode 使用实现标准页面布局
330
449
 
450
+
331
451
  **交互节点**:代码生成后,主动询问用户是否需要调整:
332
452
  - "代码已生成,是否需要调整样式或交互细节?"
333
453
  - "是否需要补充表单校验规则?"