@tmagic/editor 1.1.0-beta.1 → 1.1.0-beta.12
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} +1449 -1205
- package/dist/tmagic-editor.mjs.map +1 -0
- package/dist/tmagic-editor.umd.js +1463 -1219
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/package.json +23 -21
- package/src/Editor.vue +24 -15
- package/src/components/ContentMenu.vue +87 -99
- package/src/components/Icon.vue +1 -1
- package/src/components/ScrollViewer.vue +2 -2
- package/src/components/ToolButton.vue +150 -167
- package/src/fields/UISelect.vue +51 -72
- package/src/index.ts +2 -1
- package/src/layouts/AddPageBox.vue +2 -2
- 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 +2 -2
- package/src/layouts/sidebar/LayerPanel.vue +52 -12
- package/src/layouts/sidebar/Sidebar.vue +1 -1
- package/src/layouts/sidebar/TabPane.vue +2 -2
- 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 +140 -147
- package/src/layouts/workspace/Workspace.vue +14 -12
- package/src/services/BaseService.ts +5 -10
- package/src/services/componentList.ts +3 -3
- package/src/services/editor.ts +208 -147
- package/src/services/events.ts +1 -1
- package/src/services/history.ts +1 -1
- package/src/services/props.ts +74 -49
- 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 -27
- 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 +22 -14
- package/{dist/types/src → types}/services/events.d.ts +0 -0
- package/{dist/types/src → types}/services/history.d.ts +0 -0
- package/types/services/props.d.ts +97 -0
- 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 -23
- 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/services/props.d.ts +0 -42
- 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,62 @@
|
|
|
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
|
+
'doPaste',
|
|
75
|
+
'duAlignCenter',
|
|
72
76
|
'alignCenter',
|
|
73
77
|
'moveLayer',
|
|
74
78
|
'moveToContainer',
|
|
@@ -84,14 +88,16 @@ class Editor extends BaseService {
|
|
|
84
88
|
|
|
85
89
|
/**
|
|
86
90
|
* 设置当前指点节点配置
|
|
87
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode'
|
|
91
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes'
|
|
88
92
|
* @param value MNode
|
|
89
93
|
* @returns MNode
|
|
90
94
|
*/
|
|
91
95
|
public set<T = MNode>(name: keyof StoreState, value: T) {
|
|
92
96
|
this.state[name] = value as any;
|
|
93
|
-
|
|
94
|
-
|
|
97
|
+
// set nodes时将node设置为nodes第一个元素
|
|
98
|
+
if (name === 'nodes') {
|
|
99
|
+
this.set('node', (value as unknown as MNode[])[0]);
|
|
100
|
+
}
|
|
95
101
|
if (name === 'root') {
|
|
96
102
|
this.state.pageLength = (value as unknown as MApp)?.items?.length || 0;
|
|
97
103
|
this.emit('root-change', value);
|
|
@@ -100,7 +106,7 @@ class Editor extends BaseService {
|
|
|
100
106
|
|
|
101
107
|
/**
|
|
102
108
|
* 获取当前指点节点配置
|
|
103
|
-
* @param name 'root' | 'page' | 'parent' | 'node'
|
|
109
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes'
|
|
104
110
|
* @returns MNode
|
|
105
111
|
*/
|
|
106
112
|
public get<T = MNode>(name: keyof StoreState): T {
|
|
@@ -192,7 +198,7 @@ class Editor extends BaseService {
|
|
|
192
198
|
*/
|
|
193
199
|
public async select(config: MNode | Id): Promise<MNode> | never {
|
|
194
200
|
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
|
195
|
-
this.set('
|
|
201
|
+
this.set('nodes', [node]);
|
|
196
202
|
this.set('page', page || null);
|
|
197
203
|
this.set('parent', parent || null);
|
|
198
204
|
|
|
@@ -267,85 +273,110 @@ class Editor extends BaseService {
|
|
|
267
273
|
}
|
|
268
274
|
|
|
269
275
|
/**
|
|
270
|
-
*
|
|
271
|
-
* @param
|
|
272
|
-
* @
|
|
273
|
-
* @returns 添加后的节点
|
|
276
|
+
* 多选
|
|
277
|
+
* @param ids 指定节点ID
|
|
278
|
+
* @returns 加入多选的节点配置
|
|
274
279
|
*/
|
|
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('未找到父元素');
|
|
280
|
+
public multiSelect(ids: Id[]): void {
|
|
281
|
+
const nodes: MNode[] = [];
|
|
282
|
+
const idsUnique = uniq(ids);
|
|
283
|
+
idsUnique.forEach((id) => {
|
|
284
|
+
const { node } = this.getNodeInfo(id);
|
|
285
|
+
if (!node) return;
|
|
286
|
+
nodes.push(node);
|
|
287
|
+
});
|
|
288
|
+
this.set('nodes', nodes);
|
|
289
|
+
}
|
|
294
290
|
|
|
295
|
-
|
|
296
|
-
const
|
|
297
|
-
|
|
291
|
+
public async doAdd(node: MNode, parent: MContainer): Promise<MNode> {
|
|
292
|
+
const root = this.get<MApp>('root');
|
|
293
|
+
const curNode = this.get<MNode>('node');
|
|
294
|
+
const stage = this.get<StageCore | null>('stage');
|
|
298
295
|
|
|
299
|
-
if ((
|
|
296
|
+
if ((parent?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && node.type !== NodeType.PAGE) {
|
|
300
297
|
throw new Error('app下不能添加组件');
|
|
301
298
|
}
|
|
302
299
|
|
|
303
|
-
|
|
300
|
+
// 新增节点添加到配置中
|
|
301
|
+
parent?.items?.push(node);
|
|
304
302
|
|
|
305
|
-
const
|
|
306
|
-
|
|
303
|
+
const layout = await this.getLayout(toRaw(parent), node as MNode);
|
|
304
|
+
node.style = getInitPositionStyle(node.style, layout);
|
|
307
305
|
|
|
308
|
-
await stage?.add({
|
|
306
|
+
await stage?.add({
|
|
307
|
+
config: cloneDeep(node),
|
|
308
|
+
parent: cloneDeep(parent),
|
|
309
|
+
parentId: parent.id,
|
|
310
|
+
root: cloneDeep(root),
|
|
311
|
+
});
|
|
309
312
|
|
|
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
|
-
}
|
|
313
|
+
node.style = fixNodePosition(node, parent, stage);
|
|
317
314
|
|
|
318
|
-
await
|
|
315
|
+
await stage?.update({ config: cloneDeep(node), parentId: parent.id, root: cloneDeep(root) });
|
|
319
316
|
|
|
320
|
-
this.addModifiedNodeId(
|
|
321
|
-
|
|
322
|
-
|
|
317
|
+
this.addModifiedNodeId(node.id);
|
|
318
|
+
|
|
319
|
+
return node;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* 向指点容器添加组件节点
|
|
324
|
+
* @param addConfig 将要添加的组件节点配置
|
|
325
|
+
* @param parent 要添加到的容器组件节点配置,如果不设置,默认为当前选中的组件的父节点
|
|
326
|
+
* @returns 添加后的节点
|
|
327
|
+
*/
|
|
328
|
+
public async add(addNode: AddMNode | MNode[], parent?: MContainer | null): Promise<MNode | MNode[]> {
|
|
329
|
+
const stage = this.get<StageCore | null>('stage');
|
|
330
|
+
|
|
331
|
+
// 新增多个组件只存在于粘贴多个组件,粘贴的是一个完整的config,所以不再需要getPropsValue
|
|
332
|
+
const addNodes = [];
|
|
333
|
+
if (!Array.isArray(addNode)) {
|
|
334
|
+
const { type, inputEvent, ...config } = addNode;
|
|
335
|
+
|
|
336
|
+
if (!type) throw new Error('组件类型不能为空');
|
|
337
|
+
|
|
338
|
+
addNodes.push({ ...toRaw(await propsService.getPropsValue(type, config)) });
|
|
339
|
+
} else {
|
|
340
|
+
addNodes.push(...addNode);
|
|
323
341
|
}
|
|
324
342
|
|
|
325
|
-
|
|
343
|
+
const newNodes = await Promise.all(
|
|
344
|
+
addNodes.map((node) => {
|
|
345
|
+
const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
|
|
346
|
+
if (!parentNode) throw new Error('未找到父元素');
|
|
347
|
+
return this.doAdd(node, parentNode);
|
|
348
|
+
}),
|
|
349
|
+
);
|
|
326
350
|
|
|
327
|
-
if (
|
|
328
|
-
|
|
351
|
+
if (newNodes.length > 1) {
|
|
352
|
+
const newNodeIds = newNodes.map((node) => node.id);
|
|
353
|
+
// 触发选中样式
|
|
354
|
+
stage?.multiSelect(newNodeIds);
|
|
355
|
+
await this.multiSelect(newNodeIds);
|
|
356
|
+
} else {
|
|
357
|
+
await this.select(newNodes[0]);
|
|
358
|
+
|
|
359
|
+
if (isPage(newNodes[0])) {
|
|
360
|
+
this.state.pageLength += 1;
|
|
361
|
+
} else {
|
|
362
|
+
// 新增页面,这个时候页面还有渲染出来,此时select会出错,在runtime-ready的时候回去select
|
|
363
|
+
stage?.select(newNodes[0].id);
|
|
364
|
+
}
|
|
329
365
|
}
|
|
330
366
|
|
|
331
|
-
this.
|
|
367
|
+
this.pushHistoryState();
|
|
332
368
|
|
|
333
|
-
|
|
334
|
-
}
|
|
369
|
+
this.emit('add', newNodes);
|
|
335
370
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
* @param {Object} node
|
|
339
|
-
* @return {Object} 删除的组件配置
|
|
340
|
-
*/
|
|
341
|
-
public async remove(node: MNode): Promise<MNode | void> {
|
|
342
|
-
if (!node?.id) return;
|
|
371
|
+
return Array.isArray(addNode) ? newNodes : newNodes[0];
|
|
372
|
+
}
|
|
343
373
|
|
|
374
|
+
public async doRemove(node: MNode): Promise<void> {
|
|
344
375
|
const root = this.get<MApp | null>('root');
|
|
345
376
|
|
|
346
377
|
if (!root) throw new Error('没有root');
|
|
347
378
|
|
|
348
|
-
const { parent, node: curNode } = this.getNodeInfo(node.id
|
|
379
|
+
const { parent, node: curNode } = this.getNodeInfo(node.id);
|
|
349
380
|
|
|
350
381
|
if (!parent || !curNode) throw new Error('找不要删除的节点');
|
|
351
382
|
|
|
@@ -355,7 +386,7 @@ class Editor extends BaseService {
|
|
|
355
386
|
|
|
356
387
|
parent.items?.splice(index, 1);
|
|
357
388
|
const stage = this.get<StageCore | null>('stage');
|
|
358
|
-
stage?.remove({ id: node.id, root: cloneDeep(
|
|
389
|
+
stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
|
|
359
390
|
|
|
360
391
|
if (node.type === NodeType.PAGE) {
|
|
361
392
|
this.state.pageLength -= 1;
|
|
@@ -372,9 +403,7 @@ class Editor extends BaseService {
|
|
|
372
403
|
this.resetModifiedNodeId();
|
|
373
404
|
historyService.reset();
|
|
374
405
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
return node;
|
|
406
|
+
return;
|
|
378
407
|
}
|
|
379
408
|
} else {
|
|
380
409
|
await this.select(parent);
|
|
@@ -382,19 +411,25 @@ class Editor extends BaseService {
|
|
|
382
411
|
}
|
|
383
412
|
|
|
384
413
|
this.addModifiedNodeId(parent.id);
|
|
385
|
-
this.pushHistoryState();
|
|
386
|
-
|
|
387
|
-
this.emit('remove', node);
|
|
388
|
-
|
|
389
|
-
return node;
|
|
390
414
|
}
|
|
391
415
|
|
|
392
416
|
/**
|
|
393
|
-
*
|
|
394
|
-
* @param
|
|
395
|
-
* @
|
|
417
|
+
* 删除组件
|
|
418
|
+
* @param {Object} node
|
|
419
|
+
* @return {Object} 删除的组件配置
|
|
396
420
|
*/
|
|
397
|
-
public async
|
|
421
|
+
public async remove(nodeOrNodeList: MNode | MNode[]): Promise<void> {
|
|
422
|
+
const nodes = Array.isArray(nodeOrNodeList) ? nodeOrNodeList : [nodeOrNodeList];
|
|
423
|
+
|
|
424
|
+
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
425
|
+
|
|
426
|
+
// 更新历史记录
|
|
427
|
+
this.pushHistoryState();
|
|
428
|
+
|
|
429
|
+
this.emit('remove');
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
public async doUpdate(config: MNode) {
|
|
398
433
|
if (!config?.id) throw new Error('没有配置或者配置缺少id值');
|
|
399
434
|
|
|
400
435
|
const info = this.getNodeInfo(config.id, false);
|
|
@@ -434,22 +469,42 @@ class Editor extends BaseService {
|
|
|
434
469
|
|
|
435
470
|
parentNodeItems[index] = newConfig;
|
|
436
471
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
}
|
|
472
|
+
// 将update后的配置更新到nodes中
|
|
473
|
+
const nodes = this.get('nodes');
|
|
474
|
+
const targetIndex = nodes.findIndex((nodeItem: MNode) => `${nodeItem.id}` === `${newConfig.id}`);
|
|
475
|
+
nodes.splice(targetIndex, 1, newConfig);
|
|
476
|
+
this.set('nodes', nodes);
|
|
440
477
|
|
|
441
|
-
this.get<StageCore | null>('stage')?.update({
|
|
478
|
+
this.get<StageCore | null>('stage')?.update({
|
|
479
|
+
config: cloneDeep(newConfig),
|
|
480
|
+
parentId: parent.id,
|
|
481
|
+
root: cloneDeep(this.get('root')),
|
|
482
|
+
});
|
|
442
483
|
|
|
443
484
|
if (newConfig.type === NodeType.PAGE) {
|
|
444
485
|
this.set('page', newConfig);
|
|
445
486
|
}
|
|
446
487
|
|
|
447
488
|
this.addModifiedNodeId(newConfig.id);
|
|
489
|
+
|
|
490
|
+
return newConfig;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* 更新节点
|
|
495
|
+
* @param config 新的节点配置,配置中需要有id信息
|
|
496
|
+
* @returns 更新后的节点配置
|
|
497
|
+
*/
|
|
498
|
+
public async update(config: MNode | MNode[]): Promise<MNode | MNode[]> {
|
|
499
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
500
|
+
|
|
501
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doUpdate(node)));
|
|
502
|
+
|
|
448
503
|
this.pushHistoryState();
|
|
449
504
|
|
|
450
|
-
this.emit('update',
|
|
505
|
+
this.emit('update', newNodes);
|
|
451
506
|
|
|
452
|
-
return
|
|
507
|
+
return Array.isArray(config) ? newNodes : newNodes[0];
|
|
453
508
|
}
|
|
454
509
|
|
|
455
510
|
/**
|
|
@@ -471,7 +526,11 @@ class Editor extends BaseService {
|
|
|
471
526
|
await this.update(parent);
|
|
472
527
|
await this.select(node);
|
|
473
528
|
|
|
474
|
-
this.get<StageCore | null>('stage')?.update({
|
|
529
|
+
this.get<StageCore | null>('stage')?.update({
|
|
530
|
+
config: cloneDeep(node),
|
|
531
|
+
parentId: parent.id,
|
|
532
|
+
root: cloneDeep(this.get('root')),
|
|
533
|
+
});
|
|
475
534
|
|
|
476
535
|
this.addModifiedNodeId(parent.id);
|
|
477
536
|
this.pushHistoryState();
|
|
@@ -482,67 +541,51 @@ class Editor extends BaseService {
|
|
|
482
541
|
* @param config 组件节点配置
|
|
483
542
|
* @returns 组件节点配置
|
|
484
543
|
*/
|
|
485
|
-
public async copy(config: MNode): Promise<void> {
|
|
486
|
-
|
|
544
|
+
public async copy(config: MNode | MNode[]): Promise<void> {
|
|
545
|
+
await storageService.setItem(COPY_STORAGE_KEY, Array.isArray(config) ? config : [config], {
|
|
546
|
+
protocol: Protocol.OBJECT,
|
|
547
|
+
});
|
|
487
548
|
}
|
|
488
549
|
|
|
489
550
|
/**
|
|
490
551
|
* 从localStorage中获取节点,然后添加到当前容器中
|
|
491
|
-
* @param position
|
|
552
|
+
* @param position 粘贴的坐标
|
|
492
553
|
* @returns 添加后的组件节点配置
|
|
493
554
|
*/
|
|
494
|
-
public async paste(position:
|
|
495
|
-
const
|
|
496
|
-
// eslint-disable-next-line prefer-const
|
|
497
|
-
let config: any = {};
|
|
498
|
-
if (!configStr) {
|
|
499
|
-
return;
|
|
500
|
-
}
|
|
555
|
+
public async paste(position: PastePosition = {}): Promise<MNode | MNode[] | void> {
|
|
556
|
+
const config: MNode[] = await storageService.getItem(COPY_STORAGE_KEY);
|
|
501
557
|
|
|
502
|
-
|
|
503
|
-
// eslint-disable-next-line no-eval
|
|
504
|
-
eval(`config = ${configStr}`);
|
|
505
|
-
} catch (e) {
|
|
506
|
-
console.error(e);
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
558
|
+
if (!Array.isArray(config)) return;
|
|
509
559
|
|
|
510
|
-
await
|
|
511
|
-
if (config.style) {
|
|
512
|
-
config.style = {
|
|
513
|
-
...config.style,
|
|
514
|
-
...position,
|
|
515
|
-
};
|
|
516
|
-
}
|
|
560
|
+
const pasteConfigs = await this.doPaste(config, position);
|
|
517
561
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
562
|
+
return this.add(pasteConfigs);
|
|
563
|
+
}
|
|
521
564
|
|
|
522
|
-
|
|
565
|
+
public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
|
|
566
|
+
const pasteConfigs = await beforePaste(position, cloneDeep(config));
|
|
567
|
+
return pasteConfigs;
|
|
523
568
|
}
|
|
524
569
|
|
|
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));
|
|
570
|
+
public async doAlignCenter(config: MNode): Promise<MNode> {
|
|
571
|
+
const parent = this.getParentById(config.id);
|
|
572
|
+
|
|
573
|
+
if (!parent) throw new Error('找不到父节点');
|
|
574
|
+
|
|
575
|
+
const node = cloneDeep(toRaw(config));
|
|
576
|
+
const layout = await this.getLayout(parent, node);
|
|
534
577
|
if (layout === Layout.RELATIVE) {
|
|
535
|
-
return;
|
|
578
|
+
return config;
|
|
536
579
|
}
|
|
537
580
|
|
|
538
|
-
if (!node.style) return;
|
|
581
|
+
if (!node.style) return config;
|
|
539
582
|
|
|
540
583
|
const stage = this.get<StageCore>('stage');
|
|
541
584
|
const doc = stage?.renderer.contentWindow?.document;
|
|
542
585
|
|
|
543
586
|
if (doc) {
|
|
544
|
-
const parentEl = doc.getElementById(`${parent.id}`);
|
|
545
587
|
const el = doc.getElementById(`${node.id}`);
|
|
588
|
+
const parentEl = el?.offsetParent;
|
|
546
589
|
if (parentEl && el) {
|
|
547
590
|
node.style.left = (parentEl.clientWidth - el.clientWidth) / 2;
|
|
548
591
|
}
|
|
@@ -550,15 +593,25 @@ class Editor extends BaseService {
|
|
|
550
593
|
node.style.left = (parent.style.width - node.style.width) / 2;
|
|
551
594
|
}
|
|
552
595
|
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
config: cloneDeep(toRaw(node)),
|
|
556
|
-
root: cloneDeep(this.get<MApp>('root')),
|
|
557
|
-
});
|
|
558
|
-
this.addModifiedNodeId(config.id);
|
|
559
|
-
this.pushHistoryState();
|
|
596
|
+
return node;
|
|
597
|
+
}
|
|
560
598
|
|
|
561
|
-
|
|
599
|
+
/**
|
|
600
|
+
* 将指点节点设置居中
|
|
601
|
+
* @param config 组件节点配置
|
|
602
|
+
* @returns 当前组件节点配置
|
|
603
|
+
*/
|
|
604
|
+
public async alignCenter(config: MNode | MNode[]): Promise<MNode | MNode[]> {
|
|
605
|
+
const nodes = Array.isArray(config) ? config : [config];
|
|
606
|
+
const stage = this.get<StageCore | null>('stage');
|
|
607
|
+
|
|
608
|
+
const newNodes = await Promise.all(nodes.map((node) => this.doAlignCenter(node)));
|
|
609
|
+
|
|
610
|
+
const newNode = await this.update(newNodes);
|
|
611
|
+
|
|
612
|
+
await stage?.multiSelect(newNodes.map((node) => node.id));
|
|
613
|
+
|
|
614
|
+
return newNode;
|
|
562
615
|
}
|
|
563
616
|
|
|
564
617
|
/**
|
|
@@ -567,7 +620,7 @@ class Editor extends BaseService {
|
|
|
567
620
|
*/
|
|
568
621
|
public async moveLayer(offset: number | LayerOffset): Promise<void> {
|
|
569
622
|
const parent = this.get<MContainer>('parent');
|
|
570
|
-
const node = this.get('node');
|
|
623
|
+
const node = this.get<MNode>('node');
|
|
571
624
|
const brothers: MNode[] = parent?.items || [];
|
|
572
625
|
const index = brothers.findIndex((item) => `${item.id}` === `${node?.id}`);
|
|
573
626
|
|
|
@@ -579,10 +632,15 @@ class Editor extends BaseService {
|
|
|
579
632
|
brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);
|
|
580
633
|
}
|
|
581
634
|
|
|
635
|
+
const grandparent = this.getParentById(parent.id);
|
|
582
636
|
this.get<StageCore | null>('stage')?.update({
|
|
583
637
|
config: cloneDeep(toRaw(parent)),
|
|
638
|
+
parentId: grandparent?.id,
|
|
584
639
|
root: cloneDeep(this.get<MApp>('root')),
|
|
585
640
|
});
|
|
641
|
+
|
|
642
|
+
this.addModifiedNodeId(parent.id);
|
|
643
|
+
this.pushHistoryState();
|
|
586
644
|
}
|
|
587
645
|
|
|
588
646
|
/**
|
|
@@ -601,7 +659,7 @@ class Editor extends BaseService {
|
|
|
601
659
|
const index = getNodeIndex(node, parent);
|
|
602
660
|
parent.items?.splice(index, 1);
|
|
603
661
|
|
|
604
|
-
await stage.remove({ id: node.id, root });
|
|
662
|
+
await stage.remove({ id: node.id, parentId: parent.id, root });
|
|
605
663
|
|
|
606
664
|
const layout = await this.getLayout(target);
|
|
607
665
|
|
|
@@ -610,13 +668,14 @@ class Editor extends BaseService {
|
|
|
610
668
|
return srcValue;
|
|
611
669
|
}
|
|
612
670
|
});
|
|
613
|
-
newConfig.style = getInitPositionStyle(newConfig.style, layout
|
|
671
|
+
newConfig.style = getInitPositionStyle(newConfig.style, layout);
|
|
614
672
|
|
|
615
673
|
target.items.push(newConfig);
|
|
616
674
|
|
|
617
675
|
await stage.select(targetId);
|
|
618
676
|
|
|
619
|
-
|
|
677
|
+
const targetParent = this.getParentById(target.id);
|
|
678
|
+
await stage.update({ config: cloneDeep(target), parentId: targetParent?.id, root });
|
|
620
679
|
|
|
621
680
|
await this.select(newConfig);
|
|
622
681
|
stage.select(newConfig.id);
|
|
@@ -653,7 +712,7 @@ class Editor extends BaseService {
|
|
|
653
712
|
const node = toRaw(this.get('node'));
|
|
654
713
|
if (!node || isPage(node)) return;
|
|
655
714
|
|
|
656
|
-
const { style, id } = node;
|
|
715
|
+
const { style, id, type } = node;
|
|
657
716
|
if (!style || style.position !== 'absolute') return;
|
|
658
717
|
|
|
659
718
|
if (top && !isNumber(style.top)) return;
|
|
@@ -661,6 +720,7 @@ class Editor extends BaseService {
|
|
|
661
720
|
|
|
662
721
|
this.update({
|
|
663
722
|
id,
|
|
723
|
+
type,
|
|
664
724
|
style: {
|
|
665
725
|
...style,
|
|
666
726
|
left: Number(style.left) + left,
|
|
@@ -673,6 +733,7 @@ class Editor extends BaseService {
|
|
|
673
733
|
this.removeAllListeners();
|
|
674
734
|
this.set('root', null);
|
|
675
735
|
this.set('node', null);
|
|
736
|
+
this.set('nodes', []);
|
|
676
737
|
this.set('page', null);
|
|
677
738
|
this.set('parent', null);
|
|
678
739
|
}
|
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