@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
|
@@ -3,18 +3,23 @@
|
|
|
3
3
|
<m-form-table
|
|
4
4
|
v-if="isOldVersion"
|
|
5
5
|
ref="eventForm"
|
|
6
|
-
:size="props.size"
|
|
7
|
-
:model="model"
|
|
8
6
|
name="events"
|
|
7
|
+
:size="size"
|
|
8
|
+
:disabled="disabled"
|
|
9
|
+
:model="model"
|
|
9
10
|
:config="tableConfig"
|
|
10
11
|
@change="onChangeHandler"
|
|
11
12
|
></m-form-table>
|
|
12
13
|
|
|
13
14
|
<div v-else class="fullWidth">
|
|
14
|
-
<TMagicButton class="create-button" type="primary" size="
|
|
15
|
+
<TMagicButton class="create-button" type="primary" :size="size" :disabled="disabled" @click="addEvent()"
|
|
16
|
+
>添加事件</TMagicButton
|
|
17
|
+
>
|
|
15
18
|
<m-form-panel
|
|
16
19
|
v-for="(cardItem, index) in model[name]"
|
|
17
20
|
:key="index"
|
|
21
|
+
:disabled="disabled"
|
|
22
|
+
:size="size"
|
|
18
23
|
:config="actionsConfig"
|
|
19
24
|
:model="cardItem"
|
|
20
25
|
@change="onChangeHandler"
|
|
@@ -24,37 +29,45 @@
|
|
|
24
29
|
class="fullWidth"
|
|
25
30
|
:config="eventNameConfig"
|
|
26
31
|
:model="cardItem"
|
|
32
|
+
:disabled="disabled"
|
|
33
|
+
:size="size"
|
|
27
34
|
@change="onChangeHandler"
|
|
28
35
|
></m-form-container>
|
|
29
|
-
<TMagicButton
|
|
36
|
+
<TMagicButton
|
|
37
|
+
style="color: #f56c6c"
|
|
38
|
+
text
|
|
39
|
+
:icon="Delete"
|
|
40
|
+
:disabled="disabled"
|
|
41
|
+
:size="size"
|
|
42
|
+
@click="removeEvent(index)"
|
|
43
|
+
></TMagicButton>
|
|
30
44
|
</template>
|
|
31
45
|
</m-form-panel>
|
|
32
46
|
</div>
|
|
33
47
|
</div>
|
|
34
48
|
</template>
|
|
35
49
|
|
|
36
|
-
<script lang="ts" setup
|
|
37
|
-
import { computed,
|
|
50
|
+
<script lang="ts" setup>
|
|
51
|
+
import { computed, inject } from 'vue';
|
|
38
52
|
import { Delete } from '@element-plus/icons-vue';
|
|
39
53
|
import { has } from 'lodash-es';
|
|
40
54
|
|
|
41
55
|
import { TMagicButton } from '@tmagic/design';
|
|
42
|
-
import { FormState } from '@tmagic/form';
|
|
56
|
+
import type { FieldProps, FormState } from '@tmagic/form';
|
|
43
57
|
import { ActionType } from '@tmagic/schema';
|
|
44
58
|
|
|
45
|
-
import type { EventSelectConfig, Services } from '@editor/type';
|
|
59
|
+
import type { CodeSelectColConfig, DataSourceMethodSelectConfig, EventSelectConfig, Services } from '@editor/type';
|
|
46
60
|
|
|
47
|
-
|
|
61
|
+
defineOptions({
|
|
62
|
+
name: 'MEditorEventSelect',
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const props = defineProps<FieldProps<EventSelectConfig>>();
|
|
48
66
|
|
|
49
|
-
const props = defineProps<{
|
|
50
|
-
config: EventSelectConfig;
|
|
51
|
-
model: any;
|
|
52
|
-
prop: string;
|
|
53
|
-
name: string;
|
|
54
|
-
size: 'small' | 'default' | 'large';
|
|
55
|
-
}>();
|
|
56
67
|
const emit = defineEmits(['change']);
|
|
57
68
|
|
|
69
|
+
const services = inject<Services>('services');
|
|
70
|
+
|
|
58
71
|
// 事件名称下拉框表单配置
|
|
59
72
|
const eventNameConfig = computed(() => {
|
|
60
73
|
const defaultEventNameConfig = {
|
|
@@ -76,7 +89,7 @@ const actionTypeConfig = computed(() => {
|
|
|
76
89
|
const defaultActionTypeConfig = {
|
|
77
90
|
name: 'actionType',
|
|
78
91
|
text: '联动类型',
|
|
79
|
-
labelWidth: '
|
|
92
|
+
labelWidth: '80px',
|
|
80
93
|
type: 'select',
|
|
81
94
|
defaultValue: ActionType.COMP,
|
|
82
95
|
options: () => [
|
|
@@ -88,8 +101,15 @@ const actionTypeConfig = computed(() => {
|
|
|
88
101
|
{
|
|
89
102
|
text: '代码',
|
|
90
103
|
label: '代码',
|
|
104
|
+
disabled: !Object.keys(services?.codeBlockService.getCodeDsl() || {}).length,
|
|
91
105
|
value: ActionType.CODE,
|
|
92
106
|
},
|
|
107
|
+
{
|
|
108
|
+
text: '数据源',
|
|
109
|
+
label: '数据源',
|
|
110
|
+
disabled: !services?.dataSourceService.get('dataSources')?.filter((ds) => ds.methods?.length).length,
|
|
111
|
+
value: ActionType.DATA_SOURCE,
|
|
112
|
+
},
|
|
93
113
|
],
|
|
94
114
|
};
|
|
95
115
|
return { ...defaultActionTypeConfig, ...props.config.actionTypeConfig };
|
|
@@ -100,7 +120,7 @@ const targetCompConfig = computed(() => {
|
|
|
100
120
|
const defaultTargetCompConfig = {
|
|
101
121
|
name: 'to',
|
|
102
122
|
text: '联动组件',
|
|
103
|
-
labelWidth: '
|
|
123
|
+
labelWidth: '80px',
|
|
104
124
|
type: 'ui-select',
|
|
105
125
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
|
|
106
126
|
};
|
|
@@ -112,7 +132,7 @@ const compActionConfig = computed(() => {
|
|
|
112
132
|
const defaultCompActionConfig = {
|
|
113
133
|
name: 'method',
|
|
114
134
|
text: '动作',
|
|
115
|
-
labelWidth: '
|
|
135
|
+
labelWidth: '80px',
|
|
116
136
|
type: 'select',
|
|
117
137
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
|
|
118
138
|
options: (mForm: FormState, { model }: any) => {
|
|
@@ -130,14 +150,27 @@ const compActionConfig = computed(() => {
|
|
|
130
150
|
|
|
131
151
|
// 代码联动配置
|
|
132
152
|
const codeActionConfig = computed(() => {
|
|
133
|
-
const defaultCodeActionConfig = {
|
|
153
|
+
const defaultCodeActionConfig: CodeSelectColConfig = {
|
|
134
154
|
type: 'code-select-col',
|
|
135
155
|
labelWidth: 0,
|
|
136
|
-
|
|
156
|
+
name: 'codeId',
|
|
157
|
+
disabled: () => !services?.codeBlockService.getEditStatus(),
|
|
158
|
+
display: (mForm, { model }) => model.actionType === ActionType.CODE,
|
|
137
159
|
};
|
|
138
160
|
return { ...defaultCodeActionConfig, ...props.config.codeActionConfig };
|
|
139
161
|
});
|
|
140
162
|
|
|
163
|
+
// 数据源联动配置
|
|
164
|
+
const dataSourceActionConfig = computed(() => {
|
|
165
|
+
const defaultDataSourceActionConfig: DataSourceMethodSelectConfig = {
|
|
166
|
+
type: 'data-source-method-select',
|
|
167
|
+
name: 'dataSourceMethod',
|
|
168
|
+
labelWidth: 0,
|
|
169
|
+
display: (mForm, { model }) => model.actionType === ActionType.DATA_SOURCE,
|
|
170
|
+
};
|
|
171
|
+
return { ...defaultDataSourceActionConfig, ...props.config.dataSourceActionConfig };
|
|
172
|
+
});
|
|
173
|
+
|
|
141
174
|
// 兼容旧的数据格式
|
|
142
175
|
const tableConfig = computed(() => ({
|
|
143
176
|
type: 'table',
|
|
@@ -181,8 +214,15 @@ const actionsConfig = computed(() => ({
|
|
|
181
214
|
{
|
|
182
215
|
type: 'group-list',
|
|
183
216
|
name: 'actions',
|
|
217
|
+
expandAll: true,
|
|
184
218
|
enableToggleMode: false,
|
|
185
|
-
items: [
|
|
219
|
+
items: [
|
|
220
|
+
actionTypeConfig.value,
|
|
221
|
+
targetCompConfig.value,
|
|
222
|
+
compActionConfig.value,
|
|
223
|
+
codeActionConfig.value,
|
|
224
|
+
dataSourceActionConfig.value,
|
|
225
|
+
],
|
|
186
226
|
},
|
|
187
227
|
],
|
|
188
228
|
}));
|
package/src/fields/KeyValue.vue
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
class="m-fileds-key-value-delete"
|
|
22
22
|
type="danger"
|
|
23
23
|
:size="size"
|
|
24
|
+
:disabled="disabled"
|
|
24
25
|
circle
|
|
25
26
|
plain
|
|
26
27
|
:icon="Delete"
|
|
@@ -28,7 +29,9 @@
|
|
|
28
29
|
></TMagicButton>
|
|
29
30
|
</div>
|
|
30
31
|
|
|
31
|
-
<TMagicButton type="primary" :size="size" plain :icon="Plus" @click="addHandler"
|
|
32
|
+
<TMagicButton type="primary" :size="size" :disabled="disabled" plain :icon="Plus" @click="addHandler"
|
|
33
|
+
>添加</TMagicButton
|
|
34
|
+
>
|
|
32
35
|
</div>
|
|
33
36
|
</template>
|
|
34
37
|
|
|
@@ -37,21 +40,20 @@ import { ref, watchEffect } from 'vue';
|
|
|
37
40
|
import { Delete, Plus } from '@element-plus/icons-vue';
|
|
38
41
|
|
|
39
42
|
import { TMagicButton, TMagicInput } from '@tmagic/design';
|
|
43
|
+
import type { FieldProps } from '@tmagic/form';
|
|
44
|
+
|
|
45
|
+
defineOptions({
|
|
46
|
+
name: 'MEditorKeyValue',
|
|
47
|
+
});
|
|
40
48
|
|
|
41
49
|
const props = withDefaults(
|
|
42
|
-
defineProps<
|
|
43
|
-
|
|
50
|
+
defineProps<
|
|
51
|
+
FieldProps<{
|
|
44
52
|
type: 'key-value';
|
|
45
53
|
name: string;
|
|
46
54
|
text: string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
name: string;
|
|
50
|
-
prop: string;
|
|
51
|
-
disabled: boolean;
|
|
52
|
-
lastValues?: Record<string, any>;
|
|
53
|
-
size?: 'large' | 'default' | 'small';
|
|
54
|
-
}>(),
|
|
55
|
+
}>
|
|
56
|
+
>(),
|
|
55
57
|
{
|
|
56
58
|
disabled: false,
|
|
57
59
|
},
|
package/src/fields/UISelect.vue
CHANGED
|
@@ -1,32 +1,61 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-fields-ui-select" v-if="uiSelectMode" @click="cancelHandler">
|
|
3
|
-
<TMagicButton type="danger" :icon="Delete" text style="padding: 0"
|
|
3
|
+
<TMagicButton type="danger" :icon="Delete" :disabled="disabled" :size="size" text style="padding: 0"
|
|
4
|
+
>取消</TMagicButton
|
|
5
|
+
>
|
|
4
6
|
</div>
|
|
5
|
-
<div class="m-fields-ui-select" v-else
|
|
6
|
-
<
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
<div class="m-fields-ui-select" v-else style="display: flex">
|
|
8
|
+
<template v-if="val">
|
|
9
|
+
<TMagicTooltip content="清除" placement="top">
|
|
10
|
+
<TMagicButton
|
|
11
|
+
style="padding: 0"
|
|
12
|
+
type="danger"
|
|
13
|
+
:icon="Close"
|
|
14
|
+
:disabled="disabled"
|
|
15
|
+
:size="size"
|
|
16
|
+
text
|
|
17
|
+
@click.stop="deleteHandler"
|
|
18
|
+
></TMagicButton>
|
|
19
|
+
</TMagicTooltip>
|
|
20
|
+
|
|
21
|
+
<TMagicTooltip content="点击选中组件" placement="top">
|
|
22
|
+
<TMagicButton
|
|
23
|
+
text
|
|
24
|
+
style="padding: 0; margin: 0"
|
|
25
|
+
:disabled="disabled"
|
|
26
|
+
:size="size"
|
|
27
|
+
@click="selectNode(val)"
|
|
28
|
+
@mouseenter="highlight(val)"
|
|
29
|
+
@mouseleave="unhightlight"
|
|
30
|
+
>{{ `${toName}_${val}` }}</TMagicButton
|
|
31
|
+
>
|
|
32
|
+
</TMagicTooltip>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<TMagicTooltip v-else content="点击此处选择" placement="top">
|
|
36
|
+
<TMagicButton text style="padding: 0; margin: 0" :disabled="disabled" :size="size" @click="startSelect"
|
|
37
|
+
>点击此处选择</TMagicButton
|
|
38
|
+
>
|
|
11
39
|
</TMagicTooltip>
|
|
12
40
|
</div>
|
|
13
41
|
</template>
|
|
14
42
|
|
|
15
|
-
<script lang="ts" setup
|
|
43
|
+
<script lang="ts" setup>
|
|
16
44
|
import { computed, inject, ref } from 'vue';
|
|
17
45
|
import { Close, Delete } from '@element-plus/icons-vue';
|
|
46
|
+
import { throttle } from 'lodash-es';
|
|
18
47
|
|
|
19
48
|
import { TMagicButton, TMagicTooltip } from '@tmagic/design';
|
|
20
|
-
import { FormState } from '@tmagic/form';
|
|
49
|
+
import type { FieldProps, FormState } from '@tmagic/form';
|
|
50
|
+
import type { Id } from '@tmagic/schema';
|
|
21
51
|
|
|
22
52
|
import type { Services } from '@editor/type';
|
|
23
53
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}>();
|
|
54
|
+
defineOptions({
|
|
55
|
+
name: 'MEditorUISelect',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const props = defineProps<FieldProps<any>>();
|
|
30
59
|
|
|
31
60
|
const emit = defineEmits(['change']);
|
|
32
61
|
|
|
@@ -73,6 +102,21 @@ const deleteHandler = () => {
|
|
|
73
102
|
mForm?.$emit('field-change', props.prop, '');
|
|
74
103
|
}
|
|
75
104
|
};
|
|
105
|
+
|
|
106
|
+
const selectNode = async (id: Id) => {
|
|
107
|
+
await services?.editorService.select(id);
|
|
108
|
+
services?.editorService.get('stage')?.select(id);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const highlight = throttle((id: Id) => {
|
|
112
|
+
services?.editorService.highlight(id);
|
|
113
|
+
services?.editorService.get('stage')?.highlight(id);
|
|
114
|
+
}, 150);
|
|
115
|
+
|
|
116
|
+
const unhightlight = () => {
|
|
117
|
+
services?.editorService.set('highlightNode', null);
|
|
118
|
+
services?.editorService.get('stage')?.clearHighlight();
|
|
119
|
+
};
|
|
76
120
|
</script>
|
|
77
121
|
|
|
78
122
|
<style lang="scss">
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (C) 2023 THL A29 Limited, a Tencent company. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export * from './use-code-block-edit';
|
|
20
|
+
export * from './use-data-source-method';
|
|
21
|
+
export * from './use-stage';
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { nextTick, ref } from 'vue';
|
|
2
|
+
import { cloneDeep } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
import { tMagicMessage } from '@tmagic/design';
|
|
5
|
+
import type { CodeBlockContent } from '@tmagic/schema';
|
|
6
|
+
|
|
7
|
+
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
|
8
|
+
import type { CodeBlockService } from '@editor/services/codeBlock';
|
|
9
|
+
|
|
10
|
+
export const useCodeBlockEdit = (codeBlockService?: CodeBlockService) => {
|
|
11
|
+
const codeConfig = ref<CodeBlockContent>();
|
|
12
|
+
const codeId = ref<string>();
|
|
13
|
+
const codeBlockEditor = ref<InstanceType<typeof CodeBlockEditor>>();
|
|
14
|
+
|
|
15
|
+
// 新增代码块
|
|
16
|
+
const createCodeBlock = async () => {
|
|
17
|
+
if (!codeBlockService) {
|
|
18
|
+
tMagicMessage.error('新增代码块失败');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
codeConfig.value = {
|
|
23
|
+
name: '代码块',
|
|
24
|
+
content: `({app, params}) => {\n // place your code here\n}`,
|
|
25
|
+
params: [],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
codeId.value = await codeBlockService.getUniqueId();
|
|
29
|
+
|
|
30
|
+
await nextTick();
|
|
31
|
+
|
|
32
|
+
codeBlockEditor.value?.show();
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// 编辑代码块
|
|
36
|
+
const editCode = async (id: string) => {
|
|
37
|
+
const codeBlock = await codeBlockService?.getCodeContentById(id);
|
|
38
|
+
|
|
39
|
+
if (!codeBlock) {
|
|
40
|
+
tMagicMessage.error('获取代码块内容失败');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let codeContent = codeBlock.content;
|
|
45
|
+
|
|
46
|
+
if (typeof codeContent !== 'string') {
|
|
47
|
+
codeContent = codeContent.toString();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
codeConfig.value = {
|
|
51
|
+
...cloneDeep(codeBlock),
|
|
52
|
+
content: codeContent,
|
|
53
|
+
};
|
|
54
|
+
codeId.value = id;
|
|
55
|
+
|
|
56
|
+
await nextTick();
|
|
57
|
+
|
|
58
|
+
codeBlockEditor.value?.show();
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// 删除代码块
|
|
62
|
+
const deleteCode = async (key: string) => {
|
|
63
|
+
codeBlockService?.deleteCodeDslByIds([key]);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const submitCodeBlockHandler = async (values: CodeBlockContent) => {
|
|
67
|
+
if (!codeId.value) return;
|
|
68
|
+
|
|
69
|
+
await codeBlockService?.setCodeDslById(codeId.value, values);
|
|
70
|
+
|
|
71
|
+
codeBlockEditor.value?.hide();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
codeId,
|
|
76
|
+
codeConfig,
|
|
77
|
+
codeBlockEditor,
|
|
78
|
+
|
|
79
|
+
createCodeBlock,
|
|
80
|
+
editCode,
|
|
81
|
+
deleteCode,
|
|
82
|
+
submitCodeBlockHandler,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { nextTick, ref } from 'vue';
|
|
2
|
+
import { cloneDeep } from 'lodash-es';
|
|
3
|
+
|
|
4
|
+
import { tMagicMessage } from '@tmagic/design';
|
|
5
|
+
import type { CodeBlockContent, DataSourceSchema } from '@tmagic/schema';
|
|
6
|
+
|
|
7
|
+
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
|
8
|
+
import { getConfig } from '@editor/utils/config';
|
|
9
|
+
|
|
10
|
+
export const useDataSourceMethod = () => {
|
|
11
|
+
const codeConfig = ref<CodeBlockContent>();
|
|
12
|
+
const codeBlockEditor = ref<InstanceType<typeof CodeBlockEditor>>();
|
|
13
|
+
|
|
14
|
+
const dataSource = ref<DataSourceSchema>();
|
|
15
|
+
const dataSourceMethod = ref('');
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
codeConfig,
|
|
19
|
+
codeBlockEditor,
|
|
20
|
+
|
|
21
|
+
createCode: async (model: DataSourceSchema) => {
|
|
22
|
+
codeConfig.value = {
|
|
23
|
+
name: '',
|
|
24
|
+
content: `({ params, dataSource, app }) => {\n // place your code here\n}`,
|
|
25
|
+
params: [],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
await nextTick();
|
|
29
|
+
|
|
30
|
+
dataSource.value = model;
|
|
31
|
+
dataSourceMethod.value = '';
|
|
32
|
+
|
|
33
|
+
codeBlockEditor.value?.show();
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
editCode: async (model: DataSourceSchema, methodName: string) => {
|
|
37
|
+
const method = model.methods?.find((method) => method.name === methodName);
|
|
38
|
+
|
|
39
|
+
if (!method) {
|
|
40
|
+
tMagicMessage.error('获取数据源方法失败');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let codeContent = method.content;
|
|
45
|
+
|
|
46
|
+
if (typeof codeContent !== 'string') {
|
|
47
|
+
codeContent = codeContent.toString();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
codeConfig.value = {
|
|
51
|
+
...cloneDeep(method),
|
|
52
|
+
content: codeContent,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
await nextTick();
|
|
56
|
+
|
|
57
|
+
dataSource.value = model;
|
|
58
|
+
dataSourceMethod.value = methodName;
|
|
59
|
+
|
|
60
|
+
codeBlockEditor.value?.show();
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
deleteCode: async (model: DataSourceSchema, methodName: string) => {
|
|
64
|
+
if (!model.methods) return;
|
|
65
|
+
|
|
66
|
+
const index = model.methods.findIndex((method) => method.name === methodName);
|
|
67
|
+
|
|
68
|
+
if (index === -1) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
model.methods.splice(index, 1);
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
submitCode: (values: CodeBlockContent) => {
|
|
76
|
+
if (!dataSource.value) return;
|
|
77
|
+
|
|
78
|
+
if (!dataSource.value.methods) {
|
|
79
|
+
dataSource.value.methods = [];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (values.content) {
|
|
83
|
+
// 在保存的时候转换代码内容
|
|
84
|
+
const parseDSL = getConfig('parseDSL');
|
|
85
|
+
if (typeof values.content === 'string') {
|
|
86
|
+
values.content = parseDSL<(...args: any[]) => any>(values.content);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (dataSourceMethod.value) {
|
|
91
|
+
const index = dataSource.value.methods.findIndex((method) => method.name === dataSourceMethod.value);
|
|
92
|
+
dataSource.value.methods.splice(index, 1, values);
|
|
93
|
+
} else {
|
|
94
|
+
dataSource.value.methods.push(values);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
codeBlockEditor.value?.hide();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
};
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { computed } from 'vue';
|
|
2
2
|
|
|
3
|
+
import type { MNode } from '@tmagic/schema';
|
|
3
4
|
import StageCore, { GuidesType, RemoveEventData, SortEventData, UpdateEventData } from '@tmagic/stage';
|
|
4
5
|
|
|
5
6
|
import editorService from '@editor/services/editor';
|
|
6
7
|
import uiService from '@editor/services/ui';
|
|
7
8
|
import { H_GUIDE_LINE_STORAGE_KEY, StageOptions, V_GUIDE_LINE_STORAGE_KEY } from '@editor/type';
|
|
8
|
-
|
|
9
|
-
import { getGuideLineFromCache } from './editor';
|
|
9
|
+
import { getGuideLineFromCache } from '@editor/utils/editor';
|
|
10
10
|
|
|
11
11
|
const root = computed(() => editorService.get('root'));
|
|
12
12
|
const page = computed(() => editorService.get('page'));
|
|
@@ -74,11 +74,8 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
stage.on('remove', (ev: RemoveEventData) => {
|
|
77
|
-
editorService.
|
|
78
|
-
|
|
79
|
-
id: el.id,
|
|
80
|
-
})),
|
|
81
|
-
);
|
|
77
|
+
const nodes = ev.data.map(({ el }) => editorService.getNodeById(el.id));
|
|
78
|
+
editorService.remove(nodes.filter((node) => Boolean(node)) as MNode[]);
|
|
82
79
|
});
|
|
83
80
|
|
|
84
81
|
stage.on('select-parent', () => {
|
|
@@ -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)">
|
|
@@ -23,4 +21,8 @@
|
|
|
23
21
|
</svg>
|
|
24
22
|
</template>
|
|
25
23
|
|
|
26
|
-
<script lang="ts" setup
|
|
24
|
+
<script lang="ts" setup>
|
|
25
|
+
defineOptions({
|
|
26
|
+
name: 'MEditorCodeIcon',
|
|
27
|
+
});
|
|
28
|
+
</script>
|
package/src/index.ts
CHANGED
|
@@ -22,6 +22,11 @@ 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';
|
|
26
|
+
import DataSourceInput from './fields/DataSourceInput.vue';
|
|
27
|
+
import DataSourceMethods from './fields/DataSourceMethods.vue';
|
|
28
|
+
import DataSourceMethodSelect from './fields/DataSourceMethodSelect.vue';
|
|
29
|
+
import DataSourceSelect from './fields/DataSourceSelect.vue';
|
|
25
30
|
import EventSelect from './fields/EventSelect.vue';
|
|
26
31
|
import KeyValue from './fields/KeyValue.vue';
|
|
27
32
|
import uiSelect from './fields/UISelect.vue';
|
|
@@ -34,6 +39,7 @@ import './theme/index.scss';
|
|
|
34
39
|
|
|
35
40
|
export type { MoveableOptions } from '@tmagic/stage';
|
|
36
41
|
export * from './type';
|
|
42
|
+
export * from './hooks';
|
|
37
43
|
export * from './utils';
|
|
38
44
|
export { default as TMagicEditor } from './Editor.vue';
|
|
39
45
|
export { default as TMagicCodeEditor } from './layouts/CodeEditor.vue';
|
|
@@ -51,21 +57,31 @@ export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
|
|
|
51
57
|
export { default as CodeSelect } from './fields/CodeSelect.vue';
|
|
52
58
|
export { default as CodeSelectCol } from './fields/CodeSelectCol.vue';
|
|
53
59
|
export { default as DataSourceFields } from './fields/DataSourceFields.vue';
|
|
60
|
+
export { default as DataSourceMethods } from './fields/DataSourceMethods.vue';
|
|
61
|
+
export { default as DataSourceInput } from './fields/DataSourceInput.vue';
|
|
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';
|
|
54
65
|
export { default as EventSelect } from './fields/EventSelect.vue';
|
|
55
66
|
export { default as KeyValue } from './fields/KeyValue.vue';
|
|
56
67
|
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
|
68
|
+
export { default as CodeBlockListPanel } from './layouts/sidebar/code-block/CodeBlockListPanel.vue';
|
|
57
69
|
export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
58
70
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
59
71
|
export { default as ContentMenu } from './components/ContentMenu.vue';
|
|
60
72
|
export { default as Icon } from './components/Icon.vue';
|
|
61
|
-
export { default as LayoutContainer } from './components/
|
|
73
|
+
export { default as LayoutContainer } from './components/SplitView.vue';
|
|
74
|
+
export { default as SplitView } from './components/SplitView.vue';
|
|
75
|
+
export { default as Resizer } from './components/Resizer.vue';
|
|
76
|
+
export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue';
|
|
62
77
|
|
|
63
78
|
const defaultInstallOpt: InstallOptions = {
|
|
64
|
-
//
|
|
79
|
+
// eslint-disable-next-line no-eval
|
|
80
|
+
parseDSL: (dsl: string) => eval(dsl),
|
|
65
81
|
};
|
|
66
82
|
|
|
67
83
|
export default {
|
|
68
|
-
install: (app: App, opt?: InstallOptions): void => {
|
|
84
|
+
install: (app: App, opt?: Partial<InstallOptions>): void => {
|
|
69
85
|
const option = Object.assign(defaultInstallOpt, opt || {});
|
|
70
86
|
|
|
71
87
|
// eslint-disable-next-line no-param-reassign
|
|
@@ -81,5 +97,10 @@ export default {
|
|
|
81
97
|
app.component('m-fields-event-select', EventSelect);
|
|
82
98
|
app.component('m-fields-data-source-fields', DataSourceFields);
|
|
83
99
|
app.component('m-fields-key-value', KeyValue);
|
|
100
|
+
app.component('m-fields-data-source-input', DataSourceInput);
|
|
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);
|
|
84
105
|
},
|
|
85
106
|
};
|