@tmagic/editor 1.3.0-alpha.9 → 1.3.0-beta.0
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 +77 -218
- package/dist/tmagic-editor.js +4143 -3302
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +5289 -4434
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +15 -15
- package/src/Editor.vue +4 -5
- package/src/components/CodeBlockEditor.vue +257 -0
- package/src/components/CodeParams.vue +60 -0
- package/src/components/ContentMenu.vue +11 -3
- package/src/editorProps.ts +30 -5
- package/src/fields/Code.vue +23 -19
- package/src/fields/CodeLink.vue +6 -7
- package/src/fields/CodeSelect.vue +12 -9
- package/src/fields/CodeSelectCol.vue +70 -81
- package/src/fields/DataSourceFieldSelect.vue +47 -0
- package/src/fields/DataSourceFields.vue +28 -22
- package/src/fields/DataSourceInput.vue +21 -58
- package/src/fields/DataSourceMethodSelect.vue +136 -0
- package/src/fields/DataSourceMethods.vue +103 -0
- package/src/fields/DataSourceSelect.vue +5 -12
- package/src/fields/EventSelect.vue +53 -19
- package/src/fields/KeyValue.vue +9 -11
- package/src/fields/UISelect.vue +54 -14
- 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/CenterIcon.vue +13 -0
- package/src/icons/CodeIcon.vue +0 -2
- package/src/icons/FolderMinusIcon.vue +22 -0
- package/src/index.ts +12 -0
- package/src/initService.ts +69 -16
- package/src/layouts/CodeEditor.vue +35 -3
- package/src/layouts/Framework.vue +7 -3
- package/src/layouts/PropsPanel.vue +8 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +4 -6
- package/src/layouts/sidebar/LayerMenu.vue +20 -21
- package/src/layouts/sidebar/LayerPanel.vue +12 -2
- package/src/layouts/sidebar/Sidebar.vue +22 -36
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +81 -119
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +64 -0
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +27 -47
- package/src/layouts/sidebar/data-source/DataSourceList.vue +145 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +58 -85
- package/src/layouts/workspace/Stage.vue +3 -2
- package/src/layouts/workspace/ViewerMenu.vue +10 -35
- package/src/services/codeBlock.ts +18 -71
- package/src/services/dataSource.ts +16 -1
- package/src/services/dep.ts +22 -20
- package/src/services/editor.ts +46 -18
- package/src/services/props.ts +2 -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-methods.scss +13 -0
- package/src/theme/data-source.scss +11 -0
- package/src/theme/event.scss +15 -12
- package/src/theme/framework.scss +0 -3
- package/src/theme/layout.scss +4 -0
- package/src/theme/sidebar.scss +18 -60
- package/src/theme/theme.scss +1 -0
- package/src/type.ts +47 -7
- package/src/utils/content-menu.ts +92 -0
- package/src/utils/data-source/formConfigs/base.ts +28 -30
- package/src/utils/data-source/index.ts +65 -2
- package/src/utils/dep.ts +33 -7
- package/src/utils/index.ts +1 -1
- package/src/utils/props.ts +298 -189
- package/src/utils/undo-redo.ts +1 -1
- package/types/Editor.vue.d.ts +30 -6
- 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 +2 -2
- package/types/components/ToolButton.vue.d.ts +3 -3
- package/types/editorProps.d.ts +19 -5
- package/types/fields/Code.vue.d.ts +24 -19
- package/types/fields/CodeLink.vue.d.ts +12 -21
- package/types/fields/CodeSelect.vue.d.ts +6 -17
- package/types/fields/CodeSelectCol.vue.d.ts +10 -14
- package/types/fields/DataSourceFieldSelect.vue.d.ts +29 -0
- package/types/fields/DataSourceFields.vue.d.ts +7 -18
- package/types/fields/DataSourceInput.vue.d.ts +10 -30
- 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 +13 -29
- package/types/fields/EventSelect.vue.d.ts +2 -13
- package/types/fields/KeyValue.vue.d.ts +9 -24
- package/types/fields/UISelect.vue.d.ts +2 -11
- package/types/hooks/index.d.ts +3 -0
- package/types/{components/FunctionEditor.vue.d.ts → hooks/use-code-block-edit.d.ts} +31 -121
- package/types/hooks/use-data-source-method.d.ts +123 -0
- package/types/icons/CenterIcon.vue.d.ts +2 -0
- package/types/icons/FolderMinusIcon.vue.d.ts +2 -0
- package/types/index.d.ts +6 -0
- package/types/initService.d.ts +2 -2
- package/types/layouts/CodeEditor.vue.d.ts +7 -4
- package/types/layouts/PropsPanel.vue.d.ts +274 -2
- package/types/layouts/sidebar/Sidebar.vue.d.ts +0 -3
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +4 -9
- package/types/layouts/sidebar/code-block/{CodeBlockEditor.vue.d.ts → CodeBlockListPanel.vue.d.ts} +9 -5
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -1
- 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/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/props.d.ts +10 -115
- package/types/type.d.ts +42 -7
- package/types/utils/content-menu.d.ts +7 -0
- package/types/utils/data-source/formConfigs/base.d.ts +1 -2
- package/types/utils/data-source/index.d.ts +5 -0
- package/types/utils/dep.d.ts +4 -2
- package/types/utils/index.d.ts +1 -1
- package/types/utils/props.d.ts +13 -102
- package/src/components/CodeDraftEditor.vue +0 -148
- package/src/components/FunctionEditor.vue +0 -197
- package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +0 -100
- package/types/components/CodeDraftEditor.vue.d.ts +0 -61
- /package/types/{utils/stage.d.ts → hooks/use-stage.d.ts} +0 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4H21V6H2V4Z" fill="black" fill-opacity="0.9" />
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M5 11H18V13H5V11Z" fill="black" fill-opacity="0.9" />
|
|
5
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 18H21V20H2V18Z" fill="black" fill-opacity="0.9" />
|
|
6
|
+
</svg>
|
|
7
|
+
</template>
|
|
8
|
+
|
|
9
|
+
<script lang="ts" setup>
|
|
10
|
+
defineOptions({
|
|
11
|
+
name: 'MEditorCenterIcon',
|
|
12
|
+
});
|
|
13
|
+
</script>
|
package/src/icons/CodeIcon.vue
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<!-- 代码icon,cdn链接:https://cloudcache.tencent-cloud.com/qcloud/ui/static/government/0d463ed5-6407-4498-8865-3d05b5e70115.svg -->
|
|
3
2
|
<svg viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
4
|
-
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
|
|
5
3
|
<defs><rect id="path-1" x="0" y="0" width="32" height="32"></rect></defs>
|
|
6
4
|
<g id="组件规范" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
7
5
|
<g id="03图标" transform="translate(-561.000000, -2356.000000)">
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg
|
|
3
|
+
width="1em"
|
|
4
|
+
height="1em"
|
|
5
|
+
viewBox="0 0 16 16"
|
|
6
|
+
class="bi bi-folder-minus"
|
|
7
|
+
fill="currentColor"
|
|
8
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
9
|
+
>
|
|
10
|
+
<path
|
|
11
|
+
fill-rule="evenodd"
|
|
12
|
+
d="M9.828 4H2.19a1 1 0 0 0-.996 1.09l.637 7a1 1 0 0 0 .995.91H9v1H2.826a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31L.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3h3.982a2 2 0 0 1 1.992 2.181L15.546 8H14.54l.265-2.91A1 1 0 0 0 13.81 4H9.828zm-2.95-1.707L7.587 3H2.19c-.24 0-.47.042-.684.12L1.5 2.98a1 1 0 0 1 1-.98h3.672a1 1 0 0 1 .707.293z"
|
|
13
|
+
/>
|
|
14
|
+
<path fill-rule="evenodd" d="M11 11.5a.5.5 0 0 1 .5-.5h4a.5.5 0 0 1 0 1h-4a.5.5 0 0 1-.5-.5z" />
|
|
15
|
+
</svg>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script lang="ts" setup>
|
|
19
|
+
defineOptions({
|
|
20
|
+
name: 'MEditorFolderMinusIcon',
|
|
21
|
+
});
|
|
22
|
+
</script>
|
package/src/index.ts
CHANGED
|
@@ -22,7 +22,10 @@ import CodeLink from './fields/CodeLink.vue';
|
|
|
22
22
|
import CodeSelect from './fields/CodeSelect.vue';
|
|
23
23
|
import CodeSelectCol from './fields/CodeSelectCol.vue';
|
|
24
24
|
import DataSourceFields from './fields/DataSourceFields.vue';
|
|
25
|
+
import DataSourceFieldSelect from './fields/DataSourceFieldSelect.vue';
|
|
25
26
|
import DataSourceInput from './fields/DataSourceInput.vue';
|
|
27
|
+
import DataSourceMethods from './fields/DataSourceMethods.vue';
|
|
28
|
+
import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue';
|
|
26
29
|
import DataSourceSelect from './fields/DataSourceSelect.vue';
|
|
27
30
|
import EventSelect from './fields/EventSelect.vue';
|
|
28
31
|
import KeyValue from './fields/KeyValue.vue';
|
|
@@ -36,6 +39,7 @@ import './theme/index.scss';
|
|
|
36
39
|
|
|
37
40
|
export type { MoveableOptions } from '@tmagic/stage';
|
|
38
41
|
export * from './type';
|
|
42
|
+
export * from './hooks';
|
|
39
43
|
export * from './utils';
|
|
40
44
|
export { default as TMagicEditor } from './Editor.vue';
|
|
41
45
|
export { default as TMagicCodeEditor } from './layouts/CodeEditor.vue';
|
|
@@ -53,11 +57,15 @@ export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
|
|
|
53
57
|
export { default as CodeSelect } from './fields/CodeSelect.vue';
|
|
54
58
|
export { default as CodeSelectCol } from './fields/CodeSelectCol.vue';
|
|
55
59
|
export { default as DataSourceFields } from './fields/DataSourceFields.vue';
|
|
60
|
+
export { default as DataSourceMethods } from './fields/DataSourceMethods.vue';
|
|
56
61
|
export { default as DataSourceInput } from './fields/DataSourceInput.vue';
|
|
57
62
|
export { default as DataSourceSelect } from './fields/DataSourceSelect.vue';
|
|
63
|
+
export { default as DataSourceMethodSelect } from './fields/DataSourceMethodSelect.vue';
|
|
64
|
+
export { default as DataSourceFieldSelect } from './fields/DataSourceFieldSelect.vue';
|
|
58
65
|
export { default as EventSelect } from './fields/EventSelect.vue';
|
|
59
66
|
export { default as KeyValue } from './fields/KeyValue.vue';
|
|
60
67
|
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
|
68
|
+
export { default as CodeBlockListPanel } from './layouts/sidebar/code-block/CodeBlockListPanel.vue';
|
|
61
69
|
export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
62
70
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
63
71
|
export { default as ContentMenu } from './components/ContentMenu.vue';
|
|
@@ -65,6 +73,7 @@ export { default as Icon } from './components/Icon.vue';
|
|
|
65
73
|
export { default as LayoutContainer } from './components/SplitView.vue';
|
|
66
74
|
export { default as SplitView } from './components/SplitView.vue';
|
|
67
75
|
export { default as Resizer } from './components/Resizer.vue';
|
|
76
|
+
export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue';
|
|
68
77
|
|
|
69
78
|
const defaultInstallOpt: InstallOptions = {
|
|
70
79
|
// eslint-disable-next-line no-eval
|
|
@@ -90,5 +99,8 @@ export default {
|
|
|
90
99
|
app.component('m-fields-key-value', KeyValue);
|
|
91
100
|
app.component('m-fields-data-source-input', DataSourceInput);
|
|
92
101
|
app.component('m-fields-data-source-select', DataSourceSelect);
|
|
102
|
+
app.component('m-fields-data-source-methods', DataSourceMethods);
|
|
103
|
+
app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
|
|
104
|
+
app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
|
|
93
105
|
},
|
|
94
106
|
};
|
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];
|
|
@@ -26,6 +31,7 @@ export const initServiceState = (
|
|
|
26
31
|
uiService,
|
|
27
32
|
codeBlockService,
|
|
28
33
|
keybindingService,
|
|
34
|
+
dataSourceService,
|
|
29
35
|
}: Services,
|
|
30
36
|
) => {
|
|
31
37
|
// 初始值变化,重新设置节点信息
|
|
@@ -47,6 +53,14 @@ export const initServiceState = (
|
|
|
47
53
|
},
|
|
48
54
|
);
|
|
49
55
|
|
|
56
|
+
watch(
|
|
57
|
+
() => props.datasourceList,
|
|
58
|
+
(datasourceList) => dataSourceService.set('datasourceTypeList', datasourceList),
|
|
59
|
+
{
|
|
60
|
+
immediate: true,
|
|
61
|
+
},
|
|
62
|
+
);
|
|
63
|
+
|
|
50
64
|
watch(
|
|
51
65
|
() => props.propsConfigs,
|
|
52
66
|
(configs) => propsService.setPropsConfigs(configs),
|
|
@@ -82,6 +96,30 @@ export const initServiceState = (
|
|
|
82
96
|
},
|
|
83
97
|
);
|
|
84
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
|
+
|
|
85
123
|
watch(
|
|
86
124
|
() => props.defaultSelected,
|
|
87
125
|
(defaultSelected) => defaultSelected && editorService.select(defaultSelected),
|
|
@@ -139,6 +177,7 @@ export const initServiceEvents = (
|
|
|
139
177
|
|
|
140
178
|
if (app.dsl) {
|
|
141
179
|
app.dsl.dataSourceDeps = root.dataSourceDeps;
|
|
180
|
+
app.dsl.dataSourceCondDeps = root.dataSourceCondDeps;
|
|
142
181
|
app.dsl.dataSources = root.dataSources;
|
|
143
182
|
}
|
|
144
183
|
|
|
@@ -159,23 +198,34 @@ export const initServiceEvents = (
|
|
|
159
198
|
};
|
|
160
199
|
|
|
161
200
|
const targetAddHandler = (target: Target) => {
|
|
162
|
-
if (target.type !== 'data-source') return;
|
|
163
|
-
|
|
164
201
|
const root = editorService.get('root');
|
|
165
202
|
if (!root) return;
|
|
166
203
|
|
|
167
|
-
if (
|
|
168
|
-
root.dataSourceDeps
|
|
204
|
+
if (target.type === DepTargetType.DATA_SOURCE) {
|
|
205
|
+
if (!root.dataSourceDeps) {
|
|
206
|
+
root.dataSourceDeps = {};
|
|
207
|
+
}
|
|
208
|
+
root.dataSourceDeps[target.id] = target.deps;
|
|
169
209
|
}
|
|
170
210
|
|
|
171
|
-
|
|
211
|
+
if (target.type === DepTargetType.DATA_SOURCE_COND) {
|
|
212
|
+
if (!root.dataSourceCondDeps) {
|
|
213
|
+
root.dataSourceCondDeps = {};
|
|
214
|
+
}
|
|
215
|
+
root.dataSourceCondDeps[target.id] = target.deps;
|
|
216
|
+
}
|
|
172
217
|
};
|
|
173
218
|
|
|
174
219
|
const targetRemoveHandler = (id: string | number) => {
|
|
175
220
|
const root = editorService.get('root');
|
|
176
|
-
if (!root?.dataSourceDeps) return;
|
|
177
221
|
|
|
178
|
-
|
|
222
|
+
if (root?.dataSourceDeps) {
|
|
223
|
+
delete root.dataSourceDeps[id];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (root?.dataSourceCondDeps) {
|
|
227
|
+
delete root.dataSourceCondDeps[id];
|
|
228
|
+
}
|
|
179
229
|
};
|
|
180
230
|
|
|
181
231
|
const depUpdateHandler = (node: MNode) => {
|
|
@@ -191,6 +241,12 @@ export const initServiceEvents = (
|
|
|
191
241
|
depService.on('dep-update', depUpdateHandler);
|
|
192
242
|
depService.on('collected', collectedHandler);
|
|
193
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
|
+
|
|
194
250
|
const rootChangeHandler = async (value: MApp, preValue?: MApp | null) => {
|
|
195
251
|
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
|
196
252
|
let node;
|
|
@@ -218,14 +274,14 @@ export const initServiceEvents = (
|
|
|
218
274
|
codeBlockService.setCodeDsl(value.codeBlocks);
|
|
219
275
|
dataSourceService.set('dataSources', value.dataSources);
|
|
220
276
|
|
|
221
|
-
depService.removeTargets(
|
|
277
|
+
depService.removeTargets(DepTargetType.CODE_BLOCK);
|
|
222
278
|
|
|
223
279
|
Object.entries(value.codeBlocks).forEach(([id, code]) => {
|
|
224
280
|
depService.addTarget(createCodeBlockTarget(id, code));
|
|
225
281
|
});
|
|
226
282
|
|
|
227
283
|
value.dataSources.forEach((ds) => {
|
|
228
|
-
|
|
284
|
+
initDataSourceDepTarget(ds);
|
|
229
285
|
});
|
|
230
286
|
|
|
231
287
|
if (value && Array.isArray(value.items)) {
|
|
@@ -279,17 +335,14 @@ export const initServiceEvents = (
|
|
|
279
335
|
codeBlockService.on('remove', codeBlockRemoveHandler);
|
|
280
336
|
|
|
281
337
|
const dataSourceAddHandler = (config: DataSourceSchema) => {
|
|
282
|
-
|
|
338
|
+
initDataSourceDepTarget(config);
|
|
283
339
|
getApp()?.dataSourceManager?.addDataSource(config);
|
|
284
340
|
};
|
|
285
341
|
|
|
286
342
|
const dataSourceUpdateHandler = (config: DataSourceSchema) => {
|
|
287
|
-
if (config.title) {
|
|
288
|
-
depService.getTarget(config.id)!.name = config.title;
|
|
289
|
-
}
|
|
290
343
|
const root = editorService.get('root');
|
|
291
344
|
|
|
292
|
-
const targets = depService.getTargets(
|
|
345
|
+
const targets = depService.getTargets(DepTargetType.DATA_SOURCE);
|
|
293
346
|
|
|
294
347
|
const nodes = getNodes(Object.keys(targets[config.id].deps), root?.items);
|
|
295
348
|
|
|
@@ -1,26 +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
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
|
+
|
|
11
30
|
defineOptions({
|
|
12
31
|
name: 'MEditorCodeEditor',
|
|
13
32
|
});
|
|
14
33
|
|
|
15
34
|
const props = withDefaults(
|
|
16
35
|
defineProps<{
|
|
17
|
-
initValues?:
|
|
18
|
-
modifiedValues?:
|
|
36
|
+
initValues?: any;
|
|
37
|
+
modifiedValues?: any;
|
|
19
38
|
type?: 'diff';
|
|
20
39
|
language?: string;
|
|
21
40
|
options?: {
|
|
22
41
|
[key: string]: any;
|
|
23
42
|
};
|
|
43
|
+
height?: string;
|
|
24
44
|
autoSave?: boolean;
|
|
25
45
|
}>(),
|
|
26
46
|
{
|
|
@@ -155,6 +175,17 @@ onUnmounted(() => {
|
|
|
155
175
|
resizeObserver.disconnect();
|
|
156
176
|
});
|
|
157
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
|
+
|
|
158
189
|
defineExpose({
|
|
159
190
|
values,
|
|
160
191
|
|
|
@@ -171,6 +202,7 @@ defineExpose({
|
|
|
171
202
|
},
|
|
172
203
|
|
|
173
204
|
setEditorValue,
|
|
205
|
+
getEditorValue,
|
|
174
206
|
|
|
175
207
|
focus() {
|
|
176
208
|
vsEditor?.focus();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor">
|
|
2
|
+
<div class="m-editor" ref="content">
|
|
3
3
|
<slot name="header"></slot>
|
|
4
4
|
|
|
5
5
|
<slot name="nav"></slot>
|
|
@@ -67,6 +67,8 @@ const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
|
67
67
|
const codeOptions = inject('codeOptions', {});
|
|
68
68
|
const { editorService, uiService } = inject<Services>('services') || {};
|
|
69
69
|
|
|
70
|
+
const content = ref<HTMLDivElement>();
|
|
71
|
+
|
|
70
72
|
const root = computed(() => editorService?.get('root'));
|
|
71
73
|
|
|
72
74
|
const pageLength = computed(() => editorService?.get('pageLength') || 0);
|
|
@@ -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);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="m-editor-props-panel" v-
|
|
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,6 +8,7 @@
|
|
|
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>
|
|
@@ -17,7 +18,7 @@
|
|
|
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';
|
|
@@ -26,6 +27,10 @@ defineOptions({
|
|
|
26
27
|
name: 'MEditorPropsPanel',
|
|
27
28
|
});
|
|
28
29
|
|
|
30
|
+
defineProps<{
|
|
31
|
+
extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
|
|
32
|
+
}>();
|
|
33
|
+
|
|
29
34
|
const emit = defineEmits(['mounted']);
|
|
30
35
|
|
|
31
36
|
const internalInstance = getCurrentInstance();
|
|
@@ -78,5 +83,5 @@ const submit = async () => {
|
|
|
78
83
|
}
|
|
79
84
|
};
|
|
80
85
|
|
|
81
|
-
defineExpose({ submit });
|
|
86
|
+
defineExpose({ configForm, submit });
|
|
82
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>
|
|
@@ -36,7 +34,7 @@ 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';
|
|
@@ -84,7 +82,7 @@ const appendComponent = ({ text, type, data = {} }: ComponentItem): void => {
|
|
|
84
82
|
const dragstartHandler = ({ text, type, data = {} }: ComponentItem, e: DragEvent) => {
|
|
85
83
|
if (e.dataTransfer) {
|
|
86
84
|
e.dataTransfer.setData(
|
|
87
|
-
'text/
|
|
85
|
+
'text/json',
|
|
88
86
|
serialize({
|
|
89
87
|
name: text,
|
|
90
88
|
type,
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
<script lang="ts" setup>
|
|
6
6
|
import { computed, inject, markRaw, ref } from 'vue';
|
|
7
|
-
import {
|
|
7
|
+
import { Files, Plus } from '@element-plus/icons-vue';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import { isPage } from '@tmagic/utils';
|
|
10
10
|
|
|
11
11
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
12
|
+
import FolderMinusIcon from '@editor/icons/FolderMinusIcon.vue';
|
|
12
13
|
import type { ComponentGroup, MenuButton, MenuComponent, Services } from '@editor/type';
|
|
14
|
+
import { useCopyMenu, useDeleteMenu, useMoveToMenu, usePasteMenu } from '@editor/utils/content-menu';
|
|
13
15
|
|
|
14
16
|
defineOptions({
|
|
15
17
|
name: 'MEditorLayerMenu',
|
|
@@ -19,12 +21,14 @@ const props = defineProps<{
|
|
|
19
21
|
layerContentMenu: (MenuButton | MenuComponent)[];
|
|
20
22
|
}>();
|
|
21
23
|
|
|
24
|
+
const emit = defineEmits<{
|
|
25
|
+
'collapse-all': [];
|
|
26
|
+
}>();
|
|
27
|
+
|
|
22
28
|
const services = inject<Services>('services');
|
|
23
29
|
const menu = ref<InstanceType<typeof ContentMenu>>();
|
|
24
30
|
const node = computed(() => services?.editorService.get('node'));
|
|
25
31
|
const nodes = computed(() => services?.editorService.get('nodes'));
|
|
26
|
-
const isRoot = computed(() => node.value?.type === NodeType.ROOT);
|
|
27
|
-
const isPage = computed(() => node.value?.type === NodeType.PAGE);
|
|
28
32
|
const componentList = computed(() => services?.componentListService.getList() || []);
|
|
29
33
|
|
|
30
34
|
const createMenuItems = (group: ComponentGroup): MenuButton[] =>
|
|
@@ -81,29 +85,24 @@ const getSubMenuData = computed<MenuButton[]>(() => {
|
|
|
81
85
|
const menuData = computed<(MenuButton | MenuComponent)[]>(() => [
|
|
82
86
|
{
|
|
83
87
|
type: 'button',
|
|
84
|
-
text: '
|
|
85
|
-
icon:
|
|
86
|
-
display: () => node.value
|
|
87
|
-
items: getSubMenuData.value,
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
type: 'button',
|
|
91
|
-
text: '复制',
|
|
92
|
-
icon: markRaw(CopyDocument),
|
|
93
|
-
display: () => !isRoot.value,
|
|
88
|
+
text: '全部折叠',
|
|
89
|
+
icon: FolderMinusIcon,
|
|
90
|
+
display: () => isPage(node.value),
|
|
94
91
|
handler: () => {
|
|
95
|
-
|
|
92
|
+
emit('collapse-all');
|
|
96
93
|
},
|
|
97
94
|
},
|
|
98
95
|
{
|
|
99
96
|
type: 'button',
|
|
100
|
-
text: '
|
|
101
|
-
icon: markRaw(
|
|
102
|
-
display: () =>
|
|
103
|
-
|
|
104
|
-
node.value && services?.editorService.remove(nodes.value || []);
|
|
105
|
-
},
|
|
97
|
+
text: '新增',
|
|
98
|
+
icon: markRaw(Plus),
|
|
99
|
+
display: () => node.value?.items && nodes.value?.length === 1,
|
|
100
|
+
items: getSubMenuData.value,
|
|
106
101
|
},
|
|
102
|
+
useCopyMenu(),
|
|
103
|
+
usePasteMenu(),
|
|
104
|
+
useDeleteMenu(),
|
|
105
|
+
useMoveToMenu(services),
|
|
107
106
|
...props.layerContentMenu,
|
|
108
107
|
]);
|
|
109
108
|
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
</TMagicTree>
|
|
43
43
|
|
|
44
44
|
<Teleport to="body">
|
|
45
|
-
<LayerMenu ref="menu" :layer-content-menu="layerContentMenu"></LayerMenu>
|
|
45
|
+
<LayerMenu ref="menu" :layer-content-menu="layerContentMenu" @collapse-all="collapseAllHandler"></LayerMenu>
|
|
46
46
|
</Teleport>
|
|
47
47
|
</TMagicScrollbar>
|
|
48
48
|
</template>
|
|
@@ -156,7 +156,7 @@ const handleDragEnd = async (e: any) => {
|
|
|
156
156
|
if (!tree.value) return;
|
|
157
157
|
const { data: node } = e;
|
|
158
158
|
const parent = editorService?.getParentById(node.id, false) as MContainer;
|
|
159
|
-
const layout = await editorService?.getLayout(parent);
|
|
159
|
+
const layout = await editorService?.getLayout(parent, node);
|
|
160
160
|
node.style.position = layout;
|
|
161
161
|
if (layout === Layout.RELATIVE) {
|
|
162
162
|
node.style.top = 0;
|
|
@@ -356,4 +356,14 @@ const contextmenu = async (event: MouseEvent, data: MNode): Promise<void> => {
|
|
|
356
356
|
|
|
357
357
|
menu.value?.show(event);
|
|
358
358
|
};
|
|
359
|
+
|
|
360
|
+
const collapseAllHandler = () => {
|
|
361
|
+
const page = editorService?.get('page');
|
|
362
|
+
if (!tree.value || !page) return;
|
|
363
|
+
const rootNode = tree.value.getNode(page.id);
|
|
364
|
+
rootNode.childNodes.forEach((node: any) => {
|
|
365
|
+
node.collapse();
|
|
366
|
+
handleCollapse(node.data);
|
|
367
|
+
});
|
|
368
|
+
};
|
|
359
369
|
</script>
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
<div class="m-editor-sidebar" v-if="data.type === 'tabs' && data.items.length">
|
|
3
|
+
<div class="m-editor-sidebar-header">
|
|
4
|
+
<div
|
|
5
|
+
class="m-editor-sidebar-header-item"
|
|
6
|
+
v-for="(config, index) in sideBarItems"
|
|
7
|
+
:key="config.$key ?? index"
|
|
8
|
+
:class="{ 'is-active': activeTabName === config.text }"
|
|
9
|
+
@click="activeTabName = config.text || `${index}`"
|
|
10
|
+
>
|
|
11
|
+
<MIcon v-if="config.icon" :icon="config.icon"></MIcon>
|
|
12
|
+
<div v-if="config.text" class="magic-editor-tab-panel-title">{{ config.text }}</div>
|
|
13
|
+
</div>
|
|
14
|
+
</div>
|
|
15
|
+
<div
|
|
16
|
+
class="m-editor-sidebar-content"
|
|
10
17
|
v-for="(config, index) in sideBarItems"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
:key="config.$key || index"
|
|
18
|
+
:key="config.$key ?? index"
|
|
19
|
+
v-show="activeTabName === config.text"
|
|
14
20
|
>
|
|
15
|
-
<template #label>
|
|
16
|
-
<div :key="config.text">
|
|
17
|
-
<MIcon v-if="config.icon" :icon="config.icon"></MIcon>
|
|
18
|
-
<div v-if="config.text" class="magic-editor-tab-panel-title">{{ config.text }}</div>
|
|
19
|
-
</div>
|
|
20
|
-
</template>
|
|
21
|
-
|
|
22
21
|
<component v-if="config" :is="config.component" v-bind="config.props || {}" v-on="config?.listeners || {}">
|
|
23
22
|
<template
|
|
24
23
|
#component-list-panel-header
|
|
@@ -58,14 +57,6 @@
|
|
|
58
57
|
<component v-else-if="config.slots?.codeBlockPanelTool" :is="config.slots.codeBlockPanelTool" />
|
|
59
58
|
</template>
|
|
60
59
|
|
|
61
|
-
<template
|
|
62
|
-
#code-block-edit-panel-header="{ id }"
|
|
63
|
-
v-if="config.$key === 'code-block' || config.slots?.codeBlockEditPanelHeader"
|
|
64
|
-
>
|
|
65
|
-
<slot v-if="config.$key === 'code-block'" name="code-block-edit-panel-header" :id="id"></slot>
|
|
66
|
-
<component v-else-if="config.slots?.codeBlockEditPanelHeader" :is="config.slots.codeBlockEditPanelHeader" />
|
|
67
|
-
</template>
|
|
68
|
-
|
|
69
60
|
<template
|
|
70
61
|
#layer-node-content="{ data: nodeData, node }"
|
|
71
62
|
v-if="config.$key === 'layer' || config.slots?.layerNodeContent"
|
|
@@ -79,21 +70,19 @@
|
|
|
79
70
|
/>
|
|
80
71
|
</template>
|
|
81
72
|
</component>
|
|
82
|
-
</
|
|
83
|
-
</
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
84
75
|
</template>
|
|
85
76
|
|
|
86
|
-
<script lang="ts"
|
|
77
|
+
<script setup lang="ts">
|
|
87
78
|
import { computed, ref, watch } from 'vue';
|
|
88
79
|
import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
|
|
89
80
|
|
|
90
|
-
import { getConfig } from '@tmagic/design';
|
|
91
|
-
|
|
92
81
|
import MIcon from '@editor/components/Icon.vue';
|
|
93
82
|
import type { MenuButton, MenuComponent, SideComponent, SideItem } from '@editor/type';
|
|
94
83
|
import { SideBarData } from '@editor/type';
|
|
95
84
|
|
|
96
|
-
import
|
|
85
|
+
import CodeBlockListPanel from './code-block/CodeBlockListPanel.vue';
|
|
97
86
|
import DataSourceListPanel from './data-source/DataSourceListPanel.vue';
|
|
98
87
|
import ComponentListPanel from './ComponentListPanel.vue';
|
|
99
88
|
import LayerPanel from './LayerPanel.vue';
|
|
@@ -112,9 +101,6 @@ const props = withDefaults(
|
|
|
112
101
|
},
|
|
113
102
|
);
|
|
114
103
|
|
|
115
|
-
const tabPaneComponent = getConfig('components')?.tabPane;
|
|
116
|
-
const tabsComponent = getConfig('components')?.tabs;
|
|
117
|
-
|
|
118
104
|
const activeTabName = ref(props.data?.status);
|
|
119
105
|
|
|
120
106
|
const getItemConfig = (data: SideItem): SideComponent => {
|
|
@@ -143,7 +129,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
143
129
|
type: 'component',
|
|
144
130
|
icon: EditPen,
|
|
145
131
|
text: '代码编辑',
|
|
146
|
-
component:
|
|
132
|
+
component: CodeBlockListPanel,
|
|
147
133
|
slots: {},
|
|
148
134
|
},
|
|
149
135
|
'data-source': {
|