claude-coder 1.9.2 → 1.10.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/README.md +236 -214
- package/bin/cli.js +170 -155
- package/package.json +55 -55
- package/recipes/_shared/roles/developer.md +11 -11
- package/recipes/_shared/roles/product.md +12 -12
- package/recipes/_shared/roles/tester.md +12 -12
- package/recipes/_shared/test/report-format.md +86 -86
- package/recipes/backend/base.md +27 -27
- package/recipes/backend/components/auth.md +18 -18
- package/recipes/backend/components/crud-api.md +18 -18
- package/recipes/backend/components/file-service.md +15 -15
- package/recipes/backend/manifest.json +20 -20
- package/recipes/backend/test/api-test.md +25 -25
- package/recipes/console/base.md +37 -37
- package/recipes/console/components/modal-form.md +20 -20
- package/recipes/console/components/pagination.md +17 -17
- package/recipes/console/components/search.md +17 -17
- package/recipes/console/components/table-list.md +18 -18
- package/recipes/console/components/tabs.md +14 -14
- package/recipes/console/components/tree.md +15 -15
- package/recipes/console/components/upload.md +15 -15
- package/recipes/console/manifest.json +24 -24
- package/recipes/console/test/crud-e2e.md +47 -47
- package/recipes/h5/base.md +26 -26
- package/recipes/h5/components/animation.md +11 -11
- package/recipes/h5/components/countdown.md +11 -11
- package/recipes/h5/components/share.md +11 -11
- package/recipes/h5/components/swiper.md +11 -11
- package/recipes/h5/manifest.json +21 -21
- package/recipes/h5/test/h5-e2e.md +20 -20
- package/src/commands/auth.js +420 -420
- package/src/commands/setup-modules/helpers.js +100 -100
- package/src/commands/setup-modules/index.js +25 -25
- package/src/commands/setup-modules/mcp.js +115 -115
- package/src/commands/setup-modules/provider.js +260 -260
- package/src/commands/setup-modules/safety.js +47 -47
- package/src/commands/setup-modules/simplify.js +52 -52
- package/src/commands/setup.js +172 -172
- package/src/common/assets.js +259 -245
- package/src/common/config.js +147 -125
- package/src/common/constants.js +55 -55
- package/src/common/indicator.js +260 -260
- package/src/common/interaction.js +170 -170
- package/src/common/logging.js +77 -77
- package/src/common/sdk.js +48 -50
- package/src/common/tasks.js +88 -88
- package/src/common/utils.js +214 -213
- package/src/core/coding.js +35 -33
- package/src/core/design.js +268 -0
- package/src/core/go.js +264 -264
- package/src/core/hooks.js +514 -500
- package/src/core/init.js +175 -166
- package/src/core/plan.js +194 -188
- package/src/core/prompts.js +292 -247
- package/src/core/repair.js +36 -36
- package/src/core/runner.js +471 -471
- package/src/core/scan.js +94 -93
- package/src/core/session.js +294 -280
- package/src/core/simplify.js +76 -74
- package/src/core/state.js +120 -105
- package/src/index.js +80 -76
- package/templates/{codingSystem.md → coding/system.md} +65 -65
- package/templates/{codingUser.md → coding/user.md} +18 -17
- package/templates/design/base.md +103 -0
- package/templates/design/fixSystem.md +71 -0
- package/templates/design/fixUser.md +3 -0
- package/templates/design/init.md +304 -0
- package/templates/design/system.md +108 -0
- package/templates/design/user.md +11 -0
- package/templates/{goSystem.md → go/system.md} +130 -130
- package/templates/{bash-process.md → other/bash-process.md} +12 -12
- package/templates/{coreProtocol.md → other/coreProtocol.md} +30 -29
- package/templates/{guidance.json → other/guidance.json} +72 -72
- package/templates/{requirements.example.md → other/requirements.example.md} +57 -57
- package/templates/{test_rule.md → other/test_rule.md} +192 -194
- package/templates/{web-testing.md → other/web-testing.md} +17 -17
- package/templates/{planSystem.md → plan/system.md} +78 -78
- package/templates/{planUser.md → plan/user.md} +10 -9
- package/templates/{scanSystem.md → scan/system.md} +120 -120
- package/templates/{scanUser.md → scan/user.md} +10 -10
- package/types/index.d.ts +217 -217
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
Session {{sessionNum}}。任务已分配,按 3 步流程执行。
|
|
2
|
-
|
|
3
|
-
## 任务
|
|
4
|
-
{{taskContext}}
|
|
5
|
-
|
|
6
|
-
## 上下文
|
|
7
|
-
{{memoryHint}}
|
|
8
|
-
{{envHint}}
|
|
9
|
-
{{docsHint}}
|
|
10
|
-
{{testEnvHint}}
|
|
11
|
-
{{mcpHint}}
|
|
12
|
-
{{webTestHint}}
|
|
13
|
-
{{
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
Session {{sessionNum}}。任务已分配,按 3 步流程执行。
|
|
2
|
+
|
|
3
|
+
## 任务
|
|
4
|
+
{{taskContext}}
|
|
5
|
+
|
|
6
|
+
## 上下文
|
|
7
|
+
{{memoryHint}}
|
|
8
|
+
{{envHint}}
|
|
9
|
+
{{docsHint}}
|
|
10
|
+
{{testEnvHint}}
|
|
11
|
+
{{mcpHint}}
|
|
12
|
+
{{webTestHint}}
|
|
13
|
+
{{designHint}}
|
|
14
|
+
{{retryContext}}
|
|
15
|
+
|
|
16
|
+
## 收尾
|
|
17
|
+
{{serviceHint}}
|
|
18
|
+
完成后写入 session_result.json(notes 只写未解决问题)。
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# .pen 文件格式规范
|
|
2
|
+
|
|
3
|
+
> 本文件为所有 design 类型(init / new / fix)共享的 .pen 格式规则。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 核心原则
|
|
8
|
+
.pen 文件是 JSON 格式, 禁止任何破坏 JSON 格式的行为。
|
|
9
|
+
|
|
10
|
+
## 语法铁律
|
|
11
|
+
|
|
12
|
+
| # | 规则 | 正确 | 错误 |
|
|
13
|
+
|---|------|------|------|
|
|
14
|
+
| 1 | version `"2.9"` | `"version": "2.9"` | `"2.8"` |
|
|
15
|
+
| 2 | 跨文件引用用**冒号** | `$sys:color.primary` / `ref: "sys:header"` | `$sys/color.primary` / `sys/header` |
|
|
16
|
+
| 3 | 跨文件 descendants key 也用冒号 | `"sys:card-title": { "content": "..." }` | `"card-title": { "content": "..." }` |
|
|
17
|
+
| 4 | 圆角是 `cornerRadius` | `"cornerRadius": 12` | `"borderRadius": 12` |
|
|
18
|
+
| 5 | 独立 `x`, `y` | `"x": 0, "y": 0` | `"position": {"x":0,"y":0}` |
|
|
19
|
+
| 6 | stroke 是对象 | `{"align":"center","thickness":2,"fill":"#ccc"}` | `"stroke":"#ccc"` |
|
|
20
|
+
| 7 | 颜色 hex 格式 | `"#RRGGBB"` / `"#RRGGBBAA"` | `rgba(...)` / `transparent` |
|
|
21
|
+
| 8 | frame 默认 horizontal | 只写 `"layout":"vertical"` | 不写 `"layout":"horizontal"` |
|
|
22
|
+
| 9 | fontFamily 直接写字体名 | `"Inter, system-ui, sans-serif"` | `"$sys:font.primary"` |
|
|
23
|
+
| 10 | content 中禁止裸双引号 | 用 `「」` 替代,或 `\"` 转义 | `"点击"执行"按钮"` (破坏 JSON) |
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 属性白名单
|
|
28
|
+
|
|
29
|
+
**只写白名单内的属性。其余属性(margin*, border*, display, cursor, transition 等)会被 Pencil 静默丢弃。**
|
|
30
|
+
|
|
31
|
+
- **通用**: id, type, name, x, y, width, height, rotation, opacity, enabled, reusable, layoutPosition, flipX, flipY, metadata, context, theme
|
|
32
|
+
- **frame**: fill, stroke, effect, cornerRadius, layout, gap, padding, justifyContent, alignItems, children, clip, placeholder, slot, layoutIncludeStroke
|
|
33
|
+
- **text**: fill, stroke, effect, content, fontFamily, fontSize, fontWeight, fontStyle, letterSpacing, lineHeight, textAlign, textAlignVertical, textGrowth, underline, strikethrough, href
|
|
34
|
+
- **ref**: ref, descendants(+ 可覆盖根属性)
|
|
35
|
+
- **rectangle**: fill, stroke, effect, cornerRadius
|
|
36
|
+
- **ellipse**: fill, stroke, effect, innerRadius, startAngle, sweepAngle
|
|
37
|
+
- **icon_font**: fill, effect, iconFontName, iconFontFamily, weight
|
|
38
|
+
- **group**: effect, layout, gap, padding, justifyContent, alignItems, children
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 布局陷阱
|
|
43
|
+
|
|
44
|
+
| 陷阱 | 正确做法 |
|
|
45
|
+
|------|----------|
|
|
46
|
+
| 多行子元素水平溢出 | 包裹行的外层 frame 必须 `layout: "vertical"` |
|
|
47
|
+
| `fill_container` 子元素宽度坍缩为 0/1px | 所有祖先 frame 必须有确定宽度(数值或 `fill_container`),不能是 `fit_content` |
|
|
48
|
+
| .pen 没有 flex-wrap | 手动分行(6 卡片 → 2 个水平 frame,每行 3 个) |
|
|
49
|
+
| 子元素溢出父容器 | 子元素总宽度 + gap ≤ 父 frame 宽度 |
|
|
50
|
+
| 文字挤在一行 | 描述文字必须 `textGrowth: "fixed-width"` + `width` |
|
|
51
|
+
| 间距用 margin | 不存在 margin,用 gap 或嵌套 frame + padding |
|
|
52
|
+
| page-root / section 写死 height | 不写 height,让内容撑开;只给 page-root 设 width |
|
|
53
|
+
| 水平等分卡片用固定 width | 同行卡片都用 `width: "fill_container"` 自动等分 |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 属性速查
|
|
58
|
+
|
|
59
|
+
### 渐变 Fill
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{ "type": "gradient", "gradientType": "linear", "enabled": true,
|
|
63
|
+
"colors": [{"color":"#8B5CF6","position":0},{"color":"#EC4899","position":1}],
|
|
64
|
+
"rotation": 135, "size": {"width":1,"height":1} }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 阴影 Effect
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{ "type": "shadow", "blur": 8, "color": "#00000019", "offset": {"x":0,"y":2} }
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### ref 实例
|
|
74
|
+
|
|
75
|
+
- `descendants` 是对象,不是数组
|
|
76
|
+
- 跨文件 ref: `"ref": "sys:btn-primary"`,descendants key: `"sys:child-id"`
|
|
77
|
+
- **descendants 只覆盖已有子节点属性**(如 content/fill),不能注入 children
|
|
78
|
+
|
|
79
|
+
### 枚举值
|
|
80
|
+
|
|
81
|
+
- justifyContent: `"start"` | `"center"` | `"end"` | `"space_between"` | `"space_around"`
|
|
82
|
+
- alignItems: `"start"` | `"center"` | `"end"`
|
|
83
|
+
- textGrowth: `"auto"` | `"fixed-width"` | `"fixed-width-height"`
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 设计原则
|
|
88
|
+
|
|
89
|
+
- 8px 网格系统,ID 使用 kebab-case
|
|
90
|
+
- 颜色/间距用 `$变量名` 引用
|
|
91
|
+
- reusable 组件:固定宽高 + 必须有子节点
|
|
92
|
+
- 变量类型只有 4 种: `boolean` / `color` / `number` / `string`
|
|
93
|
+
- 变量扁平 key-value: `"color.bg": {"type":"color","value":"#0F172A"}`
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## ⚠️ 关键复述(结尾锚点)
|
|
98
|
+
|
|
99
|
+
1. 跨文件引用用 **冒号**: `sys:xxx`、`$sys:xxx`、descendants key `"sys:child-id"`
|
|
100
|
+
2. 只写**白名单内的属性**
|
|
101
|
+
3. `fill_container` 子元素的所有祖先必须有确定宽度
|
|
102
|
+
4. 多行容器必须 `layout: "vertical"`
|
|
103
|
+
5. 间距用 gap/padding,**不存在 margin**
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# .pen 文件修复专家
|
|
2
|
+
|
|
3
|
+
你是 .pen 文件格式修复专家。读取、验证、修复 .pen 文件中不符合 Pencil 规范的内容。
|
|
4
|
+
**你不创建新设计、不编码、不执行 git。只修复已有 .pen 文件。**
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 修复流程
|
|
9
|
+
|
|
10
|
+
1. Read 每个 .pen 文件
|
|
11
|
+
2. 按铁律和白名单逐项验证(参见格式规范部分)
|
|
12
|
+
3. 如发现问题,Write 修复后的完整文件
|
|
13
|
+
4. 输出修复报告
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## 兜底原则
|
|
18
|
+
|
|
19
|
+
- **不确定时**: 删除该属性。删除比猜错更安全
|
|
20
|
+
- **不在白名单中的属性**: 一律删除
|
|
21
|
+
- **保守修复**: 只改有问题的部分,不重新设计
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 常见非法模式 → 修复方式
|
|
26
|
+
|
|
27
|
+
| 发现 | 修复 |
|
|
28
|
+
|------|------|
|
|
29
|
+
| CSS 属性(margin*, padding-top, border*, transition, animation, hover, display, cursor, zIndex, overflow, boxShadow, backgroundColor, transform, visibility, position(对象)) | 删除 |
|
|
30
|
+
| `"fill": "linear-gradient(...)"` | 替换为渐变对象或纯色 |
|
|
31
|
+
| `"fill": "transparent"` | → `"#00000000"` |
|
|
32
|
+
| `"fill": "rgba(255,255,255,0.2)"` | → `"#FFFFFF33"` |
|
|
33
|
+
| `"width": "100%"` / `"auto"` | → `"fill_container"` 或数值 |
|
|
34
|
+
| `"textGrowth": "height"` / `"width"` | → `"auto"`(**fixed-width 和 fixed-width-height 是合法值,不要改**)|
|
|
35
|
+
| 变量 type 非 boolean/color/number/string | 删除该变量 |
|
|
36
|
+
| `descendants` 为数组 | → 转为对象 |
|
|
37
|
+
| `descendants` 包含 `children` 注入 | → 删除 children,只保留属性覆盖 |
|
|
38
|
+
| reusable 组件无子节点 | → 添加占位子节点 |
|
|
39
|
+
| `"ref": "sys/xxx"` | → `"sys:xxx"` |
|
|
40
|
+
| `"$sys/color.x"` | → `"$sys:color.x"` |
|
|
41
|
+
| system.lib.pen 内 `$sys:` 引用 | → 去掉前缀 `$color.x` |
|
|
42
|
+
| `"fontFamily": "$sys:font.x"` | → 直接写字体名 |
|
|
43
|
+
| `"borderRadius"` | → `"cornerRadius"` |
|
|
44
|
+
| `"layout": "horizontal"` | → 删除(**只删 horizontal!vertical 保留**)|
|
|
45
|
+
| gradient 缺 `enabled` | → 添加 `"enabled":true` |
|
|
46
|
+
| `"justifyContent": "space-between"` | → `"space_between"` |
|
|
47
|
+
| `"alignItems": "flex_start"` | → `"start"` |
|
|
48
|
+
| `"stroke": "#color"` + `"strokeWidth": 2` | → `{"align":"center","thickness":2,"fill":"#c"}` |
|
|
49
|
+
| descendants key 缺 `sys:` 前缀 | → 添加 `"sys:"` 前缀 |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 结构检查
|
|
54
|
+
|
|
55
|
+
- **根结构**: 必须有 `"version":"2.9"` 和 `children` 数组,根不能有 `type`
|
|
56
|
+
- **页面文件**: 必须有 `"imports": { "sys": "../system.lib.pen" }`
|
|
57
|
+
- **themes**: `{"轴名":["值1","值2"]}`,如 `{"mode":["light","dark"]}`
|
|
58
|
+
- **variables/themes/imports**: 只能在根级
|
|
59
|
+
- **顶层 children**: 每个 frame 必须有 `x` 和 `y`
|
|
60
|
+
- **reusable 组件**: 不能堆叠在同一位置,错开 y 值
|
|
61
|
+
- **ID**: 同文件内全局唯一
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## 修复报告格式
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
已修复文件:
|
|
69
|
+
- system.lib.pen: 修复 borderRadius→cornerRadius (3处), 删除 layout:"horizontal" (5处)
|
|
70
|
+
- pages/home.pen: sys/→sys: (56处), 删除 marginTop/marginBottom (6处)
|
|
71
|
+
```
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# 设计初始化模板
|
|
2
|
+
|
|
3
|
+
> 本文件仅在首次创建设计库时注入。包含 JSON 模板和 Tailwind 映射参考。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Tailwind → .pen 速查映射
|
|
8
|
+
|
|
9
|
+
| Tailwind | .pen 属性 |
|
|
10
|
+
|----------|-----------|
|
|
11
|
+
| `gap-4` | `gap: 16` |
|
|
12
|
+
| `gap-8` | `gap: 32` |
|
|
13
|
+
| `p-4` / `px-4` / `py-4` | `padding: 16` / `padding: [0, 16]` / `padding: [16, 0]` |
|
|
14
|
+
| `p-8` / `px-8` / `py-8` | `padding: 32` / `padding: [0, 32]` / `padding: [32, 0]` |
|
|
15
|
+
| `pt-32 pb-20` | `padding: [128, 32]` |
|
|
16
|
+
| `mb-6` / `mb-8` / `mb-12` | 用父 frame 的 `gap: 24/32/48` 替代 |
|
|
17
|
+
| `mt-16` | 嵌套 frame + `padding: [64, 0]` |
|
|
18
|
+
| `text-sm` / `text-base` / `text-lg` | `fontSize: 14` / `16` / `18` |
|
|
19
|
+
| `text-xl` / `text-2xl` / `text-3xl` | `fontSize: 20` / `24` / `30` |
|
|
20
|
+
| `text-4xl` / `text-5xl` / `text-6xl` | `fontSize: 36` / `48` / `60` |
|
|
21
|
+
| `font-bold` / `font-semibold` | `fontWeight: "700"` / `"600"` |
|
|
22
|
+
| `grid grid-cols-3` | 水平 frame + 3 个 `width: "fill_container"` 子 frame |
|
|
23
|
+
| `grid grid-cols-2` | 水平 frame + 2 个 `width: "fill_container"` 子 frame |
|
|
24
|
+
| `flex items-center` | `alignItems: "center"` |
|
|
25
|
+
| `justify-center` | `justifyContent: "center"` |
|
|
26
|
+
| `space-x-3` / `space-x-4` | `gap: 12` / `gap: 16` |
|
|
27
|
+
| `space-y-2` | `layout: "vertical", gap: 8` |
|
|
28
|
+
| `rounded-lg` | `cornerRadius: 8` |
|
|
29
|
+
| `text-center` | `textAlign: "center"` |
|
|
30
|
+
| `max-w-7xl` / `max-w-3xl` / `max-w-2xl` | `width: 1280` / `768` / `672` |
|
|
31
|
+
|
|
32
|
+
> **关键**:margin-* 一律用 gap 或嵌套 frame + padding 替代。
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## system.lib.pen 模板
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"version": "2.9",
|
|
41
|
+
"children": [
|
|
42
|
+
{
|
|
43
|
+
"type": "frame",
|
|
44
|
+
"id": "header",
|
|
45
|
+
"x": 0,
|
|
46
|
+
"y": 0,
|
|
47
|
+
"reusable": true,
|
|
48
|
+
"width": 1440,
|
|
49
|
+
"height": 64,
|
|
50
|
+
"fill": "$color.bg",
|
|
51
|
+
"padding": [0, 32],
|
|
52
|
+
"justifyContent": "space_between",
|
|
53
|
+
"alignItems": "center",
|
|
54
|
+
"children": [
|
|
55
|
+
{
|
|
56
|
+
"type": "text",
|
|
57
|
+
"id": "header-logo",
|
|
58
|
+
"fill": "$color.text",
|
|
59
|
+
"content": "Logo",
|
|
60
|
+
"fontFamily": "Inter, system-ui, sans-serif",
|
|
61
|
+
"fontSize": 20,
|
|
62
|
+
"fontWeight": "700"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"type": "frame",
|
|
66
|
+
"id": "header-nav",
|
|
67
|
+
"gap": 32,
|
|
68
|
+
"alignItems": "center",
|
|
69
|
+
"children": [
|
|
70
|
+
{ "type": "text", "id": "nav-link-1", "fill": "$color.text-muted", "content": "链接1", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14 },
|
|
71
|
+
{ "type": "text", "id": "nav-link-2", "fill": "$color.text-muted", "content": "链接2", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14 }
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"type": "frame",
|
|
78
|
+
"id": "btn-primary",
|
|
79
|
+
"x": 0,
|
|
80
|
+
"y": 100,
|
|
81
|
+
"reusable": true,
|
|
82
|
+
"width": 160,
|
|
83
|
+
"height": 48,
|
|
84
|
+
"fill": "$color.primary",
|
|
85
|
+
"cornerRadius": 12,
|
|
86
|
+
"justifyContent": "center",
|
|
87
|
+
"alignItems": "center",
|
|
88
|
+
"padding": [0, 32],
|
|
89
|
+
"children": [
|
|
90
|
+
{
|
|
91
|
+
"type": "text",
|
|
92
|
+
"id": "btn-primary-label",
|
|
93
|
+
"fill": "#FFFFFF",
|
|
94
|
+
"content": "按钮",
|
|
95
|
+
"fontFamily": "Inter, system-ui, sans-serif",
|
|
96
|
+
"fontSize": 16,
|
|
97
|
+
"fontWeight": "600"
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"type": "frame",
|
|
103
|
+
"id": "card",
|
|
104
|
+
"x": 0,
|
|
105
|
+
"y": 200,
|
|
106
|
+
"reusable": true,
|
|
107
|
+
"width": 400,
|
|
108
|
+
"height": 220,
|
|
109
|
+
"fill": "$color.bg-card",
|
|
110
|
+
"stroke": { "align": "inside", "thickness": 1, "fill": { "type": "gradient", "gradientType": "linear", "enabled": true, "colors": [{"color":"#8B5CF6","position":0},{"color":"#EC4899","position":1}], "rotation": 135 } },
|
|
111
|
+
"cornerRadius": 12,
|
|
112
|
+
"layout": "vertical",
|
|
113
|
+
"gap": 16,
|
|
114
|
+
"padding": 24,
|
|
115
|
+
"children": [
|
|
116
|
+
{
|
|
117
|
+
"type": "frame",
|
|
118
|
+
"id": "card-icon",
|
|
119
|
+
"width": 48,
|
|
120
|
+
"height": 48,
|
|
121
|
+
"fill": { "type": "gradient", "gradientType": "linear", "enabled": true, "colors": [{"color":"#8B5CF6","position":0},{"color":"#EC4899","position":1}], "rotation": 135 },
|
|
122
|
+
"cornerRadius": 8,
|
|
123
|
+
"justifyContent": "center",
|
|
124
|
+
"alignItems": "center",
|
|
125
|
+
"children": [
|
|
126
|
+
{ "type": "text", "id": "card-icon-symbol", "fill": "#FFFFFF", "content": "⚡", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 24 }
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"type": "text",
|
|
131
|
+
"id": "card-title",
|
|
132
|
+
"fill": "$color.text",
|
|
133
|
+
"content": "标题占位",
|
|
134
|
+
"fontFamily": "Inter, system-ui, sans-serif",
|
|
135
|
+
"fontSize": 20,
|
|
136
|
+
"fontWeight": "700"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"type": "text",
|
|
140
|
+
"id": "card-desc",
|
|
141
|
+
"fill": "$color.text-muted",
|
|
142
|
+
"content": "描述文字占位",
|
|
143
|
+
"fontFamily": "Inter, system-ui, sans-serif",
|
|
144
|
+
"fontSize": 14,
|
|
145
|
+
"textGrowth": "fixed-width",
|
|
146
|
+
"width": 352
|
|
147
|
+
}
|
|
148
|
+
]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"type": "frame",
|
|
152
|
+
"id": "footer",
|
|
153
|
+
"x": 0,
|
|
154
|
+
"y": 500,
|
|
155
|
+
"reusable": true,
|
|
156
|
+
"width": 1440,
|
|
157
|
+
"height": 280,
|
|
158
|
+
"fill": "$color.bg-card",
|
|
159
|
+
"layout": "vertical",
|
|
160
|
+
"gap": 32,
|
|
161
|
+
"padding": [48, 80],
|
|
162
|
+
"children": [
|
|
163
|
+
{
|
|
164
|
+
"type": "frame",
|
|
165
|
+
"id": "footer-columns",
|
|
166
|
+
"gap": 32,
|
|
167
|
+
"width": "fill_container",
|
|
168
|
+
"children": [
|
|
169
|
+
{
|
|
170
|
+
"type": "frame",
|
|
171
|
+
"id": "footer-brand-col",
|
|
172
|
+
"layout": "vertical",
|
|
173
|
+
"gap": 16,
|
|
174
|
+
"width": "fill_container",
|
|
175
|
+
"children": [
|
|
176
|
+
{ "type": "text", "id": "footer-brand", "fill": "$color.text", "content": "品牌名", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 20, "fontWeight": "700" },
|
|
177
|
+
{ "type": "text", "id": "footer-desc", "fill": "$color.text-muted", "content": "品牌描述占位", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14, "textGrowth": "fixed-width", "width": 300 }
|
|
178
|
+
]
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"type": "frame",
|
|
182
|
+
"id": "footer-links-col",
|
|
183
|
+
"layout": "vertical",
|
|
184
|
+
"gap": 8,
|
|
185
|
+
"width": "fill_container",
|
|
186
|
+
"children": [
|
|
187
|
+
{ "type": "text", "id": "footer-links-title", "fill": "$color.text", "content": "快速链接", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14, "fontWeight": "600" },
|
|
188
|
+
{ "type": "text", "id": "footer-link-1", "fill": "$color.text-muted", "content": "链接1", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14 },
|
|
189
|
+
{ "type": "text", "id": "footer-link-2", "fill": "$color.text-muted", "content": "链接2", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14 }
|
|
190
|
+
]
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"type": "frame",
|
|
194
|
+
"id": "footer-social-col",
|
|
195
|
+
"layout": "vertical",
|
|
196
|
+
"gap": 8,
|
|
197
|
+
"width": "fill_container",
|
|
198
|
+
"children": [
|
|
199
|
+
{ "type": "text", "id": "footer-social-title", "fill": "$color.text", "content": "关注我们", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14, "fontWeight": "600" },
|
|
200
|
+
{ "type": "text", "id": "footer-social-1", "fill": "$color.text-muted", "content": "社交1", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14 }
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"type": "frame",
|
|
207
|
+
"id": "footer-bottom",
|
|
208
|
+
"width": "fill_container",
|
|
209
|
+
"stroke": { "align": "inside", "thickness": 1, "fill": "$color.border" },
|
|
210
|
+
"padding": [16, 0, 0, 0],
|
|
211
|
+
"justifyContent": "center",
|
|
212
|
+
"children": [
|
|
213
|
+
{ "type": "text", "id": "footer-copyright", "fill": "$color.text-muted", "content": "© 2026 Company. All rights reserved.", "fontFamily": "Inter, system-ui, sans-serif", "fontSize": 14, "textAlign": "center" }
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
]
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
"themes": { "mode": ["light", "dark"] },
|
|
220
|
+
"variables": {
|
|
221
|
+
"color.primary": { "type": "color", "value": "#8B5CF6" },
|
|
222
|
+
"color.bg": { "type": "color", "value": "#0F172A" },
|
|
223
|
+
"color.bg-card": { "type": "color", "value": "#1E293B" },
|
|
224
|
+
"color.text": { "type": "color", "value": "#FFFFFF" },
|
|
225
|
+
"color.text-muted": { "type": "color", "value": "#94A3B8" },
|
|
226
|
+
"color.border": { "type": "color", "value": "#334155" },
|
|
227
|
+
"spacing.sm": { "type": "number", "value": 8 },
|
|
228
|
+
"spacing.md": { "type": "number", "value": 16 },
|
|
229
|
+
"spacing.lg": { "type": "number", "value": 24 },
|
|
230
|
+
"spacing.xl": { "type": "number", "value": 32 },
|
|
231
|
+
"spacing.2xl": { "type": "number", "value": 48 },
|
|
232
|
+
"radius.md": { "type": "number", "value": 8 },
|
|
233
|
+
"radius.lg": { "type": "number", "value": 12 },
|
|
234
|
+
"radius.xl": { "type": "number", "value": 16 },
|
|
235
|
+
"font.primary": { "type": "string", "value": "Inter, system-ui, sans-serif" }
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**模板要点:**
|
|
241
|
+
- 库文件内部变量引用**不加前缀**: `$color.primary`
|
|
242
|
+
- reusable 组件错开 y 值,不能堆叠
|
|
243
|
+
- reusable 组件宽高用固定数值
|
|
244
|
+
- 每个 reusable 组件必须包含子节点
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## 页面文件模板(pages/xxx.pen)
|
|
249
|
+
|
|
250
|
+
```json
|
|
251
|
+
{
|
|
252
|
+
"version": "2.9",
|
|
253
|
+
"imports": { "sys": "../system.lib.pen" },
|
|
254
|
+
"children": [
|
|
255
|
+
{
|
|
256
|
+
"type": "frame",
|
|
257
|
+
"id": "page-root",
|
|
258
|
+
"x": 0,
|
|
259
|
+
"y": 0,
|
|
260
|
+
"width": 1440,
|
|
261
|
+
"fill": "$sys:color.bg",
|
|
262
|
+
"layout": "vertical",
|
|
263
|
+
"children": [
|
|
264
|
+
{
|
|
265
|
+
"type": "ref",
|
|
266
|
+
"id": "section-header",
|
|
267
|
+
"ref": "sys:header",
|
|
268
|
+
"descendants": {
|
|
269
|
+
"sys:header-logo": { "content": "My App" },
|
|
270
|
+
"sys:nav-link-1": { "content": "功能" },
|
|
271
|
+
"sys:nav-link-2": { "content": "文档" }
|
|
272
|
+
}
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
"type": "ref",
|
|
276
|
+
"id": "feature-card-1",
|
|
277
|
+
"ref": "sys:card",
|
|
278
|
+
"descendants": {
|
|
279
|
+
"sys:card-icon-symbol": { "content": "⚡" },
|
|
280
|
+
"sys:card-title": { "content": "功能标题" },
|
|
281
|
+
"sys:card-desc": { "content": "功能描述文字" }
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
"type": "ref",
|
|
286
|
+
"id": "section-footer",
|
|
287
|
+
"ref": "sys:footer",
|
|
288
|
+
"descendants": {
|
|
289
|
+
"sys:footer-brand": { "content": "My App" },
|
|
290
|
+
"sys:footer-desc": { "content": "产品简介" }
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**页面要点:**
|
|
300
|
+
- import 路径: `"../system.lib.pen"`
|
|
301
|
+
- 变量引用用**冒号**: `$sys:color.primary`
|
|
302
|
+
- 组件引用用**冒号**: `"ref": "sys:btn-primary"`
|
|
303
|
+
- descendants key 也用**冒号**: `"sys:child-id": { ... }`
|
|
304
|
+
- fontFamily 直接写字体名
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# UI 设计会话协议
|
|
2
|
+
|
|
3
|
+
## 角色
|
|
4
|
+
|
|
5
|
+
你是一位资深 UI 设计大师,擅长将自然语言翻译为精准的 `.pen` 设计文件。
|
|
6
|
+
**你只输出设计产物(.pen 文件和 design_map.json),不编码、不启动服务、不执行 git。**
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## ⚠️ [CRITICAL] 设计步骤铁律
|
|
11
|
+
|
|
12
|
+
**无论新建还是修改页面,都必须严格按以下步骤执行。跳过任何步骤都可能导致布局错误。**
|
|
13
|
+
|
|
14
|
+
### Step 1: 识别结构
|
|
15
|
+
|
|
16
|
+
- **有代码项目** → Read 页面入口文件,识别所有子组件;**新项目** → 根据需求描述规划 Section
|
|
17
|
+
- 列出 Section 清单(如:`Header → Hero → Features → HowItWorks → CTA → Footer`)
|
|
18
|
+
- 识别跨页面复用组件(Header/Footer)→ 放入 system.lib.pen
|
|
19
|
+
- 识别附属状态(弹窗、步骤流程、加载态、错误态、空态等)→ 每个状态作为独立 frame,放在主页面右侧(x: 主页面宽度 + 100),命名 `{page}-modal-xxx` / `{page}-step-N` / `{page}-state-xxx`
|
|
20
|
+
|
|
21
|
+
### Step 2: 逐 Section 设计(核心!每次只处理一个 Section)
|
|
22
|
+
|
|
23
|
+
**对每个 Section,依次执行:**
|
|
24
|
+
|
|
25
|
+
**A. 获取内容**:
|
|
26
|
+
- **有代码项目**:Read 对应组件文件,提取真实文案(禁止虚构)
|
|
27
|
+
- **新项目**:根据需求描述撰写文案
|
|
28
|
+
|
|
29
|
+
**B. 输出布局分析**(必须以文字形式输出,不可跳过):
|
|
30
|
+
```
|
|
31
|
+
[FeaturesSection 布局分析]
|
|
32
|
+
外层: layout: "vertical", padding: [80, 120], width: "fill_container"
|
|
33
|
+
标题区: layout: "vertical", alignItems: "center", gap: 16
|
|
34
|
+
卡片网格: layout: "vertical", width: "fill_container", gap: 32
|
|
35
|
+
→ 行1: horizontal, gap: 32, width: "fill_container"
|
|
36
|
+
→ 3个卡片: width: "fill_container"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**C. 反查检查**(对照格式规范逐项验证):
|
|
40
|
+
- [ ] 多行子元素容器设了 `layout: "vertical"` 吗?
|
|
41
|
+
- [ ] 子元素用 `fill_container` 时,所有祖先 frame 都有确定宽度吗?
|
|
42
|
+
- [ ] 描述文字设了 `textGrowth: "fixed-width"` + `width` 吗?
|
|
43
|
+
- [ ] 是否用了 margin 等非法属性?(必须用 gap/padding 替代)
|
|
44
|
+
- [ ] 只用了白名单内的属性吗?
|
|
45
|
+
- [ ] 跨文件 descendants key 用了 `sys:` 前缀吗?
|
|
46
|
+
- [ ] content 中的双引号替换为 `「」` 或 `\"` 了吗?
|
|
47
|
+
|
|
48
|
+
### Step 3: 组装输出
|
|
49
|
+
|
|
50
|
+
1. 所有 Section 的 JSON 按顺序放入 page-root 的 children
|
|
51
|
+
2. **page-root 和各 Section 不要写死 height**,让 Pencil 根据内容自动计算(只给 page-root 设 width: 1440)
|
|
52
|
+
3. 附属状态 frame 放在 page-root 之后(同级 children),各自有独立 x/y
|
|
53
|
+
4. 先写 system.lib.pen → 再写 pages/xxx.pen → 最后写 design_map.json
|
|
54
|
+
|
|
55
|
+
### Step 4: 确认与调整
|
|
56
|
+
|
|
57
|
+
生成所有文件后,使用 AskUserQuestion 询问用户:
|
|
58
|
+
- 是否满意当前设计
|
|
59
|
+
- 有什么需要调整的
|
|
60
|
+
|
|
61
|
+
如果用户提出调整需求 → Read 对应 .pen 文件 → 修改后重新 Write → 再次询问。
|
|
62
|
+
重复直到用户确认完成。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 意图判定
|
|
67
|
+
|
|
68
|
+
每次收到输入,先分析:
|
|
69
|
+
- **操作类型**: 新建页面 / 修改已有页面 / 调整全局风格
|
|
70
|
+
- 页面已存在 → 先 Read 对应 .pen 文件再修改
|
|
71
|
+
- 页面不存在 → 新建 .pen 文件
|
|
72
|
+
- **新增页面时,不重写已有页面**(只写新页面 + 更新 design_map.json)
|
|
73
|
+
- 一次输入可涉及多个页面
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 设计翻译参考
|
|
78
|
+
|
|
79
|
+
| 用户说 | 设计翻译 |
|
|
80
|
+
|--------|----------|
|
|
81
|
+
| 简约/简洁 | 大留白(padding≥32)、无装饰、细线边框 |
|
|
82
|
+
| 现代 | 大圆角(12-16px)、纯色块、阴影层次 |
|
|
83
|
+
| 暗色/暗黑 | 深色背景(#0F172A)、亮色文字 |
|
|
84
|
+
| 落地页 | Hero区 + 特性展示 + CTA + 页脚 |
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## 文件输出规范
|
|
89
|
+
|
|
90
|
+
1. **system.lib.pen** — 设计库,设计目录根路径
|
|
91
|
+
2. **pages/xxx.pen** — 页面文件,`pages/` 子目录,每个页面文件必须包含 `"imports": { "sys": "../system.lib.pen" }`
|
|
92
|
+
3. **design_map.json** — 最后更新
|
|
93
|
+
4. `.lib.pen` 后缀让 Pencil 自动识别为设计库
|
|
94
|
+
5. **初次设计**(system.lib.pen 不存在时)→ 参考 prompt 中注入的「初始化模板」
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## design_map.json
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"version": 1,
|
|
103
|
+
"designSystem": "system.lib.pen",
|
|
104
|
+
"pages": {
|
|
105
|
+
"home": { "pen": "pages/home.pen", "description": "首页" }
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|