Skip to content

Commit bf0a0c3

Browse files
committed
chore: optimize schema protocol and example docs
1 parent e1d7653 commit bf0a0c3

File tree

11 files changed

+1051
-774
lines changed

11 files changed

+1051
-774
lines changed

packages/canvas/DesignCanvas/src/mcp/resources/editPageSchemaExample.md

Lines changed: 119 additions & 192 deletions
Large diffs are not rendered by default.

packages/canvas/DesignCanvas/src/mcp/resources/editPageSchemaExample.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,12 @@ import { pickSectionByHeading } from './utils'
33

44
// 分节枚举与标题映射(左侧为模板入参 section,右侧为文档中的中文/英文二级标题)
55
const EDIT_EXAMPLE_SECTION_TITLES: Record<string, string> = {
6-
state: 'State 示例',
7-
css: 'CSS 示例',
8-
lifeCycles: 'LifeCycles 示例',
9-
methods: 'Methods 示例',
10-
schema: 'Schema 整体操作示例',
11-
case: '实战案例:创建一个动态表单页面',
12-
'do-dont': "Do & Don't 最佳实践",
13-
faq: '常见问题解答'
6+
overview: '概述',
7+
state: 'State',
8+
css: 'CSS',
9+
lifeCycles: 'LifeCycles',
10+
methods: 'Methods',
11+
schema: 'Schema'
1412
}
1513

1614
// 根资源:编辑页面 Schema 的示例(整份文档)

packages/canvas/DesignCanvas/src/mcp/resources/pageSchema.md

Lines changed: 217 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@
22

33
页面 schema 是 TinyEngine 在画布中表示页面/区块结构与行为的数据模型。其根节点(RootNode)涵盖样式、属性、状态、方法、生命周期、数据源与子节点树等信息。
44

5-
本协议文档用于帮助模型准确理解字段语义与约束,指导正确调用 `edit_page_schema` 工具进行编辑。
5+
## structure
66

7-
## 字段
7+
TinyEngine 的页面 schema 结构如下:
88

99
```typescript
1010
export interface IFuncType {
1111
type: 'JSFunction'
1212
value: string
1313
}
1414

15-
// 关键字段(简化展示,与 TinyEngine 运行时 RootNode 结构一致)
15+
// 关键字段:
1616
export interface RootNode {
1717
id?: string
18-
componentName: string // 'Page' | 'Block' | 其他组件名
18+
componentName: string
1919
fileName?: string
20-
css?: string
20+
css?: string // 页面 css,等同于 vue 的 style 标签内容
2121
props?: Record<string, any>
22-
state?: Record<string, any> // 顶层键-值映射
22+
state?: Record<string, any>
2323
lifeCycles?: Record<string, IFuncType> // { setup?: IFuncType, onMounted?: IFuncType, ... }
2424
methods?: Record<string, IFuncType>
2525
dataSource?: any
@@ -29,10 +29,12 @@ export interface RootNode {
2929
```
3030

3131
说明:
32-
- `state` 为对象(map),键是状态名,值可以是字面量或特殊结构(如 `JSResource``JSExpression``computed``accessor`)。`edit_page_schema``merge` 策略对其执行“顶层键”级别的新增、更新与删除。
32+
- `componentName` 为合法值:`Page` | `Block`。当前 schema 类型。page 为页面,block 为区块。
33+
- `fileName` 为文件名。TinyEngine 出码时,会根据 `fileName` 生成文件名。
34+
- `css` 为页面 CSS,等同于 vue 单文件的 style 标签内容。
35+
- `state` 为页面状态,等同于 vue 单文件中的 reactive 响应式对象。为对象(map),键是状态名。
3336
- `lifeCycles``methods` 的值必须是函数单元:`{ type: 'JSFunction', value: string }`
34-
- `css` 为整页样式字符串,`merge` 策略为“末尾追加”;`replace` 为整体覆盖。
35-
- `children` 是可嵌套的节点树,涉及精细化增删改应使用“节点类工具”(如 `add_node``change_node_props` 等),而非本工具的 `schema` 合并。
37+
- `children` 为页面结构描述,等同于 vue 单文件的 template 标签内容。是可嵌套的节点树。
3638

3739
## State
3840

@@ -44,42 +46,120 @@ export interface RootNode {
4446
- `remove`:删除指定顶层键;
4547
- 不会进行深层递归合并,聚焦于“顶层键”。
4648

47-
示例(节选):
49+
### 示例
50+
51+
#### state 值示例
52+
53+
1. 常规值示例:
4854

4955
```json
5056
{
51-
"section": "state",
52-
"strategy": "merge",
53-
"payload": {
54-
"add": {
55-
"companyName": "",
56-
"theme": {
57-
"type": "JSExpression",
58-
"value": "props.dark ? 'dark' : 'light'"
59-
}
57+
"state": {
58+
"firstName": "Opentiny",
59+
"age": 18,
60+
"food": ["apple", "orange", "banana"],
61+
"isLoading": false,
62+
"desc": {
63+
"description": "",
64+
"money": 100,
65+
"other": null,
66+
"rest": [{"type": "primary", "text": "主要操作"}]
6067
},
61-
"update": {
62-
"buttons": [{ "type": "primary", "text": "主要操作" }]
68+
"utilsExample": "this.utils.test()",
69+
"methodExample": {
70+
"type": "JSFunction",
71+
"value": "function methodExample(){ return 'methodExample' }"
6372
},
64-
"remove": ["deprecatedKey"]
73+
"i18nExample": {
74+
"type": "i18n",
75+
"key": "lowcode.example"
76+
}
6577
}
6678
}
6779
```
6880

81+
vue 等效代码:
82+
83+
```javascript
84+
const state = vue.reactive({
85+
firstName: "Opentiny",
86+
age: 18,
87+
food: ["apple", "orange", "banana"],
88+
isLoading: false,
89+
desc: {
90+
description: "",
91+
money: 100,
92+
other: null,
93+
rest: [{"type": "primary", "text": "主要操作"}]
94+
},
95+
utilsExample: utils.test(),
96+
methodExample: function methodExample(){ return 'methodExample' },
97+
i18nExample: t('lowcode.example')
98+
})
99+
```
100+
101+
2. getter/setter 示例:
102+
103+
```json
104+
{
105+
"state": {
106+
"firstName": "",
107+
"lastName": "",
108+
"fullName": {
109+
"defaultValue": "",
110+
"accessor": {
111+
"getter": {
112+
"type": "JSFunction",
113+
"value": "function getter() { this.state.fullName = `${this.props.firstName} ${this.props.lastName}` }"
114+
},
115+
"setter": {
116+
"type": "JSFunction",
117+
"value": "function setter(val) { this.state.fullName = `${this.props.firstName} ${this.props.lastName}` }"
118+
}
119+
}
120+
}
121+
}
122+
}
123+
```
124+
125+
vue 等效代码:
126+
127+
```javascript
128+
const state = vue.reactive({
129+
firstName: "",
130+
lastName: "",
131+
fullName: ""
132+
})
133+
134+
vue.watchEffect(
135+
wrap(function getter() {
136+
this.state.fullName = `${this.props.firstName} ${this.props.lastName}`
137+
})
138+
)
139+
140+
vue.watchEffect(
141+
wrap(function setter() {
142+
this.state.fullName = `${this.props.firstName} ${this.props.lastName}`
143+
})
144+
)
145+
```
146+
69147
## CSS
70148

71-
- `merge`:在原有 CSS 文本末尾追加新片段(必要时自动换行)。
72-
- `replace`:整体覆盖。
149+
**说明**:
73150

74-
示例:
151+
- CSS 为页面 CSS,等同于 vue 单文件的 style 标签内容。
152+
- merge 策略:
153+
- `merge`:在原有 CSS 文本末尾追加新片段(必要时自动换行)。
154+
- `replace`:整体覆盖。
155+
156+
### 示例
157+
158+
1. css schema 示例
75159

76160
```json
77161
{
78-
"section": "css",
79-
"strategy": "merge",
80-
"payload": {
81-
"css": ".page-base-style{ padding:24px; }"
82-
}
162+
"css": ".container { padding: 24px; margin: 20px; }\n.button-danger.button{ display: flex; justify-content: center; }"
83163
}
84164
```
85165

@@ -93,18 +173,20 @@ export interface RootNode {
93173
- `remove`:删除指定键;
94174
- `replace`:以 `all` 重建或用 `add+update` 重建。
95175

96-
示例:
176+
### 示例
177+
178+
1. lifeCycles schema 示例:
97179

98180
```json
99181
{
100-
"section": "lifeCycles",
101-
"strategy": "merge",
102-
"payload": {
103-
"add": {
104-
"onMounted": {
105-
"type": "JSFunction",
106-
"value": "function onMounted(){ this.getTableData && this.getTableData() }"
107-
}
182+
"lifeCycles": {
183+
"setup": {
184+
"type": "JSFunction",
185+
"value": "function setup ({ props, state, watch, onMounted }) { console.log('lifecycle example') }"
186+
},
187+
"onMounted": {
188+
"type": "JSFunction",
189+
"value": "function onMounted(){ this.getTableData && this.getTableData() }"
108190
}
109191
}
110192
}
@@ -115,18 +197,16 @@ export interface RootNode {
115197
- 结构:`Record<string, IFuncType>``IFuncType` 同上。
116198
- `merge/replace` 行为与 `lifeCycles` 相同。
117199

118-
示例:
200+
### 示例
201+
202+
1. methods schema 示例
119203

120204
```json
121205
{
122-
"section": "methods",
123-
"strategy": "merge",
124-
"payload": {
125-
"add": {
126-
"handleSearch": {
127-
"type": "JSFunction",
128-
"value": "function(e){ return ['搜索:', this.i18n('operation.search'), e] }"
129-
}
206+
"methods": {
207+
"methodExample": {
208+
"type": "JSFunction",
209+
"value": "function methodExample() {\n console.log('example')\n}\n"
130210
}
131211
}
132212
}
@@ -142,42 +222,104 @@ export interface Node {
142222
componentName: string
143223
props: Record<string, any>
144224
children?: Node[]
145-
componentType?: 'Block' | 'PageStart' | 'PageSection'
146-
slot?: string | Record<string, any>
225+
componentType?: 'Block'
147226
loop?: Record<string, any>
148227
loopArgs?: string[]
149228
condition?: boolean | Record<string, any>
150229
}
151230
```
152231

153-
本工具不负责 `children` 的细粒度结构编辑。请优先使用节点类工具(如 `add_node``change_node_props``del_node` 等)。
154-
155-
## Schema 合并策略
156-
157-
`section = 'schema'``strategy = 'merge'` 时,仅支持对“顶层允许键”进行浅层更新:
158-
159-
允许键清单:`css``lifeCycles``methods``state``props``fileName``componentName``dataSource``children`
160-
161-
注意:
162-
- 未在允许清单内的键将被忽略;
163-
- `children` 的细化变更请改用节点类工具;
164-
- `strategy = 'replace'` 会整体替换页面 schema,具有破坏性,须谨慎。
232+
### 示例
165233

166-
## 常见陷阱
234+
1. 常规值示例
167235

168-
1.`state` 写成数组。应为对象(map)。
169-
2. `lifeCycles/methods` 未按 `JSFunction` 单元传入,或传入空字符串。
170-
3. 误用 `schema.merge` 期望深层合并。实际上仅“顶层允许键”的浅合并。
171-
4. 追加 CSS 时忘记换行导致样式黏连。
172-
5. 使用 `replace` 且未提前读取现有结构,轻易覆盖重要字段。
236+
```json
237+
{
238+
"children": [
239+
{
240+
"componentName": "div",
241+
"props": {
242+
"className": "py-10 rounded-md"
243+
},
244+
"id": "2b2cabf0",
245+
"children": [
246+
{
247+
"componentName": "TinyTimeLine",
248+
"props": {
249+
"active": "2",
250+
"data": [
251+
{
252+
"name": "基础配置"
253+
},
254+
{
255+
"name": "网络配置"
256+
}
257+
],
258+
"horizontal": true,
259+
"style": "border-radius: 0px;"
260+
},
261+
"id": "dd764b17"
262+
}
263+
]
264+
}
265+
]
266+
}
267+
```
173268

174-
## FAQ
269+
2. 使用 condition 进行条件渲染示例(等同于 vue 中的 v-if )
175270

176-
Q:如何确认当前页面结构?
177-
A:先调用 `get_page_schema` 工具查看再决定编辑策略。
271+
```json
272+
{
273+
"children": [
274+
{
275+
"componentName": "div",
276+
"props": {
277+
"className": "py-10 rounded-md"
278+
},
279+
"id": "2b2cabf0",
280+
"children": [],
281+
"condition": {
282+
"type": "JSExpression",
283+
"value": "this.state.showContainer"
284+
}
285+
}
286+
]
287+
}
288+
```
178289

179-
Q:为什么我的 `lifeCycles.update` 不生效?
180-
A:仅对已存在的键有效;若键不存在,请使用 `add` 或在 `replace` 模式下通过 `all` 重建。
290+
3. 使用 loop 与 loopArgs 进行循环渲染示例
181291

182-
Q:是否支持按组件粒度更新 `children`
183-
A:请改用节点类工具,如 `add_node``change_node_props``del_node` 等。
292+
```json
293+
{
294+
"children": [
295+
{
296+
"componentName": "TinyButton",
297+
"props": {
298+
"text": {
299+
"type": "JSExpression",
300+
"value": "item.text"
301+
},
302+
"className": "component-base-style",
303+
"key": {
304+
"type": "JSExpression",
305+
"value": "index"
306+
},
307+
"type": {
308+
"type": "JSExpression",
309+
"value": "item.type"
310+
}
311+
},
312+
"children": [],
313+
"id": "22455446",
314+
"loop": {
315+
"type": "JSExpression",
316+
"value": "this.state.loopExample"
317+
},
318+
"loopArgs": [
319+
"item",
320+
"index"
321+
]
322+
}
323+
]
324+
}
325+
```

0 commit comments

Comments
 (0)