@tmagic/editor 1.0.0-beta.1 → 1.0.0-beta.10
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/LICENSE +5432 -0
- package/dist/style.css +53 -24
- package/dist/tmagic-editor.es.js +832 -403
- package/dist/tmagic-editor.es.js.map +1 -1
- package/dist/tmagic-editor.umd.js +849 -403
- package/dist/tmagic-editor.umd.js.map +1 -1
- package/dist/types/src/Editor.vue.d.ts +5 -5
- package/dist/types/src/components/ScrollViewer.vue.d.ts +23 -0
- package/dist/types/src/layouts/CodeEditor.vue.d.ts +5 -4
- package/dist/types/src/layouts/NavMenu.vue.d.ts +2 -1
- package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +10 -3
- package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +8 -3
- package/dist/types/src/layouts/workspace/Stage.vue.d.ts +77 -42
- package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +2 -9
- package/dist/types/src/services/BaseService.d.ts +4 -1
- package/dist/types/src/services/editor.d.ts +11 -4
- package/dist/types/src/services/ui.d.ts +10 -3
- package/dist/types/src/type.d.ts +20 -6
- package/dist/types/src/utils/editor.d.ts +1 -2
- package/dist/types/src/utils/scroll-viewer.d.ts +35 -0
- package/package.json +15 -12
- package/src/Editor.vue +5 -5
- package/src/components/ScrollViewer.vue +66 -0
- package/src/components/ToolButton.vue +5 -3
- package/src/layouts/AddPageBox.vue +3 -1
- package/src/layouts/CodeEditor.vue +35 -59
- package/src/layouts/NavMenu.vue +7 -3
- package/src/layouts/PropsPanel.vue +6 -10
- package/src/layouts/sidebar/LayerMenu.vue +14 -39
- package/src/layouts/sidebar/LayerPanel.vue +63 -16
- package/src/layouts/workspace/PageBar.vue +113 -14
- package/src/layouts/workspace/Stage.vue +67 -61
- package/src/layouts/workspace/ViewerMenu.vue +5 -3
- package/src/layouts/workspace/Workspace.vue +3 -37
- package/src/services/BaseService.ts +70 -22
- package/src/services/editor.ts +98 -52
- package/src/services/ui.ts +42 -5
- package/src/theme/common/var.scss +2 -2
- package/src/theme/layer-panel.scss +9 -0
- package/src/theme/nav-menu.scss +3 -3
- package/src/theme/page-bar.scss +21 -2
- package/src/theme/props-panel.scss +8 -0
- package/src/theme/stage.scss +8 -7
- package/src/type.ts +23 -6
- package/src/utils/editor.ts +5 -23
- package/src/utils/scroll-viewer.ts +216 -0
- package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
package/src/services/editor.ts
CHANGED
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
19
|
import { reactive, toRaw } from 'vue';
|
|
20
|
-
import { cloneDeep } from 'lodash-es';
|
|
20
|
+
import { cloneDeep, mergeWith } from 'lodash-es';
|
|
21
21
|
import serialize from 'serialize-javascript';
|
|
22
22
|
|
|
23
23
|
import type { Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
24
|
+
import { NodeType } from '@tmagic/schema';
|
|
24
25
|
import type StageCore from '@tmagic/stage';
|
|
25
26
|
import { getNodePath, isPop } from '@tmagic/utils';
|
|
26
27
|
|
|
@@ -31,7 +32,6 @@ import { LayerOffset, Layout } from '@editor/type';
|
|
|
31
32
|
import {
|
|
32
33
|
change2Fixed,
|
|
33
34
|
COPY_STORAGE_KEY,
|
|
34
|
-
defaults,
|
|
35
35
|
Fixed2Other,
|
|
36
36
|
getNodeIndex,
|
|
37
37
|
initPosition,
|
|
@@ -52,29 +52,35 @@ class Editor extends BaseService {
|
|
|
52
52
|
parent: null,
|
|
53
53
|
node: null,
|
|
54
54
|
stage: null,
|
|
55
|
+
highlightNode: null,
|
|
55
56
|
modifiedNodeIds: new Map(),
|
|
56
57
|
});
|
|
57
58
|
|
|
58
59
|
constructor() {
|
|
59
|
-
super(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
60
|
+
super(
|
|
61
|
+
[
|
|
62
|
+
'getLayout',
|
|
63
|
+
'select',
|
|
64
|
+
'add',
|
|
65
|
+
'remove',
|
|
66
|
+
'update',
|
|
67
|
+
'sort',
|
|
68
|
+
'copy',
|
|
69
|
+
'paste',
|
|
70
|
+
'alignCenter',
|
|
71
|
+
'moveLayer',
|
|
72
|
+
'undo',
|
|
73
|
+
'redo',
|
|
74
|
+
'highlight',
|
|
75
|
+
],
|
|
76
|
+
// 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
|
|
77
|
+
['select', 'update', 'moveLayer'],
|
|
78
|
+
);
|
|
73
79
|
}
|
|
74
80
|
|
|
75
81
|
/**
|
|
76
82
|
* 设置当前指点节点配置
|
|
77
|
-
* @param name 'root' | 'page' | 'parent' | 'node'
|
|
83
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode'
|
|
78
84
|
* @param value MNode
|
|
79
85
|
* @returns MNode
|
|
80
86
|
*/
|
|
@@ -120,7 +126,7 @@ class Editor extends BaseService {
|
|
|
120
126
|
info.parent = path[path.length - 2] as MContainer;
|
|
121
127
|
|
|
122
128
|
path.forEach((item) => {
|
|
123
|
-
if (item.type ===
|
|
129
|
+
if (item.type === NodeType.PAGE) {
|
|
124
130
|
info.page = item as MPage;
|
|
125
131
|
return;
|
|
126
132
|
}
|
|
@@ -167,24 +173,12 @@ class Editor extends BaseService {
|
|
|
167
173
|
}
|
|
168
174
|
|
|
169
175
|
/**
|
|
170
|
-
*
|
|
171
|
-
* @param config
|
|
176
|
+
* 选中指定节点(将指定节点设置成当前选中状态)
|
|
177
|
+
* @param config 指定节点配置或者ID
|
|
172
178
|
* @returns 当前选中的节点配置
|
|
173
179
|
*/
|
|
174
|
-
public async select(config: MNode | Id): Promise<MNode> {
|
|
175
|
-
|
|
176
|
-
if (typeof config === 'string' || typeof config === 'number') {
|
|
177
|
-
id = config;
|
|
178
|
-
} else {
|
|
179
|
-
id = config.id;
|
|
180
|
-
}
|
|
181
|
-
if (!id) {
|
|
182
|
-
throw new Error('没有ID,无法选中');
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
const { node, parent, page } = this.getNodeInfo(id);
|
|
186
|
-
if (!node) throw new Error('获取不到组件信息');
|
|
187
|
-
|
|
180
|
+
public async select(config: MNode | Id): Promise<MNode> | never {
|
|
181
|
+
const { node, page, parent } = this.selectedConfigExceptionHandler(config);
|
|
188
182
|
this.set('node', node);
|
|
189
183
|
this.set('page', page || null);
|
|
190
184
|
this.set('parent', parent || null);
|
|
@@ -194,8 +188,19 @@ class Editor extends BaseService {
|
|
|
194
188
|
} else {
|
|
195
189
|
historyService.empty();
|
|
196
190
|
}
|
|
191
|
+
return node!;
|
|
192
|
+
}
|
|
197
193
|
|
|
198
|
-
|
|
194
|
+
/**
|
|
195
|
+
* 高亮指定节点
|
|
196
|
+
* @param config 指定节点配置或者ID
|
|
197
|
+
* @returns 当前高亮的节点配置
|
|
198
|
+
*/
|
|
199
|
+
public highlight(config: MNode | Id): void {
|
|
200
|
+
const { node } = this.selectedConfigExceptionHandler(config);
|
|
201
|
+
const currentHighlightNode = this.get('highlightNode');
|
|
202
|
+
if (currentHighlightNode === node) return;
|
|
203
|
+
this.set('highlightNode', node);
|
|
199
204
|
}
|
|
200
205
|
|
|
201
206
|
/**
|
|
@@ -209,7 +214,7 @@ class Editor extends BaseService {
|
|
|
209
214
|
|
|
210
215
|
let parentNode: MNode | undefined;
|
|
211
216
|
|
|
212
|
-
if (type ===
|
|
217
|
+
if (type === NodeType.PAGE) {
|
|
213
218
|
parentNode = this.get<MApp>('root');
|
|
214
219
|
// 由于支持中间件扩展,在parent参数为undefined时,parent会变成next函数
|
|
215
220
|
} else if (parent && typeof parent !== 'function') {
|
|
@@ -225,18 +230,24 @@ class Editor extends BaseService {
|
|
|
225
230
|
const layout = await this.getLayout(parentNode);
|
|
226
231
|
const newNode = initPosition({ ...toRaw(await propsService.getPropsValue(type)), ...config }, layout);
|
|
227
232
|
|
|
228
|
-
if ((parentNode?.type ===
|
|
233
|
+
if ((parentNode?.type === NodeType.ROOT || curNode.type === NodeType.ROOT) && newNode.type !== NodeType.PAGE) {
|
|
229
234
|
throw new Error('app下不能添加组件');
|
|
230
235
|
}
|
|
231
236
|
|
|
232
237
|
parentNode?.items?.push(newNode);
|
|
233
238
|
|
|
234
|
-
|
|
239
|
+
const stage = this.get<StageCore | null>('stage');
|
|
240
|
+
|
|
241
|
+
await stage?.add({ config: cloneDeep(newNode), root: cloneDeep(this.get('root')) });
|
|
235
242
|
|
|
236
243
|
await this.select(newNode);
|
|
237
244
|
|
|
238
245
|
this.addModifiedNodeId(newNode.id);
|
|
239
|
-
|
|
246
|
+
if (type !== NodeType.PAGE) {
|
|
247
|
+
this.pushHistoryState();
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
stage?.select(newNode.id);
|
|
240
251
|
|
|
241
252
|
return newNode;
|
|
242
253
|
}
|
|
@@ -262,12 +273,17 @@ class Editor extends BaseService {
|
|
|
262
273
|
if (typeof index !== 'number' || index === -1) throw new Error('找不要删除的节点');
|
|
263
274
|
|
|
264
275
|
parent.items?.splice(index, 1);
|
|
265
|
-
this.get<StageCore>('stage')
|
|
276
|
+
const stage = this.get<StageCore | null>('stage');
|
|
277
|
+
stage?.remove({ id: node.id, root: this.get('root') });
|
|
266
278
|
|
|
267
|
-
if (node.type ===
|
|
268
|
-
|
|
279
|
+
if (node.type === NodeType.PAGE) {
|
|
280
|
+
if (root.items[0]) {
|
|
281
|
+
await this.select(root.items[0]);
|
|
282
|
+
stage?.select(root.items[0].id);
|
|
283
|
+
}
|
|
269
284
|
} else {
|
|
270
285
|
await this.select(parent);
|
|
286
|
+
stage?.select(parent.id);
|
|
271
287
|
}
|
|
272
288
|
|
|
273
289
|
this.addModifiedNodeId(parent.id);
|
|
@@ -289,20 +305,25 @@ class Editor extends BaseService {
|
|
|
289
305
|
if (!info.node) throw new Error(`获取不到id为${config.id}的节点`);
|
|
290
306
|
|
|
291
307
|
const node = cloneDeep(toRaw(info.node));
|
|
292
|
-
const { parent } = info;
|
|
293
|
-
if (!parent) throw new Error('获取不到父级节点');
|
|
294
308
|
|
|
295
309
|
let newConfig = await this.toggleFixedPosition(toRaw(config), node, this.get<MApp>('root'));
|
|
296
310
|
|
|
297
|
-
|
|
311
|
+
newConfig = mergeWith(cloneDeep(node), newConfig, (objValue, srcValue) => {
|
|
312
|
+
if (Array.isArray(srcValue)) {
|
|
313
|
+
return srcValue;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
298
316
|
|
|
299
317
|
if (!newConfig.type) throw new Error('配置缺少type值');
|
|
300
318
|
|
|
301
|
-
if (newConfig.type ===
|
|
319
|
+
if (newConfig.type === NodeType.ROOT) {
|
|
302
320
|
this.set('root', newConfig);
|
|
303
321
|
return newConfig;
|
|
304
322
|
}
|
|
305
323
|
|
|
324
|
+
const { parent } = info;
|
|
325
|
+
if (!parent) throw new Error('获取不到父级节点');
|
|
326
|
+
|
|
306
327
|
const parentNodeItems = parent.items;
|
|
307
328
|
const index = getNodeIndex(newConfig, parent);
|
|
308
329
|
|
|
@@ -316,13 +337,12 @@ class Editor extends BaseService {
|
|
|
316
337
|
|
|
317
338
|
parentNodeItems[index] = newConfig;
|
|
318
339
|
|
|
319
|
-
if (newConfig.id === this.get('node').id) {
|
|
340
|
+
if (`${newConfig.id}` === `${this.get('node').id}`) {
|
|
320
341
|
this.set('node', newConfig);
|
|
342
|
+
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(newConfig), root: this.get('root') });
|
|
321
343
|
}
|
|
322
344
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
if (newConfig.type === 'page') {
|
|
345
|
+
if (newConfig.type === NodeType.PAGE) {
|
|
326
346
|
this.set('page', newConfig);
|
|
327
347
|
}
|
|
328
348
|
|
|
@@ -351,6 +371,8 @@ class Editor extends BaseService {
|
|
|
351
371
|
await this.update(parent);
|
|
352
372
|
await this.select(node);
|
|
353
373
|
|
|
374
|
+
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(node), root: this.get('root') });
|
|
375
|
+
|
|
354
376
|
this.addModifiedNodeId(parent.id);
|
|
355
377
|
this.pushHistoryState();
|
|
356
378
|
}
|
|
@@ -414,7 +436,7 @@ class Editor extends BaseService {
|
|
|
414
436
|
}
|
|
415
437
|
|
|
416
438
|
await this.update(node);
|
|
417
|
-
this.get<StageCore>('stage')?.update({ config: cloneDeep(toRaw(node)), root: this.get('root') });
|
|
439
|
+
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(toRaw(node)), root: this.get('root') });
|
|
418
440
|
this.addModifiedNodeId(config.id);
|
|
419
441
|
this.pushHistoryState();
|
|
420
442
|
|
|
@@ -439,7 +461,7 @@ class Editor extends BaseService {
|
|
|
439
461
|
brothers.splice(index + parseInt(`${offset}`, 10), 0, brothers.splice(index, 1)[0]);
|
|
440
462
|
}
|
|
441
463
|
|
|
442
|
-
this.get<StageCore>('stage')?.update({ config: cloneDeep(toRaw(parent)), root: this.get('root') });
|
|
464
|
+
this.get<StageCore | null>('stage')?.update({ config: cloneDeep(toRaw(parent)), root: this.get('root') });
|
|
443
465
|
}
|
|
444
466
|
|
|
445
467
|
/**
|
|
@@ -514,6 +536,30 @@ class Editor extends BaseService {
|
|
|
514
536
|
|
|
515
537
|
return newConfig;
|
|
516
538
|
}
|
|
539
|
+
|
|
540
|
+
private selectedConfigExceptionHandler(config: MNode | Id): EditorNodeInfo {
|
|
541
|
+
let id: Id;
|
|
542
|
+
if (typeof config === 'string' || typeof config === 'number') {
|
|
543
|
+
id = config;
|
|
544
|
+
} else {
|
|
545
|
+
id = config.id;
|
|
546
|
+
}
|
|
547
|
+
if (!id) {
|
|
548
|
+
throw new Error('没有ID,无法选中');
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
const { node, parent, page } = this.getNodeInfo(id);
|
|
552
|
+
if (!node) throw new Error('获取不到组件信息');
|
|
553
|
+
|
|
554
|
+
if (node.id === this.state.root?.id) {
|
|
555
|
+
throw new Error('不能选根节点');
|
|
556
|
+
}
|
|
557
|
+
return {
|
|
558
|
+
node,
|
|
559
|
+
parent,
|
|
560
|
+
page,
|
|
561
|
+
};
|
|
562
|
+
}
|
|
517
563
|
}
|
|
518
564
|
|
|
519
565
|
export type EditorService = Editor;
|
package/src/services/ui.ts
CHANGED
|
@@ -21,19 +21,29 @@ import { reactive, toRaw } from 'vue';
|
|
|
21
21
|
import type StageCore from '@tmagic/stage';
|
|
22
22
|
|
|
23
23
|
import editorService from '@editor/services/editor';
|
|
24
|
-
import { GetColumnWidth, SetColumnWidth, UiState } from '@editor/type';
|
|
24
|
+
import type { GetColumnWidth, SetColumnWidth, StageRect, UiState } from '@editor/type';
|
|
25
25
|
|
|
26
26
|
import BaseService from './BaseService';
|
|
27
27
|
|
|
28
|
+
const DEFAULT_LEFT_COLUMN_WIDTH = 310;
|
|
29
|
+
const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
30
|
+
|
|
28
31
|
const state = reactive<UiState>({
|
|
29
32
|
uiSelectMode: false,
|
|
30
33
|
showSrc: false,
|
|
31
34
|
zoom: 1,
|
|
32
|
-
|
|
35
|
+
stageContainerRect: {
|
|
36
|
+
width: 0,
|
|
37
|
+
height: 0,
|
|
38
|
+
},
|
|
39
|
+
stageRect: {
|
|
40
|
+
width: 375,
|
|
41
|
+
height: 817,
|
|
42
|
+
},
|
|
33
43
|
columnWidth: {
|
|
34
|
-
left:
|
|
35
|
-
center: globalThis.document.body.clientWidth -
|
|
36
|
-
right:
|
|
44
|
+
left: DEFAULT_LEFT_COLUMN_WIDTH,
|
|
45
|
+
center: globalThis.document.body.clientWidth - DEFAULT_LEFT_COLUMN_WIDTH - DEFAULT_RIGHT_COLUMN_WIDTH,
|
|
46
|
+
right: DEFAULT_RIGHT_COLUMN_WIDTH,
|
|
37
47
|
},
|
|
38
48
|
showGuides: true,
|
|
39
49
|
showRule: true,
|
|
@@ -57,6 +67,11 @@ class Ui extends BaseService {
|
|
|
57
67
|
return;
|
|
58
68
|
}
|
|
59
69
|
|
|
70
|
+
if (name === 'stageRect') {
|
|
71
|
+
this.setStageRect(value as unknown as StageRect);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
if (name === 'showGuides') {
|
|
61
76
|
mask?.showGuides(value as unknown as boolean);
|
|
62
77
|
}
|
|
@@ -66,6 +81,10 @@ class Ui extends BaseService {
|
|
|
66
81
|
}
|
|
67
82
|
|
|
68
83
|
(state as any)[name] = value;
|
|
84
|
+
|
|
85
|
+
if (name === 'stageContainerRect') {
|
|
86
|
+
state.zoom = this.calcZoom();
|
|
87
|
+
}
|
|
69
88
|
}
|
|
70
89
|
|
|
71
90
|
public get<T>(name: keyof typeof state): T {
|
|
@@ -94,6 +113,24 @@ class Ui extends BaseService {
|
|
|
94
113
|
|
|
95
114
|
state.columnWidth = columnWidth;
|
|
96
115
|
}
|
|
116
|
+
|
|
117
|
+
private setStageRect(value: StageRect) {
|
|
118
|
+
state.stageRect = {
|
|
119
|
+
...state.stageRect,
|
|
120
|
+
...value,
|
|
121
|
+
};
|
|
122
|
+
state.zoom = this.calcZoom();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
private calcZoom() {
|
|
126
|
+
const { stageRect, stageContainerRect } = state;
|
|
127
|
+
const { height, width } = stageContainerRect;
|
|
128
|
+
if (!width || !height) return 1;
|
|
129
|
+
if (width > stageRect.width && height > stageRect.height) {
|
|
130
|
+
return 1;
|
|
131
|
+
}
|
|
132
|
+
return Math.min((width - 100) / stageRect.width || 1, (height - 100) / stageRect.height || 1);
|
|
133
|
+
}
|
|
97
134
|
}
|
|
98
135
|
|
|
99
136
|
export type UiService = Ui;
|
|
@@ -5,9 +5,9 @@ $--border-color: #d9dbdd;
|
|
|
5
5
|
|
|
6
6
|
$--nav-height: 35px;
|
|
7
7
|
$--nav-color: #070303;
|
|
8
|
-
$--nav--background-color: #
|
|
8
|
+
$--nav--background-color: #ffffff;
|
|
9
9
|
|
|
10
10
|
$--sidebar-heder-background-color: $--theme-color;
|
|
11
|
-
$--sidebar-content-background-color: #
|
|
11
|
+
$--sidebar-content-background-color: #ffffff;
|
|
12
12
|
|
|
13
13
|
$--page-bar-height: 32px;
|
|
@@ -50,6 +50,15 @@
|
|
|
50
50
|
color: #fff;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
.magic-editor-layer-panel .cus-tree-node {
|
|
54
|
+
width: 100%;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.magic-editor-layer-panel .cus-tree-node-hover {
|
|
58
|
+
background-color: #f3f5f9;
|
|
59
|
+
width: 100%;
|
|
60
|
+
}
|
|
61
|
+
|
|
53
62
|
.magic-editor-layer-panel .el-tree-node:focus > .el-tree-node__content {
|
|
54
63
|
background-color: $--sidebar-heder-background-color;
|
|
55
64
|
color: #fff;
|
package/src/theme/nav-menu.scss
CHANGED
package/src/theme/page-bar.scss
CHANGED
|
@@ -6,18 +6,25 @@
|
|
|
6
6
|
width: 100%;
|
|
7
7
|
height: $--page-bar-height;
|
|
8
8
|
line-height: $--page-bar-height;
|
|
9
|
-
background-color: #f3f3f3;
|
|
10
9
|
color: $--font-color;
|
|
10
|
+
background-color: #f3f3f3;
|
|
11
11
|
border-top: 1px solid $--border-color;
|
|
12
12
|
z-index: 2;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
|
|
15
|
+
&-items {
|
|
16
|
+
display: flex;
|
|
17
|
+
transition: transform 0.3s;
|
|
18
|
+
}
|
|
13
19
|
|
|
14
|
-
|
|
20
|
+
&-item {
|
|
15
21
|
padding: 0 10px;
|
|
16
22
|
cursor: pointer;
|
|
17
23
|
border-right: 1px solid $--border-color;
|
|
18
24
|
display: flex;
|
|
19
25
|
justify-items: center;
|
|
20
26
|
align-items: center;
|
|
27
|
+
background-color: #f3f3f3;
|
|
21
28
|
|
|
22
29
|
&.active {
|
|
23
30
|
background-color: #fff;
|
|
@@ -27,5 +34,17 @@
|
|
|
27
34
|
cursor: pointer;
|
|
28
35
|
}
|
|
29
36
|
}
|
|
37
|
+
|
|
38
|
+
&-icon {
|
|
39
|
+
position: relative;
|
|
40
|
+
z-index: 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.m-editor-page-bar-title {
|
|
44
|
+
max-width: 150px;
|
|
45
|
+
text-overflow: ellipsis;
|
|
46
|
+
white-space: nowrap;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
}
|
|
30
49
|
}
|
|
31
50
|
}
|
package/src/theme/stage.scss
CHANGED
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
position: relative;
|
|
3
3
|
width: 100%;
|
|
4
4
|
height: calc(100% - $--page-bar-height);
|
|
5
|
-
overflow:
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
display: flex;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
align-items: center;
|
|
6
9
|
}
|
|
7
10
|
|
|
8
11
|
.m-editor-stage-container {
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
width: 100%;
|
|
13
|
+
height: 100%;
|
|
11
14
|
z-index: 0;
|
|
12
|
-
top: 50%;
|
|
13
|
-
margin: 0 auto;
|
|
14
15
|
position: relative;
|
|
15
|
-
width: 375px;
|
|
16
|
-
height: 80%;
|
|
17
16
|
border: 1px solid $--border-color;
|
|
17
|
+
transition: transform 0.3s;
|
|
18
|
+
box-sizing: content-box;
|
|
18
19
|
|
|
19
20
|
&::-webkit-scrollbar {
|
|
20
21
|
width: 0 !important;
|
package/src/type.ts
CHANGED
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import { Component } from 'vue';
|
|
19
|
+
import type { Component } from 'vue';
|
|
20
20
|
|
|
21
|
-
import { FormConfig } from '@tmagic/form';
|
|
22
|
-
import { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
23
|
-
import StageCore from '@tmagic/stage';
|
|
21
|
+
import type { FormConfig } from '@tmagic/form';
|
|
22
|
+
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
23
|
+
import type StageCore from '@tmagic/stage';
|
|
24
24
|
|
|
25
25
|
import type { ComponentListService } from '@editor/services/componentList';
|
|
26
26
|
import type { EditorService } from '@editor/services/editor';
|
|
@@ -50,6 +50,7 @@ export interface StoreState {
|
|
|
50
50
|
page: MPage | null;
|
|
51
51
|
parent: MContainer | null;
|
|
52
52
|
node: MNode | null;
|
|
53
|
+
highlightNode: MNode | null;
|
|
53
54
|
stage: StageCore | null;
|
|
54
55
|
modifiedNodeIds: Map<Id, Id>;
|
|
55
56
|
}
|
|
@@ -75,6 +76,11 @@ export interface GetColumnWidth {
|
|
|
75
76
|
right: number;
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
export interface StageRect {
|
|
80
|
+
width: number;
|
|
81
|
+
height: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
78
84
|
export interface UiState {
|
|
79
85
|
/** 当前点击画布是否触发选中,true: 不触发,false: 触发,默认为false */
|
|
80
86
|
uiSelectMode: boolean;
|
|
@@ -82,8 +88,10 @@ export interface UiState {
|
|
|
82
88
|
showSrc: boolean;
|
|
83
89
|
/** 画布显示放大倍数,默认为 1 */
|
|
84
90
|
zoom: number;
|
|
85
|
-
/**
|
|
86
|
-
|
|
91
|
+
/** 画布容器的宽高 */
|
|
92
|
+
stageContainerRect: StageRect;
|
|
93
|
+
/** 画布顶层div的宽高,可用于改变画布的大小 */
|
|
94
|
+
stageRect: StageRect;
|
|
87
95
|
/** 编辑器列布局每一列的宽度,分为左中右三列 */
|
|
88
96
|
columnWidth: GetColumnWidth;
|
|
89
97
|
/** 是否显示画布参考线,true: 显示,false: 不显示,默认为true */
|
|
@@ -222,6 +230,11 @@ export interface ComponentGroup {
|
|
|
222
230
|
items: ComponentItem[];
|
|
223
231
|
}
|
|
224
232
|
|
|
233
|
+
export interface UpdateData {
|
|
234
|
+
id: Id;
|
|
235
|
+
[key: string]: any;
|
|
236
|
+
}
|
|
237
|
+
|
|
225
238
|
export enum LayerOffset {
|
|
226
239
|
TOP = 'top',
|
|
227
240
|
BOTTOM = 'bottom',
|
|
@@ -234,3 +247,7 @@ export enum Layout {
|
|
|
234
247
|
RELATIVE = 'relative',
|
|
235
248
|
ABSOLUTE = 'absolute',
|
|
236
249
|
}
|
|
250
|
+
|
|
251
|
+
export enum Keys {
|
|
252
|
+
ESCAPE = 'Space',
|
|
253
|
+
}
|
package/src/utils/editor.ts
CHANGED
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
import {
|
|
19
|
+
import { random } from 'lodash-es';
|
|
20
20
|
|
|
21
|
-
import { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
21
|
+
import type { Id, MApp, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
22
|
+
import { NodeType } from '@tmagic/schema';
|
|
22
23
|
import { getNodePath, isPop } from '@tmagic/utils';
|
|
23
24
|
|
|
24
25
|
import { Layout } from '@editor/type';
|
|
@@ -34,7 +35,7 @@ export const generateId = (type: string | number): string => `${type}_${random(1
|
|
|
34
35
|
*/
|
|
35
36
|
export const getPageList = (app: MApp): MPage[] => {
|
|
36
37
|
if (app.items && Array.isArray(app.items)) {
|
|
37
|
-
return app.items.filter((item: MPage) => item.type ===
|
|
38
|
+
return app.items.filter((item: MPage) => item.type === NodeType.PAGE);
|
|
38
39
|
}
|
|
39
40
|
return [];
|
|
40
41
|
};
|
|
@@ -108,7 +109,7 @@ export const setNewItemId = (config: MNode, parent?: MPage) => {
|
|
|
108
109
|
config.name = `${config.name?.replace(/_(\d+)$/, '')}_${config.id}`;
|
|
109
110
|
|
|
110
111
|
// 只有弹窗在页面下的一级子元素才有效
|
|
111
|
-
if (isPop(config) && parent?.type ===
|
|
112
|
+
if (isPop(config) && parent?.type === NodeType.PAGE) {
|
|
112
113
|
updatePopId(oldId, config.id, parent);
|
|
113
114
|
}
|
|
114
115
|
|
|
@@ -223,22 +224,3 @@ export const Fixed2Other = async (node: MNode, root: MApp, getLayout: (node: MNo
|
|
|
223
224
|
|
|
224
225
|
return toRelative(node);
|
|
225
226
|
};
|
|
226
|
-
|
|
227
|
-
export const defaults = (object: any, source: any) => {
|
|
228
|
-
let o = source;
|
|
229
|
-
if (Array.isArray(object)) {
|
|
230
|
-
o = object;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
Object.entries(o).forEach(([key, value]: [string, any]) => {
|
|
234
|
-
if (typeof object[key] === 'undefined') {
|
|
235
|
-
object[key] = value;
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (value && typeof value !== 'string' && Object.keys(value).length) {
|
|
240
|
-
object[key] = defaults(cloneDeep(object[key]), value);
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
return object;
|
|
244
|
-
};
|