@tmagic/editor 1.3.0-alpha.2 → 1.3.0-alpha.21
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 +91 -120
- package/dist/tmagic-editor.js +4609 -3257
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +5708 -4337
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +21 -22
- package/src/Editor.vue +29 -7
- package/src/components/CodeBlockEditor.vue +170 -0
- package/src/components/CodeParams.vue +60 -0
- package/src/components/ContentMenu.vue +30 -11
- package/src/components/Icon.vue +5 -1
- package/src/components/Resizer.vue +45 -0
- package/src/components/ScrollBar.vue +5 -1
- package/src/components/ScrollViewer.vue +5 -1
- package/src/components/SearchInput.vue +4 -0
- package/src/components/{Layout.vue → SplitView.vue} +8 -4
- package/src/components/ToolButton.vue +5 -1
- package/src/editorProps.ts +35 -4
- package/src/fields/Code.vue +28 -20
- package/src/fields/CodeLink.vue +15 -10
- package/src/fields/CodeSelect.vue +19 -10
- package/src/fields/CodeSelectCol.vue +67 -83
- package/src/fields/DataSourceFieldSelect.vue +47 -0
- package/src/fields/DataSourceFields.vue +24 -21
- package/src/fields/DataSourceInput.vue +318 -0
- package/src/fields/DataSourceMethodSelect.vue +136 -0
- package/src/fields/DataSourceMethods.vue +103 -0
- package/src/fields/DataSourceSelect.vue +68 -0
- package/src/fields/EventSelect.vue +62 -22
- package/src/fields/KeyValue.vue +13 -11
- package/src/fields/UISelect.vue +59 -15
- package/src/hooks/index.ts +21 -0
- package/src/hooks/use-code-block-edit.ts +84 -0
- package/src/hooks/use-data-source-method.ts +100 -0
- package/src/{utils/stage.ts → hooks/use-stage.ts} +4 -7
- package/src/icons/AppManageIcon.vue +5 -1
- package/src/icons/CenterIcon.vue +13 -0
- package/src/icons/CodeIcon.vue +5 -3
- package/src/index.ts +24 -3
- package/src/initService.ts +75 -16
- package/src/layouts/AddPageBox.vue +5 -1
- package/src/layouts/CodeEditor.vue +66 -11
- package/src/layouts/Framework.vue +32 -28
- package/src/layouts/NavMenu.vue +5 -1
- package/src/layouts/PropsPanel.vue +14 -4
- package/src/layouts/sidebar/ComponentListPanel.vue +11 -10
- package/src/layouts/sidebar/LayerMenu.vue +13 -25
- package/src/layouts/sidebar/LayerNode.vue +40 -0
- package/src/layouts/sidebar/LayerPanel.vue +71 -28
- package/src/layouts/sidebar/Sidebar.vue +13 -17
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +84 -118
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +63 -0
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +39 -34
- package/src/layouts/sidebar/data-source/DataSourceList.vue +145 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +17 -65
- package/src/layouts/workspace/Breadcrumb.vue +5 -1
- package/src/layouts/workspace/PageBar.vue +5 -1
- package/src/layouts/workspace/PageBarScrollContainer.vue +5 -1
- package/src/layouts/workspace/Stage.vue +30 -8
- package/src/layouts/workspace/ViewerMenu.vue +15 -36
- package/src/layouts/workspace/Workspace.vue +9 -134
- package/src/services/codeBlock.ts +20 -72
- package/src/services/dataSource.ts +17 -2
- package/src/services/dep.ts +23 -20
- package/src/services/editor.ts +3 -3
- package/src/services/keybinding.ts +185 -0
- package/src/services/props.ts +2 -2
- package/src/services/storage.ts +3 -2
- package/src/theme/code-block.scss +5 -117
- package/src/theme/code-editor.scss +27 -2
- package/src/theme/content-menu.scss +1 -1
- package/src/theme/data-source-input.scss +18 -0
- package/src/theme/data-source-methods.scss +13 -0
- package/src/theme/event.scss +15 -12
- package/src/theme/framework.scss +0 -3
- package/src/theme/layer-panel.scss +6 -0
- package/src/theme/layout.scss +4 -0
- package/src/theme/resizer.scss +25 -10
- package/src/theme/stage.scss +4 -0
- package/src/theme/theme.scss +2 -0
- package/src/type.ts +105 -7
- package/src/utils/config.ts +1 -1
- package/src/utils/content-menu.ts +92 -0
- package/src/utils/data-source/formConfigs/base.ts +35 -30
- package/src/utils/data-source/index.ts +75 -6
- package/src/utils/dep.ts +39 -7
- package/src/utils/index.ts +1 -1
- package/src/utils/keybinding-config.ts +120 -0
- package/src/utils/props.ts +298 -155
- package/src/utils/undo-redo.ts +1 -1
- package/types/Editor.vue.d.ts +37 -4
- package/types/components/CodeBlockEditor.vue.d.ts +23 -0
- package/types/components/CodeParams.vue.d.ts +26 -0
- package/types/components/ContentMenu.vue.d.ts +8 -3
- package/types/components/Icon.vue.d.ts +2 -2
- package/types/{layouts → components}/Resizer.vue.d.ts +2 -2
- package/types/components/ScrollBar.vue.d.ts +1 -1
- package/types/components/ScrollViewer.vue.d.ts +8 -5
- package/types/components/SearchInput.vue.d.ts +1 -1
- package/types/components/{Layout.vue.d.ts → SplitView.vue.d.ts} +9 -6
- package/types/components/ToolButton.vue.d.ts +10 -7
- package/types/editorProps.d.ts +23 -4
- package/types/fields/Code.vue.d.ts +23 -18
- package/types/fields/CodeLink.vue.d.ts +13 -22
- package/types/fields/CodeSelect.vue.d.ts +12 -20
- package/types/fields/CodeSelectCol.vue.d.ts +14 -15
- package/types/fields/DataSourceFieldSelect.vue.d.ts +29 -0
- package/types/fields/DataSourceFields.vue.d.ts +13 -21
- package/types/fields/DataSourceInput.vue.d.ts +34 -0
- package/types/fields/DataSourceMethodSelect.vue.d.ts +29 -0
- package/types/fields/DataSourceMethods.vue.d.ts +32 -0
- package/types/fields/DataSourceSelect.vue.d.ts +40 -0
- package/types/fields/EventSelect.vue.d.ts +3 -14
- package/types/fields/KeyValue.vue.d.ts +15 -27
- package/types/fields/UISelect.vue.d.ts +3 -12
- package/types/hooks/index.d.ts +3 -0
- package/types/hooks/use-code-block-edit.d.ts +125 -0
- package/types/hooks/use-data-source-method.d.ts +123 -0
- package/types/icons/AppManageIcon.vue.d.ts +1 -1
- package/types/icons/CenterIcon.vue.d.ts +2 -0
- package/types/icons/CodeIcon.vue.d.ts +1 -1
- package/types/index.d.ts +12 -2
- package/types/initService.d.ts +2 -2
- package/types/layouts/AddPageBox.vue.d.ts +1 -1
- package/types/layouts/CodeEditor.vue.d.ts +18 -10
- package/types/layouts/Framework.vue.d.ts +11 -32
- package/types/layouts/NavMenu.vue.d.ts +7 -4
- package/types/layouts/PropsPanel.vue.d.ts +276 -4
- package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +4 -4
- package/types/layouts/sidebar/LayerMenu.vue.d.ts +2 -2
- package/types/layouts/sidebar/LayerNode.vue.d.ts +16 -0
- package/types/layouts/sidebar/LayerPanel.vue.d.ts +5 -5
- package/types/layouts/sidebar/Sidebar.vue.d.ts +16 -16
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +7 -12
- package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +28 -0
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +4 -2
- package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +14 -0
- package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +1 -11
- package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -1
- package/types/layouts/workspace/PageBar.vue.d.ts +5 -5
- package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +2 -2
- package/types/layouts/workspace/Stage.vue.d.ts +2 -2
- package/types/layouts/workspace/ViewerMenu.vue.d.ts +7 -4
- package/types/layouts/workspace/Workspace.vue.d.ts +9 -9
- package/types/services/codeBlock.d.ts +6 -37
- package/types/services/dataSource.d.ts +7 -1
- package/types/services/dep.d.ts +12 -21
- package/types/services/editor.d.ts +1 -1
- package/types/services/keybinding.d.ts +20 -0
- package/types/services/props.d.ts +10 -115
- package/types/type.d.ts +97 -7
- package/types/utils/config.d.ts +1 -1
- package/types/utils/content-menu.d.ts +7 -0
- package/types/utils/data-source/formConfigs/base.d.ts +2 -2
- package/types/utils/data-source/index.d.ts +7 -1
- package/types/utils/dep.d.ts +4 -2
- package/types/utils/index.d.ts +1 -1
- package/types/utils/keybinding-config.d.ts +3 -0
- package/types/utils/props.d.ts +13 -102
- package/src/components/CodeDraftEditor.vue +0 -144
- package/src/components/FunctionEditor.vue +0 -190
- package/src/layouts/Resizer.vue +0 -32
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +0 -96
- package/types/components/CodeDraftEditor.vue.d.ts +0 -58
- package/types/components/FunctionEditor.vue.d.ts +0 -192
- package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +0 -25
- /package/types/{utils/stage.d.ts → hooks/use-stage.d.ts} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-workspace"
|
|
2
|
+
<div class="m-editor-workspace">
|
|
3
3
|
<Breadcrumb></Breadcrumb>
|
|
4
4
|
|
|
5
5
|
<slot name="stage">
|
|
@@ -15,149 +15,24 @@
|
|
|
15
15
|
</div>
|
|
16
16
|
</template>
|
|
17
17
|
|
|
18
|
-
<script lang="ts" setup
|
|
19
|
-
import { computed, inject
|
|
20
|
-
import KeyController from 'keycon';
|
|
18
|
+
<script lang="ts" setup>
|
|
19
|
+
import { computed, inject } from 'vue';
|
|
21
20
|
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
import type { MenuButton, MenuComponent, Services } from '@editor/type';
|
|
21
|
+
import { MenuButton, MenuComponent, Services } from '@editor/type';
|
|
25
22
|
|
|
26
23
|
import Breadcrumb from './Breadcrumb.vue';
|
|
27
24
|
import PageBar from './PageBar.vue';
|
|
28
25
|
import MagicStage from './Stage.vue';
|
|
29
26
|
|
|
27
|
+
defineOptions({
|
|
28
|
+
name: 'MEditorWorkspace',
|
|
29
|
+
});
|
|
30
|
+
|
|
30
31
|
defineProps<{
|
|
31
32
|
stageContentMenu: (MenuButton | MenuComponent)[];
|
|
32
33
|
}>();
|
|
33
34
|
|
|
34
35
|
const services = inject<Services>('services');
|
|
35
|
-
const workspace = ref<HTMLDivElement>();
|
|
36
|
-
const nodes = computed(() => services?.editorService.get('nodes'));
|
|
37
|
-
const page = computed(() => services?.editorService.get('page'));
|
|
38
|
-
|
|
39
|
-
const mouseenterHandler = () => {
|
|
40
|
-
workspace.value?.focus();
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const mouseleaveHandler = () => {
|
|
44
|
-
workspace.value?.blur();
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
let keycon: KeyController;
|
|
48
|
-
|
|
49
|
-
onMounted(() => {
|
|
50
|
-
workspace.value?.addEventListener('mouseenter', mouseenterHandler);
|
|
51
|
-
workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
|
|
52
36
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
|
|
56
|
-
|
|
57
|
-
const ctrl = isMac ? 'meta' : 'ctrl';
|
|
58
|
-
|
|
59
|
-
keycon
|
|
60
|
-
.keyup('delete', (e) => {
|
|
61
|
-
e.inputEvent.preventDefault();
|
|
62
|
-
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
63
|
-
services?.editorService.remove(nodes.value);
|
|
64
|
-
})
|
|
65
|
-
.keyup('backspace', (e) => {
|
|
66
|
-
e.inputEvent.preventDefault();
|
|
67
|
-
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
68
|
-
services?.editorService.remove(nodes.value);
|
|
69
|
-
})
|
|
70
|
-
.keydown([ctrl, 'c'], (e) => {
|
|
71
|
-
e.inputEvent.preventDefault();
|
|
72
|
-
nodes.value && services?.editorService.copy(nodes.value);
|
|
73
|
-
})
|
|
74
|
-
.keydown([ctrl, 'v'], (e) => {
|
|
75
|
-
e.inputEvent.preventDefault();
|
|
76
|
-
nodes.value && services?.editorService.paste({ offsetX: 10, offsetY: 10 });
|
|
77
|
-
})
|
|
78
|
-
.keydown([ctrl, 'x'], (e) => {
|
|
79
|
-
e.inputEvent.preventDefault();
|
|
80
|
-
if (!nodes.value || isPage(nodes.value[0])) return;
|
|
81
|
-
services?.editorService.copy(nodes.value);
|
|
82
|
-
services?.editorService.remove(nodes.value);
|
|
83
|
-
})
|
|
84
|
-
.keydown([ctrl, 'z'], (e) => {
|
|
85
|
-
e.inputEvent.preventDefault();
|
|
86
|
-
services?.editorService.undo();
|
|
87
|
-
})
|
|
88
|
-
.keydown([ctrl, 'shift', 'z'], (e) => {
|
|
89
|
-
e.inputEvent.preventDefault();
|
|
90
|
-
services?.editorService.redo();
|
|
91
|
-
})
|
|
92
|
-
.keydown('up', (e) => {
|
|
93
|
-
e.inputEvent.preventDefault();
|
|
94
|
-
services?.editorService.move(0, -1);
|
|
95
|
-
})
|
|
96
|
-
.keydown('down', (e) => {
|
|
97
|
-
e.inputEvent.preventDefault();
|
|
98
|
-
services?.editorService.move(0, 1);
|
|
99
|
-
})
|
|
100
|
-
.keydown('left', (e) => {
|
|
101
|
-
e.inputEvent.preventDefault();
|
|
102
|
-
services?.editorService.move(-1, 0);
|
|
103
|
-
})
|
|
104
|
-
.keydown('right', (e) => {
|
|
105
|
-
e.inputEvent.preventDefault();
|
|
106
|
-
services?.editorService.move(1, 0);
|
|
107
|
-
})
|
|
108
|
-
.keydown([ctrl, 'up'], (e) => {
|
|
109
|
-
e.inputEvent.preventDefault();
|
|
110
|
-
services?.editorService.move(0, -10);
|
|
111
|
-
})
|
|
112
|
-
.keydown([ctrl, 'down'], (e) => {
|
|
113
|
-
e.inputEvent.preventDefault();
|
|
114
|
-
services?.editorService.move(0, 10);
|
|
115
|
-
})
|
|
116
|
-
.keydown([ctrl, 'left'], (e) => {
|
|
117
|
-
e.inputEvent.preventDefault();
|
|
118
|
-
services?.editorService.move(-10, 0);
|
|
119
|
-
})
|
|
120
|
-
.keydown([ctrl, 'right'], (e) => {
|
|
121
|
-
e.inputEvent.preventDefault();
|
|
122
|
-
services?.editorService.move(10, 0);
|
|
123
|
-
})
|
|
124
|
-
.keydown('tab', (e) => {
|
|
125
|
-
e.inputEvent.preventDefault();
|
|
126
|
-
services?.editorService.selectNextNode();
|
|
127
|
-
})
|
|
128
|
-
.keydown([ctrl, 'tab'], (e) => {
|
|
129
|
-
e.inputEvent.preventDefault();
|
|
130
|
-
services?.editorService.selectNextPage();
|
|
131
|
-
})
|
|
132
|
-
.keydown([ctrl, '='], (e) => {
|
|
133
|
-
e.inputEvent.preventDefault();
|
|
134
|
-
services?.uiService.zoom(0.1);
|
|
135
|
-
})
|
|
136
|
-
.keydown([ctrl, 'numpadplus'], (e) => {
|
|
137
|
-
e.inputEvent.preventDefault();
|
|
138
|
-
services?.uiService.zoom(0.1);
|
|
139
|
-
})
|
|
140
|
-
.keydown([ctrl, '-'], (e) => {
|
|
141
|
-
e.inputEvent.preventDefault();
|
|
142
|
-
services?.uiService.zoom(-0.1);
|
|
143
|
-
})
|
|
144
|
-
.keydown([ctrl, 'numpad-'], (e) => {
|
|
145
|
-
e.inputEvent.preventDefault();
|
|
146
|
-
services?.uiService.zoom(-0.1);
|
|
147
|
-
})
|
|
148
|
-
.keydown([ctrl, '0'], async (e) => {
|
|
149
|
-
e.inputEvent.preventDefault();
|
|
150
|
-
services?.uiService.set('zoom', await services.uiService.calcZoom());
|
|
151
|
-
})
|
|
152
|
-
.keydown([ctrl, '1'], (e) => {
|
|
153
|
-
e.inputEvent.preventDefault();
|
|
154
|
-
services?.uiService.set('zoom', 1);
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
onUnmounted(() => {
|
|
159
|
-
workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
|
|
160
|
-
workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
|
|
161
|
-
keycon.destroy();
|
|
162
|
-
});
|
|
37
|
+
const page = computed(() => services?.editorService.get('page'));
|
|
163
38
|
</script>
|
|
@@ -19,32 +19,26 @@
|
|
|
19
19
|
import { reactive } from 'vue';
|
|
20
20
|
import { keys, pick } from 'lodash-es';
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import type { ColumnConfig } from '@tmagic/form';
|
|
23
|
+
import type { CodeBlockContent, CodeBlockDSL, Id } from '@tmagic/schema';
|
|
23
24
|
|
|
24
25
|
import type { CodeState } from '@editor/type';
|
|
25
26
|
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
|
27
|
+
import { getConfig } from '@editor/utils/config';
|
|
26
28
|
|
|
27
29
|
import BaseService from './BaseService';
|
|
28
30
|
|
|
29
31
|
class CodeBlock extends BaseService {
|
|
30
32
|
private state = reactive<CodeState>({
|
|
31
|
-
isShowCodeEditor: false,
|
|
32
33
|
codeDsl: null,
|
|
33
|
-
id: '',
|
|
34
34
|
editable: true,
|
|
35
35
|
combineIds: [],
|
|
36
36
|
undeletableList: [],
|
|
37
|
+
paramsColConfig: undefined,
|
|
37
38
|
});
|
|
38
39
|
|
|
39
40
|
constructor() {
|
|
40
|
-
super([
|
|
41
|
-
'setCodeDslById',
|
|
42
|
-
'setCodeEditorShowStatus',
|
|
43
|
-
'setEditStatus',
|
|
44
|
-
'setCombineIds',
|
|
45
|
-
'setUndeleteableList',
|
|
46
|
-
'deleteCodeDslByIds',
|
|
47
|
-
]);
|
|
41
|
+
super(['setCodeDslById', 'setEditStatus', 'setCombineIds', 'setUndeleteableList', 'deleteCodeDslByIds']);
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
/**
|
|
@@ -85,7 +79,7 @@ class CodeBlock extends BaseService {
|
|
|
85
79
|
* @param {CodeBlockContent} codeConfig 代码块内容配置信息
|
|
86
80
|
* @returns {void}
|
|
87
81
|
*/
|
|
88
|
-
public async setCodeDslById(id: Id, codeConfig: CodeBlockContent): Promise<void> {
|
|
82
|
+
public async setCodeDslById(id: Id, codeConfig: Partial<CodeBlockContent>): Promise<void> {
|
|
89
83
|
const codeDsl = this.getCodeDsl();
|
|
90
84
|
|
|
91
85
|
if (!codeDsl) {
|
|
@@ -95,8 +89,11 @@ class CodeBlock extends BaseService {
|
|
|
95
89
|
const codeConfigProcessed = codeConfig;
|
|
96
90
|
if (codeConfig.content) {
|
|
97
91
|
// 在保存的时候转换代码内容
|
|
98
|
-
|
|
99
|
-
|
|
92
|
+
const parseDSL = getConfig('parseDSL');
|
|
93
|
+
if (typeof codeConfig.content === 'string') {
|
|
94
|
+
codeConfig.content = parseDSL<(...args: any[]) => any>(codeConfig.content);
|
|
95
|
+
}
|
|
96
|
+
codeConfigProcessed.content = codeConfig.content;
|
|
100
97
|
}
|
|
101
98
|
|
|
102
99
|
const existContent = codeDsl[id] || {};
|
|
@@ -119,43 +116,6 @@ class CodeBlock extends BaseService {
|
|
|
119
116
|
return pick(codeDsl, ids) as CodeBlockDSL;
|
|
120
117
|
}
|
|
121
118
|
|
|
122
|
-
/**
|
|
123
|
-
* 设置代码编辑面板展示状态
|
|
124
|
-
* @param {boolean} status 是否展示代码编辑面板
|
|
125
|
-
* @returns {void}
|
|
126
|
-
*/
|
|
127
|
-
public async setCodeEditorShowStatus(status: boolean): Promise<void> {
|
|
128
|
-
this.state.isShowCodeEditor = status;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* 获取代码编辑面板展示状态
|
|
133
|
-
* @returns {boolean} 是否展示代码编辑面板
|
|
134
|
-
*/
|
|
135
|
-
public getCodeEditorShowStatus(): boolean {
|
|
136
|
-
return this.state.isShowCodeEditor;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* 设置代码编辑面板展示状态及展示内容
|
|
141
|
-
* @param {boolean} status 是否展示代码编辑面板
|
|
142
|
-
* @param {Id} id 代码块id
|
|
143
|
-
* @returns {void}
|
|
144
|
-
*/
|
|
145
|
-
public setCodeEditorContent(status: boolean, id: Id): void {
|
|
146
|
-
if (!id) return;
|
|
147
|
-
this.setId(id);
|
|
148
|
-
this.state.isShowCodeEditor = status;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* 获取当前选中的代码块内容
|
|
153
|
-
* @returns {CodeBlockContent | null}
|
|
154
|
-
*/
|
|
155
|
-
public getCurrentDsl(): CodeBlockContent | null {
|
|
156
|
-
return this.getCodeContentById(this.state.id);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
119
|
/**
|
|
160
120
|
* 获取编辑状态
|
|
161
121
|
* @returns {boolean} 是否可编辑
|
|
@@ -173,24 +133,6 @@ class CodeBlock extends BaseService {
|
|
|
173
133
|
this.state.editable = status;
|
|
174
134
|
}
|
|
175
135
|
|
|
176
|
-
/**
|
|
177
|
-
* 设置当前选中的代码块ID
|
|
178
|
-
* @param {Id} id 代码块id
|
|
179
|
-
* @returns {void}
|
|
180
|
-
*/
|
|
181
|
-
public setId(id: Id): void {
|
|
182
|
-
if (!id) return;
|
|
183
|
-
this.state.id = id;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
* 获取当前选中的代码块ID
|
|
188
|
-
* @returns {Id} id 代码块id
|
|
189
|
-
*/
|
|
190
|
-
public getId(): Id {
|
|
191
|
-
return this.state.id;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
136
|
/**
|
|
195
137
|
* 设置当前选中组件已关联绑定的代码块id数组
|
|
196
138
|
* @param {string[]} ids 代码块id数组
|
|
@@ -262,11 +204,19 @@ class CodeBlock extends BaseService {
|
|
|
262
204
|
});
|
|
263
205
|
}
|
|
264
206
|
|
|
207
|
+
public setParamsColConfig(config: ColumnConfig): void {
|
|
208
|
+
this.state.paramsColConfig = config;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public getParamsColConfig(): ColumnConfig | undefined {
|
|
212
|
+
return this.state.paramsColConfig;
|
|
213
|
+
}
|
|
214
|
+
|
|
265
215
|
/**
|
|
266
216
|
* 生成代码块唯一id
|
|
267
217
|
* @returns {Id} 代码块唯一id
|
|
268
218
|
*/
|
|
269
|
-
public async getUniqueId(): Promise<
|
|
219
|
+
public async getUniqueId(): Promise<string> {
|
|
270
220
|
const newId = `code_${Math.random().toString(10).substring(2).substring(0, 4)}`;
|
|
271
221
|
// 判断是否重复
|
|
272
222
|
const dsl = await this.getCodeDsl();
|
|
@@ -276,9 +226,7 @@ class CodeBlock extends BaseService {
|
|
|
276
226
|
}
|
|
277
227
|
|
|
278
228
|
public resetState() {
|
|
279
|
-
this.state.isShowCodeEditor = false;
|
|
280
229
|
this.state.codeDsl = null;
|
|
281
|
-
this.state.id = '';
|
|
282
230
|
this.state.editable = true;
|
|
283
231
|
this.state.combineIds = [];
|
|
284
232
|
this.state.undeletableList = [];
|
|
@@ -2,23 +2,30 @@ import { reactive } from 'vue';
|
|
|
2
2
|
import { cloneDeep } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import type { FormConfig } from '@tmagic/form';
|
|
5
|
-
import { DataSourceSchema } from '@tmagic/schema';
|
|
5
|
+
import type { DataSourceSchema } from '@tmagic/schema';
|
|
6
6
|
import { guid } from '@tmagic/utils';
|
|
7
7
|
|
|
8
|
+
import type { DatasourceTypeOption } from '@editor/type';
|
|
8
9
|
import { getFormConfig } from '@editor/utils/data-source';
|
|
9
10
|
|
|
10
11
|
import BaseService from './BaseService';
|
|
11
12
|
|
|
12
13
|
interface State {
|
|
14
|
+
datasourceTypeList: DatasourceTypeOption[];
|
|
13
15
|
dataSources: DataSourceSchema[];
|
|
16
|
+
editable: boolean;
|
|
14
17
|
configs: Record<string, FormConfig>;
|
|
18
|
+
values: Record<string, Partial<DataSourceSchema>>;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
type StateKey = keyof State;
|
|
18
22
|
class DataSource extends BaseService {
|
|
19
23
|
private state = reactive<State>({
|
|
24
|
+
datasourceTypeList: [],
|
|
20
25
|
dataSources: [],
|
|
26
|
+
editable: true,
|
|
21
27
|
configs: {},
|
|
28
|
+
values: {},
|
|
22
29
|
});
|
|
23
30
|
|
|
24
31
|
public set<K extends StateKey, T extends State[K]>(name: K, value: T) {
|
|
@@ -30,13 +37,21 @@ class DataSource extends BaseService {
|
|
|
30
37
|
}
|
|
31
38
|
|
|
32
39
|
public getFormConfig(type = 'base') {
|
|
33
|
-
return getFormConfig(type, this.get('configs'));
|
|
40
|
+
return getFormConfig(type, this.get('datasourceTypeList'), this.get('configs'));
|
|
34
41
|
}
|
|
35
42
|
|
|
36
43
|
public setFormConfig(type: string, config: FormConfig) {
|
|
37
44
|
this.get('configs')[type] = config;
|
|
38
45
|
}
|
|
39
46
|
|
|
47
|
+
public getFormValue(type = 'base') {
|
|
48
|
+
return this.get('values')[type];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public setFormValue(type: string, value: Partial<DataSourceSchema>) {
|
|
52
|
+
this.get('values')[type] = value;
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
public add(config: DataSourceSchema) {
|
|
41
56
|
const newConfig = {
|
|
42
57
|
...config,
|
package/src/services/dep.ts
CHANGED
|
@@ -19,27 +19,24 @@ import { EventEmitter } from 'events';
|
|
|
19
19
|
|
|
20
20
|
import { reactive } from 'vue';
|
|
21
21
|
|
|
22
|
-
import { MNode } from '@tmagic/schema';
|
|
22
|
+
import type { Dep, Id, MNode } from '@tmagic/schema';
|
|
23
|
+
import { isObject } from '@tmagic/utils';
|
|
24
|
+
|
|
25
|
+
import { DepTargetType } from '@editor/type';
|
|
23
26
|
|
|
24
27
|
type IsTarget = (key: string | number, value: any) => boolean;
|
|
25
28
|
|
|
26
29
|
interface TargetOptions {
|
|
27
30
|
isTarget: IsTarget;
|
|
28
31
|
id: string | number;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
interface Dep {
|
|
34
|
-
[key: string | number]: {
|
|
35
|
-
name: string;
|
|
36
|
-
keys: (string | number)[];
|
|
37
|
-
};
|
|
32
|
+
/** 类型,数据源、代码块或其他 */
|
|
33
|
+
type?: DepTargetType | string;
|
|
34
|
+
name?: string;
|
|
38
35
|
}
|
|
39
36
|
|
|
40
37
|
interface TargetList {
|
|
41
|
-
[
|
|
42
|
-
[
|
|
38
|
+
[type: DepTargetType | string]: {
|
|
39
|
+
[targetId: string | number]: Target;
|
|
43
40
|
};
|
|
44
41
|
}
|
|
45
42
|
|
|
@@ -60,11 +57,11 @@ export class Target extends EventEmitter {
|
|
|
60
57
|
/**
|
|
61
58
|
* 目标名称,用于显示在依赖列表中
|
|
62
59
|
*/
|
|
63
|
-
public name
|
|
60
|
+
public name?: string;
|
|
64
61
|
/**
|
|
65
62
|
* 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type
|
|
66
63
|
*/
|
|
67
|
-
public type =
|
|
64
|
+
public type: DepTargetType | string = DepTargetType.DEFAULT;
|
|
68
65
|
/**
|
|
69
66
|
* 依赖详情
|
|
70
67
|
* 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }
|
|
@@ -156,14 +153,14 @@ export class Target extends EventEmitter {
|
|
|
156
153
|
}
|
|
157
154
|
|
|
158
155
|
export class Watcher extends EventEmitter {
|
|
159
|
-
|
|
156
|
+
private targets = reactive<TargetList>({});
|
|
160
157
|
|
|
161
158
|
/**
|
|
162
159
|
* 获取指定类型中的所有target
|
|
163
160
|
* @param type 分类
|
|
164
161
|
* @returns Target[]
|
|
165
162
|
*/
|
|
166
|
-
public getTargets(type =
|
|
163
|
+
public getTargets(type: DepTargetType | string = DepTargetType.DEFAULT) {
|
|
167
164
|
return this.targets[type] || {};
|
|
168
165
|
}
|
|
169
166
|
|
|
@@ -230,7 +227,7 @@ export class Watcher extends EventEmitter {
|
|
|
230
227
|
* @param type 分类
|
|
231
228
|
* @returns void
|
|
232
229
|
*/
|
|
233
|
-
public removeTargets(type =
|
|
230
|
+
public removeTargets(type: DepTargetType | string = DepTargetType.DEFAULT) {
|
|
234
231
|
const targets = this.targets[type];
|
|
235
232
|
|
|
236
233
|
if (!targets) return;
|
|
@@ -262,6 +259,7 @@ export class Watcher extends EventEmitter {
|
|
|
262
259
|
Object.values(this.targets).forEach((targets) => {
|
|
263
260
|
Object.values(targets).forEach((target) => {
|
|
264
261
|
nodes.forEach((node) => {
|
|
262
|
+
// 先删除原有依赖,重新收集
|
|
265
263
|
target.removeDep(node);
|
|
266
264
|
this.collectItem(node, target, deep);
|
|
267
265
|
});
|
|
@@ -276,13 +274,15 @@ export class Watcher extends EventEmitter {
|
|
|
276
274
|
* @param nodes 需要清除依赖的节点
|
|
277
275
|
*/
|
|
278
276
|
public clear(nodes?: MNode[]) {
|
|
277
|
+
const clearedItemsNodeIds: Id[] = [];
|
|
279
278
|
Object.values(this.targets).forEach((targets) => {
|
|
280
279
|
Object.values(targets).forEach((target) => {
|
|
281
280
|
if (nodes) {
|
|
282
281
|
nodes.forEach((node) => {
|
|
283
282
|
target.removeDep(node);
|
|
284
283
|
|
|
285
|
-
if (Array.isArray(node.items)) {
|
|
284
|
+
if (Array.isArray(node.items) && node.items.length && !clearedItemsNodeIds.includes(node.id)) {
|
|
285
|
+
clearedItemsNodeIds.push(node.id);
|
|
286
286
|
this.clear(node.items);
|
|
287
287
|
}
|
|
288
288
|
});
|
|
@@ -304,9 +304,11 @@ export class Watcher extends EventEmitter {
|
|
|
304
304
|
this.emit('update-dep', node, fullKey);
|
|
305
305
|
} else if (!keyIsItems && Array.isArray(value)) {
|
|
306
306
|
value.forEach((item, index) => {
|
|
307
|
-
|
|
307
|
+
if (isObject(item)) {
|
|
308
|
+
collectTarget(item, `${fullKey}.${index}`);
|
|
309
|
+
}
|
|
308
310
|
});
|
|
309
|
-
} else if (
|
|
311
|
+
} else if (isObject(value)) {
|
|
310
312
|
collectTarget(value, fullKey);
|
|
311
313
|
}
|
|
312
314
|
|
|
@@ -318,6 +320,7 @@ export class Watcher extends EventEmitter {
|
|
|
318
320
|
};
|
|
319
321
|
|
|
320
322
|
Object.entries(config).forEach(([key, value]) => {
|
|
323
|
+
if (typeof value === 'undefined' || value === '') return;
|
|
321
324
|
doCollect(key, value);
|
|
322
325
|
});
|
|
323
326
|
};
|
package/src/services/editor.ts
CHANGED
|
@@ -193,7 +193,7 @@ class Editor extends BaseService {
|
|
|
193
193
|
/**
|
|
194
194
|
* 只有容器拥有布局
|
|
195
195
|
*/
|
|
196
|
-
public async getLayout(parent: MNode, node?: MNode): Promise<Layout> {
|
|
196
|
+
public async getLayout(parent: MNode, node?: MNode | null): Promise<Layout> {
|
|
197
197
|
if (node && typeof node !== 'function' && isFixed(node)) return Layout.FIXED;
|
|
198
198
|
|
|
199
199
|
if (parent.layout) {
|
|
@@ -705,9 +705,9 @@ class Editor extends BaseService {
|
|
|
705
705
|
brothers.splice(index, 1);
|
|
706
706
|
|
|
707
707
|
if (offset === LayerOffset.TOP) {
|
|
708
|
-
brothers.splice(isRelative ? 0 : brothers.length
|
|
708
|
+
brothers.splice(isRelative ? 0 : brothers.length, 0, node);
|
|
709
709
|
} else if (offset === LayerOffset.BOTTOM) {
|
|
710
|
-
brothers.splice(isRelative ? brothers.length
|
|
710
|
+
brothers.splice(isRelative ? brothers.length : 0, 0, node);
|
|
711
711
|
} else {
|
|
712
712
|
brothers.splice(index + (isRelative ? -offset : offset), 0, node);
|
|
713
713
|
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import KeyController, { KeyControllerEvent } from 'keycon';
|
|
2
|
+
|
|
3
|
+
import { isPage } from '@tmagic/utils';
|
|
4
|
+
|
|
5
|
+
import { KeyBindingCacheItem, KeyBindingCommand, KeyBindingItem } from '@editor/type';
|
|
6
|
+
|
|
7
|
+
import BaseService from './BaseService';
|
|
8
|
+
import editorService from './editor';
|
|
9
|
+
import uiService from './ui';
|
|
10
|
+
|
|
11
|
+
class Keybinding extends BaseService {
|
|
12
|
+
public ctrlKey = /mac os x/.test(navigator.userAgent.toLowerCase()) ? 'meta' : 'ctrl';
|
|
13
|
+
|
|
14
|
+
private controllers = new Map<string, KeyController>();
|
|
15
|
+
|
|
16
|
+
private bindingList: KeyBindingCacheItem[] = [];
|
|
17
|
+
|
|
18
|
+
private commands: Record<KeyBindingCommand | string, (e: KeyboardEvent) => void | Promise<void>> = {
|
|
19
|
+
[KeyBindingCommand.DELETE_NODE]: () => {
|
|
20
|
+
const nodes = editorService.get('nodes');
|
|
21
|
+
|
|
22
|
+
if (!nodes || isPage(nodes[0])) return;
|
|
23
|
+
editorService.remove(nodes);
|
|
24
|
+
},
|
|
25
|
+
[KeyBindingCommand.COPY_NODE]: () => {
|
|
26
|
+
const nodes = editorService.get('nodes');
|
|
27
|
+
nodes && editorService.copy(nodes);
|
|
28
|
+
},
|
|
29
|
+
[KeyBindingCommand.CUT_NODE]: () => {
|
|
30
|
+
const nodes = editorService.get('nodes');
|
|
31
|
+
|
|
32
|
+
if (!nodes || isPage(nodes[0])) return;
|
|
33
|
+
editorService.copy(nodes);
|
|
34
|
+
editorService.remove(nodes);
|
|
35
|
+
},
|
|
36
|
+
[KeyBindingCommand.PASTE_NODE]: () => {
|
|
37
|
+
const nodes = editorService.get('nodes');
|
|
38
|
+
nodes && editorService.paste({ offsetX: 10, offsetY: 10 });
|
|
39
|
+
},
|
|
40
|
+
[KeyBindingCommand.UNDO]: () => {
|
|
41
|
+
editorService.undo();
|
|
42
|
+
},
|
|
43
|
+
[KeyBindingCommand.REDO]: () => {
|
|
44
|
+
editorService.redo();
|
|
45
|
+
},
|
|
46
|
+
[KeyBindingCommand.ZOOM_IN]: () => {
|
|
47
|
+
uiService.zoom(0.1);
|
|
48
|
+
},
|
|
49
|
+
[KeyBindingCommand.ZOOM_OUT]: () => {
|
|
50
|
+
uiService.zoom(-0.1);
|
|
51
|
+
},
|
|
52
|
+
[KeyBindingCommand.ZOOM_RESET]: () => {
|
|
53
|
+
uiService.set('zoom', 1);
|
|
54
|
+
},
|
|
55
|
+
[KeyBindingCommand.ZOOM_FIT]: async () => {
|
|
56
|
+
uiService.set('zoom', await uiService.calcZoom());
|
|
57
|
+
},
|
|
58
|
+
[KeyBindingCommand.MOVE_UP_1]: () => {
|
|
59
|
+
editorService.move(0, -1);
|
|
60
|
+
},
|
|
61
|
+
[KeyBindingCommand.MOVE_DOWN_1]: () => {
|
|
62
|
+
editorService.move(0, 1);
|
|
63
|
+
},
|
|
64
|
+
[KeyBindingCommand.MOVE_LEFT_1]: () => {
|
|
65
|
+
editorService.move(-1, 0);
|
|
66
|
+
},
|
|
67
|
+
[KeyBindingCommand.MOVE_RIGHT_1]: () => {
|
|
68
|
+
editorService.move(1, 0);
|
|
69
|
+
},
|
|
70
|
+
[KeyBindingCommand.MOVE_UP_10]: () => {
|
|
71
|
+
editorService.move(0, -10);
|
|
72
|
+
},
|
|
73
|
+
[KeyBindingCommand.MOVE_DOWN_10]: () => {
|
|
74
|
+
editorService.move(0, 10);
|
|
75
|
+
},
|
|
76
|
+
[KeyBindingCommand.MOVE_LEFT_10]: () => {
|
|
77
|
+
editorService.move(-10, 0);
|
|
78
|
+
},
|
|
79
|
+
[KeyBindingCommand.MOVE_RIGHT_10]: () => {
|
|
80
|
+
editorService.move(10, 0);
|
|
81
|
+
},
|
|
82
|
+
[KeyBindingCommand.SWITCH_NODE]: () => {
|
|
83
|
+
editorService.selectNextNode();
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
public registeCommand(command: string, handler: (e: KeyboardEvent) => void | Promise<void>) {
|
|
88
|
+
this.commands[command] = handler;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public unregisteCommand(command: string) {
|
|
92
|
+
delete this.commands[command];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
public registeEl(name: string, el?: HTMLElement) {
|
|
96
|
+
if (name !== 'global' && !el) {
|
|
97
|
+
throw new Error('只有name为global可以不传el');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const keycon = new KeyController(el);
|
|
101
|
+
this.controllers.set(name, keycon);
|
|
102
|
+
this.bind(name);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
public unregisteEl(name: string) {
|
|
106
|
+
this.controllers.get(name)?.destroy();
|
|
107
|
+
this.controllers.delete(name);
|
|
108
|
+
this.bindingList.forEach((item) => {
|
|
109
|
+
item.binded = false;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public registe(maps: KeyBindingItem[]) {
|
|
114
|
+
for (const keybindingItem of maps) {
|
|
115
|
+
const { command, keybinding, when } = keybindingItem;
|
|
116
|
+
|
|
117
|
+
for (const [type = '', eventType = 'keydown'] of when) {
|
|
118
|
+
const cacheItem: KeyBindingCacheItem = { type, command, keybinding, eventType, binded: false };
|
|
119
|
+
|
|
120
|
+
this.bindingList.push(cacheItem);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
this.bind();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
public reset() {
|
|
128
|
+
this.controllers.forEach((keycon) => {
|
|
129
|
+
keycon.destroy();
|
|
130
|
+
});
|
|
131
|
+
this.controllers.clear();
|
|
132
|
+
this.bindingList = [];
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public destroy() {
|
|
136
|
+
this.reset();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private bind(name?: string) {
|
|
140
|
+
for (const item of this.bindingList) {
|
|
141
|
+
const { type, eventType, command, keybinding, binded } = item;
|
|
142
|
+
|
|
143
|
+
if (name && name !== type) {
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (binded) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const keycon = this.controllers.get(type);
|
|
152
|
+
if (!keycon) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const handler = (e: KeyControllerEvent) => {
|
|
157
|
+
e.inputEvent.preventDefault();
|
|
158
|
+
|
|
159
|
+
this.commands[command]?.(e.inputEvent);
|
|
160
|
+
};
|
|
161
|
+
this.getKeyconKeys(keybinding).forEach((keys) => {
|
|
162
|
+
if (keys[0]) {
|
|
163
|
+
keycon[eventType](keys, handler);
|
|
164
|
+
} else {
|
|
165
|
+
keycon[eventType](handler);
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
item.binded = true;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private getKeyconKeys(keybinding: string | string[] = '') {
|
|
174
|
+
const splitKey = (key: string) => key.split('+').map((k) => (k === 'ctrl' ? this.ctrlKey : k));
|
|
175
|
+
|
|
176
|
+
if (Array.isArray(keybinding)) {
|
|
177
|
+
return keybinding.map((key) => splitKey(key));
|
|
178
|
+
}
|
|
179
|
+
return [splitKey(keybinding)];
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export type KeybindingService = Keybinding;
|
|
184
|
+
|
|
185
|
+
export default new Keybinding();
|