@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.
- package/dist/style.css +14 -17
- package/dist/tmagic-editor.mjs +709 -562
- package/dist/tmagic-editor.mjs.map +1 -1
- package/dist/tmagic-editor.umd.js +715 -567
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/package.json +9 -9
- package/src/Editor.vue +1 -0
- package/src/components/CodeDraftEditor.vue +130 -0
- package/src/components/FunctionEditor.vue +144 -0
- package/src/fields/CodeSelect.vue +80 -101
- package/src/layouts/CodeEditor.vue +1 -2
- package/src/layouts/sidebar/LayerPanel.vue +99 -86
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +23 -79
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +37 -71
- package/src/services/codeBlock.ts +111 -120
- package/src/services/editor.ts +19 -5
- package/src/theme/code-block.scss +14 -17
- package/src/type.ts +36 -38
- package/src/utils/editor.ts +9 -1
- package/src/utils/props.ts +2 -2
- package/types/components/CodeDraftEditor.vue.d.ts +148 -0
- package/types/components/FunctionEditor.vue.d.ts +120 -0
- package/types/fields/CodeSelect.vue.d.ts +9 -9
- package/types/layouts/CodeEditor.vue.d.ts +5 -12
- package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +1 -1
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +6 -5
- package/types/services/codeBlock.d.ts +55 -35
- package/types/services/editor.d.ts +1 -0
- package/types/services/props.d.ts +1 -1
- package/types/type.d.ts +32 -35
- package/types/utils/editor.d.ts +1 -0
- package/types/utils/props.d.ts +1 -1
|
@@ -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 {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
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 =
|
|
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 {
|
|
91
|
+
* @param {Id} id 代码块id
|
|
86
92
|
* @returns {CodeBlockContent | null}
|
|
87
93
|
*/
|
|
88
|
-
public async getCodeContentById(id:
|
|
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 {
|
|
103
|
+
* @param {Id} id 代码块id
|
|
98
104
|
* @param {CodeBlockContent} codeConfig 代码块内容配置信息
|
|
99
105
|
* @returns {void}
|
|
100
106
|
*/
|
|
101
|
-
public async setCodeDslById(id:
|
|
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]:
|
|
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 {
|
|
163
|
+
* @param {Id} id 代码块id
|
|
152
164
|
* @returns {void}
|
|
153
165
|
*/
|
|
154
|
-
public setCodeEditorContent(status: boolean, id:
|
|
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 {
|
|
199
|
+
* @param {Id} id 代码块id
|
|
188
200
|
* @returns {void}
|
|
189
201
|
*/
|
|
190
|
-
public setId(id:
|
|
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 {
|
|
209
|
+
* @returns {Id} id 代码块id
|
|
198
210
|
*/
|
|
199
|
-
public getId():
|
|
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
|
|
246
|
-
const
|
|
247
|
-
if (!
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
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 {
|
|
272
|
+
* @returns {Id[]}
|
|
310
273
|
*/
|
|
311
|
-
public getUndeletableList():
|
|
274
|
+
public getUndeletableList(): Id[] {
|
|
312
275
|
return this.state.undeletableList;
|
|
313
276
|
}
|
|
314
277
|
|
|
315
278
|
/**
|
|
316
279
|
* 设置不可删除列表:为业务逻辑预留的不可删除的代码块列表,由业务逻辑维护(如代码块上线后不可删除)
|
|
317
|
-
* @param {
|
|
280
|
+
* @param {Id[]} codeIds 代码块id数组
|
|
318
281
|
* @returns {void}
|
|
319
282
|
*/
|
|
320
|
-
public async setUndeleteableList(codeIds:
|
|
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 {
|
|
310
|
+
* @param {Id[]} codeIds 需要删除的代码块id数组
|
|
327
311
|
* @returns {CodeBlockDSL} 删除后的code dsl
|
|
328
312
|
*/
|
|
329
|
-
public async deleteCodeDslByIds(codeIds:
|
|
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 {
|
|
322
|
+
* @returns {Id} 代码块唯一id
|
|
339
323
|
*/
|
|
340
|
-
public async getUniqueId(): Promise<
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
}
|
package/src/services/editor.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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% -
|
|
164
|
+
height: calc(100% - 65px);
|
|
171
165
|
}
|
|
172
166
|
.m-editor-content-bottom {
|
|
173
|
-
height:
|
|
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:
|
|
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:
|
|
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
|
-
|
|
346
|
-
|
|
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
|
|
352
|
+
export interface CodeDslItem {
|
|
357
353
|
/** 代码块id */
|
|
358
|
-
id:
|
|
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
|
|
368
|
-
/**
|
|
369
|
-
|
|
365
|
+
export interface CombineInfo {
|
|
366
|
+
/** 组件id */
|
|
367
|
+
compId: Id;
|
|
368
|
+
/** 组件名称 */
|
|
369
|
+
compName: string;
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
export interface
|
|
373
|
-
/**
|
|
374
|
-
|
|
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
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
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
|
}
|
package/src/utils/editor.ts
CHANGED
|
@@ -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: ');
|
package/src/utils/props.ts
CHANGED
|
@@ -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
|
},
|