@tmagic/editor 1.2.0-beta.11 → 1.2.0-beta.13

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.
@@ -19,12 +19,12 @@
19
19
  import { reactive } from 'vue';
20
20
  import { cloneDeep, forIn, isEmpty, keys, omit, pick } from 'lodash-es';
21
21
 
22
- import { Id, MNode } from '@tmagic/schema';
22
+ import { CodeBlockContent, CodeBlockDSL, HookType, Id, MApp, MNode } from '@tmagic/schema';
23
23
 
24
24
  import editorService from '../services/editor';
25
- import type { CodeBlockContent, CodeBlockDSL, CodeState } from '../type';
26
- import { CodeEditorMode, CodeSelectOp } from '../type';
27
- import { error, info } from '../utils/logger';
25
+ import type { CodeRelation, CodeState, HookData } from '../type';
26
+ import { CODE_DRAFT_STORAGE_KEY, CodeEditorMode } from '../type';
27
+ import { info } from '../utils/logger';
28
28
 
29
29
  import BaseService from './BaseService';
30
30
 
@@ -37,6 +37,7 @@ class CodeBlock extends BaseService {
37
37
  mode: CodeEditorMode.EDITOR,
38
38
  combineIds: [],
39
39
  undeletableList: [],
40
+ relations: {},
40
41
  });
41
42
 
42
43
  constructor() {
@@ -70,22 +71,27 @@ class CodeBlock extends BaseService {
70
71
 
71
72
  /**
72
73
  * 获取活动的代码块dsl数据源(默认从dsl中的codeBlocks字段读取)
74
+ * 方法要支持钩子添加扩展,会被重写为异步方法,因此这里显示写为异步以提醒调用者需以异步形式调用
73
75
  * @param {boolean} forceRefresh 是否强制从活动dsl拉取刷新
74
76
  * @returns {CodeBlockDSL | null}
75
77
  */
76
78
  public async getCodeDsl(forceRefresh = false): Promise<CodeBlockDSL | null> {
79
+ return this.getCodeDslSync(forceRefresh);
80
+ }
81
+
82
+ public getCodeDslSync(forceRefresh = false): CodeBlockDSL | null {
77
83
  if (!this.state.codeDsl || forceRefresh) {
78
- this.state.codeDsl = await editorService.getCodeDsl();
84
+ this.state.codeDsl = editorService.getCodeDslSync();
79
85
  }
80
86
  return this.state.codeDsl;
81
87
  }
82
88
 
83
89
  /**
84
90
  * 根据代码块id获取代码块内容
85
- * @param {string} id 代码块id
91
+ * @param {Id} id 代码块id
86
92
  * @returns {CodeBlockContent | null}
87
93
  */
88
- public async getCodeContentById(id: string): Promise<CodeBlockContent | null> {
94
+ public async getCodeContentById(id: Id): Promise<CodeBlockContent | null> {
89
95
  if (!id) return null;
90
96
  const totalCodeDsl = await this.getCodeDsl();
91
97
  if (!totalCodeDsl) return null;
@@ -94,16 +100,20 @@ class CodeBlock extends BaseService {
94
100
 
95
101
  /**
96
102
  * 设置代码块ID和代码内容到源dsl
97
- * @param {string} id 代码块id
103
+ * @param {Id} id 代码块id
98
104
  * @param {CodeBlockContent} codeConfig 代码块内容配置信息
99
105
  * @returns {void}
100
106
  */
101
- public async setCodeDslById(id: string, codeConfig: CodeBlockContent): Promise<void> {
107
+ public async setCodeDslById(id: Id, codeConfig: CodeBlockContent): Promise<void> {
102
108
  let codeDsl = await this.getCodeDsl();
103
109
  if (!codeDsl) {
104
110
  // dsl中无代码块字段
105
111
  codeDsl = {
106
- [id]: codeConfig,
112
+ [id]: {
113
+ ...codeConfig,
114
+ // eslint-disable-next-line no-eval
115
+ content: eval(codeConfig.content),
116
+ },
107
117
  };
108
118
  } else {
109
119
  const existContent = codeDsl[id] || {};
@@ -112,6 +122,8 @@ class CodeBlock extends BaseService {
112
122
  [id]: {
113
123
  ...existContent,
114
124
  ...codeConfig,
125
+ // eslint-disable-next-line no-eval
126
+ content: eval(codeConfig.content),
115
127
  },
116
128
  };
117
129
  }
@@ -148,10 +160,10 @@ class CodeBlock extends BaseService {
148
160
  /**
149
161
  * 设置代码编辑面板展示状态及展示内容
150
162
  * @param {boolean} status 是否展示代码编辑面板
151
- * @param {string} id 代码块id
163
+ * @param {Id} id 代码块id
152
164
  * @returns {void}
153
165
  */
154
- public setCodeEditorContent(status: boolean, id: string): void {
166
+ public setCodeEditorContent(status: boolean, id: Id): void {
155
167
  if (!id) return;
156
168
  this.setId(id);
157
169
  this.state.isShowCodeEditor = status;
@@ -184,19 +196,19 @@ class CodeBlock extends BaseService {
184
196
 
185
197
  /**
186
198
  * 设置当前选中的代码块ID
187
- * @param {string} id 代码块id
199
+ * @param {Id} id 代码块id
188
200
  * @returns {void}
189
201
  */
190
- public setId(id: string) {
202
+ public setId(id: Id) {
191
203
  if (!id) return;
192
204
  this.state.id = id;
193
205
  }
194
206
 
195
207
  /**
196
208
  * 获取当前选中的代码块ID
197
- * @returns {string} id 代码块id
209
+ * @returns {Id} id 代码块id
198
210
  */
199
- public getId(): string {
211
+ public getId(): Id {
200
212
  return this.state.id;
201
213
  }
202
214
 
@@ -235,98 +247,70 @@ class CodeBlock extends BaseService {
235
247
  }
236
248
 
237
249
  /**
238
- * 设置绑定关系
239
- * @param {Id} 组件id
240
- * @param {string[]} diffCodeIds 代码块id数组
241
- * @param {CodeSelectOp} opFlag 操作类型
242
- * @param {string} hook 代码块挂载hook名称
250
+ * 刷新绑定关系
243
251
  * @returns {void}
244
252
  */
245
- public async setCombineRelation(compId: Id, diffCodeIds: string[], opFlag: CodeSelectOp, hook: string) {
246
- const codeDsl = cloneDeep(await this.getCodeDsl());
247
- if (!codeDsl) return;
248
- if (opFlag === CodeSelectOp.DELETE) {
249
- try {
250
- diffCodeIds.forEach((codeId) => {
251
- const compsContent = codeDsl[codeId].comps;
252
- const index = compsContent?.[compId].findIndex((item) => item === hook);
253
- if (typeof index !== 'undefined' && index !== -1) {
254
- compsContent?.[compId].splice(index, 1);
255
- }
256
- });
257
- } catch (e) {
258
- error(e);
259
- throw new Error('解绑代码块失败');
260
- }
261
- } else if (opFlag === CodeSelectOp.ADD) {
262
- try {
263
- diffCodeIds.forEach((codeId) => {
264
- const compsContent = codeDsl[codeId].comps;
265
- const existHooks = compsContent?.[compId];
266
- if (isEmpty(existHooks)) {
267
- // comps属性不存在,或者comps为空:新增
268
- codeDsl[codeId].comps = {
269
- ...(codeDsl[codeId].comps || {}),
270
- [compId]: [hook],
271
- };
272
- } else {
273
- // 往已有的关系中添加hook
274
- existHooks?.push(hook);
275
- }
276
- });
277
- } catch (e) {
278
- error(e);
279
- throw new Error('绑定代码块失败');
280
- }
281
- } else if (opFlag === CodeSelectOp.CHANGE) {
282
- // 单选修改
283
- forIn(codeDsl, (codeBlockContent, codeId) => {
284
- if (codeId === diffCodeIds[0]) {
285
- // 增加
286
- codeBlockContent.comps = {
287
- ...(codeBlockContent?.comps || {}),
288
- [compId]: [hook],
289
- };
290
- } else if (isEmpty(diffCodeIds) || codeId !== diffCodeIds[0]) {
291
- // 清空或者移除之前的选项
292
- const compHooks = codeBlockContent?.comps?.[compId];
293
- // continue
294
- if (!compHooks) return true;
295
- const index = compHooks.findIndex((hookName) => hookName === hook);
296
- if (index !== -1) {
297
- compHooks.splice(index, 1);
298
- // break
299
- return false;
300
- }
301
- }
302
- });
303
- }
304
- this.setCodeDsl(codeDsl);
253
+ public refreshCombineInfo(): CodeRelation | null {
254
+ const root = editorService.get<MApp | null>('root');
255
+ if (!root) return null;
256
+ const relations = {};
257
+ this.recurseMNode(root, relations);
258
+ this.state.relations = relations;
259
+ return this.state.relations;
260
+ }
261
+
262
+ /**
263
+ * 获取绑定关系
264
+ * @returns {CodeRelation}
265
+ */
266
+ public getCombineInfo(): CodeRelation {
267
+ return this.state.relations;
305
268
  }
306
269
 
307
270
  /**
308
271
  * 获取不可删除列表
309
- * @returns {string[]}
272
+ * @returns {Id[]}
310
273
  */
311
- public getUndeletableList(): string[] {
274
+ public getUndeletableList(): Id[] {
312
275
  return this.state.undeletableList;
313
276
  }
314
277
 
315
278
  /**
316
279
  * 设置不可删除列表:为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除)
317
- * @param {string[]} codeIds 代码块id数组
280
+ * @param {Id[]} codeIds 代码块id数组
318
281
  * @returns {void}
319
282
  */
320
- public async setUndeleteableList(codeIds: string[]): Promise<void> {
283
+ public async setUndeleteableList(codeIds: Id[]): Promise<void> {
321
284
  this.state.undeletableList = codeIds;
322
285
  }
323
286
 
287
+ /**
288
+ * 设置代码草稿
289
+ */
290
+ public setCodeDraft(codeId: Id, content: string): void {
291
+ globalThis.localStorage.setItem(`${CODE_DRAFT_STORAGE_KEY}_${codeId}`, content);
292
+ }
293
+
294
+ /**
295
+ * 获取代码草稿
296
+ */
297
+ public getCodeDraft(codeId: Id): string | null {
298
+ return globalThis.localStorage.getItem(`${CODE_DRAFT_STORAGE_KEY}_${codeId}`);
299
+ }
300
+
301
+ /**
302
+ * 删除代码草稿
303
+ */
304
+ public removeCodeDraft(codeId: Id): void {
305
+ globalThis.localStorage.removeItem(`${CODE_DRAFT_STORAGE_KEY}_${codeId}`);
306
+ }
307
+
324
308
  /**
325
309
  * 在dsl数据源中删除指定id的代码块
326
- * @param {string[]} codeIds 需要删除的代码块id数组
310
+ * @param {Id[]} codeIds 需要删除的代码块id数组
327
311
  * @returns {CodeBlockDSL} 删除后的code dsl
328
312
  */
329
- public async deleteCodeDslByIds(codeIds: string[]): Promise<CodeBlockDSL> {
313
+ public async deleteCodeDslByIds(codeIds: Id[]): Promise<CodeBlockDSL> {
330
314
  const currentDsl = await this.getCodeDsl();
331
315
  const newDsl = omit(currentDsl, codeIds);
332
316
  await this.setCodeDsl(newDsl);
@@ -335,9 +319,9 @@ class CodeBlock extends BaseService {
335
319
 
336
320
  /**
337
321
  * 生成代码块唯一id
338
- * @returns {string} 代码块唯一id
322
+ * @returns {Id} 代码块唯一id
339
323
  */
340
- public async getUniqueId(): Promise<string> {
324
+ public async getUniqueId(): Promise<Id> {
341
325
  const newId = `code_${Math.random().toString(10).substring(2).substring(0, 4)}`;
342
326
  // 判断是否重复
343
327
  const dsl = await this.getCodeDsl();
@@ -346,33 +330,6 @@ class CodeBlock extends BaseService {
346
330
  return await this.getUniqueId();
347
331
  }
348
332
 
349
- /**
350
- * 一对一解除绑定关系 功能隐藏,暂时注释
351
- * @param {string} compId 组件id
352
- * @param {string} codeId 代码块id
353
- * @param {string[]} codeHooks 代码块挂载hook名称
354
- * @returns {boolean} 结果
355
- */
356
- // public async unbind(compId: Id, codeId: string, codeHooks: string[]): Promise<boolean> {
357
- // const nodeInfo = editorService.getNodeById(compId);
358
- // if (!nodeInfo) return false;
359
- // // 更新node节点信息
360
- // codeHooks.forEach((hook) => {
361
- // if (!isEmpty(nodeInfo[hook])) {
362
- // const newHookInfo = nodeInfo[hook].filter((item: string) => item !== codeId);
363
- // nodeInfo[hook] = newHookInfo;
364
- // editorService.update(nodeInfo);
365
- // }
366
- // });
367
- // // 更新绑定关系
368
- // const oldRelation = await this.getCompRelation();
369
- // const oldCodeIds = oldRelation[compId];
370
- // // 不能直接splice修改原数组,会导致绑定关系更新错乱
371
- // const newCodeIds = oldCodeIds.filter((item) => item !== codeId);
372
- // this.setCompRelation(compId, newCodeIds);
373
- // return true;
374
- // }
375
-
376
333
  /**
377
334
  * 通过组件id解除绑定关系(删除组件)
378
335
  * @param {MNode} compId 组件节点
@@ -381,7 +338,7 @@ class CodeBlock extends BaseService {
381
338
  public async deleteCompsInRelation(node: MNode) {
382
339
  const codeDsl = cloneDeep(await this.getCodeDsl());
383
340
  if (!codeDsl) return;
384
- this.recurseNodes(node, codeDsl);
341
+ this.refreshRelationDeep(node, codeDsl);
385
342
  this.setCodeDsl(codeDsl);
386
343
  }
387
344
 
@@ -395,8 +352,13 @@ class CodeBlock extends BaseService {
395
352
  this.state.undeletableList = [];
396
353
  }
397
354
 
398
- // 删除组件时 如果是容器 需要遍历删除其包含节点的绑定信息
399
- private recurseNodes(node: MNode, codeDsl: CodeBlockDSL) {
355
+ /**
356
+ * 删除组件时 如果是容器 需要遍历删除其包含节点的绑定信息
357
+ * @param {MNode} node 节点信息
358
+ * @param {CodeBlockDSL} codeDsl 代码块
359
+ * @returns void
360
+ */
361
+ private refreshRelationDeep(node: MNode, codeDsl: CodeBlockDSL) {
400
362
  if (!node.id) return;
401
363
  forIn(codeDsl, (codeBlockContent) => {
402
364
  const compsContent = codeBlockContent.comps || {};
@@ -404,7 +366,36 @@ class CodeBlock extends BaseService {
404
366
  });
405
367
  if (!isEmpty(node.items)) {
406
368
  node.items.forEach((item: MNode) => {
407
- this.recurseNodes(item, codeDsl);
369
+ this.refreshRelationDeep(item, codeDsl);
370
+ });
371
+ }
372
+ }
373
+
374
+ /**
375
+ * 递归遍历dsl中挂载了代码块的节点,并更新绑定关系数据
376
+ * @param {MContainer} node 节点信息
377
+ * @returns void
378
+ */
379
+ private recurseMNode(node: MNode, relations: CodeRelation) {
380
+ forIn(node, (value, key) => {
381
+ if (value?.hookType === HookType.CODE && !isEmpty(value.hookData)) {
382
+ value.hookData.forEach((relationItem: HookData) => {
383
+ // continue
384
+ if (!relationItem.codeId) return;
385
+ if (!relations[relationItem.codeId]) {
386
+ relations[relationItem.codeId] = {};
387
+ }
388
+ const codeItem = relations[relationItem.codeId];
389
+ if (isEmpty(codeItem[node.id])) {
390
+ codeItem[node.id] = [];
391
+ }
392
+ codeItem[node.id].push(key);
393
+ });
394
+ }
395
+ });
396
+ if (!isEmpty(node.items)) {
397
+ node.items.forEach((item: MNode) => {
398
+ this.recurseMNode(item, relations);
408
399
  });
409
400
  }
410
401
  }
@@ -17,7 +17,7 @@
17
17
  */
18
18
 
19
19
  import { reactive, toRaw } from 'vue';
20
- import { cloneDeep, mergeWith, uniq } from 'lodash-es';
20
+ import { cloneDeep, isObject, mergeWith, uniq } from 'lodash-es';
21
21
 
22
22
  import type { CodeBlockDSL, Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
23
23
  import { NodeType } from '@tmagic/schema';
@@ -375,7 +375,9 @@ class Editor extends BaseService {
375
375
  }
376
376
  }
377
377
 
378
- this.pushHistoryState();
378
+ if (!isPage(newNodes[0])) {
379
+ this.pushHistoryState();
380
+ }
379
381
 
380
382
  this.emit('add', newNodes);
381
383
 
@@ -437,8 +439,10 @@ class Editor extends BaseService {
437
439
 
438
440
  await Promise.all(nodes.map((node) => this.doRemove(node)));
439
441
 
440
- // 更新历史记录
441
- this.pushHistoryState();
442
+ if (!isPage(nodes[0])) {
443
+ // 更新历史记录
444
+ this.pushHistoryState();
445
+ }
442
446
 
443
447
  this.emit('remove', nodes);
444
448
  }
@@ -455,6 +459,10 @@ class Editor extends BaseService {
455
459
  let newConfig = await this.toggleFixedPosition(toRaw(config), node, this.get<MApp>('root'));
456
460
 
457
461
  newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue) => {
462
+ if (isObject(srcValue) && Array.isArray(objValue)) {
463
+ // 原来的配置是数组,新的配置是对象,则直接使用新的值
464
+ return srcValue;
465
+ }
458
466
  if (Array.isArray(srcValue)) {
459
467
  return srcValue;
460
468
  }
@@ -517,7 +525,7 @@ class Editor extends BaseService {
517
525
  this.pushHistoryState();
518
526
 
519
527
  this.emit('update', newNodes);
520
-
528
+ codeBlockService.refreshCombineInfo();
521
529
  return Array.isArray(config) ? newNodes : newNodes[0];
522
530
  }
523
531
 
@@ -780,6 +788,12 @@ class Editor extends BaseService {
780
788
  return root.codeBlocks || null;
781
789
  }
782
790
 
791
+ public getCodeDslSync(): CodeBlockDSL | null {
792
+ const root = this.get<MApp | null>('root');
793
+ if (!root) return null;
794
+ return root.codeBlocks || null;
795
+ }
796
+
783
797
  /**
784
798
  * 设置代码块到dsl的codeBlocks字段
785
799
  * @param {CodeBlockDSL} codeDsl 代码DSL
@@ -3,6 +3,9 @@
3
3
  .el-tree-node__content {
4
4
  height: auto;
5
5
  }
6
+ .el-tree-node__label {
7
+ width: 100%;
8
+ }
6
9
  .code-header-wrapper {
7
10
  display: flex;
8
11
  align-items: center;
@@ -74,19 +77,6 @@
74
77
 
75
78
  .m-fields-code-select {
76
79
  width: 100%;
77
- .el-card__body {
78
- padding: 5px;
79
- }
80
- .tool-bar {
81
- display: flex;
82
- align-items: center;
83
- justify-content: end;
84
- height: 20px;
85
- .tool-item {
86
- display: flex;
87
- align-items: center;
88
- }
89
- }
90
80
  }
91
81
  .code-editor-dialog {
92
82
  .el-dialog__body {
@@ -97,7 +87,7 @@
97
87
  height: 100%;
98
88
  background: #fff;
99
89
  .el-card__body {
100
- height: calc(100% - 80px);
90
+ height: 100%;
101
91
  background: #fff;
102
92
  }
103
93
  }
@@ -109,6 +99,9 @@
109
99
  .side-tree {
110
100
  height: 100%;
111
101
  overflow: auto;
102
+ .el-tree-node__label {
103
+ width: 100%;
104
+ }
112
105
 
113
106
  .list-container {
114
107
  width: 100%;
@@ -134,6 +127,7 @@
134
127
  display: flex;
135
128
  align-items: center;
136
129
  font-size: 16px;
130
+ margin-bottom: 10px;
137
131
  .code-name-label {
138
132
  margin-right: 10px;
139
133
  }
@@ -155,7 +149,7 @@
155
149
  position: absolute;
156
150
  top: 0;
157
151
  left: 4px;
158
- width: calc(100% - 9px);
152
+ width: 100%;
159
153
  height: 100%;
160
154
  z-index: 10;
161
155
  background: #fff;
@@ -167,14 +161,17 @@
167
161
  .m-editor-wrapper {
168
162
  height: 100%;
169
163
  .m-editor-container {
170
- height: calc(100% - 70px);
164
+ height: calc(100% - 65px);
171
165
  }
172
166
  .m-editor-content-bottom {
173
- height: 40px;
167
+ height: 45px;
174
168
  width: 100%;
175
169
  display: flex;
176
170
  justify-content: end;
177
171
  background: #fff;
172
+ position: absolute;
173
+ right: 20px;
174
+ bottom: 0;
178
175
  > button {
179
176
  height: 30px;
180
177
  margin-top: 15px;
package/src/type.ts CHANGED
@@ -19,7 +19,7 @@
19
19
  import type { Component } from 'vue';
20
20
 
21
21
  import type { FormConfig } from '@tmagic/form';
22
- import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
22
+ import type { CodeBlockContent, CodeBlockDSL, Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
23
23
  import type StageCore from '@tmagic/stage';
24
24
  import type { ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
25
25
 
@@ -309,28 +309,13 @@ export interface ScrollViewerEvent {
309
309
  scrollWidth: number;
310
310
  }
311
311
 
312
- export interface CodeBlockDSL {
313
- [id: string]: CodeBlockContent;
314
- }
315
-
316
- export interface CodeBlockContent {
317
- /** 代码块名称 */
318
- name: string;
319
- /** 代码块内容 */
320
- content: string;
321
- /** 代码块与组件的绑定关系 */
322
- comps?: CodeRelation;
323
- /** 扩展字段 */
324
- [propName: string]: any;
325
- }
326
-
327
312
  export type CodeState = {
328
313
  /** 是否展示代码块编辑区 */
329
314
  isShowCodeEditor: boolean;
330
315
  /** 代码块DSL数据源 */
331
316
  codeDsl: CodeBlockDSL | null;
332
317
  /** 当前选中的代码块id */
333
- id: string;
318
+ id: Id;
334
319
  /** 代码块是否可编辑 */
335
320
  editable: boolean;
336
321
  /** 代码编辑面板的展示模式 */
@@ -338,12 +323,23 @@ export type CodeState = {
338
323
  /** list模式下左侧展示的代码列表 */
339
324
  combineIds: string[];
340
325
  /** 为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除) */
341
- undeletableList: string[];
326
+ undeletableList: Id[];
327
+ /** 代码块和组件的绑定关系 */
328
+ relations: CodeRelation;
329
+ };
330
+
331
+ export type HookData = {
332
+ /** 代码块id */
333
+ codeId: Id;
334
+ /** 参数 */
335
+ params?: object;
342
336
  };
343
337
 
344
338
  export type CodeRelation = {
345
- /** 组件id:['created'] */
346
- [compId: string | number]: string[];
339
+ [codeId: Id]: {
340
+ /** 组件id:['created'] */
341
+ [compId: Id]: string[];
342
+ };
347
343
  };
348
344
 
349
345
  export enum CodeEditorMode {
@@ -353,28 +349,29 @@ export enum CodeEditorMode {
353
349
  EDITOR = 'editor',
354
350
  }
355
351
 
356
- export interface CodeDslList {
352
+ export interface CodeDslItem {
357
353
  /** 代码块id */
358
- id: string;
354
+ id: Id;
359
355
  /** 代码块名称 */
360
356
  name: string;
361
357
  /** 代码块函数内容 */
362
358
  codeBlockContent?: CodeBlockContent;
363
359
  /** 是否展示代码绑定关系 */
364
360
  showRelation?: boolean;
361
+ /** 代码块对应绑定的组件信息 */
362
+ combineInfo?: CombineInfo[];
365
363
  }
366
364
 
367
- export interface ListState {
368
- /** 代码块列表 */
369
- codeList: CodeDslList[];
365
+ export interface CombineInfo {
366
+ /** 组件id */
367
+ compId: Id;
368
+ /** 组件名称 */
369
+ compName: string;
370
370
  }
371
371
 
372
- export interface ListRelationState extends ListState {
373
- /** 与代码块绑定的组件id信息 */
374
- bindComps: {
375
- /** 代码块id : 组件信息 */
376
- [id: string]: MNode[];
377
- };
372
+ export interface ListState {
373
+ /** 代码块列表 */
374
+ codeList: CodeDslItem[];
378
375
  }
379
376
 
380
377
  export enum CodeDeleteErrorType {
@@ -384,11 +381,12 @@ export enum CodeDeleteErrorType {
384
381
  BIND = 'bind',
385
382
  }
386
383
 
387
- export enum CodeSelectOp {
388
- /** 增加 */
389
- ADD = 'add',
390
- /** 删除 */
391
- DELETE = 'delete',
392
- /** 单选修改 */
393
- CHANGE = 'change',
384
+ // 代码块草稿localStorage key
385
+ export const CODE_DRAFT_STORAGE_KEY = 'magicCodeDraft';
386
+
387
+ export interface CodeParamStatement {
388
+ /** 参数名称 */
389
+ name: string;
390
+ /** 参数类型 */
391
+ type?: string;
394
392
  }
@@ -16,13 +16,14 @@
16
16
  * limitations under the License.
17
17
  */
18
18
 
19
+ import serialize from 'serialize-javascript';
20
+
19
21
  import type { MApp, MContainer, MNode, MPage } from '@tmagic/schema';
20
22
  import { NodeType } from '@tmagic/schema';
21
23
  import type StageCore from '@tmagic/stage';
22
24
  import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
23
25
 
24
26
  import { Layout } from '../type';
25
-
26
27
  export const COPY_STORAGE_KEY = '$MagicEditorCopyData';
27
28
 
28
29
  /**
@@ -237,3 +238,10 @@ export const fixNodePosition = (config: MNode, parent: MContainer, stage: StageC
237
238
  left: fixNodeLeft(config, parent, stage?.renderer.contentWindow?.document),
238
239
  };
239
240
  };
241
+
242
+ // 序列化配置
243
+ export const serializeConfig = (config: any) =>
244
+ serialize(config, {
245
+ space: 2,
246
+ unsafe: true,
247
+ }).replace(/"(\w+)":\s/g, '$1: ');
@@ -226,14 +226,14 @@ export const fillConfig = (config: FormConfig = []) => [
226
226
  {
227
227
  name: 'created',
228
228
  text: 'created',
229
- type: 'code-select',
230
229
  labelWidth: '100px',
230
+ type: 'code-select',
231
231
  },
232
232
  {
233
233
  name: 'mounted',
234
234
  text: 'mounted',
235
- type: 'code-select',
236
235
  labelWidth: '100px',
236
+ type: 'code-select',
237
237
  },
238
238
  ],
239
239
  },