@tmagic/editor 1.3.6 → 1.3.8
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 +34 -11
- package/dist/tmagic-editor.js +1360 -957
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +1382 -977
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +17 -17
- package/src/Editor.vue +15 -7
- package/src/components/CodeBlockEditor.vue +2 -2
- package/src/components/ContentMenu.vue +5 -5
- package/src/components/ScrollBar.vue +2 -2
- package/src/components/ScrollViewer.vue +2 -2
- package/src/components/SplitView.vue +2 -2
- package/src/components/Tree.vue +1 -1
- package/src/components/TreeNode.vue +3 -3
- package/src/editorProps.ts +14 -4
- package/src/fields/PageFragmentSelect.vue +63 -0
- package/src/hooks/use-getso.ts +2 -2
- package/src/hooks/use-stage.ts +18 -1
- package/src/index.ts +3 -0
- package/src/initService.ts +15 -5
- package/src/layouts/AddPageBox.vue +16 -4
- package/src/layouts/CodeEditor.vue +2 -2
- package/src/layouts/Framework.vue +19 -3
- package/src/layouts/PropsPanel.vue +9 -7
- package/src/layouts/page-bar/AddButton.vue +48 -0
- package/src/layouts/page-bar/PageBar.vue +158 -0
- package/src/layouts/{workspace → page-bar}/PageBarScrollContainer.vue +61 -35
- package/src/layouts/page-bar/SwitchTypeButton.vue +45 -0
- package/src/layouts/sidebar/Sidebar.vue +2 -0
- package/src/layouts/sidebar/layer/LayerMenu.vue +39 -27
- package/src/layouts/sidebar/layer/LayerPanel.vue +7 -1
- package/src/layouts/sidebar/layer/use-click.ts +5 -3
- package/src/layouts/sidebar/layer/use-keybinding.ts +8 -8
- package/src/layouts/sidebar/layer/use-node-status.ts +3 -3
- package/src/layouts/workspace/Workspace.vue +6 -7
- package/src/layouts/workspace/viewer/NodeListMenu.vue +2 -2
- package/src/layouts/workspace/viewer/Stage.vue +12 -5
- package/src/layouts/workspace/viewer/ViewerMenu.vue +93 -80
- package/src/services/dataSource.ts +17 -0
- package/src/services/dep.ts +4 -0
- package/src/services/editor.ts +66 -35
- package/src/services/history.ts +6 -2
- package/src/services/keybinding.ts +48 -13
- package/src/theme/code-block.scss +0 -16
- package/src/theme/page-bar.scss +18 -1
- package/src/theme/page-fragment-select.scss +14 -0
- package/src/theme/theme.scss +1 -0
- package/src/theme/tree.scss +6 -0
- package/src/type.ts +23 -7
- package/src/utils/content-menu.ts +2 -2
- package/src/utils/editor.ts +22 -15
- package/src/utils/operator.ts +4 -4
- package/types/components/ToolButton.vue.d.ts +2 -2
- package/types/editorProps.d.ts +11 -2
- package/types/fields/PageFragmentSelect.vue.d.ts +31 -0
- package/types/index.d.ts +1 -0
- package/types/layouts/AddPageBox.vue.d.ts +14 -1
- package/types/layouts/Framework.vue.d.ts +14 -1
- package/types/layouts/PropsPanel.vue.d.ts +19 -10
- package/types/layouts/page-bar/AddButton.vue.d.ts +16 -0
- package/types/layouts/page-bar/PageBar.vue.d.ts +28 -0
- package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +24 -0
- package/types/layouts/page-bar/SwitchTypeButton.vue.d.ts +20 -0
- package/types/layouts/sidebar/Sidebar.vue.d.ts +2 -0
- package/types/layouts/sidebar/layer/LayerMenu.vue.d.ts +22 -3
- package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +2 -0
- package/types/layouts/sidebar/layer/use-click.d.ts +25 -3
- package/types/layouts/sidebar/layer/use-keybinding.d.ts +1 -1
- package/types/layouts/workspace/Workspace.vue.d.ts +2 -0
- package/types/layouts/workspace/viewer/Stage.vue.d.ts +2 -0
- package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +8 -0
- package/types/services/dataSource.d.ts +2 -0
- package/types/services/dep.d.ts +1 -0
- package/types/services/editor.d.ts +3 -2
- package/types/services/history.d.ts +3 -2
- package/types/services/keybinding.d.ts +21 -1
- package/types/type.d.ts +26 -12
- package/types/utils/editor.d.ts +9 -7
- package/src/layouts/workspace/PageBar.vue +0 -87
- package/types/layouts/workspace/PageBar.vue.d.ts +0 -15
- package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +0 -9
|
@@ -3,15 +3,14 @@
|
|
|
3
3
|
<Breadcrumb></Breadcrumb>
|
|
4
4
|
|
|
5
5
|
<slot name="stage">
|
|
6
|
-
<MagicStage
|
|
6
|
+
<MagicStage
|
|
7
|
+
v-if="page"
|
|
8
|
+
:stage-content-menu="stageContentMenu"
|
|
9
|
+
:custom-content-menu="customContentMenu"
|
|
10
|
+
></MagicStage>
|
|
7
11
|
</slot>
|
|
8
12
|
|
|
9
13
|
<slot name="workspace-content"></slot>
|
|
10
|
-
|
|
11
|
-
<PageBar>
|
|
12
|
-
<template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
|
|
13
|
-
<template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
|
|
14
|
-
</PageBar>
|
|
15
14
|
</div>
|
|
16
15
|
</template>
|
|
17
16
|
|
|
@@ -22,7 +21,6 @@ import type { MenuButton, MenuComponent, Services, WorkspaceSlots } from '@edito
|
|
|
22
21
|
|
|
23
22
|
import MagicStage from './viewer/Stage.vue';
|
|
24
23
|
import Breadcrumb from './Breadcrumb.vue';
|
|
25
|
-
import PageBar from './PageBar.vue';
|
|
26
24
|
|
|
27
25
|
defineSlots<WorkspaceSlots>();
|
|
28
26
|
|
|
@@ -32,6 +30,7 @@ defineOptions({
|
|
|
32
30
|
|
|
33
31
|
defineProps<{
|
|
34
32
|
stageContentMenu: (MenuButton | MenuComponent)[];
|
|
33
|
+
customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
|
|
35
34
|
}>();
|
|
36
35
|
|
|
37
36
|
const services = inject<Services>('services');
|
|
@@ -56,6 +56,8 @@ const unWatch = watch(
|
|
|
56
56
|
(stage) => {
|
|
57
57
|
if (!stage) return;
|
|
58
58
|
|
|
59
|
+
nextTick(() => unWatch());
|
|
60
|
+
|
|
59
61
|
stage.on('select', (el: HTMLElement, event: MouseEvent) => {
|
|
60
62
|
const els = stage.renderer.getElementsFromPoint(event) || [];
|
|
61
63
|
const ids = els.map((el) => el.id).filter((id) => Boolean(id));
|
|
@@ -64,8 +66,6 @@ const unWatch = watch(
|
|
|
64
66
|
|
|
65
67
|
filterTextChangeHandler(ids);
|
|
66
68
|
});
|
|
67
|
-
|
|
68
|
-
unWatch();
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
immediate: true,
|
|
@@ -25,13 +25,18 @@
|
|
|
25
25
|
<NodeListMenu></NodeListMenu>
|
|
26
26
|
|
|
27
27
|
<Teleport to="body">
|
|
28
|
-
<ViewerMenu
|
|
28
|
+
<ViewerMenu
|
|
29
|
+
ref="menu"
|
|
30
|
+
:is-multi-select="isMultiSelect"
|
|
31
|
+
:stage-content-menu="stageContentMenu"
|
|
32
|
+
:custom-content-menu="customContentMenu"
|
|
33
|
+
></ViewerMenu>
|
|
29
34
|
</Teleport>
|
|
30
35
|
</ScrollViewer>
|
|
31
36
|
</template>
|
|
32
37
|
|
|
33
38
|
<script lang="ts" setup>
|
|
34
|
-
import { computed, inject, markRaw, nextTick,
|
|
39
|
+
import { computed, inject, markRaw, nextTick, onBeforeUnmount, onMounted, ref, toRaw, watch, watchEffect } from 'vue';
|
|
35
40
|
import { cloneDeep } from 'lodash-es';
|
|
36
41
|
|
|
37
42
|
import type { MApp, MContainer } from '@tmagic/schema';
|
|
@@ -52,6 +57,7 @@ defineOptions({
|
|
|
52
57
|
|
|
53
58
|
defineProps<{
|
|
54
59
|
stageContentMenu: (MenuButton | MenuComponent)[];
|
|
60
|
+
customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
|
|
55
61
|
}>();
|
|
56
62
|
|
|
57
63
|
let stage: StageCore | null = null;
|
|
@@ -108,6 +114,7 @@ watch(zoom, (zoom) => {
|
|
|
108
114
|
|
|
109
115
|
watch(page, (page) => {
|
|
110
116
|
if (runtime && page) {
|
|
117
|
+
services?.editorService.set('stageLoading', true);
|
|
111
118
|
runtime.updatePageId?.(page.id);
|
|
112
119
|
nextTick(() => {
|
|
113
120
|
stage?.select(page.id);
|
|
@@ -135,15 +142,15 @@ const resizeObserver = new ResizeObserver((entries) => {
|
|
|
135
142
|
onMounted(() => {
|
|
136
143
|
if (stageWrap.value?.container) {
|
|
137
144
|
resizeObserver.observe(stageWrap.value.container);
|
|
138
|
-
services?.keybindingService.
|
|
145
|
+
services?.keybindingService.registerEl(KeyBindingContainerKey.STAGE, stageWrap.value.container);
|
|
139
146
|
}
|
|
140
147
|
});
|
|
141
148
|
|
|
142
|
-
|
|
149
|
+
onBeforeUnmount(() => {
|
|
143
150
|
stage?.destroy();
|
|
144
151
|
resizeObserver.disconnect();
|
|
145
152
|
services?.editorService.set('stage', null);
|
|
146
|
-
services?.keybindingService.
|
|
153
|
+
services?.keybindingService.unregisterEl('stage');
|
|
147
154
|
services?.editorService.off('root-change', rootChangeHandler);
|
|
148
155
|
});
|
|
149
156
|
|
|
@@ -7,7 +7,7 @@ import { computed, inject, markRaw, ref, watch } from 'vue';
|
|
|
7
7
|
import { Bottom, Top } from '@element-plus/icons-vue';
|
|
8
8
|
|
|
9
9
|
import { NodeType } from '@tmagic/schema';
|
|
10
|
-
import { isPage } from '@tmagic/utils';
|
|
10
|
+
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
11
11
|
|
|
12
12
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
13
13
|
import CenterIcon from '@editor/icons/CenterIcon.vue';
|
|
@@ -19,8 +19,16 @@ defineOptions({
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
const props = withDefaults(
|
|
22
|
-
defineProps<{
|
|
23
|
-
|
|
22
|
+
defineProps<{
|
|
23
|
+
isMultiSelect?: boolean;
|
|
24
|
+
stageContentMenu: (MenuButton | MenuComponent)[];
|
|
25
|
+
customContentMenu?: (menus: (MenuButton | MenuComponent)[], type: string) => (MenuButton | MenuComponent)[];
|
|
26
|
+
}>(),
|
|
27
|
+
{
|
|
28
|
+
isMultiSelect: false,
|
|
29
|
+
stageContentMenu: () => [],
|
|
30
|
+
customContentMenu: (menus: (MenuButton | MenuComponent)[]) => menus,
|
|
31
|
+
},
|
|
24
32
|
);
|
|
25
33
|
|
|
26
34
|
const services = inject<Services>('services');
|
|
@@ -32,83 +40,88 @@ const node = computed(() => editorService?.get('node'));
|
|
|
32
40
|
const nodes = computed(() => editorService?.get('nodes'));
|
|
33
41
|
const parent = computed(() => editorService?.get('parent'));
|
|
34
42
|
|
|
35
|
-
const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
43
|
+
const menuData = computed<(MenuButton | MenuComponent)[]>(() =>
|
|
44
|
+
props.customContentMenu(
|
|
45
|
+
[
|
|
46
|
+
{
|
|
47
|
+
type: 'button',
|
|
48
|
+
text: '水平居中',
|
|
49
|
+
icon: markRaw(CenterIcon),
|
|
50
|
+
display: () => canCenter.value,
|
|
51
|
+
handler: () => {
|
|
52
|
+
if (!nodes.value) return;
|
|
53
|
+
editorService?.alignCenter(nodes.value);
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
useCopyMenu(),
|
|
57
|
+
usePasteMenu(menu),
|
|
58
|
+
{
|
|
59
|
+
type: 'divider',
|
|
60
|
+
direction: 'horizontal',
|
|
61
|
+
display: () => {
|
|
62
|
+
if (!node.value) return false;
|
|
63
|
+
return !isPage(node.value) && !isPageFragment(node.value);
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: 'button',
|
|
68
|
+
text: '上移一层',
|
|
69
|
+
icon: markRaw(Top),
|
|
70
|
+
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
71
|
+
handler: () => {
|
|
72
|
+
editorService?.moveLayer(1);
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: 'button',
|
|
77
|
+
text: '下移一层',
|
|
78
|
+
icon: markRaw(Bottom),
|
|
79
|
+
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
80
|
+
handler: () => {
|
|
81
|
+
editorService?.moveLayer(-1);
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
type: 'button',
|
|
86
|
+
text: '置顶',
|
|
87
|
+
icon: markRaw(Top),
|
|
88
|
+
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
89
|
+
handler: () => {
|
|
90
|
+
editorService?.moveLayer(LayerOffset.TOP);
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
type: 'button',
|
|
95
|
+
text: '置底',
|
|
96
|
+
icon: markRaw(Bottom),
|
|
97
|
+
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
98
|
+
handler: () => {
|
|
99
|
+
editorService?.moveLayer(LayerOffset.BOTTOM);
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
useMoveToMenu(services),
|
|
103
|
+
{
|
|
104
|
+
type: 'divider',
|
|
105
|
+
direction: 'horizontal',
|
|
106
|
+
display: () => !isPage(node.value) && !isPageFragment(node.value) && !props.isMultiSelect,
|
|
107
|
+
},
|
|
108
|
+
useDeleteMenu(),
|
|
109
|
+
{
|
|
110
|
+
type: 'divider',
|
|
111
|
+
direction: 'horizontal',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: 'button',
|
|
115
|
+
text: '清空参考线',
|
|
116
|
+
handler: () => {
|
|
117
|
+
editorService?.get('stage')?.clearGuides();
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
...props.stageContentMenu,
|
|
121
|
+
],
|
|
122
|
+
'viewer',
|
|
123
|
+
),
|
|
124
|
+
);
|
|
112
125
|
|
|
113
126
|
watch(
|
|
114
127
|
parent,
|
|
@@ -33,6 +33,23 @@ class DataSource extends BaseService {
|
|
|
33
33
|
methods: {},
|
|
34
34
|
});
|
|
35
35
|
|
|
36
|
+
constructor() {
|
|
37
|
+
super([
|
|
38
|
+
{ name: 'getFormConfig', isAsync: false },
|
|
39
|
+
{ name: 'setFormConfig', isAsync: false },
|
|
40
|
+
{ name: 'getFormValue', isAsync: false },
|
|
41
|
+
{ name: 'setFormValue', isAsync: false },
|
|
42
|
+
{ name: 'getFormEvent', isAsync: false },
|
|
43
|
+
{ name: 'setFormEvent', isAsync: false },
|
|
44
|
+
{ name: 'getFormMethod', isAsync: false },
|
|
45
|
+
{ name: 'setFormMethod', isAsync: false },
|
|
46
|
+
{ name: 'add', isAsync: false },
|
|
47
|
+
{ name: 'update', isAsync: false },
|
|
48
|
+
{ name: 'remove', isAsync: false },
|
|
49
|
+
{ name: 'createId', isAsync: false },
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
|
|
36
53
|
public set<K extends StateKey, T extends State[K]>(name: K, value: T) {
|
|
37
54
|
this.state[name] = value;
|
|
38
55
|
}
|
package/src/services/dep.ts
CHANGED
|
@@ -62,6 +62,10 @@ class Dep extends BaseService {
|
|
|
62
62
|
return this.watcher.clear(nodes);
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
public clearByType(type: DepTargetType, nodes?: MNode[]) {
|
|
66
|
+
return this.watcher.clearByType(type, nodes);
|
|
67
|
+
}
|
|
68
|
+
|
|
65
69
|
public hasTarget(id: Id, type: string = DepTargetType.DEFAULT) {
|
|
66
70
|
return this.watcher.hasTarget(id, type);
|
|
67
71
|
}
|
package/src/services/editor.ts
CHANGED
|
@@ -20,10 +20,9 @@ import { reactive, toRaw } from 'vue';
|
|
|
20
20
|
import { cloneDeep, get, isObject, mergeWith, uniq } from 'lodash-es';
|
|
21
21
|
|
|
22
22
|
import { DepTargetType } from '@tmagic/dep';
|
|
23
|
-
import type { Id, MApp, MComponent, MContainer, MNode, MPage } from '@tmagic/schema';
|
|
23
|
+
import type { Id, MApp, MComponent, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
|
24
24
|
import { NodeType } from '@tmagic/schema';
|
|
25
|
-
import
|
|
26
|
-
import { getNodePath, isNumber, isPage, isPop } from '@tmagic/utils';
|
|
25
|
+
import { getNodePath, isNumber, isPage, isPageFragment, isPop } from '@tmagic/utils';
|
|
27
26
|
|
|
28
27
|
import depService from '@editor/services/dep';
|
|
29
28
|
import historyService from '@editor/services/history';
|
|
@@ -37,8 +36,10 @@ import {
|
|
|
37
36
|
fixNodePosition,
|
|
38
37
|
getInitPositionStyle,
|
|
39
38
|
getNodeIndex,
|
|
39
|
+
getPageFragmentList,
|
|
40
|
+
getPageList,
|
|
40
41
|
isFixed,
|
|
41
|
-
|
|
42
|
+
setChildrenLayout,
|
|
42
43
|
setLayout,
|
|
43
44
|
} from '@editor/utils/editor';
|
|
44
45
|
import { beforePaste, getAddParent } from '@editor/utils/operator';
|
|
@@ -54,9 +55,12 @@ class Editor extends BaseService {
|
|
|
54
55
|
node: null,
|
|
55
56
|
nodes: [],
|
|
56
57
|
stage: null,
|
|
58
|
+
stageLoading: true,
|
|
57
59
|
highlightNode: null,
|
|
58
60
|
modifiedNodeIds: new Map(),
|
|
59
61
|
pageLength: 0,
|
|
62
|
+
pageFragmentLength: 0,
|
|
63
|
+
disabledMultiSelect: false,
|
|
60
64
|
});
|
|
61
65
|
private isHistoryStateChange = false;
|
|
62
66
|
|
|
@@ -92,7 +96,7 @@ class Editor extends BaseService {
|
|
|
92
96
|
|
|
93
97
|
/**
|
|
94
98
|
* 设置当前指点节点配置
|
|
95
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
|
|
99
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength
|
|
96
100
|
* @param value MNode
|
|
97
101
|
*/
|
|
98
102
|
public set<K extends StoreStateKey, T extends StoreState[K]>(name: K, value: T) {
|
|
@@ -109,10 +113,15 @@ class Editor extends BaseService {
|
|
|
109
113
|
throw new Error('root 不能为数组');
|
|
110
114
|
}
|
|
111
115
|
|
|
112
|
-
if (value && isObject(value)
|
|
113
|
-
|
|
116
|
+
if (value && isObject(value)) {
|
|
117
|
+
const app = value as MApp;
|
|
118
|
+
this.state.pageLength = getPageList(app).length || 0;
|
|
119
|
+
this.state.pageFragmentLength = getPageFragmentList(app).length || 0;
|
|
120
|
+
this.state.stageLoading = this.state.pageLength !== 0;
|
|
114
121
|
} else {
|
|
115
122
|
this.state.pageLength = 0;
|
|
123
|
+
this.state.pageFragmentLength = 0;
|
|
124
|
+
this.state.stageLoading = false;
|
|
116
125
|
}
|
|
117
126
|
|
|
118
127
|
this.emit('root-change', value, preValue);
|
|
@@ -121,7 +130,7 @@ class Editor extends BaseService {
|
|
|
121
130
|
|
|
122
131
|
/**
|
|
123
132
|
* 获取当前指点节点配置
|
|
124
|
-
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength'
|
|
133
|
+
* @param name 'root' | 'page' | 'parent' | 'node' | 'highlightNode' | 'nodes' | 'stage' | 'modifiedNodeIds' | 'pageLength' | 'pageFragmentLength'
|
|
125
134
|
* @returns MNode
|
|
126
135
|
*/
|
|
127
136
|
public get<K extends StoreStateKey>(name: K): StoreState[K] {
|
|
@@ -163,8 +172,8 @@ class Editor extends BaseService {
|
|
|
163
172
|
info.parent = path[path.length - 2] as MContainer;
|
|
164
173
|
|
|
165
174
|
path.forEach((item) => {
|
|
166
|
-
if (item
|
|
167
|
-
info.page = item as MPage;
|
|
175
|
+
if (isPage(item) || isPageFragment(item)) {
|
|
176
|
+
info.page = item as MPage | MPageFragment;
|
|
168
177
|
return;
|
|
169
178
|
}
|
|
170
179
|
});
|
|
@@ -312,6 +321,17 @@ class Editor extends BaseService {
|
|
|
312
321
|
this.set('nodes', nodes);
|
|
313
322
|
}
|
|
314
323
|
|
|
324
|
+
public selectRoot() {
|
|
325
|
+
const root = this.get('root');
|
|
326
|
+
if (!root) return;
|
|
327
|
+
|
|
328
|
+
this.set('nodes', [root]);
|
|
329
|
+
this.set('parent', null);
|
|
330
|
+
this.set('page', null);
|
|
331
|
+
this.set('stage', null);
|
|
332
|
+
this.set('highlightNode', null);
|
|
333
|
+
}
|
|
334
|
+
|
|
315
335
|
public async doAdd(node: MNode, parent: MContainer): Promise<MNode> {
|
|
316
336
|
const root = this.get('root');
|
|
317
337
|
|
|
@@ -322,11 +342,11 @@ class Editor extends BaseService {
|
|
|
322
342
|
|
|
323
343
|
if (!curNode) throw new Error('当前选中节点为空');
|
|
324
344
|
|
|
325
|
-
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && node
|
|
345
|
+
if ((parent.type === NodeType.ROOT || curNode?.type === NodeType.ROOT) && !(isPage(node) || isPageFragment(node))) {
|
|
326
346
|
throw new Error('app下不能添加组件');
|
|
327
347
|
}
|
|
328
348
|
|
|
329
|
-
if (parent.id !== curNode.id && node
|
|
349
|
+
if (parent.id !== curNode.id && !(isPage(node) || isPageFragment(node))) {
|
|
330
350
|
const index = parent.items.indexOf(curNode);
|
|
331
351
|
parent.items?.splice(index + 1, 0, node);
|
|
332
352
|
} else {
|
|
@@ -380,7 +400,7 @@ class Editor extends BaseService {
|
|
|
380
400
|
const newNodes = await Promise.all(
|
|
381
401
|
addNodes.map((node) => {
|
|
382
402
|
const root = this.get('root');
|
|
383
|
-
if (isPage(node) && root) {
|
|
403
|
+
if ((isPage(node) || isPageFragment(node)) && root) {
|
|
384
404
|
return this.doAdd(node, root);
|
|
385
405
|
}
|
|
386
406
|
const parentNode = parent && typeof parent !== 'function' ? parent : getAddParent(node);
|
|
@@ -399,13 +419,15 @@ class Editor extends BaseService {
|
|
|
399
419
|
|
|
400
420
|
if (isPage(newNodes[0])) {
|
|
401
421
|
this.state.pageLength += 1;
|
|
422
|
+
} else if (isPageFragment(newNodes[0])) {
|
|
423
|
+
this.state.pageFragmentLength += 1;
|
|
402
424
|
} else {
|
|
403
425
|
// 新增页面,这个时候页面还有渲染出来,此时select会出错,在runtime-ready的时候回去select
|
|
404
426
|
stage?.select(newNodes[0].id);
|
|
405
427
|
}
|
|
406
428
|
}
|
|
407
429
|
|
|
408
|
-
if (!isPage(newNodes[0])) {
|
|
430
|
+
if (!(isPage(newNodes[0]) || isPageFragment(newNodes[0]))) {
|
|
409
431
|
this.pushHistoryState();
|
|
410
432
|
}
|
|
411
433
|
|
|
@@ -418,7 +440,7 @@ class Editor extends BaseService {
|
|
|
418
440
|
const root = this.get('root');
|
|
419
441
|
if (!root) throw new Error('root不能为空');
|
|
420
442
|
|
|
421
|
-
const { parent, node: curNode } = this.getNodeInfo(node.id);
|
|
443
|
+
const { parent, node: curNode } = this.getNodeInfo(node.id, false);
|
|
422
444
|
|
|
423
445
|
if (!parent || !curNode) throw new Error('找不要删除的节点');
|
|
424
446
|
|
|
@@ -430,29 +452,38 @@ class Editor extends BaseService {
|
|
|
430
452
|
const stage = this.get('stage');
|
|
431
453
|
stage?.remove({ id: node.id, parentId: parent.id, root: cloneDeep(root) });
|
|
432
454
|
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
await this.select(root.items[0]);
|
|
438
|
-
stage?.select(root.items[0].id);
|
|
455
|
+
const selectDefault = async (pages: MNode[]) => {
|
|
456
|
+
if (pages[0]) {
|
|
457
|
+
await this.select(pages[0]);
|
|
458
|
+
stage?.select(pages[0].id);
|
|
439
459
|
} else {
|
|
440
|
-
this.
|
|
441
|
-
this.set('parent', null);
|
|
442
|
-
this.set('page', null);
|
|
443
|
-
this.set('stage', null);
|
|
444
|
-
this.set('highlightNode', null);
|
|
445
|
-
this.resetModifiedNodeId();
|
|
446
|
-
historyService.reset();
|
|
460
|
+
this.selectRoot();
|
|
447
461
|
|
|
448
|
-
|
|
462
|
+
historyService.resetPage();
|
|
449
463
|
}
|
|
464
|
+
};
|
|
465
|
+
|
|
466
|
+
const rootItems = root.items || [];
|
|
467
|
+
|
|
468
|
+
if (isPage(node)) {
|
|
469
|
+
this.state.pageLength -= 1;
|
|
470
|
+
|
|
471
|
+
await selectDefault(getPageList(root));
|
|
472
|
+
} else if (isPageFragment(node)) {
|
|
473
|
+
this.state.pageFragmentLength -= 1;
|
|
474
|
+
|
|
475
|
+
await selectDefault(getPageFragmentList(root));
|
|
450
476
|
} else {
|
|
451
477
|
await this.select(parent);
|
|
452
478
|
stage?.select(parent.id);
|
|
479
|
+
|
|
480
|
+
this.addModifiedNodeId(parent.id);
|
|
453
481
|
}
|
|
454
482
|
|
|
455
|
-
|
|
483
|
+
if (!rootItems.length) {
|
|
484
|
+
this.resetModifiedNodeId();
|
|
485
|
+
historyService.reset();
|
|
486
|
+
}
|
|
456
487
|
}
|
|
457
488
|
|
|
458
489
|
/**
|
|
@@ -464,7 +495,7 @@ class Editor extends BaseService {
|
|
|
464
495
|
|
|
465
496
|
await Promise.all(nodes.map((node) => this.doRemove(node)));
|
|
466
497
|
|
|
467
|
-
if (!isPage(nodes[0])) {
|
|
498
|
+
if (!(isPage(nodes[0]) || isPageFragment(nodes[0]))) {
|
|
468
499
|
// 更新历史记录
|
|
469
500
|
this.pushHistoryState();
|
|
470
501
|
}
|
|
@@ -514,7 +545,7 @@ class Editor extends BaseService {
|
|
|
514
545
|
const newLayout = await this.getLayout(newConfig);
|
|
515
546
|
const layout = await this.getLayout(node);
|
|
516
547
|
if (Array.isArray(newConfig.items) && newLayout !== layout) {
|
|
517
|
-
newConfig =
|
|
548
|
+
newConfig = setChildrenLayout(newConfig as MContainer, newLayout);
|
|
518
549
|
}
|
|
519
550
|
|
|
520
551
|
parentNodeItems[index] = newConfig;
|
|
@@ -531,8 +562,8 @@ class Editor extends BaseService {
|
|
|
531
562
|
root: cloneDeep(root),
|
|
532
563
|
});
|
|
533
564
|
|
|
534
|
-
if (newConfig
|
|
535
|
-
this.set('page', newConfig as MPage);
|
|
565
|
+
if (isPage(newConfig) || isPageFragment(newConfig)) {
|
|
566
|
+
this.set('page', newConfig as MPage | MPageFragment);
|
|
536
567
|
}
|
|
537
568
|
|
|
538
569
|
this.addModifiedNodeId(newConfig.id);
|
|
@@ -613,7 +644,7 @@ class Editor extends BaseService {
|
|
|
613
644
|
public copyWithRelated(config: MNode | MNode[]): void {
|
|
614
645
|
const copyNodes: MNode[] = Array.isArray(config) ? config : [config];
|
|
615
646
|
// 关联的组件也一并复制
|
|
616
|
-
depService.
|
|
647
|
+
depService.clearByType(DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
617
648
|
depService.collect(copyNodes, true, DepTargetType.RELATED_COMP_WHEN_COPY);
|
|
618
649
|
const customTarget = depService.getTarget(
|
|
619
650
|
DepTargetType.RELATED_COMP_WHEN_COPY,
|
package/src/services/history.ts
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { reactive } from 'vue';
|
|
20
20
|
|
|
21
|
-
import type { MPage } from '@tmagic/schema';
|
|
21
|
+
import type { MPage, MPageFragment } from '@tmagic/schema';
|
|
22
22
|
|
|
23
23
|
import type { HistoryState, StepValue } from '@editor/type';
|
|
24
24
|
import { UndoRedo } from '@editor/utils/undo-redo';
|
|
@@ -41,12 +41,16 @@ class History extends BaseService {
|
|
|
41
41
|
|
|
42
42
|
public reset() {
|
|
43
43
|
this.state.pageSteps = {};
|
|
44
|
+
this.resetPage();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public resetPage() {
|
|
44
48
|
this.state.pageId = undefined;
|
|
45
49
|
this.state.canRedo = false;
|
|
46
50
|
this.state.canUndo = false;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
public changePage(page: MPage): void {
|
|
53
|
+
public changePage(page: MPage | MPageFragment): void {
|
|
50
54
|
if (!page) return;
|
|
51
55
|
|
|
52
56
|
this.state.pageId = page.id;
|