@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
package/src/initService.ts
CHANGED
|
@@ -7,9 +7,14 @@ import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage } from
|
|
|
7
7
|
import { getNodes } from '@tmagic/utils';
|
|
8
8
|
|
|
9
9
|
import type { Target } from './services/dep';
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
createCodeBlockTarget,
|
|
12
|
+
createDataSourceCondTarget,
|
|
13
|
+
createDataSourceMethodTarget,
|
|
14
|
+
createDataSourceTarget,
|
|
15
|
+
} from './utils/dep';
|
|
11
16
|
import editorProps from './editorProps';
|
|
12
|
-
import
|
|
17
|
+
import { DepTargetType, Services } from './type';
|
|
13
18
|
|
|
14
19
|
export declare type LooseRequired<T> = {
|
|
15
20
|
[P in string & keyof T]: T[P];
|
|
@@ -25,6 +30,8 @@ export const initServiceState = (
|
|
|
25
30
|
eventsService,
|
|
26
31
|
uiService,
|
|
27
32
|
codeBlockService,
|
|
33
|
+
keybindingService,
|
|
34
|
+
dataSourceService,
|
|
28
35
|
}: Services,
|
|
29
36
|
) => {
|
|
30
37
|
// 初始值变化,重新设置节点信息
|
|
@@ -46,6 +53,14 @@ export const initServiceState = (
|
|
|
46
53
|
},
|
|
47
54
|
);
|
|
48
55
|
|
|
56
|
+
watch(
|
|
57
|
+
() => props.datasourceList,
|
|
58
|
+
(datasourceList) => dataSourceService.set('datasourceTypeList', datasourceList),
|
|
59
|
+
{
|
|
60
|
+
immediate: true,
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
|
|
49
64
|
watch(
|
|
50
65
|
() => props.propsConfigs,
|
|
51
66
|
(configs) => propsService.setPropsConfigs(configs),
|
|
@@ -81,6 +96,30 @@ export const initServiceState = (
|
|
|
81
96
|
},
|
|
82
97
|
);
|
|
83
98
|
|
|
99
|
+
watch(
|
|
100
|
+
() => props.datasourceConfigs,
|
|
101
|
+
(configs) => {
|
|
102
|
+
Object.entries(configs).forEach(([key, value]) => {
|
|
103
|
+
dataSourceService.setFormConfig(key, value);
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
immediate: true,
|
|
108
|
+
},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
watch(
|
|
112
|
+
() => props.datasourceValues,
|
|
113
|
+
(values) => {
|
|
114
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
115
|
+
dataSourceService.setFormValue(key, value);
|
|
116
|
+
});
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
immediate: true,
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
|
|
84
123
|
watch(
|
|
85
124
|
() => props.defaultSelected,
|
|
86
125
|
(defaultSelected) => defaultSelected && editorService.select(defaultSelected),
|
|
@@ -104,6 +143,7 @@ export const initServiceState = (
|
|
|
104
143
|
uiService.resetState();
|
|
105
144
|
componentListService.resetState();
|
|
106
145
|
codeBlockService.resetState();
|
|
146
|
+
keybindingService.reset();
|
|
107
147
|
});
|
|
108
148
|
};
|
|
109
149
|
|
|
@@ -137,6 +177,7 @@ export const initServiceEvents = (
|
|
|
137
177
|
|
|
138
178
|
if (app.dsl) {
|
|
139
179
|
app.dsl.dataSourceDeps = root.dataSourceDeps;
|
|
180
|
+
app.dsl.dataSourceCondDeps = root.dataSourceCondDeps;
|
|
140
181
|
app.dsl.dataSources = root.dataSources;
|
|
141
182
|
}
|
|
142
183
|
|
|
@@ -157,23 +198,34 @@ export const initServiceEvents = (
|
|
|
157
198
|
};
|
|
158
199
|
|
|
159
200
|
const targetAddHandler = (target: Target) => {
|
|
160
|
-
if (target.type !== 'data-source') return;
|
|
161
|
-
|
|
162
201
|
const root = editorService.get('root');
|
|
163
202
|
if (!root) return;
|
|
164
203
|
|
|
165
|
-
if (
|
|
166
|
-
root.dataSourceDeps
|
|
204
|
+
if (target.type === DepTargetType.DATA_SOURCE) {
|
|
205
|
+
if (!root.dataSourceDeps) {
|
|
206
|
+
root.dataSourceDeps = {};
|
|
207
|
+
}
|
|
208
|
+
root.dataSourceDeps[target.id] = target.deps;
|
|
167
209
|
}
|
|
168
210
|
|
|
169
|
-
|
|
211
|
+
if (target.type === DepTargetType.DATA_SOURCE_COND) {
|
|
212
|
+
if (!root.dataSourceCondDeps) {
|
|
213
|
+
root.dataSourceCondDeps = {};
|
|
214
|
+
}
|
|
215
|
+
root.dataSourceCondDeps[target.id] = target.deps;
|
|
216
|
+
}
|
|
170
217
|
};
|
|
171
218
|
|
|
172
219
|
const targetRemoveHandler = (id: string | number) => {
|
|
173
220
|
const root = editorService.get('root');
|
|
174
|
-
if (!root?.dataSourceDeps) return;
|
|
175
221
|
|
|
176
|
-
|
|
222
|
+
if (root?.dataSourceDeps) {
|
|
223
|
+
delete root.dataSourceDeps[id];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (root?.dataSourceCondDeps) {
|
|
227
|
+
delete root.dataSourceCondDeps[id];
|
|
228
|
+
}
|
|
177
229
|
};
|
|
178
230
|
|
|
179
231
|
const depUpdateHandler = (node: MNode) => {
|
|
@@ -189,6 +241,12 @@ export const initServiceEvents = (
|
|
|
189
241
|
depService.on('dep-update', depUpdateHandler);
|
|
190
242
|
depService.on('collected', collectedHandler);
|
|
191
243
|
|
|
244
|
+
const initDataSourceDepTarget = (ds: DataSourceSchema) => {
|
|
245
|
+
depService.addTarget(createDataSourceTarget(ds.id));
|
|
246
|
+
depService.addTarget(createDataSourceMethodTarget(ds.id));
|
|
247
|
+
depService.addTarget(createDataSourceCondTarget(ds.id));
|
|
248
|
+
};
|
|
249
|
+
|
|
192
250
|
const rootChangeHandler = async (value: MApp, preValue?: MApp | null) => {
|
|
193
251
|
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
|
194
252
|
let node;
|
|
@@ -216,14 +274,14 @@ export const initServiceEvents = (
|
|
|
216
274
|
codeBlockService.setCodeDsl(value.codeBlocks);
|
|
217
275
|
dataSourceService.set('dataSources', value.dataSources);
|
|
218
276
|
|
|
219
|
-
depService.removeTargets(
|
|
277
|
+
depService.removeTargets(DepTargetType.CODE_BLOCK);
|
|
220
278
|
|
|
221
279
|
Object.entries(value.codeBlocks).forEach(([id, code]) => {
|
|
222
280
|
depService.addTarget(createCodeBlockTarget(id, code));
|
|
223
281
|
});
|
|
224
282
|
|
|
225
283
|
value.dataSources.forEach((ds) => {
|
|
226
|
-
|
|
284
|
+
initDataSourceDepTarget(ds);
|
|
227
285
|
});
|
|
228
286
|
|
|
229
287
|
if (value && Array.isArray(value.items)) {
|
|
@@ -234,18 +292,22 @@ export const initServiceEvents = (
|
|
|
234
292
|
}
|
|
235
293
|
};
|
|
236
294
|
|
|
295
|
+
// 新增节点,收集依赖
|
|
237
296
|
const nodeAddHandler = (nodes: MNode[]) => {
|
|
238
297
|
depService.collect(nodes);
|
|
239
298
|
};
|
|
240
299
|
|
|
300
|
+
// 节点更新,收集依赖
|
|
241
301
|
const nodeUpdateHandler = (nodes: MNode[]) => {
|
|
242
302
|
depService.collect(nodes);
|
|
243
303
|
};
|
|
244
304
|
|
|
305
|
+
// 节点删除,清除对齐的依赖收集
|
|
245
306
|
const nodeRemoveHandler = (nodes: MNode[]) => {
|
|
246
307
|
depService.clear(nodes);
|
|
247
308
|
};
|
|
248
309
|
|
|
310
|
+
// 由于历史记录变化是更新整个page,所以历史记录变化时,需要重新收集依赖
|
|
249
311
|
const historyChangeHandler = (page: MPage) => {
|
|
250
312
|
depService.collect([page], true);
|
|
251
313
|
};
|
|
@@ -273,17 +335,14 @@ export const initServiceEvents = (
|
|
|
273
335
|
codeBlockService.on('remove', codeBlockRemoveHandler);
|
|
274
336
|
|
|
275
337
|
const dataSourceAddHandler = (config: DataSourceSchema) => {
|
|
276
|
-
|
|
338
|
+
initDataSourceDepTarget(config);
|
|
277
339
|
getApp()?.dataSourceManager?.addDataSource(config);
|
|
278
340
|
};
|
|
279
341
|
|
|
280
342
|
const dataSourceUpdateHandler = (config: DataSourceSchema) => {
|
|
281
|
-
if (config.title) {
|
|
282
|
-
depService.getTarget(config.id)!.name = config.title;
|
|
283
|
-
}
|
|
284
343
|
const root = editorService.get('root');
|
|
285
344
|
|
|
286
|
-
const targets = depService.getTargets(
|
|
345
|
+
const targets = depService.getTargets(DepTargetType.DATA_SOURCE);
|
|
287
346
|
|
|
288
347
|
const nodes = getNodes(Object.keys(targets[config.id].deps), root?.items);
|
|
289
348
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</div>
|
|
12
12
|
</template>
|
|
13
13
|
|
|
14
|
-
<script lang="ts" setup
|
|
14
|
+
<script lang="ts" setup>
|
|
15
15
|
import { inject, toRaw } from 'vue';
|
|
16
16
|
import { Plus } from '@element-plus/icons-vue';
|
|
17
17
|
|
|
@@ -21,6 +21,10 @@ import MIcon from '@editor/components/Icon.vue';
|
|
|
21
21
|
import type { Services } from '@editor/type';
|
|
22
22
|
import { generatePageNameByApp } from '@editor/utils';
|
|
23
23
|
|
|
24
|
+
defineOptions({
|
|
25
|
+
name: 'MEditorAddPageBox',
|
|
26
|
+
});
|
|
27
|
+
|
|
24
28
|
const services = inject<Services>('services');
|
|
25
29
|
|
|
26
30
|
const clickHandler = () => {
|
|
@@ -1,22 +1,46 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div :class="`magic-code-editor`">
|
|
3
|
+
<Teleport to="body" :disabled="!fullScreen">
|
|
4
|
+
<div
|
|
5
|
+
:class="`magic-code-editor-wrapper${fullScreen ? ' full-screen' : ''}`"
|
|
6
|
+
:style="!fullScreen && height ? `height: ${height}` : '100%'"
|
|
7
|
+
>
|
|
8
|
+
<TMagicButton
|
|
9
|
+
class="magic-code-editor-full-screen-icon"
|
|
10
|
+
circle
|
|
11
|
+
size="small"
|
|
12
|
+
:icon="FullScreen"
|
|
13
|
+
@click="fullScreenHandler"
|
|
14
|
+
></TMagicButton>
|
|
15
|
+
<div ref="codeEditor" class="magic-code-editor-content"></div>
|
|
16
|
+
</div>
|
|
17
|
+
</Teleport>
|
|
18
|
+
</div>
|
|
3
19
|
</template>
|
|
4
20
|
|
|
5
|
-
<script lang="ts" setup
|
|
21
|
+
<script lang="ts" setup>
|
|
6
22
|
import { onMounted, onUnmounted, ref, watch } from 'vue';
|
|
23
|
+
import { FullScreen } from '@element-plus/icons-vue';
|
|
7
24
|
import { throttle } from 'lodash-es';
|
|
8
25
|
import * as monaco from 'monaco-editor';
|
|
9
26
|
import serialize from 'serialize-javascript';
|
|
10
27
|
|
|
28
|
+
import { TMagicButton } from '@tmagic/design';
|
|
29
|
+
|
|
30
|
+
defineOptions({
|
|
31
|
+
name: 'MEditorCodeEditor',
|
|
32
|
+
});
|
|
33
|
+
|
|
11
34
|
const props = withDefaults(
|
|
12
35
|
defineProps<{
|
|
13
|
-
initValues?: string |
|
|
14
|
-
modifiedValues?: string |
|
|
36
|
+
initValues?: string | Record<string | number, any> | null;
|
|
37
|
+
modifiedValues?: string | Record<string | number, any> | null;
|
|
15
38
|
type?: 'diff';
|
|
16
39
|
language?: string;
|
|
17
40
|
options?: {
|
|
18
41
|
[key: string]: any;
|
|
19
42
|
};
|
|
43
|
+
height?: string;
|
|
20
44
|
autoSave?: boolean;
|
|
21
45
|
}>(),
|
|
22
46
|
{
|
|
@@ -33,10 +57,14 @@ const emit = defineEmits(['initd', 'save']);
|
|
|
33
57
|
const toString = (v: string | any, language: string): string => {
|
|
34
58
|
let value = '';
|
|
35
59
|
if (typeof v !== 'string') {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
if (props.language.toLocaleLowerCase() === 'json') {
|
|
61
|
+
value = JSON.stringify(v, null, 2);
|
|
62
|
+
} else {
|
|
63
|
+
value = serialize(v, {
|
|
64
|
+
space: 2,
|
|
65
|
+
unsafe: true,
|
|
66
|
+
}).replace(/"(\w+)":\s/g, '$1: ');
|
|
67
|
+
}
|
|
40
68
|
} else {
|
|
41
69
|
value = v;
|
|
42
70
|
}
|
|
@@ -77,7 +105,7 @@ const setEditorValue = (v: string | any, m: string | any) => {
|
|
|
77
105
|
};
|
|
78
106
|
|
|
79
107
|
const getEditorValue = () =>
|
|
80
|
-
props.type === 'diff' ? vsDiffEditor?.getModifiedEditor().getValue() : vsEditor?.getValue();
|
|
108
|
+
(props.type === 'diff' ? vsDiffEditor?.getModifiedEditor().getValue() : vsEditor?.getValue()) || '';
|
|
81
109
|
|
|
82
110
|
const init = async () => {
|
|
83
111
|
if (!codeEditor.value) return;
|
|
@@ -105,13 +133,19 @@ const init = async () => {
|
|
|
105
133
|
if (e.keyCode === 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
|
|
106
134
|
e.preventDefault();
|
|
107
135
|
e.stopPropagation();
|
|
108
|
-
|
|
136
|
+
const newValue = getEditorValue();
|
|
137
|
+
values.value = newValue;
|
|
138
|
+
emit('save', newValue);
|
|
109
139
|
}
|
|
110
140
|
});
|
|
111
141
|
|
|
112
142
|
if (props.type !== 'diff' && props.autoSave) {
|
|
113
143
|
vsEditor?.onDidBlurEditorWidget(() => {
|
|
114
|
-
|
|
144
|
+
const newValue = getEditorValue();
|
|
145
|
+
if (values.value !== newValue) {
|
|
146
|
+
values.value = newValue;
|
|
147
|
+
emit('save', newValue);
|
|
148
|
+
}
|
|
115
149
|
});
|
|
116
150
|
}
|
|
117
151
|
|
|
@@ -141,11 +175,32 @@ onUnmounted(() => {
|
|
|
141
175
|
resizeObserver.disconnect();
|
|
142
176
|
});
|
|
143
177
|
|
|
178
|
+
const fullScreen = ref(false);
|
|
179
|
+
const fullScreenHandler = () => {
|
|
180
|
+
fullScreen.value = !fullScreen.value;
|
|
181
|
+
setTimeout(() => {
|
|
182
|
+
vsEditor?.focus();
|
|
183
|
+
vsEditor?.layout();
|
|
184
|
+
vsDiffEditor?.focus();
|
|
185
|
+
vsDiffEditor?.layout();
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
|
|
144
189
|
defineExpose({
|
|
190
|
+
values,
|
|
191
|
+
|
|
145
192
|
getEditor() {
|
|
146
193
|
return vsEditor || vsDiffEditor;
|
|
147
194
|
},
|
|
148
195
|
|
|
196
|
+
getVsEditor() {
|
|
197
|
+
return vsEditor;
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
getVsDiffEditor() {
|
|
201
|
+
return vsDiffEditor;
|
|
202
|
+
},
|
|
203
|
+
|
|
149
204
|
setEditorValue,
|
|
150
205
|
|
|
151
206
|
focus() {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor">
|
|
3
|
-
<slot name="
|
|
2
|
+
<div class="m-editor" ref="content">
|
|
3
|
+
<slot name="header"></slot>
|
|
4
4
|
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@save="saveCode"
|
|
11
|
-
|
|
5
|
+
<slot name="nav"></slot>
|
|
6
|
+
|
|
7
|
+
<slot name="content-before"></slot>
|
|
8
|
+
|
|
9
|
+
<slot name="src-code" v-if="showSrc">
|
|
10
|
+
<CodeEditor class="m-editor-content" :init-values="root" :options="codeOptions" @save="saveCode"></CodeEditor>
|
|
11
|
+
</slot>
|
|
12
12
|
|
|
13
|
-
<
|
|
13
|
+
<SplitView
|
|
14
14
|
v-else
|
|
15
15
|
class="m-editor-content"
|
|
16
16
|
left-class="m-editor-framework-left"
|
|
@@ -33,41 +33,43 @@
|
|
|
33
33
|
</slot>
|
|
34
34
|
</template>
|
|
35
35
|
|
|
36
|
-
<template v-if="pageLength > 0
|
|
36
|
+
<template v-if="pageLength > 0" #right>
|
|
37
37
|
<TMagicScrollbar>
|
|
38
38
|
<slot name="props-panel"></slot>
|
|
39
39
|
</TMagicScrollbar>
|
|
40
40
|
</template>
|
|
41
|
-
</
|
|
41
|
+
</SplitView>
|
|
42
|
+
|
|
43
|
+
<slot name="content-after"></slot>
|
|
44
|
+
<slot name="footer"></slot>
|
|
42
45
|
</div>
|
|
43
46
|
</template>
|
|
44
47
|
|
|
45
|
-
<script lang="ts" setup
|
|
48
|
+
<script lang="ts" setup>
|
|
46
49
|
import { computed, inject, ref, watch } from 'vue';
|
|
47
50
|
|
|
48
51
|
import { TMagicScrollbar } from '@tmagic/design';
|
|
49
52
|
|
|
50
|
-
import
|
|
53
|
+
import SplitView from '@editor/components/SplitView.vue';
|
|
51
54
|
import type { GetColumnWidth, Services } from '@editor/type';
|
|
55
|
+
import { getConfig } from '@editor/utils/config';
|
|
52
56
|
|
|
53
57
|
import AddPageBox from './AddPageBox.vue';
|
|
58
|
+
import CodeEditor from './CodeEditor.vue';
|
|
59
|
+
|
|
60
|
+
defineOptions({
|
|
61
|
+
name: 'MEditorFramework',
|
|
62
|
+
});
|
|
54
63
|
|
|
55
64
|
const DEFAULT_LEFT_COLUMN_WIDTH = 310;
|
|
56
65
|
const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
57
66
|
|
|
58
|
-
|
|
59
|
-
defineProps<{
|
|
60
|
-
codeOptions?: Record<string, any>;
|
|
61
|
-
}>(),
|
|
62
|
-
{
|
|
63
|
-
codeOptions: () => ({}),
|
|
64
|
-
},
|
|
65
|
-
);
|
|
66
|
-
|
|
67
|
+
const codeOptions = inject('codeOptions', {});
|
|
67
68
|
const { editorService, uiService } = inject<Services>('services') || {};
|
|
68
69
|
|
|
70
|
+
const content = ref<HTMLDivElement>();
|
|
71
|
+
|
|
69
72
|
const root = computed(() => editorService?.get('root'));
|
|
70
|
-
const nodes = computed(() => editorService?.get('nodes') || []);
|
|
71
73
|
|
|
72
74
|
const pageLength = computed(() => editorService?.get('pageLength') || 0);
|
|
73
75
|
const showSrc = computed(() => uiService?.get('showSrc'));
|
|
@@ -91,13 +93,15 @@ watch(
|
|
|
91
93
|
|
|
92
94
|
columnWidth.value.left = left;
|
|
93
95
|
|
|
96
|
+
const container = content.value || document.body;
|
|
97
|
+
|
|
94
98
|
if (length <= 0) {
|
|
95
99
|
columnWidth.value.right = undefined;
|
|
96
|
-
columnWidth.value.center =
|
|
100
|
+
columnWidth.value.center = container.clientWidth - left;
|
|
97
101
|
} else {
|
|
98
102
|
const right = columnWidth.value.right || RightColumnWidthCacheData || DEFAULT_RIGHT_COLUMN_WIDTH;
|
|
99
103
|
columnWidth.value.right = right;
|
|
100
|
-
columnWidth.value.center =
|
|
104
|
+
columnWidth.value.center = container.clientWidth - left - right;
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
uiService?.set('columnWidth', columnWidth.value as GetColumnWidth);
|
|
@@ -131,8 +135,8 @@ const columnWidthChange = (columnW: GetColumnWidth) => {
|
|
|
131
135
|
|
|
132
136
|
const saveCode = (value: string) => {
|
|
133
137
|
try {
|
|
134
|
-
|
|
135
|
-
editorService?.set('root',
|
|
138
|
+
const parseDSL = getConfig('parseDSL');
|
|
139
|
+
editorService?.set('root', parseDSL(value));
|
|
136
140
|
} catch (e: any) {
|
|
137
141
|
console.error(e);
|
|
138
142
|
}
|
package/src/layouts/NavMenu.vue
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
</div>
|
|
7
7
|
</template>
|
|
8
8
|
|
|
9
|
-
<script lang="ts" setup
|
|
9
|
+
<script lang="ts" setup>
|
|
10
10
|
import { computed, inject, markRaw } from 'vue';
|
|
11
11
|
import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
|
|
12
12
|
|
|
@@ -15,6 +15,10 @@ import { NodeType } from '@tmagic/schema';
|
|
|
15
15
|
import ToolButton from '@editor/components/ToolButton.vue';
|
|
16
16
|
import { ColumnLayout, MenuBarData, MenuButton, MenuComponent, MenuItem, Services } from '@editor/type';
|
|
17
17
|
|
|
18
|
+
defineOptions({
|
|
19
|
+
name: 'MEditorNavMenu',
|
|
20
|
+
});
|
|
21
|
+
|
|
18
22
|
const props = withDefaults(
|
|
19
23
|
defineProps<{
|
|
20
24
|
data?: MenuBarData;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-props-panel">
|
|
2
|
+
<div class="m-editor-props-panel" v-show="nodes.length === 1">
|
|
3
3
|
<slot name="props-panel-header"></slot>
|
|
4
4
|
<MForm
|
|
5
5
|
ref="configForm"
|
|
@@ -8,20 +8,29 @@
|
|
|
8
8
|
:size="propsPanelSize"
|
|
9
9
|
:init-values="values"
|
|
10
10
|
:config="curFormConfig"
|
|
11
|
+
:extend-state="extendState"
|
|
11
12
|
@change="submit"
|
|
12
13
|
></MForm>
|
|
13
14
|
</div>
|
|
14
15
|
</template>
|
|
15
16
|
|
|
16
|
-
<script lang="ts" setup
|
|
17
|
+
<script lang="ts" setup>
|
|
17
18
|
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, watchEffect } from 'vue';
|
|
18
19
|
|
|
19
20
|
import { tMagicMessage } from '@tmagic/design';
|
|
20
|
-
import type { FormValue } from '@tmagic/form';
|
|
21
|
+
import type { FormState, FormValue } from '@tmagic/form';
|
|
21
22
|
import { MForm } from '@tmagic/form';
|
|
22
23
|
|
|
23
24
|
import type { Services } from '@editor/type';
|
|
24
25
|
|
|
26
|
+
defineOptions({
|
|
27
|
+
name: 'MEditorPropsPanel',
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
defineProps<{
|
|
31
|
+
extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
32
|
+
}>();
|
|
33
|
+
|
|
25
34
|
const emit = defineEmits(['mounted']);
|
|
26
35
|
|
|
27
36
|
const internalInstance = getCurrentInstance();
|
|
@@ -31,6 +40,7 @@ const configForm = ref<InstanceType<typeof MForm>>();
|
|
|
31
40
|
const curFormConfig = ref<any>([]);
|
|
32
41
|
const services = inject<Services>('services');
|
|
33
42
|
const node = computed(() => services?.editorService.get('node'));
|
|
43
|
+
const nodes = computed(() => services?.editorService.get('nodes') || []);
|
|
34
44
|
const propsPanelSize = computed(() => services?.uiService.get('propsPanelSize') || 'small');
|
|
35
45
|
const stage = computed(() => services?.editorService.get('stage'));
|
|
36
46
|
|
|
@@ -73,5 +83,5 @@ const submit = async () => {
|
|
|
73
83
|
}
|
|
74
84
|
};
|
|
75
85
|
|
|
76
|
-
defineExpose({ submit });
|
|
86
|
+
defineExpose({ configForm, submit });
|
|
77
87
|
</script>
|
|
@@ -18,11 +18,9 @@
|
|
|
18
18
|
@drag="dragHandler"
|
|
19
19
|
>
|
|
20
20
|
<slot name="component-list-item" :component="item">
|
|
21
|
-
<MIcon :icon="item.icon"></MIcon>
|
|
21
|
+
<MIcon :title="item.text" :icon="item.icon"></MIcon>
|
|
22
22
|
|
|
23
|
-
<
|
|
24
|
-
<span>{{ item.text }}</span>
|
|
25
|
-
</TMagicTooltip>
|
|
23
|
+
<span :title="item.text">{{ item.text }}</span>
|
|
26
24
|
</slot>
|
|
27
25
|
</div>
|
|
28
26
|
</TMagicCollapseItem>
|
|
@@ -31,18 +29,22 @@
|
|
|
31
29
|
</TMagicScrollbar>
|
|
32
30
|
</template>
|
|
33
31
|
|
|
34
|
-
<script lang="ts" setup
|
|
32
|
+
<script lang="ts" setup>
|
|
35
33
|
import { computed, inject, ref } from 'vue';
|
|
36
34
|
import { Grid } from '@element-plus/icons-vue';
|
|
37
35
|
import serialize from 'serialize-javascript';
|
|
38
36
|
|
|
39
|
-
import { TMagicCollapse, TMagicCollapseItem, TMagicScrollbar
|
|
37
|
+
import { TMagicCollapse, TMagicCollapseItem, TMagicScrollbar } from '@tmagic/design';
|
|
40
38
|
import { removeClassNameByClassName } from '@tmagic/utils';
|
|
41
39
|
|
|
42
40
|
import MIcon from '@editor/components/Icon.vue';
|
|
43
41
|
import SearchInput from '@editor/components/SearchInput.vue';
|
|
44
42
|
import type { ComponentGroup, ComponentItem, Services, StageOptions } from '@editor/type';
|
|
45
43
|
|
|
44
|
+
defineOptions({
|
|
45
|
+
name: 'MEditorComponentListPanel',
|
|
46
|
+
});
|
|
47
|
+
|
|
46
48
|
const searchText = ref('');
|
|
47
49
|
|
|
48
50
|
const filterTextChangeHandler = (v: string) => {
|
|
@@ -79,14 +81,13 @@ const appendComponent = ({ text, type, data = {} }: ComponentItem): void => {
|
|
|
79
81
|
|
|
80
82
|
const dragstartHandler = ({ text, type, data = {} }: ComponentItem, e: DragEvent) => {
|
|
81
83
|
if (e.dataTransfer) {
|
|
82
|
-
e.dataTransfer.effectAllowed = 'move';
|
|
83
84
|
e.dataTransfer.setData(
|
|
84
|
-
'
|
|
85
|
+
'text/json',
|
|
85
86
|
serialize({
|
|
86
87
|
name: text,
|
|
87
88
|
type,
|
|
88
89
|
...data,
|
|
89
|
-
})
|
|
90
|
+
}),
|
|
90
91
|
);
|
|
91
92
|
}
|
|
92
93
|
};
|
|
@@ -117,6 +118,6 @@ const dragHandler = (e: DragEvent) => {
|
|
|
117
118
|
|
|
118
119
|
if (timeout || !stage.value) return;
|
|
119
120
|
|
|
120
|
-
timeout = stage.value.
|
|
121
|
+
timeout = stage.value.delayedMarkContainer(e);
|
|
121
122
|
};
|
|
122
123
|
</script>
|
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
<ContentMenu :menu-data="menuData" ref="menu" style="overflow: initial"></ContentMenu>
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
|
-
<script lang="ts" setup
|
|
5
|
+
<script lang="ts" setup>
|
|
6
6
|
import { computed, inject, markRaw, ref } from 'vue';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
import { NodeType } from '@tmagic/schema';
|
|
7
|
+
import { Files, Plus } from '@element-plus/icons-vue';
|
|
10
8
|
|
|
11
9
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
12
10
|
import type { ComponentGroup, MenuButton, MenuComponent, Services } from '@editor/type';
|
|
11
|
+
import { useCopyMenu, useDeleteMenu, useMoveToMenu, usePasteMenu } from '@editor/utils/content-menu';
|
|
12
|
+
|
|
13
|
+
defineOptions({
|
|
14
|
+
name: 'MEditorLayerMenu',
|
|
15
|
+
});
|
|
13
16
|
|
|
14
17
|
const props = defineProps<{
|
|
15
18
|
layerContentMenu: (MenuButton | MenuComponent)[];
|
|
@@ -18,8 +21,7 @@ const props = defineProps<{
|
|
|
18
21
|
const services = inject<Services>('services');
|
|
19
22
|
const menu = ref<InstanceType<typeof ContentMenu>>();
|
|
20
23
|
const node = computed(() => services?.editorService.get('node'));
|
|
21
|
-
const
|
|
22
|
-
const isPage = computed(() => node.value?.type === NodeType.PAGE);
|
|
24
|
+
const nodes = computed(() => services?.editorService.get('nodes'));
|
|
23
25
|
const componentList = computed(() => services?.componentListService.getList() || []);
|
|
24
26
|
|
|
25
27
|
const createMenuItems = (group: ComponentGroup): MenuButton[] =>
|
|
@@ -78,27 +80,13 @@ const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
|
|
|
78
80
|
type: 'button',
|
|
79
81
|
text: '新增',
|
|
80
82
|
icon: markRaw(Plus),
|
|
81
|
-
display: () => node.value?.items,
|
|
83
|
+
display: () => node.value?.items && nodes.value?.length === 1,
|
|
82
84
|
items: getSubMenuData.value,
|
|
83
85
|
},
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
display: () => !isRoot.value,
|
|
89
|
-
handler: () => {
|
|
90
|
-
node.value && services?.editorService.copy(node.value);
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
type: 'button',
|
|
95
|
-
text: '删除',
|
|
96
|
-
icon: markRaw(Delete),
|
|
97
|
-
display: () => !isRoot.value && !isPage.value,
|
|
98
|
-
handler: () => {
|
|
99
|
-
node.value && services?.editorService.remove(node.value);
|
|
100
|
-
},
|
|
101
|
-
},
|
|
86
|
+
useCopyMenu(),
|
|
87
|
+
usePasteMenu(),
|
|
88
|
+
useDeleteMenu(),
|
|
89
|
+
useMoveToMenu(services),
|
|
102
90
|
...props.layerContentMenu,
|
|
103
91
|
]);
|
|
104
92
|
|