@tmagic/editor 1.1.0-beta.0 → 1.1.0-beta.11
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 +5 -1
- package/dist/{tmagic-editor.es.js → tmagic-editor.mjs} +1445 -1199
- package/dist/tmagic-editor.mjs.map +1 -0
- package/dist/tmagic-editor.umd.js +1483 -1236
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/package.json +22 -20
- package/src/Editor.vue +23 -15
- package/src/components/ContentMenu.vue +87 -99
- package/src/components/Icon.vue +2 -2
- package/src/components/ScrollViewer.vue +2 -2
- package/src/components/ToolButton.vue +151 -168
- package/src/fields/UISelect.vue +51 -72
- package/src/index.ts +2 -1
- package/src/layouts/AddPageBox.vue +3 -3
- package/src/layouts/Framework.vue +1 -1
- package/src/layouts/NavMenu.vue +2 -2
- package/src/layouts/PropsPanel.vue +1 -1
- package/src/layouts/Resizer.vue +1 -1
- package/src/layouts/sidebar/ComponentListPanel.vue +6 -17
- package/src/layouts/sidebar/LayerMenu.vue +3 -3
- package/src/layouts/sidebar/LayerPanel.vue +52 -12
- package/src/layouts/sidebar/Sidebar.vue +1 -1
- package/src/layouts/sidebar/TabPane.vue +3 -3
- package/src/layouts/workspace/PageBar.vue +63 -192
- package/src/layouts/workspace/PageBarScrollContainer.vue +111 -0
- package/src/layouts/workspace/Stage.vue +198 -219
- package/src/layouts/workspace/ViewerMenu.vue +141 -148
- package/src/layouts/workspace/Workspace.vue +11 -11
- package/src/services/BaseService.ts +5 -10
- package/src/services/componentList.ts +3 -3
- package/src/services/editor.ts +197 -147
- package/src/services/events.ts +1 -1
- package/src/services/history.ts +1 -1
- package/src/services/props.ts +63 -11
- package/src/services/storage.ts +133 -0
- package/src/services/ui.ts +10 -4
- package/src/theme/component-list-panel.scss +5 -0
- package/src/theme/framework.scss +1 -1
- package/src/theme/stage.scss +2 -2
- package/src/type.ts +25 -7
- package/src/utils/config.ts +1 -1
- package/src/utils/editor.ts +20 -12
- package/src/utils/operator.ts +109 -0
- package/src/utils/props.ts +2 -24
- package/src/utils/scroll-viewer.ts +1 -1
- package/tsconfig.build.json +13 -0
- package/{dist/types/src → types}/Editor.vue.d.ts +17 -9
- package/types/components/ContentMenu.vue.d.ts +116 -0
- package/types/components/Icon.vue.d.ts +13 -0
- package/types/components/ScrollViewer.vue.d.ts +22 -0
- package/types/components/ToolButton.vue.d.ts +109 -0
- package/types/fields/Code.vue.d.ts +23 -0
- package/{dist/types/src → types}/fields/CodeLink.vue.d.ts +4 -6
- package/types/fields/UISelect.vue.d.ts +83 -0
- package/{dist/types/src → types}/index.d.ts +4 -1
- package/types/layouts/AddPageBox.vue.d.ts +4 -0
- package/{dist/types/src → types}/layouts/CodeEditor.vue.d.ts +11 -13
- package/types/layouts/Framework.vue.d.ts +22 -0
- package/types/layouts/NavMenu.vue.d.ts +25 -0
- package/types/layouts/PropsPanel.vue.d.ts +245 -0
- package/types/layouts/Resizer.vue.d.ts +12 -0
- package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +14 -0
- package/types/layouts/sidebar/LayerMenu.vue.d.ts +100 -0
- package/types/layouts/sidebar/LayerPanel.vue.d.ts +1101 -0
- package/{dist/types/src → types}/layouts/sidebar/Sidebar.vue.d.ts +3 -5
- package/types/layouts/sidebar/TabPane.vue.d.ts +14 -0
- package/types/layouts/workspace/PageBar.vue.d.ts +54 -0
- package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +48 -0
- package/types/layouts/workspace/Stage.vue.d.ts +46 -0
- package/types/layouts/workspace/ViewerMenu.vue.d.ts +88 -0
- package/types/layouts/workspace/Workspace.vue.d.ts +6 -0
- package/{dist/types/src → types}/services/BaseService.d.ts +0 -0
- package/types/services/componentList.d.ts +14 -0
- package/{dist/types/src → types}/services/editor.d.ts +21 -14
- package/{dist/types/src → types}/services/events.d.ts +0 -0
- package/{dist/types/src → types}/services/history.d.ts +0 -0
- package/{dist/types/src → types}/services/props.d.ts +26 -2
- package/types/services/storage.d.ts +56 -0
- package/{dist/types/src → types}/services/ui.d.ts +1 -1
- package/{dist/types/src → types}/type.d.ts +18 -1
- package/{dist/types/src → types}/utils/compose.d.ts +1 -1
- package/{dist/types/src → types}/utils/config.d.ts +0 -0
- package/{dist/types/src → types}/utils/editor.d.ts +6 -3
- package/{dist/types/src → types}/utils/index.d.ts +0 -0
- package/{dist/types/src → types}/utils/logger.d.ts +0 -0
- package/types/utils/operator.d.ts +21 -0
- package/{dist/types/src → types}/utils/polyfills.d.ts +0 -0
- package/{dist/types/src → types}/utils/props.d.ts +2 -22
- package/{dist/types/src → types}/utils/scroll-viewer.d.ts +0 -0
- package/{dist/types/src → types}/utils/undo-redo.d.ts +0 -0
- package/dist/tmagic-editor.es.js.map +0 -1
- package/dist/types/src/components/Icon.vue.d.ts +0 -14
- package/dist/types/src/components/ScrollViewer.vue.d.ts +0 -24
- package/dist/types/src/fields/Code.vue.d.ts +0 -25
- package/dist/types/src/layouts/AddPageBox.vue.d.ts +0 -5
- package/dist/types/src/layouts/Framework.vue.d.ts +0 -24
- package/dist/types/src/layouts/NavMenu.vue.d.ts +0 -27
- package/dist/types/src/layouts/PropsPanel.vue.d.ts +0 -13
- package/dist/types/src/layouts/Resizer.vue.d.ts +0 -14
- package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +0 -16
- package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +0 -16
- package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +0 -8
- package/dist/types/src/shims-vue.d.ts +0 -6
- package/dist/types/src/vite-env.d.ts +0 -1
- package/src/vite-env.d.ts +0 -1
package/src/services/editor.ts
CHANGED
|
@@ -17,58 +17,61 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { reactive, toRaw } from 'vue';
|
|
20
|
-
import { cloneDeep, mergeWith } from 'lodash-es';
|
|
21
|
-
import serialize from 'serialize-javascript';
|
|
20
|
+
import { cloneDeep, mergeWith, uniq } from 'lodash-es';
|
|
22
21
|
|
|
23
22
|
import type { Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
24
23
|
import { NodeType } from '@tmagic/schema';
|
|
25
24
|
import StageCore from '@tmagic/stage';
|
|
26
25
|
import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
|
|
27
26
|
|
|
28
|
-
import historyService, { StepValue } from '
|
|
29
|
-
import
|
|
30
|
-
import type { AddMNode, EditorNodeInfo, StoreState } from '
|
|
31
|
-
import { LayerOffset, Layout } from '
|
|
27
|
+
import historyService, { StepValue } from '../services/history';
|
|
28
|
+
import storageService, { Protocol } from '../services/storage';
|
|
29
|
+
import type { AddMNode, EditorNodeInfo, PastePosition, StoreState } from '../type';
|
|
30
|
+
import { LayerOffset, Layout } from '../type';
|
|
32
31
|
import {
|
|
33
32
|
change2Fixed,
|
|
34
33
|
COPY_STORAGE_KEY,
|
|
35
34
|
Fixed2Other,
|
|
36
|
-
|
|
37
|
-
generatePageNameByApp,
|
|
35
|
+
fixNodePosition,
|
|
38
36
|
getInitPositionStyle,
|
|
39
37
|
getNodeIndex,
|
|
40
38
|
isFixed,
|
|
41
39
|
setLayout,
|
|
42
|
-
} from '
|
|
43
|
-
import {
|
|
40
|
+
} from '../utils/editor';
|
|
41
|
+
import { beforePaste, getAddParent } from '../utils/operator';
|
|
44
42
|
|
|
45
43
|
import BaseService from './BaseService';
|
|
44
|
+
import propsService from './props';
|
|
46
45
|
|
|
47
46
|
class Editor extends BaseService {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
private state = reactive<StoreState>({
|
|
47
|
+
public state: StoreState = reactive({
|
|
51
48
|
root: null,
|
|
52
49
|
page: null,
|
|
53
50
|
parent: null,
|
|
54
51
|
node: null,
|
|
52
|
+
nodes: [],
|
|
55
53
|
stage: null,
|
|
56
54
|
highlightNode: null,
|
|
57
55
|
modifiedNodeIds: new Map(),
|
|
58
56
|
pageLength: 0,
|
|
59
57
|
});
|
|
58
|
+
private isHistoryStateChange = false;
|
|
60
59
|
|
|
61
60
|
constructor() {
|
|
62
61
|
super(
|
|
63
62
|
[
|
|
64
63
|
'getLayout',
|
|
65
64
|
'select',
|
|
65
|
+
'doAdd',
|
|
66
66
|
'add',
|
|
67
|
+
'doRemove',
|
|
67
68
|
'remove',
|
|
69
|
+
'doUpdate',
|
|
68
70
|
'update',
|
|
69
71
|
'sort',
|
|
70
72
|
'copy',
|
|
71
73
|
'paste',
|
|
74
|
+
'duAlignCenter',
|
|
72
75
|
'alignCenter',
|
|
73
76
|
'moveLayer',
|
|
74
77
|
'moveToContainer',
|
|
@@ -84,14 +87,16 @@ class Editor extends BaseService {
|
|
|
84
87
|
|
|
85
88
|
/**
|
|
86
89
|
* 设置当前指点节点配置
|
|
87
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode'
|
|
90
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes'
|
|
88
91
|
* @param value MNode
|
|
89
92
|
* @returns MNode
|
|
90
93
|
*/
|
|
91
94
|
public set<T = MNode>(name: keyof StoreState, value: T) {
|
|
92
95
|
this.state[name] = value as any;
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
// set nodes时将node设置为nodes第一个元素
|
|
97
|
+
if (name === 'nodes') {
|
|
98
|
+
this.set('node', (value as unknown as MNode[])[0]);
|
|
99
|
+
}
|
|
95
100
|
if (name === 'root') {
|
|
96
101
|
this.state.pageLength = (value as unknown as MApp)?.items?.length || 0;
|
|
97
102
|
this.emit('root-change', value);
|
|
@@ -100,7 +105,7 @@ class Editor extends BaseService {
|
|
|
100
105
|
|
|
101
106
|
/**
|
|
102
107
|
* 获取当前指点节点配置
|
|
103
|
-
* @param name 'root' | 'page' | 'parent' | 'node'
|
|
108
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes'
|
|
104
109
|
* @returns MNode
|
|
105
110
|
*/
|
|
106
111
|
public get<T = MNode>(name: keyof StoreState): T {
|
|
@@ -192,7 +197,7 @@ class Editor extends BaseService {
|
|
|
192
197
|
*/
|
|
193
198
|
public async select(config: MNode | Id): Promise<MNode> | never {
|
|
194
199
|
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
|
195
|
-
this.set('
|
|
200
|
+
this.set('nodes', [node]);
|
|
196
201
|
this.set('page', page || null);
|
|
197
202
|
this.set('parent', parent || null);
|
|
198
203
|
|
|
@@ -267,85 +272,110 @@ class Editor extends BaseService {
|
|
|
267
272
|
}
|
|
268
273
|
|
|
269
274
|
/**
|
|
270
|
-
*
|
|
271
|
-
* @param
|
|
272
|
-
* @
|
|
273
|
-
* @returns 添加后的节点
|
|
275
|
+
* 多选
|
|
276
|
+
* @param ids 指定节点ID
|
|
277
|
+
* @returns 加入多选的节点配置
|
|
274
278
|
*/
|
|
275
|
-
public
|
|
276
|
-
const
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
} else if (parent && typeof parent !== 'function') {
|
|
286
|
-
parentNode = parent;
|
|
287
|
-
} else if (curNode.items) {
|
|
288
|
-
parentNode = curNode;
|
|
289
|
-
} else {
|
|
290
|
-
parentNode = this.getParentById(curNode.id, false);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (!parentNode) throw new Error('未找到父元素');
|
|
279
|
+
public multiSelect(ids: Id[]): void {
|
|
280
|
+
const nodes: MNode[] = [];
|
|
281
|
+
const idsUnique = uniq(ids);
|
|
282
|
+
idsUnique.forEach((id) => {
|
|
283
|
+
const { node } = this.getNodeInfo(id);
|
|
284
|
+
if (!node) return;
|
|
285
|
+
nodes.push(node);
|
|
286
|
+
});
|
|
287
|
+
this.set('nodes', nodes);
|
|
288
|
+
}
|
|
294
289
|
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
|
|
290
|
+
public async doAdd(node: MNode, parent: MContainer): Promise<MNode> {
|
|
291
|
+
const root = this.get<MApp>('root');
|
|
292
|
+
const curNode = this.get<MNode>('node');
|
|
293
|
+
const stage = this.get<StageCore | null>('stage');
|
|
298
294
|
|
|
299
|
-
if ((
|
|
295
|
+
if ((parent?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && node.type !== NodeType.PAGE) {
|
|
300
296
|
throw new Error('app下不能添加组件');
|
|
301
297
|
}
|
|
302
298
|
|
|
303
|
-
|
|
299
|
+
// 新增节点添加到配置中
|
|
300
|
+
parent?.items?.push(node);
|
|
304
301
|
|
|
305
|
-
const
|
|
306
|
-
|
|
302
|
+
const layout = await this.getLayout(toRaw(parent), node as MNode);
|
|
303
|
+
node.style = getInitPositionStyle(node.style, layout);
|
|
304
|
+
|
|
305
|
+
await stage?.add({
|
|
306
|
+
config: cloneDeep(node),
|
|
307
|
+
parent: cloneDeep(parent),
|
|
308
|
+
parentId: parent.id,
|
|
309
|
+
root: cloneDeep(root),
|
|
310
|
+
});
|
|
307
311
|
|
|
308
|
-
|
|
312
|
+
node.style = fixNodePosition(node, parent, stage);
|
|
309
313
|
|
|
310
|
-
|
|
311
|
-
const fixedLeft = fixNodeLeft(newNode, parentNode, stage?.renderer.contentWindow?.document);
|
|
312
|
-
if (typeof fixedLeft !== 'undefined') {
|
|
313
|
-
newNode.style.left = fixedLeft;
|
|
314
|
-
await stage?.update({ config: cloneDeep(newNode), root: cloneDeep(root) });
|
|
315
|
-
}
|
|
316
|
-
}
|
|
314
|
+
await stage?.update({ config: cloneDeep(node), parentId: parent.id, root: cloneDeep(root) });
|
|
317
315
|
|
|
318
|
-
|
|
316
|
+
this.addModifiedNodeId(node.id);
|
|
319
317
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
318
|
+
return node;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* 向指点容器添加组件节点
|
|
323
|
+
* @param addConfig 将要添加的组件节点配置
|
|
324
|
+
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
325
|
+
* @returns 添加后的节点
|
|
326
|
+
*/
|
|
327
|
+
public async add(addNode: AddMNode | MNode[], parent?: MContainer | null): Promise<MNode | MNode[]> {
|
|
328
|
+
const stage = this.get<StageCore | null>('stage');
|
|
329
|
+
|
|
330
|
+
// 新增多个组件只存在于粘贴多个组件,粘贴的是一个完整的config,所以不再需要getPropsValue
|
|
331
|
+
const addNodes = [];
|
|
332
|
+
if (!Array.isArray(addNode)) {
|
|
333
|
+
const { type, inputEvent, ...config } = addNode;
|
|
334
|
+
|
|
335
|
+
if (!type) throw new Error('组件类型不能为空');
|
|
336
|
+
|
|
337
|
+
addNodes.push({ ...toRaw(await propsService.getPropsValue(type, config)) });
|
|
338
|
+
} else {
|
|
339
|
+
addNodes.push(...addNode);
|
|
323
340
|
}
|
|
324
341
|
|
|
325
|
-
|
|
342
|
+
const newNodes = await Promise.all(
|
|
343
|
+
addNodes.map((node) => {
|
|
344
|
+
const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
|
|
345
|
+
if (!parentNode) throw new Error('未找到父元素');
|
|
346
|
+
return this.doAdd(node, parentNode);
|
|
347
|
+
}),
|
|
348
|
+
);
|
|
326
349
|
|
|
327
|
-
if (
|
|
328
|
-
|
|
350
|
+
if (newNodes.length > 1) {
|
|
351
|
+
const newNodeIds = newNodes.map((node) => node.id);
|
|
352
|
+
// 触发选中样式
|
|
353
|
+
stage?.multiSelect(newNodeIds);
|
|
354
|
+
await this.multiSelect(newNodeIds);
|
|
355
|
+
} else {
|
|
356
|
+
await this.select(newNodes[0]);
|
|
357
|
+
|
|
358
|
+
if (isPage(newNodes[0])) {
|
|
359
|
+
this.state.pageLength += 1;
|
|
360
|
+
} else {
|
|
361
|
+
// 新增页面,这个时候页面还有渲染出来,此时select会出错,在runtime-ready的时候回去select
|
|
362
|
+
stage?.select(newNodes[0].id);
|
|
363
|
+
}
|
|
329
364
|
}
|
|
330
365
|
|
|
331
|
-
this.
|
|
366
|
+
this.pushHistoryState();
|
|
332
367
|
|
|
333
|
-
|
|
334
|
-
}
|
|
368
|
+
this.emit('add', newNodes);
|
|
335
369
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
* @param {Object} node
|
|
339
|
-
* @return {Object} 删除的组件配置
|
|
340
|
-
*/
|
|
341
|
-
public async remove(node: MNode): Promise<MNode | void> {
|
|
342
|
-
if (!node?.id) return;
|
|
370
|
+
return newNodes.length > 1 ? newNodes[0] : newNodes;
|
|
371
|
+
}
|
|
343
372
|
|
|
373
|
+
public async doRemove(node: MNode): Promise<void> {
|
|
344
374
|
const root = this.get<MApp | null>('root');
|
|
345
375
|
|
|
346
376
|
if (!root) throw new Error('没有root');
|
|
347
377
|
|
|
348
|
-
const { parent, node: curNode } = this.getNodeInfo(node.id
|
|
378
|
+
const { parent, node: curNode } = this.getNodeInfo(node.id);
|
|
349
379
|
|
|
350
380
|
if (!parent || !curNode) throw new Error('找不要删除的节点');
|
|
351
381
|
|
|
@@ -355,7 +385,7 @@ class Editor extends BaseService {
|
|
|
355
385
|
|
|
356
386
|
parent.items?.splice(index, 1);
|
|
357
387
|
const stage = this.get<StageCore | null>('stage');
|
|
358
|
-
stage?.remove({ id: node.id, root: cloneDeep(
|
|
388
|
+
stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
|
|
359
389
|
|
|
360
390
|
if (node.type === NodeType.PAGE) {
|
|
361
391
|
this.state.pageLength -= 1;
|
|
@@ -372,9 +402,7 @@ class Editor extends BaseService {
|
|
|
372
402
|
this.resetModifiedNodeId();
|
|
373
403
|
historyService.reset();
|
|
374
404
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
return node;
|
|
405
|
+
return;
|
|
378
406
|
}
|
|
379
407
|
} else {
|
|
380
408
|
await this.select(parent);
|
|
@@ -382,19 +410,25 @@ class Editor extends BaseService {
|
|
|
382
410
|
}
|
|
383
411
|
|
|
384
412
|
this.addModifiedNodeId(parent.id);
|
|
385
|
-
this.pushHistoryState();
|
|
386
|
-
|
|
387
|
-
this.emit('remove', node);
|
|
388
|
-
|
|
389
|
-
return node;
|
|
390
413
|
}
|
|
391
414
|
|
|
392
415
|
/**
|
|
393
|
-
*
|
|
394
|
-
* @param
|
|
395
|
-
* @
|
|
416
|
+
* 删除组件
|
|
417
|
+
* @param {Object} node
|
|
418
|
+
* @return {Object} 删除的组件配置
|
|
396
419
|
*/
|
|
397
|
-
public async
|
|
420
|
+
public async remove(nodeOrNodeList: MNode | MNode[]): Promise<void> {
|
|
421
|
+
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
422
|
+
|
|
423
|
+
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
424
|
+
|
|
425
|
+
// 更新历史记录
|
|
426
|
+
this.pushHistoryState();
|
|
427
|
+
|
|
428
|
+
this.emit('remove');
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
public async doUpdate(config: MNode) {
|
|
398
432
|
if (!config?.id) throw new Error('没有配置或者配置缺少id值');
|
|
399
433
|
|
|
400
434
|
const info = this.getNodeInfo(config.id, false);
|
|
@@ -434,22 +468,42 @@ class Editor extends BaseService {
|
|
|
434
468
|
|
|
435
469
|
parentNodeItems[index] = newConfig;
|
|
436
470
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
471
|
+
// 将update后的配置更新到nodes中
|
|
472
|
+
const nodes = this.get('nodes');
|
|
473
|
+
const targetIndex = nodes.findIndex((nodeItem: MNode) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
474
|
+
nodes.splice(targetIndex, 1, newConfig);
|
|
475
|
+
this.set('nodes', nodes);
|
|
440
476
|
|
|
441
|
-
this.get<StageCore | null>('stage')?.update({
|
|
477
|
+
this.get<StageCore | null>('stage')?.update({
|
|
478
|
+
config: cloneDeep(newConfig),
|
|
479
|
+
parentId: parent.id,
|
|
480
|
+
root: cloneDeep(this.get('root')),
|
|
481
|
+
});
|
|
442
482
|
|
|
443
483
|
if (newConfig.type === NodeType.PAGE) {
|
|
444
484
|
this.set('page', newConfig);
|
|
445
485
|
}
|
|
446
486
|
|
|
447
487
|
this.addModifiedNodeId(newConfig.id);
|
|
488
|
+
|
|
489
|
+
return newConfig;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* 更新节点
|
|
494
|
+
* @param config 新的节点配置,配置中需要有id信息
|
|
495
|
+
* @returns 更新后的节点配置
|
|
496
|
+
*/
|
|
497
|
+
public async update(config: MNode | MNode[]): Promise<MNode | MNode[]> {
|
|
498
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
499
|
+
|
|
500
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doUpdate(node)));
|
|
501
|
+
|
|
448
502
|
this.pushHistoryState();
|
|
449
503
|
|
|
450
|
-
this.emit('update',
|
|
504
|
+
this.emit('update', newNodes);
|
|
451
505
|
|
|
452
|
-
return
|
|
506
|
+
return newNodes.length > 1 ? newNodes[0] : newNodes;
|
|
453
507
|
}
|
|
454
508
|
|
|
455
509
|
/**
|
|
@@ -471,7 +525,11 @@ class Editor extends BaseService {
|
|
|
471
525
|
await this.update(parent);
|
|
472
526
|
await this.select(node);
|
|
473
527
|
|
|
474
|
-
this.get<StageCore | null>('stage')?.update({
|
|
528
|
+
this.get<StageCore | null>('stage')?.update({
|
|
529
|
+
config: cloneDeep(node),
|
|
530
|
+
parentId: parent.id,
|
|
531
|
+
root: cloneDeep(this.get('root')),
|
|
532
|
+
});
|
|
475
533
|
|
|
476
534
|
this.addModifiedNodeId(parent.id);
|
|
477
535
|
this.pushHistoryState();
|
|
@@ -482,67 +540,46 @@ class Editor extends BaseService {
|
|
|
482
540
|
* @param config 组件节点配置
|
|
483
541
|
* @returns 组件节点配置
|
|
484
542
|
*/
|
|
485
|
-
public async copy(config: MNode): Promise<void> {
|
|
486
|
-
|
|
543
|
+
public async copy(config: MNode | MNode[]): Promise<void> {
|
|
544
|
+
await storageService.setItem(COPY_STORAGE_KEY, Array.isArray(config) ? config : [config], {
|
|
545
|
+
protocol: Protocol.OBJECT,
|
|
546
|
+
});
|
|
487
547
|
}
|
|
488
548
|
|
|
489
549
|
/**
|
|
490
550
|
* 从localStorage中获取节点,然后添加到当前容器中
|
|
491
|
-
* @param position
|
|
551
|
+
* @param position 粘贴的坐标
|
|
492
552
|
* @returns 添加后的组件节点配置
|
|
493
553
|
*/
|
|
494
|
-
public async paste(position:
|
|
495
|
-
const
|
|
496
|
-
// eslint-disable-next-line prefer-const
|
|
497
|
-
let config: any = {};
|
|
498
|
-
if (!configStr) {
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
554
|
+
public async paste(position: PastePosition = {}): Promise<MNode | MNode[] | void> {
|
|
555
|
+
const config: MNode[] = await storageService.getItem(COPY_STORAGE_KEY);
|
|
501
556
|
|
|
502
|
-
|
|
503
|
-
// eslint-disable-next-line no-eval
|
|
504
|
-
eval(`config = ${configStr}`);
|
|
505
|
-
} catch (e) {
|
|
506
|
-
console.error(e);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
557
|
+
if (!Array.isArray(config)) return;
|
|
509
558
|
|
|
510
|
-
await
|
|
511
|
-
if (config.style) {
|
|
512
|
-
config.style = {
|
|
513
|
-
...config.style,
|
|
514
|
-
...position,
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
if (isPage(config)) {
|
|
519
|
-
config.name = generatePageNameByApp(this.get('root'));
|
|
520
|
-
}
|
|
559
|
+
const pasteConfigs = await beforePaste(position, config);
|
|
521
560
|
|
|
522
|
-
return
|
|
561
|
+
return this.add(pasteConfigs);
|
|
523
562
|
}
|
|
524
563
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const
|
|
532
|
-
const node = this.get<MNode>('node');
|
|
533
|
-
const layout = await this.getLayout(toRaw(parent), toRaw(node));
|
|
564
|
+
public async doAlignCenter(config: MNode): Promise<MNode> {
|
|
565
|
+
const parent = this.getParentById(config.id);
|
|
566
|
+
|
|
567
|
+
if (!parent) throw new Error('找不到父节点');
|
|
568
|
+
|
|
569
|
+
const node = cloneDeep(toRaw(config));
|
|
570
|
+
const layout = await this.getLayout(parent, node);
|
|
534
571
|
if (layout === Layout.RELATIVE) {
|
|
535
|
-
return;
|
|
572
|
+
return config;
|
|
536
573
|
}
|
|
537
574
|
|
|
538
|
-
if (!node.style) return;
|
|
575
|
+
if (!node.style) return config;
|
|
539
576
|
|
|
540
577
|
const stage = this.get<StageCore>('stage');
|
|
541
578
|
const doc = stage?.renderer.contentWindow?.document;
|
|
542
579
|
|
|
543
580
|
if (doc) {
|
|
544
|
-
const parentEl = doc.getElementById(`${parent.id}`);
|
|
545
581
|
const el = doc.getElementById(`${node.id}`);
|
|
582
|
+
const parentEl = el?.offsetParent;
|
|
546
583
|
if (parentEl && el) {
|
|
547
584
|
node.style.left = (parentEl.clientWidth - el.clientWidth) / 2;
|
|
548
585
|
}
|
|
@@ -550,15 +587,25 @@ class Editor extends BaseService {
|
|
|
550
587
|
node.style.left = (parent.style.width - node.style.width) / 2;
|
|
551
588
|
}
|
|
552
589
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
590
|
+
return node;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* 将指点节点设置居中
|
|
595
|
+
* @param config 组件节点配置
|
|
596
|
+
* @returns 当前组件节点配置
|
|
597
|
+
*/
|
|
598
|
+
public async alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]> {
|
|
599
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
600
|
+
const stage = this.get<StageCore | null>('stage');
|
|
601
|
+
|
|
602
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
|
560
603
|
|
|
561
|
-
|
|
604
|
+
const newNode = await this.update(newNodes);
|
|
605
|
+
|
|
606
|
+
await stage?.multiSelect(newNodes.map((node) => node.id));
|
|
607
|
+
|
|
608
|
+
return newNode;
|
|
562
609
|
}
|
|
563
610
|
|
|
564
611
|
/**
|
|
@@ -581,6 +628,7 @@ class Editor extends BaseService {
|
|
|
581
628
|
|
|
582
629
|
this.get<StageCore | null>('stage')?.update({
|
|
583
630
|
config: cloneDeep(toRaw(parent)),
|
|
631
|
+
parentId: parent.id,
|
|
584
632
|
root: cloneDeep(this.get<MApp>('root')),
|
|
585
633
|
});
|
|
586
634
|
}
|
|
@@ -601,7 +649,7 @@ class Editor extends BaseService {
|
|
|
601
649
|
const index = getNodeIndex(node, parent);
|
|
602
650
|
parent.items?.splice(index, 1);
|
|
603
651
|
|
|
604
|
-
await stage.remove({ id: node.id, root });
|
|
652
|
+
await stage.remove({ id: node.id, parentId: parent.id, root });
|
|
605
653
|
|
|
606
654
|
const layout = await this.getLayout(target);
|
|
607
655
|
|
|
@@ -610,13 +658,13 @@ class Editor extends BaseService {
|
|
|
610
658
|
return srcValue;
|
|
611
659
|
}
|
|
612
660
|
});
|
|
613
|
-
newConfig.style = getInitPositionStyle(newConfig.style, layout
|
|
661
|
+
newConfig.style = getInitPositionStyle(newConfig.style, layout);
|
|
614
662
|
|
|
615
663
|
target.items.push(newConfig);
|
|
616
664
|
|
|
617
665
|
await stage.select(targetId);
|
|
618
666
|
|
|
619
|
-
await stage.update({ config: cloneDeep(target), root });
|
|
667
|
+
await stage.update({ config: cloneDeep(target), parentId: parent.id, root });
|
|
620
668
|
|
|
621
669
|
await this.select(newConfig);
|
|
622
670
|
stage.select(newConfig.id);
|
|
@@ -653,7 +701,7 @@ class Editor extends BaseService {
|
|
|
653
701
|
const node = toRaw(this.get('node'));
|
|
654
702
|
if (!node || isPage(node)) return;
|
|
655
703
|
|
|
656
|
-
const { style, id } = node;
|
|
704
|
+
const { style, id, type } = node;
|
|
657
705
|
if (!style || style.position !== 'absolute') return;
|
|
658
706
|
|
|
659
707
|
if (top && !isNumber(style.top)) return;
|
|
@@ -661,6 +709,7 @@ class Editor extends BaseService {
|
|
|
661
709
|
|
|
662
710
|
this.update({
|
|
663
711
|
id,
|
|
712
|
+
type,
|
|
664
713
|
style: {
|
|
665
714
|
...style,
|
|
666
715
|
left: Number(style.left) + left,
|
|
@@ -673,6 +722,7 @@ class Editor extends BaseService {
|
|
|
673
722
|
this.removeAllListeners();
|
|
674
723
|
this.set('root', null);
|
|
675
724
|
this.set('node', null);
|
|
725
|
+
this.set('nodes', []);
|
|
676
726
|
this.set('page', null);
|
|
677
727
|
this.set('parent', null);
|
|
678
728
|
}
|
package/src/services/events.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { cloneDeep } from 'lodash-es';
|
|
|
22
22
|
import { DEFAULT_EVENTS, DEFAULT_METHODS, EventOption } from '@tmagic/core';
|
|
23
23
|
import { toLine } from '@tmagic/utils';
|
|
24
24
|
|
|
25
|
-
import type { ComponentGroup } from '
|
|
25
|
+
import type { ComponentGroup } from '../type';
|
|
26
26
|
|
|
27
27
|
import BaseService from './BaseService';
|
|
28
28
|
|
package/src/services/history.ts
CHANGED