@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.
- package/agents/opencode-extension/agents/szcd-component-expert.md +160 -40
- package/agents/qwen-extension/agents/szcd-component-expert.md +160 -40
- package/agents/src/szcd-component-expert.md +187 -40
- package/agents/src/tools.json +2 -2
- package/agents/szcd-component-expert.md +160 -40
- package/agents/szcd-component-expert.qoder.md +186 -41
- package/agents/szcd-component-expert.trae.md +185 -40
- package/opencode-extension/agents/szcd-component-expert.md +160 -40
- package/opencode-extension/skills/local-api-tool/SKILL.md +160 -28
- package/opencode-extension/skills/local-api-tool/scripts/extract-swagger.mjs +625 -0
- package/opencode-extension/skills/local-api-tool/scripts/extract_swagger.py +125 -9
- package/opencode-extension/skills/szcd-component-helper/SKILL.md +12 -13
- package/opencode-extension/skills/szcd-design-to-code/SKILL.md +250 -28
- package/package.json +1 -1
- package/qwen-extension/agents/szcd-component-expert.md +160 -40
- package/qwen-extension/qwen-extension.json +1 -1
- package/qwen-extension/skills/local-api-tool/SKILL.md +160 -28
- package/qwen-extension/skills/local-api-tool/scripts/extract-swagger.mjs +625 -0
- package/qwen-extension/skills/local-api-tool/scripts/extract_swagger.py +125 -9
- package/qwen-extension/skills/szcd-component-helper/SKILL.md +12 -13
- package/qwen-extension/skills/szcd-design-to-code/SKILL.md +250 -28
- package/standard-skill/local-api-tool/SKILL.md +160 -28
- package/standard-skill/local-api-tool/scripts/extract-swagger.mjs +625 -0
- package/standard-skill/local-api-tool/scripts/extract_swagger.py +125 -9
- package/standard-skill/szcd-component-helper/SKILL.md +12 -13
- package/standard-skill/szcd-design-to-code/SKILL.md +251 -28
|
@@ -51,7 +51,7 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
51
51
|
|
|
52
52
|
| 工具名 | 功能 | 何时使用 |
|
|
53
53
|
|--------|------|---------|
|
|
54
|
-
| `get_architecture_overview` | 获取7层架构图、模板组合模式、LLM
|
|
54
|
+
| `get_architecture_overview` | 获取7层架构图、模板组合模式、LLM映射错误提示。detail=full 额外返回 componentSummary(全量组件+设计元信息:layoutRole/variantProps/styleInjection/useCases/chartType/sketchSignals)+ styleMapping(节点样式映射)+ assetExtraction(图标/位图/图表色提取规则),设计稿→代码场景必选 full | 步骤1:架构认知(设计稿场景用 detail=full 一次拿全) |
|
|
55
55
|
| `search_components_semantic` | 基于Repowiki知识库的语义搜索,用自然语言描述匹配最适合的组件 | 步骤4:语义搜索匹配 |
|
|
56
56
|
| `get_component_full_profile` | 一站式获取组件全景画像。name支持逗号分隔批量查询,depth=deep获取Props链+源码摘要+样式注入,返回值是紧凑Markdown格式 | 步骤4:批量获取全景画像 |
|
|
57
57
|
| `get_best_practices` | 获取组件使用最佳实践和常见错误修正,指定scenario可获取组合最佳实践 | 步骤4:组合最佳实践 |
|
|
@@ -86,7 +86,7 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
86
86
|
**在正式开始之前,获取项目架构全局视图,同时验证 MCP 连接。**
|
|
87
87
|
|
|
88
88
|
执行动作:
|
|
89
|
-
1. 调用 `get_architecture_overview`(detail="
|
|
89
|
+
1. 调用 `get_architecture_overview`(detail="full")一次性获取:7 层架构图、模板组合模式、推荐使用顺序、LLM 映射错误提示,**以及 `componentSummary`(全量组件 + 设计元信息:layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)+ `styleMapping`(节点样式映射)+ `assetExtraction`(图标/位图/图表色提取规则)**——这些是步骤 3.5 推理组件候选和步骤 5 样式注入的核心依据
|
|
90
90
|
2. 如果连接失败,**立即停止并返回错误信息**,告知用户需要先配置 MCP 服务器
|
|
91
91
|
3. 如果成功,根据返回的 `templatePatterns` 初步判断用户需求匹配哪个模板
|
|
92
92
|
|
|
@@ -181,6 +181,27 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
181
181
|
| 元素归属 | 凭 x/y 坐标判定("x=272 列都是同区域") | 看 `getMultipleNodeInfo` 返回的 `parent.id/name` 字段 |
|
|
182
182
|
| 颜色提取 | 跳过 group 只取 text/rectangle | 同批提交 group ID,从 `style.fills` 取渐变背景 |
|
|
183
183
|
|
|
184
|
+
#### getMultipleNodeInfo 返回字段契约(sketch-mcp-server ≥ v1.6.1)
|
|
185
|
+
|
|
186
|
+
| 字段 | 适用类型 | 用途 |
|
|
187
|
+
|------|----------|------|
|
|
188
|
+
| `position:{x,y}` + `size:{width,height}` | 全部 | 步骤 2.6 表 1/2/3/4 的坐标推理 |
|
|
189
|
+
| `parent:{id,name,type}` | 全部(顶层除外) | 步骤 2.6 表 1 大区归属、Pass 2 质检 |
|
|
190
|
+
| `style.fills[].{color,gradient}` | rectangle / group / text | 表 5 样式映射 |
|
|
191
|
+
| `style.borders[].{color,thickness}` | rectangle / group | 表 5 样式映射 |
|
|
192
|
+
| `style.shadows[]` | rectangle / group | 表 5 样式映射 |
|
|
193
|
+
| `text.attributes[0].attributes.{fontFamily,fontSize,color,lineHeight}` | text | 字号/字重/颜色(fontFamily 编码字重,如 PingFangSC-Semibold → 600) |
|
|
194
|
+
| `children:[id]` | group / artboard | 推断容器子节点集合(与 parent 反向印证) |
|
|
195
|
+
| `isVisualContainer:bool` | group / artboard | true = 该 group 自身带 fills/borders/shadows,必须作为 UI 容器渲染(不是纯图层分组) |
|
|
196
|
+
| `shape.cornerRadius` | rectangle / oval | 圆角 |
|
|
197
|
+
|
|
198
|
+
**字段缺失自检**(任一项失败 → sketch-mcp-server 版本过旧,升级到 ≥ v1.6.1 后重跑):
|
|
199
|
+
|
|
200
|
+
- [ ] 任取一个 text 节点,`parent.id` 非空 ✅
|
|
201
|
+
- [ ] 任取一个 group 节点,`isVisualContainer` 类型是 boolean、`children` 是数组 ✅
|
|
202
|
+
- [ ] 任取一个 rectangle 节点,`style.fills` 数组存在(即使为空也要是 `[]` 不能 undefined) ✅
|
|
203
|
+
- [ ] 任取一个 text 节点,`text.attributes[0].attributes.fontFamily` 可读出(编码字重) ✅
|
|
204
|
+
|
|
184
205
|
**实战经验沉淀(重要)**:
|
|
185
206
|
|
|
186
207
|
**收获 1:首轮 `getMultipleNodeInfo` 必须全量拉取,不能挑**
|
|
@@ -195,15 +216,20 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
195
216
|
错误做法:先查 text 拿自身样式 → 再根据 parent ID 单独查 rectangle(多走一步)
|
|
196
217
|
正确做法:用 `queryNodes(type=["text","rectangle","group"])` 一次拿三类 ID,`getMultipleNodeInfo` 返回的 `parent` 字段直接告诉你归属关系
|
|
197
218
|
|
|
198
|
-
**收获 3
|
|
219
|
+
**收获 3:归属判定走 x+y+parent 三轴联合,禁止单轴定论(坐标和 parent 互为纠错器)**
|
|
199
220
|
|
|
200
|
-
|
|
221
|
+
实战教训:
|
|
222
|
+
- 反例 A:`'主题'text(x=272,y=149)` 单看 x 在右侧内容区列,但 `parent.name=leftTreeHeader` 强语义 → 归左树(情形 C:parent 修正坐标)
|
|
223
|
+
- 反例 B(反馈 #11):`'段码含义'text(x=300,y=257)` 坐标落在 `渐变容器(x=240..960, y=189..297)` 内,但 parent 是兄弟编组 `cataMain` → 视觉上属于渐变容器内(情形 B:图层拆开,按坐标渲染)
|
|
201
224
|
|
|
202
225
|
正确做法:
|
|
203
|
-
- 步骤 2
|
|
204
|
-
-
|
|
205
|
-
-
|
|
206
|
-
-
|
|
226
|
+
- 步骤 2.5 第 4 步先 `mode="tree"` 看顶层 group 分区(通常 2-5 个)
|
|
227
|
+
- 步骤 2.6 做双向校验:Pass 1 坐标推假设 → Pass 2 parent 质检 → 四类情形 A/B/C/D 处理
|
|
228
|
+
- 大区归属:`parent.name` 含 `LeftTree/树/PageContent/sidebar/cataMain` 等强语义关键字时优先于 x 分布
|
|
229
|
+
- 容器归属:必须 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]`,单轴判定无效
|
|
230
|
+
- 跨分区不比 y;同分区内按 y 升序;同行(y 差<8px)按 x 升序
|
|
231
|
+
|
|
232
|
+
详细决策矩阵见步骤 2.6。
|
|
207
233
|
|
|
208
234
|
**收获 4:信息栏/卡片容器必须先取 group 再取子元素**
|
|
209
235
|
|
|
@@ -249,14 +275,129 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
249
275
|
|
|
250
276
|
- **兜底方案**:① 用 `extractBitmaps` 提取的 PNG/PDF 资源;② `matchIconFromName` 的 Top-1(若 source=compound);③ unmatched 时按 parent 上下文 + 上表选 antd `@ant-design/icons` 复合图标;④ 在代码注释中标注"⚠️ 矢量图标用 antd 图标替代,原始 Sketch 为 shapePath"
|
|
251
277
|
|
|
252
|
-
|
|
278
|
+
**收获 8:rectangle 的 fill/border 必须以内联样式或精确选择器落到 DOM,禁止借用通用 CSS class**
|
|
279
|
+
|
|
280
|
+
实战教训(反馈 #11):5 个段码视觉块的颜色(#f2f8fd/#f5ffed/#fffbe6/#f5f6f7)完整地从 rectangle 节点拿到了,但代码却用了 `.beforebg{background:#ebf0ff}` 这种与设计稿无对应关系的通用 class,导致 5 个块颜色全错。
|
|
281
|
+
|
|
282
|
+
正确做法:
|
|
283
|
+
- 步骤 2.6 的样式映射表(表 5)必须为每个"颜色块"列出 rectangle 数据 → 内联 style 的对应关系
|
|
284
|
+
- 写代码时直接用 `<div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}>`
|
|
285
|
+
- 若必须用 CSS class,类名要能反向追到 Sketch 节点(如 `.segmentBlock-blue` 而非 `.beforebg`),且 class 内容必须**精确等于** rectangle 的 fill/border
|
|
286
|
+
- 反例排查:写完代码后 grep 一下 CSS class 名,出现 `.bg1/.box2/.before*` 这类无语义类名、且颜色和设计稿对不上 → 几乎确定是凭空兜底
|
|
287
|
+
|
|
288
|
+
### 步骤2.6:布局推理(必做,写代码前的最后一道关)
|
|
289
|
+
|
|
290
|
+
⚠️ 这一步专治"数据全拿到却放错位置"。反馈 #11 的 5 处错位全部由跳过此步骤导致。
|
|
291
|
+
|
|
292
|
+
**核心思路**:x+y 坐标先画"视觉假设",parent 字段做质检纠错。两套信号**互为纠错器**,不是单方向"谁优先"。
|
|
293
|
+
|
|
294
|
+
**输入**:步骤 2.5 产出的 `text + rectangle + group` 节点全量数据(含 `position.{x,y}`、`size.{width,height}`、`parent.{id,name,type}`、`style`、`isVisualContainer`)
|
|
295
|
+
|
|
296
|
+
#### Pass 1:坐标推假设(产出 5 张表)
|
|
297
|
+
|
|
298
|
+
每张表都必须输出,即使某类节点为空也要写"无"。
|
|
299
|
+
|
|
300
|
+
##### 表 1:分区识别表(x+y+parent 联合,定大区)
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
| 节点 name | x | y | parent.name | 推断分区 | 决策依据 |
|
|
304
|
+
|----------------|-----|-----|------------------|--------------|-------------------------|
|
|
305
|
+
| 主题(text) | 272 | 149 | leftTreeHeader | 左树标题区 | parent 强语义压过 x 列 |
|
|
306
|
+
| 段码定义(text) | 320 | 200 | cataMain | 右侧内容-顶部 | parent 含 PageContent 类语义 |
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
判定流程:
|
|
310
|
+
1. 按 x 把画板切成 1-3 列(x<300 → 左区、x≥300 → 右区,或按设计稿实际边界)
|
|
311
|
+
2. 用 `parent.name` 校验:含 `LeftTree/树/sidebar/cataMain/PageContent/header/footer` 等关键字时以 parent 为准
|
|
312
|
+
3. 冲突时遵循"收获 3"的 A/B/C/D 矩阵(见下方 Pass 2)
|
|
313
|
+
|
|
314
|
+
→ 此表输出**布局类型**:UpDown(单列)/ LeftRight(双列)/ LeftMiddleRight(三列)
|
|
315
|
+
|
|
316
|
+
##### 表 2:纵向顺序表(同分区内按 y)
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
| 分区 | 节点 | y | 推断角色 |
|
|
320
|
+
|------------|---------------|-----|-------------------|
|
|
321
|
+
| 右侧内容区 | 段码定义 | 200 | 卡片 1 |
|
|
322
|
+
| 右侧内容区 | Tabs | 420 | Tabs(type=card) |
|
|
323
|
+
| 右侧内容区 | 配置说明 | 478 | 卡片 2(Tabs 下方) |
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
铁律:**同分区内**渲染顺序按 y 升序。跨分区不比 y(左树第 100 行 y 和右内容区第 1 行 y 没有可比性)。
|
|
327
|
+
|
|
328
|
+
##### 表 3:横向排列表(同行按 x,y 差<8px 视为同行)
|
|
329
|
+
|
|
330
|
+
```
|
|
331
|
+
| 分区/容器 | 节点 | x | y | 推断角色 |
|
|
332
|
+
|-----------------|--------------|-----|-----|-------------------------|
|
|
333
|
+
| Query 操作栏 | 名称输入框 | 320 | 50 | Form.Item col-span=6 |
|
|
334
|
+
| Query 操作栏 | 状态下拉 | 540 | 50 | Form.Item col-span=6 |
|
|
335
|
+
| Query 操作栏 | 查询按钮 | 980 | 50 | 操作按钮(右对齐) |
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
判定流程:
|
|
339
|
+
1. y 差<8px 识别同一行
|
|
340
|
+
2. 同行按 x 升序排
|
|
341
|
+
3. 计算 x 间距推算 antd Col span(24 栅格)或 flex
|
|
342
|
+
4. 最右元素若 `x + width` 接近容器右边界 → 右对齐(justify-content: flex-end)
|
|
343
|
+
|
|
344
|
+
##### 表 4:容器归属表(x+y 双轴边界检测)
|
|
345
|
+
|
|
346
|
+
仅对 `isVisualContainer === true` 的 group 和带 fill/border 的 rectangle 做检测。
|
|
347
|
+
|
|
348
|
+
```
|
|
349
|
+
| 容器 | x..x+w | y..y+h | 落入子元素 |
|
|
350
|
+
|------------------|----------|----------|----------------------------------|
|
|
351
|
+
| 渐变容器(group) | 240..960 | 189..297 | 段码含义(x=300,y=257) ✅ |
|
|
352
|
+
| 段码块-蓝(rect) | 320..420 | 320..360 | (无子节点,仅样式) |
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
判定式:子元素 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]` → 渲染在容器内部。**单轴判定无效**。
|
|
356
|
+
|
|
357
|
+
##### 表 5:样式映射表(rectangle/group fill → UI 组件内联样式)
|
|
358
|
+
|
|
359
|
+
```
|
|
360
|
+
| Sketch 节点 | 数据来源 | bg/border | 映射到代码 |
|
|
361
|
+
|----------------------|--------------------------|--------------------------|-----------------------------------------------------------|
|
|
362
|
+
| 段码块-蓝(rectangle) | style.fills[0]/borders[0]| bg #f2f8fd / b #d9eafb | <div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}> |
|
|
363
|
+
| 渐变容器(group) | style.fills[0].gradient | linear #f3faff→#f8fdff | <div style={{background:'linear-gradient(180deg,#f3faff,#f8fdff)'}}> |
|
|
364
|
+
| Tab 激活态 | rect bg #fff border #0079f7 | bg #fff / b #0079f7 | Tabs type="card" + .segmentTabs .ant-tabs-tab-active 覆盖 |
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
铁律(见收获 8):rectangle 的 fill/border 必须以**内联样式**或精确选择器落到代码,**禁止**用 `.beforebg{background:#ebf0ff}` 这类与设计稿无对应关系的 CSS class。
|
|
368
|
+
|
|
369
|
+
#### Pass 2:parent 质检(按 A/B/C/D 矩阵处理冲突)
|
|
370
|
+
|
|
371
|
+
逐行扫表 1,对照 parent 字段:
|
|
372
|
+
|
|
373
|
+
| 情形 | 坐标判定 | parent 判定 | 处理 |
|
|
374
|
+
|------|----------|-------------|------|
|
|
375
|
+
| A | 在容器 X 内 | parent 链含 X | ✅ 双向一致,直接采用 |
|
|
376
|
+
| B | 在容器 X 内 | parent 是兄弟节点 Y | ⚠️ **视觉容器优先**(设计师把图层拆开了)→ 按坐标渲染到 X 内 |
|
|
377
|
+
| C | 不在容器 X 内 | parent.name 强语义 = X | ⚠️ **parent 优先**(绝对定位/溢出布局)→ 按 parent 归属,加 `position:absolute` 标注 |
|
|
378
|
+
| D | 双向都不落 | parent 是顶层 | 独立元素,按坐标走纵向顺序 |
|
|
379
|
+
|
|
380
|
+
输出**最终归属表**:在表 1 末尾追加 `情形(A/B/C/D)` 列。
|
|
381
|
+
|
|
382
|
+
#### Pass 3:自检清单(写代码前必跑)
|
|
383
|
+
|
|
384
|
+
- [ ] 表 1 是否按 x 分布判定了布局类型(UpDown / LeftRight / LeftMiddleRight)?
|
|
385
|
+
- [ ] 表 2 同分区内是否按 y 排序,没有跨分区比 y?
|
|
386
|
+
- [ ] 表 3 同行元素(y 差<8px)是否按 x 排序,计算了栅格 span 或右对齐?
|
|
387
|
+
- [ ] 表 4 容器归属是否做了 x+y 双轴检测,不是只看一轴?
|
|
388
|
+
- [ ] 表 5 所有"颜色块/卡片/渐变"样式都来自 rectangle/group 的 style.fills/borders,没有出现凭空 CSS class?
|
|
389
|
+
- [ ] Pass 2 冲突行是否标了 A/B/C/D 情形和决策依据?
|
|
390
|
+
|
|
391
|
+
任一项 ❌ → 回 Pass 1 补;禁止跳到步骤 3 前未输出全部 5 张表 + 最终归属表。
|
|
392
|
+
|
|
393
|
+
**提示(sketch-mcp-server v1.6.1+)**:
|
|
253
394
|
- 大型 .sketch 文件先 `queryNodes(pageId, type="artboard")` 锁定目标画板,避免一次性加载整个文档
|
|
254
395
|
- `queryNodes(pageId, type=["text","rectangle","group"])` 一次拿三类节点 ID(type 字段支持数组),跳过 `getPageStructure(mode="ids")` 单独调用
|
|
255
396
|
- `getPageStructure(pageId, mode="tree", maxDepth=2-3)` 用于看分区层级;`mode="summary"` 用于按类型统计概况
|
|
256
|
-
- 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}`
|
|
397
|
+
- 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段 + group/artboard 额外有 `children` 和 `isVisualContainer` —— 步骤 2.6 的双向校验同时用 parent 和 x/y,不是只挑一个
|
|
257
398
|
- `matchIconFromName` 评分制返回 Top-3 + `bestMatch.source === "compound"` 强映射,shapePath 节点优先走它
|
|
258
399
|
- 仅当结构化样式数据仍不足(如复杂渐变、阴影)时,才回退到 `renderNodeAsBase64` + `analyze_design_image`
|
|
259
|
-
- 如果 sketch-mcp-server
|
|
400
|
+
- 如果 sketch-mcp-server 工具不可用或版本 < v1.6.1(parent / isVisualContainer 字段缺失),提示用户升级:`npm install -g @szc-ft/sketch-mcp-server@latest`
|
|
260
401
|
|
|
261
402
|
### 步骤3:分析设计稿(条件执行)
|
|
262
403
|
|
|
@@ -288,6 +429,7 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
288
429
|
|
|
289
430
|
**输入**:
|
|
290
431
|
- 步骤 1 的 `get_architecture_overview` 返回的 `templatePatterns`(TreeQueryTable / QueryTabsTables / LeftRight / UpDown)
|
|
432
|
+
- 步骤 1 的 `componentSummary`:全量组件 + 设计元信息(layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)—— **推理组件候选的权威目录,长尾场景按 layoutRole / useCases / sketchSignals 直接反查**
|
|
291
433
|
- 步骤 1 的 `llmMappingHints.commonMistakes`(避免 LLM 常见映射错误)
|
|
292
434
|
- 步骤 2.5 的 Sketch 节点结构 + 样式 Token
|
|
293
435
|
- 或步骤 3 的图片分析描述
|
|
@@ -301,38 +443,15 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
301
443
|
- ❌ 在步骤 3 内部推理组件候选列表(应只产出图片描述)
|
|
302
444
|
- ❌ 跳过此环节直接调 `get_component_full_profile`(必须先有候选列表)
|
|
303
445
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
*页面级布局*:
|
|
307
|
-
| Sketch 特征 | 推断结果 | 依据 |
|
|
308
|
-
|---|---|---|
|
|
309
|
-
| 画板名称(如 "4.1-编目审核-待办") | `pageName` | 直接使用 |
|
|
310
|
-
| 左右分区布局 | `TemplateMode(templateTpye="LeftRight")` | 区域分布 |
|
|
311
|
-
| 上下分区布局 | `TemplateMode(templateTpye="TopBottom")` | 区域分布 |
|
|
312
|
-
| 标签页(Tabs) + 每个 Tab 内有表格 | `QueryTabsTables` 或 `TemplateMode` + Tabs | templatePatterns.QueryTabsTables |
|
|
446
|
+
**推理依据**:步骤 1 返回的 `componentSummary` 是组件候选的权威目录(由组件库源码动态生成),每项含 `layoutRole` / `variantProps` / `useCases` / `sketchSignals`(图表层)。按以下顺序反查:
|
|
313
447
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
| 中间表头 + 数据行图层 | `TableOrList` 组件 | 表格区域特征 |
|
|
320
|
-
| 弹窗/抽屉图层 | `ModelOrDrawer` 组件 | 弹窗交互特征 |
|
|
321
|
-
| 页面标题 + 返回箭头 | `TitleAndBack` 组件 | 标题栏特征 |
|
|
322
|
-
| 详情展示区域(只读字段) | `FormItemOrDetailItem(type="detail")` | 详情区特征 |
|
|
323
|
-
|
|
324
|
-
*数据可视化(核心 3 类)*:
|
|
325
|
-
| Sketch 特征 | 推断结果 | 依据 |
|
|
326
|
-
|---|---|---|
|
|
327
|
-
| 折线趋势图/时间序列图 | `Line` | ECharts 层图表组件 |
|
|
328
|
-
| 柱状对比图/条形图 | `Bar` | ECharts 层图表组件 |
|
|
329
|
-
| 饼图/环形图/占比图 | `Pie` | ECharts 层图表组件 |
|
|
448
|
+
1. **画板名称** → 直接作为 `pageName`
|
|
449
|
+
2. **大区切分** → 看 `componentSummary.other` 里 `layoutRole === '页面定位'` 的组件(如 TemplateMode),结合 `variantProps.templateType`(LeftRight / TopBottom)和 `templatePatterns`(TreeQueryTable / QueryTabsTables)选模板
|
|
450
|
+
3. **区域容器** → `layoutRole === '区域容器'` 的组件(LeftTree / Query / TableOrList / ModelOrDrawer / TitleAndBack / FormItemOrDetailItem 等),按 `useCases` 描述匹配 Sketch 区域语义
|
|
451
|
+
4. **图表组件** → `componentSummary.echarts[*].sketchSignals` 反查 `chartType`,锁定 Line / Bar / Pie / Scatter 等
|
|
452
|
+
5. **变体选择** → 同一组件的子类型(如 TableOrList 的 ProTable / ProList / EditableProTable)查 `variantProps` 配合 useCases
|
|
330
453
|
|
|
331
|
-
|
|
332
|
-
| Sketch 特征 | 推断结果 | 依据 |
|
|
333
|
-
|---|---|---|
|
|
334
|
-
| 可编辑表格(单元格直接输入) | `TableOrList(componentType="EditableProTable")` | 可编辑表格特征 |
|
|
335
|
-
| 卡片列表(非表格式数据卡片) | `TableOrList(componentType="ProList")` | 卡片布局特征 |
|
|
454
|
+
不要硬编码任何「Sketch 特征 → 组件」对照表——`componentSummary` 是唯一可信源,硬编码表会和服务端动态扫描结果漂移。
|
|
336
455
|
|
|
337
456
|
#### ⚠️ TemplateMode 槽位传参铁律(高频踩坑)
|
|
338
457
|
|
|
@@ -427,10 +546,22 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
427
546
|
| 组件 | 依赖的 szcd 组件 | 依赖的 hooks |
|
|
428
547
|
|------|-----------------|-------------|
|
|
429
548
|
|
|
549
|
+
### 布局顺序(来自步骤 2.6 表 2 压缩,按 y 排序)
|
|
550
|
+
[页面级垂直顺序,如:TitleAndBack → 段码定义卡片 → Tabs → 配置说明卡片]
|
|
551
|
+
|
|
552
|
+
### 关键样式映射(来自步骤 2.6 表 5,仅列非默认样式)
|
|
553
|
+
| UI 元素 | Sketch 数据来源 | 落地方式 |
|
|
554
|
+
|---------|----------------|----------|
|
|
555
|
+
| 段码块×5 | 5 个 rectangle 的 fills[0]/borders[0] | 内联 style |
|
|
556
|
+
| 渐变容器 | group(isVisualContainer) 的 fills[0].gradient | 内联 linear-gradient |
|
|
557
|
+
| Tab 激活态 | rectangle bg #fff border #0079f7 | type="card" + .segmentTabs 覆盖 |
|
|
558
|
+
|
|
430
559
|
### 备选方案(如有)
|
|
431
560
|
[说明]
|
|
432
561
|
```
|
|
433
562
|
|
|
563
|
+
用户在确认环节即可发现"段码块颜色没列上"或"Tab 样式漏识别",避免反馈 #11 那样要等代码生成后反复修。
|
|
564
|
+
|
|
434
565
|
**交互节点**:向用户确认:
|
|
435
566
|
- "以上组件方案是否合适?是否需要调整?"
|
|
436
567
|
- 提供选项:同意方案 / 需要调整 / 换一个方案
|
|
@@ -451,6 +582,20 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
451
582
|
- 复合组件配合 TemplateMode 使用实现标准页面布局
|
|
452
583
|
- Hooks 按依赖关系正确引入(如 useLeftTree、useTable)
|
|
453
584
|
|
|
585
|
+
#### 步骤 6 末尾必做:样式落地校验
|
|
586
|
+
|
|
587
|
+
代码生成完成后,**逐行核对**步骤 2.6 表 5(样式映射表)的每一项是否真落到代码里:
|
|
588
|
+
|
|
589
|
+
```
|
|
590
|
+
| 样式映射表行 | 代码中对应位置 | 校验 |
|
|
591
|
+
|---------------------------------------------|-------------------------------------------------------------|------|
|
|
592
|
+
| 段码块-蓝 bg #f2f8fd border #d9eafb | CreateOrEdit.tsx:L120 `<div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}>` | ✅ |
|
|
593
|
+
| 渐变容器 linear #f3faff→#f8fdff | CreateOrEdit.tsx:L98 `style={{background:'linear-gradient(...)'}}` | ✅ |
|
|
594
|
+
| Tab 激活态 bg #fff border #0079f7 | styles.less:L45 `.segmentTabs .ant-tabs-tab-active{...}` | ✅ |
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
❌ 如果某行找不到对应代码位置 → 直接补到代码里再继续,**禁止说"代码已生成"前留缺口**。这是反馈 #11"5 个段码块全错"的根因——所有颜色都拿到了,但没逐一回查是否落到了代码上。
|
|
598
|
+
|
|
454
599
|
|
|
455
600
|
**交互节点**:代码生成后,询问用户下一步:
|
|
456
601
|
> "代码已生成,你可以选择:
|
|
@@ -56,7 +56,7 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
56
56
|
**在正式开始之前,获取项目架构全局视图,同时验证 MCP 连接。**
|
|
57
57
|
|
|
58
58
|
执行动作:
|
|
59
|
-
1. 调用 `mcp__szcd-component-helper__get_architecture_overview`(detail="
|
|
59
|
+
1. 调用 `mcp__szcd-component-helper__get_architecture_overview`(detail="full")一次性获取:7 层架构图、模板组合模式、推荐使用顺序、LLM 映射错误提示,**以及 `componentSummary`(全量组件 + 设计元信息:layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)+ `styleMapping`(节点样式映射)+ `assetExtraction`(图标/位图/图表色提取规则)**——这些是步骤 3.5 推理组件候选和步骤 5 样式注入的核心依据
|
|
60
60
|
2. 如果连接失败,**立即停止并返回错误信息**,告知用户需要先配置 MCP 服务器
|
|
61
61
|
3. 如果成功,根据返回的 `templatePatterns` 初步判断用户需求匹配哪个模板
|
|
62
62
|
|
|
@@ -145,6 +145,27 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
145
145
|
| 元素归属 | 凭 x/y 坐标判定("x=272 列都是同区域") | 看 `getMultipleNodeInfo` 返回的 `parent.id/name` 字段 |
|
|
146
146
|
| 颜色提取 | 跳过 group 只取 text/rectangle | 同批提交 group ID,从 `style.fills` 取渐变背景 |
|
|
147
147
|
|
|
148
|
+
#### getMultipleNodeInfo 返回字段契约(sketch-mcp-server ≥ v1.6.1)
|
|
149
|
+
|
|
150
|
+
| 字段 | 适用类型 | 用途 |
|
|
151
|
+
|------|----------|------|
|
|
152
|
+
| `position:{x,y}` + `size:{width,height}` | 全部 | 步骤 2.6 表 1/2/3/4 的坐标推理 |
|
|
153
|
+
| `parent:{id,name,type}` | 全部(顶层除外) | 步骤 2.6 表 1 大区归属、Pass 2 质检 |
|
|
154
|
+
| `style.fills[].{color,gradient}` | rectangle / group / text | 表 5 样式映射 |
|
|
155
|
+
| `style.borders[].{color,thickness}` | rectangle / group | 表 5 样式映射 |
|
|
156
|
+
| `style.shadows[]` | rectangle / group | 表 5 样式映射 |
|
|
157
|
+
| `text.attributes[0].attributes.{fontFamily,fontSize,color,lineHeight}` | text | 字号/字重/颜色(fontFamily 编码字重,如 PingFangSC-Semibold → 600) |
|
|
158
|
+
| `children:[id]` | group / artboard | 推断容器子节点集合(与 parent 反向印证) |
|
|
159
|
+
| `isVisualContainer:bool` | group / artboard | true = 该 group 自身带 fills/borders/shadows,必须作为 UI 容器渲染(不是纯图层分组) |
|
|
160
|
+
| `shape.cornerRadius` | rectangle / oval | 圆角 |
|
|
161
|
+
|
|
162
|
+
**字段缺失自检**(任一项失败 → sketch-mcp-server 版本过旧,升级到 ≥ v1.6.1 后重跑):
|
|
163
|
+
|
|
164
|
+
- [ ] 任取一个 text 节点,`parent.id` 非空 ✅
|
|
165
|
+
- [ ] 任取一个 group 节点,`isVisualContainer` 类型是 boolean、`children` 是数组 ✅
|
|
166
|
+
- [ ] 任取一个 rectangle 节点,`style.fills` 数组存在(即使为空也要是 `[]` 不能 undefined) ✅
|
|
167
|
+
- [ ] 任取一个 text 节点,`text.attributes[0].attributes.fontFamily` 可读出(编码字重) ✅
|
|
168
|
+
|
|
148
169
|
**实战经验沉淀(重要)**:
|
|
149
170
|
|
|
150
171
|
**收获 1:首轮 `getMultipleNodeInfo` 必须全量拉取,不能挑**
|
|
@@ -159,15 +180,20 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
159
180
|
错误做法:先查 text 拿自身样式 → 再根据 parent ID 单独查 rectangle(多走一步)
|
|
160
181
|
正确做法:用 `queryNodes(type=["text","rectangle","group"])` 一次拿三类 ID,`getMultipleNodeInfo` 返回的 `parent` 字段直接告诉你归属关系
|
|
161
182
|
|
|
162
|
-
**收获 3
|
|
183
|
+
**收获 3:归属判定走 x+y+parent 三轴联合,禁止单轴定论(坐标和 parent 互为纠错器)**
|
|
163
184
|
|
|
164
|
-
|
|
185
|
+
实战教训:
|
|
186
|
+
- 反例 A:`'主题'text(x=272,y=149)` 单看 x 在右侧内容区列,但 `parent.name=leftTreeHeader` 强语义 → 归左树(情形 C:parent 修正坐标)
|
|
187
|
+
- 反例 B(反馈 #11):`'段码含义'text(x=300,y=257)` 坐标落在 `渐变容器(x=240..960, y=189..297)` 内,但 parent 是兄弟编组 `cataMain` → 视觉上属于渐变容器内(情形 B:图层拆开,按坐标渲染)
|
|
165
188
|
|
|
166
189
|
正确做法:
|
|
167
|
-
- 步骤 2
|
|
168
|
-
-
|
|
169
|
-
-
|
|
170
|
-
-
|
|
190
|
+
- 步骤 2.5 第 4 步先 `mode="tree"` 看顶层 group 分区(通常 2-5 个)
|
|
191
|
+
- 步骤 2.6 做双向校验:Pass 1 坐标推假设 → Pass 2 parent 质检 → 四类情形 A/B/C/D 处理
|
|
192
|
+
- 大区归属:`parent.name` 含 `LeftTree/树/PageContent/sidebar/cataMain` 等强语义关键字时优先于 x 分布
|
|
193
|
+
- 容器归属:必须 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]`,单轴判定无效
|
|
194
|
+
- 跨分区不比 y;同分区内按 y 升序;同行(y 差<8px)按 x 升序
|
|
195
|
+
|
|
196
|
+
详细决策矩阵见步骤 2.6。
|
|
171
197
|
|
|
172
198
|
**收获 4:信息栏/卡片容器必须先取 group 再取子元素**
|
|
173
199
|
|
|
@@ -213,14 +239,129 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
213
239
|
|
|
214
240
|
- **兜底方案**:① 用 `extractBitmaps` 提取的 PNG/PDF 资源;② `matchIconFromName` 的 Top-1(若 source=compound);③ unmatched 时按 parent 上下文 + 上表选 antd `@ant-design/icons` 复合图标;④ 在代码注释中标注"⚠️ 矢量图标用 antd 图标替代,原始 Sketch 为 shapePath"
|
|
215
241
|
|
|
216
|
-
|
|
242
|
+
**收获 8:rectangle 的 fill/border 必须以内联样式或精确选择器落到 DOM,禁止借用通用 CSS class**
|
|
243
|
+
|
|
244
|
+
实战教训(反馈 #11):5 个段码视觉块的颜色(#f2f8fd/#f5ffed/#fffbe6/#f5f6f7)完整地从 rectangle 节点拿到了,但代码却用了 `.beforebg{background:#ebf0ff}` 这种与设计稿无对应关系的通用 class,导致 5 个块颜色全错。
|
|
245
|
+
|
|
246
|
+
正确做法:
|
|
247
|
+
- 步骤 2.6 的样式映射表(表 5)必须为每个"颜色块"列出 rectangle 数据 → 内联 style 的对应关系
|
|
248
|
+
- 写代码时直接用 `<div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}>`
|
|
249
|
+
- 若必须用 CSS class,类名要能反向追到 Sketch 节点(如 `.segmentBlock-blue` 而非 `.beforebg`),且 class 内容必须**精确等于** rectangle 的 fill/border
|
|
250
|
+
- 反例排查:写完代码后 grep 一下 CSS class 名,出现 `.bg1/.box2/.before*` 这类无语义类名、且颜色和设计稿对不上 → 几乎确定是凭空兜底
|
|
251
|
+
|
|
252
|
+
### 步骤2.6:布局推理(必做,写代码前的最后一道关)
|
|
253
|
+
|
|
254
|
+
⚠️ 这一步专治"数据全拿到却放错位置"。反馈 #11 的 5 处错位全部由跳过此步骤导致。
|
|
255
|
+
|
|
256
|
+
**核心思路**:x+y 坐标先画"视觉假设",parent 字段做质检纠错。两套信号**互为纠错器**,不是单方向"谁优先"。
|
|
257
|
+
|
|
258
|
+
**输入**:步骤 2.5 产出的 `text + rectangle + group` 节点全量数据(含 `position.{x,y}`、`size.{width,height}`、`parent.{id,name,type}`、`style`、`isVisualContainer`)
|
|
259
|
+
|
|
260
|
+
#### Pass 1:坐标推假设(产出 5 张表)
|
|
261
|
+
|
|
262
|
+
每张表都必须输出,即使某类节点为空也要写"无"。
|
|
263
|
+
|
|
264
|
+
##### 表 1:分区识别表(x+y+parent 联合,定大区)
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
| 节点 name | x | y | parent.name | 推断分区 | 决策依据 |
|
|
268
|
+
|----------------|-----|-----|------------------|--------------|-------------------------|
|
|
269
|
+
| 主题(text) | 272 | 149 | leftTreeHeader | 左树标题区 | parent 强语义压过 x 列 |
|
|
270
|
+
| 段码定义(text) | 320 | 200 | cataMain | 右侧内容-顶部 | parent 含 PageContent 类语义 |
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
判定流程:
|
|
274
|
+
1. 按 x 把画板切成 1-3 列(x<300 → 左区、x≥300 → 右区,或按设计稿实际边界)
|
|
275
|
+
2. 用 `parent.name` 校验:含 `LeftTree/树/sidebar/cataMain/PageContent/header/footer` 等关键字时以 parent 为准
|
|
276
|
+
3. 冲突时遵循"收获 3"的 A/B/C/D 矩阵(见下方 Pass 2)
|
|
277
|
+
|
|
278
|
+
→ 此表输出**布局类型**:UpDown(单列)/ LeftRight(双列)/ LeftMiddleRight(三列)
|
|
279
|
+
|
|
280
|
+
##### 表 2:纵向顺序表(同分区内按 y)
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
| 分区 | 节点 | y | 推断角色 |
|
|
284
|
+
|------------|---------------|-----|-------------------|
|
|
285
|
+
| 右侧内容区 | 段码定义 | 200 | 卡片 1 |
|
|
286
|
+
| 右侧内容区 | Tabs | 420 | Tabs(type=card) |
|
|
287
|
+
| 右侧内容区 | 配置说明 | 478 | 卡片 2(Tabs 下方) |
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
铁律:**同分区内**渲染顺序按 y 升序。跨分区不比 y(左树第 100 行 y 和右内容区第 1 行 y 没有可比性)。
|
|
291
|
+
|
|
292
|
+
##### 表 3:横向排列表(同行按 x,y 差<8px 视为同行)
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
| 分区/容器 | 节点 | x | y | 推断角色 |
|
|
296
|
+
|-----------------|--------------|-----|-----|-------------------------|
|
|
297
|
+
| Query 操作栏 | 名称输入框 | 320 | 50 | Form.Item col-span=6 |
|
|
298
|
+
| Query 操作栏 | 状态下拉 | 540 | 50 | Form.Item col-span=6 |
|
|
299
|
+
| Query 操作栏 | 查询按钮 | 980 | 50 | 操作按钮(右对齐) |
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
判定流程:
|
|
303
|
+
1. y 差<8px 识别同一行
|
|
304
|
+
2. 同行按 x 升序排
|
|
305
|
+
3. 计算 x 间距推算 antd Col span(24 栅格)或 flex
|
|
306
|
+
4. 最右元素若 `x + width` 接近容器右边界 → 右对齐(justify-content: flex-end)
|
|
307
|
+
|
|
308
|
+
##### 表 4:容器归属表(x+y 双轴边界检测)
|
|
309
|
+
|
|
310
|
+
仅对 `isVisualContainer === true` 的 group 和带 fill/border 的 rectangle 做检测。
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
| 容器 | x..x+w | y..y+h | 落入子元素 |
|
|
314
|
+
|------------------|----------|----------|----------------------------------|
|
|
315
|
+
| 渐变容器(group) | 240..960 | 189..297 | 段码含义(x=300,y=257) ✅ |
|
|
316
|
+
| 段码块-蓝(rect) | 320..420 | 320..360 | (无子节点,仅样式) |
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
判定式:子元素 `x ∈ [容器x, 容器x+w]` **且** `y ∈ [容器y, 容器y+h]` → 渲染在容器内部。**单轴判定无效**。
|
|
320
|
+
|
|
321
|
+
##### 表 5:样式映射表(rectangle/group fill → UI 组件内联样式)
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
| Sketch 节点 | 数据来源 | bg/border | 映射到代码 |
|
|
325
|
+
|----------------------|--------------------------|--------------------------|-----------------------------------------------------------|
|
|
326
|
+
| 段码块-蓝(rectangle) | style.fills[0]/borders[0]| bg #f2f8fd / b #d9eafb | <div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}> |
|
|
327
|
+
| 渐变容器(group) | style.fills[0].gradient | linear #f3faff→#f8fdff | <div style={{background:'linear-gradient(180deg,#f3faff,#f8fdff)'}}> |
|
|
328
|
+
| Tab 激活态 | rect bg #fff border #0079f7 | bg #fff / b #0079f7 | Tabs type="card" + .segmentTabs .ant-tabs-tab-active 覆盖 |
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
铁律(见收获 8):rectangle 的 fill/border 必须以**内联样式**或精确选择器落到代码,**禁止**用 `.beforebg{background:#ebf0ff}` 这类与设计稿无对应关系的 CSS class。
|
|
332
|
+
|
|
333
|
+
#### Pass 2:parent 质检(按 A/B/C/D 矩阵处理冲突)
|
|
334
|
+
|
|
335
|
+
逐行扫表 1,对照 parent 字段:
|
|
336
|
+
|
|
337
|
+
| 情形 | 坐标判定 | parent 判定 | 处理 |
|
|
338
|
+
|------|----------|-------------|------|
|
|
339
|
+
| A | 在容器 X 内 | parent 链含 X | ✅ 双向一致,直接采用 |
|
|
340
|
+
| B | 在容器 X 内 | parent 是兄弟节点 Y | ⚠️ **视觉容器优先**(设计师把图层拆开了)→ 按坐标渲染到 X 内 |
|
|
341
|
+
| C | 不在容器 X 内 | parent.name 强语义 = X | ⚠️ **parent 优先**(绝对定位/溢出布局)→ 按 parent 归属,加 `position:absolute` 标注 |
|
|
342
|
+
| D | 双向都不落 | parent 是顶层 | 独立元素,按坐标走纵向顺序 |
|
|
343
|
+
|
|
344
|
+
输出**最终归属表**:在表 1 末尾追加 `情形(A/B/C/D)` 列。
|
|
345
|
+
|
|
346
|
+
#### Pass 3:自检清单(写代码前必跑)
|
|
347
|
+
|
|
348
|
+
- [ ] 表 1 是否按 x 分布判定了布局类型(UpDown / LeftRight / LeftMiddleRight)?
|
|
349
|
+
- [ ] 表 2 同分区内是否按 y 排序,没有跨分区比 y?
|
|
350
|
+
- [ ] 表 3 同行元素(y 差<8px)是否按 x 排序,计算了栅格 span 或右对齐?
|
|
351
|
+
- [ ] 表 4 容器归属是否做了 x+y 双轴检测,不是只看一轴?
|
|
352
|
+
- [ ] 表 5 所有"颜色块/卡片/渐变"样式都来自 rectangle/group 的 style.fills/borders,没有出现凭空 CSS class?
|
|
353
|
+
- [ ] Pass 2 冲突行是否标了 A/B/C/D 情形和决策依据?
|
|
354
|
+
|
|
355
|
+
任一项 ❌ → 回 Pass 1 补;禁止跳到步骤 3 前未输出全部 5 张表 + 最终归属表。
|
|
356
|
+
|
|
357
|
+
**提示(sketch-mcp-server v1.6.1+)**:
|
|
217
358
|
- 大型 .sketch 文件先 `queryNodes(pageId, type="artboard")` 锁定目标画板,避免一次性加载整个文档
|
|
218
359
|
- `queryNodes(pageId, type=["text","rectangle","group"])` 一次拿三类节点 ID(type 字段支持数组),跳过 `getPageStructure(mode="ids")` 单独调用
|
|
219
360
|
- `getPageStructure(pageId, mode="tree", maxDepth=2-3)` 用于看分区层级;`mode="summary"` 用于按类型统计概况
|
|
220
|
-
- 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}`
|
|
361
|
+
- 批量 `getMultipleNodeInfo` 支持任意数量 ID(内部按 100 一批自动分片),无需手动拆分;每个节点自带 `parent: {id,name,type}` 字段 + group/artboard 额外有 `children` 和 `isVisualContainer` —— 步骤 2.6 的双向校验同时用 parent 和 x/y,不是只挑一个
|
|
221
362
|
- `matchIconFromName` 评分制返回 Top-3 + `bestMatch.source === "compound"` 强映射,shapePath 节点优先走它
|
|
222
363
|
- 仅当结构化样式数据仍不足(如复杂渐变、阴影)时,才回退到 `renderNodeAsBase64` + `mcp__szcd-component-helper__analyze_design_image`
|
|
223
|
-
- 如果 sketch-mcp-server
|
|
364
|
+
- 如果 sketch-mcp-server 工具不可用或版本 < v1.6.1(parent / isVisualContainer 字段缺失),提示用户升级:`npm install -g @szc-ft/sketch-mcp-server@latest`
|
|
224
365
|
|
|
225
366
|
### 步骤3:分析设计稿(条件执行)
|
|
226
367
|
|
|
@@ -251,6 +392,7 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
251
392
|
|
|
252
393
|
**输入**:
|
|
253
394
|
- 步骤 1 的 `mcp__szcd-component-helper__get_architecture_overview` 返回的 `templatePatterns`(TreeQueryTable / QueryTabsTables / LeftRight / UpDown)
|
|
395
|
+
- 步骤 1 的 `componentSummary`:全量组件 + 设计元信息(layoutRole/variantProps/styleInjection/useCases,other/echarts 层附带 compositionSlots/requiredHooks/chartType/sketchSignals)—— **推理组件候选的权威目录,长尾场景按 layoutRole / useCases / sketchSignals 直接反查**
|
|
254
396
|
- 步骤 1 的 `llmMappingHints.commonMistakes`(避免 LLM 常见映射错误)
|
|
255
397
|
- 步骤 2.5 的 Sketch 节点结构 + 样式 Token
|
|
256
398
|
- 或步骤 3 的图片分析描述
|
|
@@ -264,38 +406,15 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
264
406
|
- ❌ 在步骤 3 内部推理组件候选列表(应只产出图片描述)
|
|
265
407
|
- ❌ 跳过此环节直接调 `get_component_full_profile`(必须先有候选列表)
|
|
266
408
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
*页面级布局*:
|
|
270
|
-
| Sketch 特征 | 推断结果 | 依据 |
|
|
271
|
-
|---|---|---|
|
|
272
|
-
| 画板名称(如 "4.1-编目审核-待办") | `pageName` | 直接使用 |
|
|
273
|
-
| 左右分区布局 | `TemplateMode(templateTpye="LeftRight")` | 区域分布 |
|
|
274
|
-
| 上下分区布局 | `TemplateMode(templateTpye="TopBottom")` | 区域分布 |
|
|
275
|
-
| 标签页(Tabs) + 每个 Tab 内有表格 | `QueryTabsTables` 或 `TemplateMode` + Tabs | templatePatterns.QueryTabsTables |
|
|
409
|
+
**推理依据**:步骤 1 返回的 `componentSummary` 是组件候选的权威目录(由组件库源码动态生成),每项含 `layoutRole` / `variantProps` / `useCases` / `sketchSignals`(图表层)。按以下顺序反查:
|
|
276
410
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
| 中间表头 + 数据行图层 | `TableOrList` 组件 | 表格区域特征 |
|
|
283
|
-
| 弹窗/抽屉图层 | `ModelOrDrawer` 组件 | 弹窗交互特征 |
|
|
284
|
-
| 页面标题 + 返回箭头 | `TitleAndBack` 组件 | 标题栏特征 |
|
|
285
|
-
| 详情展示区域(只读字段) | `FormItemOrDetailItem(type="detail")` | 详情区特征 |
|
|
286
|
-
|
|
287
|
-
*数据可视化(核心 3 类)*:
|
|
288
|
-
| Sketch 特征 | 推断结果 | 依据 |
|
|
289
|
-
|---|---|---|
|
|
290
|
-
| 折线趋势图/时间序列图 | `Line` | ECharts 层图表组件 |
|
|
291
|
-
| 柱状对比图/条形图 | `Bar` | ECharts 层图表组件 |
|
|
292
|
-
| 饼图/环形图/占比图 | `Pie` | ECharts 层图表组件 |
|
|
411
|
+
1. **画板名称** → 直接作为 `pageName`
|
|
412
|
+
2. **大区切分** → 看 `componentSummary.other` 里 `layoutRole === '页面定位'` 的组件(如 TemplateMode),结合 `variantProps.templateType`(LeftRight / TopBottom)和 `templatePatterns`(TreeQueryTable / QueryTabsTables)选模板
|
|
413
|
+
3. **区域容器** → `layoutRole === '区域容器'` 的组件(LeftTree / Query / TableOrList / ModelOrDrawer / TitleAndBack / FormItemOrDetailItem 等),按 `useCases` 描述匹配 Sketch 区域语义
|
|
414
|
+
4. **图表组件** → `componentSummary.echarts[*].sketchSignals` 反查 `chartType`,锁定 Line / Bar / Pie / Scatter 等
|
|
415
|
+
5. **变体选择** → 同一组件的子类型(如 TableOrList 的 ProTable / ProList / EditableProTable)查 `variantProps` 配合 useCases
|
|
293
416
|
|
|
294
|
-
|
|
295
|
-
| Sketch 特征 | 推断结果 | 依据 |
|
|
296
|
-
|---|---|---|
|
|
297
|
-
| 可编辑表格(单元格直接输入) | `TableOrList(componentType="EditableProTable")` | 可编辑表格特征 |
|
|
298
|
-
| 卡片列表(非表格式数据卡片) | `TableOrList(componentType="ProList")` | 卡片布局特征 |
|
|
417
|
+
不要硬编码任何「Sketch 特征 → 组件」对照表——`componentSummary` 是唯一可信源,硬编码表会和服务端动态扫描结果漂移。
|
|
299
418
|
|
|
300
419
|
#### ⚠️ TemplateMode 槽位传参铁律(高频踩坑)
|
|
301
420
|
|
|
@@ -389,10 +508,22 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
389
508
|
| 组件 | 依赖的 szcd 组件 | 依赖的 hooks |
|
|
390
509
|
|------|-----------------|-------------|
|
|
391
510
|
|
|
511
|
+
### 布局顺序(来自步骤 2.6 表 2 压缩,按 y 排序)
|
|
512
|
+
[页面级垂直顺序,如:TitleAndBack → 段码定义卡片 → Tabs → 配置说明卡片]
|
|
513
|
+
|
|
514
|
+
### 关键样式映射(来自步骤 2.6 表 5,仅列非默认样式)
|
|
515
|
+
| UI 元素 | Sketch 数据来源 | 落地方式 |
|
|
516
|
+
|---------|----------------|----------|
|
|
517
|
+
| 段码块×5 | 5 个 rectangle 的 fills[0]/borders[0] | 内联 style |
|
|
518
|
+
| 渐变容器 | group(isVisualContainer) 的 fills[0].gradient | 内联 linear-gradient |
|
|
519
|
+
| Tab 激活态 | rectangle bg #fff border #0079f7 | type="card" + .segmentTabs 覆盖 |
|
|
520
|
+
|
|
392
521
|
### 备选方案(如有)
|
|
393
522
|
[说明]
|
|
394
523
|
```
|
|
395
524
|
|
|
525
|
+
用户在确认环节即可发现"段码块颜色没列上"或"Tab 样式漏识别",避免反馈 #11 那样要等代码生成后反复修。
|
|
526
|
+
|
|
396
527
|
|
|
397
528
|
**交互节点**:向用户展示匹配结果,**必须确认方案后再生成代码**。
|
|
398
529
|
|
|
@@ -409,6 +540,20 @@ Ant Design → ProComponents → Cover 层 → Wrapper 层 → ProPackages →
|
|
|
409
540
|
- 复合组件配合 TemplateMode 使用实现标准页面布局
|
|
410
541
|
- Hooks 按依赖关系正确引入(如 useLeftTree、useTable)
|
|
411
542
|
|
|
543
|
+
#### 步骤 6 末尾必做:样式落地校验
|
|
544
|
+
|
|
545
|
+
代码生成完成后,**逐行核对**步骤 2.6 表 5(样式映射表)的每一项是否真落到代码里:
|
|
546
|
+
|
|
547
|
+
```
|
|
548
|
+
| 样式映射表行 | 代码中对应位置 | 校验 |
|
|
549
|
+
|---------------------------------------------|-------------------------------------------------------------|------|
|
|
550
|
+
| 段码块-蓝 bg #f2f8fd border #d9eafb | CreateOrEdit.tsx:L120 `<div style={{background:'#f2f8fd',border:'1px solid #d9eafb'}}>` | ✅ |
|
|
551
|
+
| 渐变容器 linear #f3faff→#f8fdff | CreateOrEdit.tsx:L98 `style={{background:'linear-gradient(...)'}}` | ✅ |
|
|
552
|
+
| Tab 激活态 bg #fff border #0079f7 | styles.less:L45 `.segmentTabs .ant-tabs-tab-active{...}` | ✅ |
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
❌ 如果某行找不到对应代码位置 → 直接补到代码里再继续,**禁止说"代码已生成"前留缺口**。这是反馈 #11"5 个段码块全错"的根因——所有颜色都拿到了,但没逐一回查是否落到了代码上。
|
|
556
|
+
|
|
412
557
|
|
|
413
558
|
**交互节点**:代码生成后,询问用户下一步:
|
|
414
559
|
> "代码已生成,你可以选择:
|