@tmagic/editor 1.3.0-alpha.8 → 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 +82 -218
- package/dist/tmagic-editor.js +4985 -3999
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +5013 -4012
- 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 +68 -0
- 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 +15 -0
- package/src/initService.ts +73 -16
- package/src/layouts/CodeEditor.vue +62 -10
- package/src/layouts/Framework.vue +7 -3
- package/src/layouts/PropsPanel.vue +8 -3
- package/src/layouts/sidebar/ComponentListPanel.vue +6 -9
- package/src/layouts/sidebar/LayerMenu.vue +20 -21
- package/src/layouts/sidebar/LayerNode.vue +40 -0
- package/src/layouts/sidebar/LayerPanel.vue +14 -5
- 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 -69
- package/src/layouts/workspace/Stage.vue +13 -5
- 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 +23 -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/layer-panel.scss +6 -0
- 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 +39 -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 +40 -0
- 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 -119
- 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 +7 -0
- package/types/initService.d.ts +2 -2
- package/types/layouts/CodeEditor.vue.d.ts +10 -4
- package/types/layouts/PropsPanel.vue.d.ts +274 -2
- package/types/layouts/sidebar/LayerNode.vue.d.ts +16 -0
- 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,103 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-editor-data-source-methods">
|
|
3
|
+
<MagicTable :data="model[name]" :columns="methodColumns"></MagicTable>
|
|
4
|
+
|
|
5
|
+
<div class="m-editor-data-source-methods-footer">
|
|
6
|
+
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="createCodeHandler"
|
|
7
|
+
>添加</TMagicButton
|
|
8
|
+
>
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
<CodeBlockEditor
|
|
12
|
+
v-if="codeConfig"
|
|
13
|
+
ref="codeBlockEditor"
|
|
14
|
+
:disabled="disabled"
|
|
15
|
+
:content="codeConfig"
|
|
16
|
+
:is-data-source="true"
|
|
17
|
+
@submit="submitCodeHandler"
|
|
18
|
+
></CodeBlockEditor>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
|
|
22
|
+
<script setup lang="ts">
|
|
23
|
+
import { TMagicButton } from '@tmagic/design';
|
|
24
|
+
import type { FieldProps } from '@tmagic/form';
|
|
25
|
+
import type { CodeBlockContent } from '@tmagic/schema';
|
|
26
|
+
import { MagicTable } from '@tmagic/table';
|
|
27
|
+
|
|
28
|
+
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
|
29
|
+
import { useDataSourceMethod } from '@editor/hooks/use-data-source-method';
|
|
30
|
+
import type { CodeParamStatement } from '@editor/type';
|
|
31
|
+
|
|
32
|
+
defineOptions({
|
|
33
|
+
name: 'MEditorDataSourceMethods',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const props = withDefaults(
|
|
37
|
+
defineProps<
|
|
38
|
+
FieldProps<{
|
|
39
|
+
type: 'data-source-methods';
|
|
40
|
+
}>
|
|
41
|
+
>(),
|
|
42
|
+
{
|
|
43
|
+
disabled: false,
|
|
44
|
+
},
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
const emit = defineEmits(['change']);
|
|
48
|
+
|
|
49
|
+
const { codeConfig, codeBlockEditor, createCode, editCode, deleteCode, submitCode } = useDataSourceMethod();
|
|
50
|
+
|
|
51
|
+
const methodColumns = [
|
|
52
|
+
{
|
|
53
|
+
label: '名称',
|
|
54
|
+
prop: 'name',
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
label: '描述',
|
|
58
|
+
prop: 'desc',
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
label: '执行时机',
|
|
62
|
+
prop: 'timing',
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: '参数',
|
|
66
|
+
prop: 'params',
|
|
67
|
+
formatter: (params: CodeParamStatement[]) => params.map((item) => item.name).join(', '),
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
label: '操作',
|
|
71
|
+
fixed: 'right',
|
|
72
|
+
actions: [
|
|
73
|
+
{
|
|
74
|
+
text: '编辑',
|
|
75
|
+
handler: (row: CodeBlockContent) => {
|
|
76
|
+
editCode(props.model, row.name);
|
|
77
|
+
emit('change', props.model[props.name]);
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
text: '删除',
|
|
82
|
+
buttonType: 'danger',
|
|
83
|
+
handler: (row: CodeBlockContent) => {
|
|
84
|
+
deleteCode(props.model, row.name);
|
|
85
|
+
emit('change', props.model[props.name]);
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
const createCodeHandler = () => {
|
|
93
|
+
createCode(props.model);
|
|
94
|
+
|
|
95
|
+
emit('change', props.model[props.name]);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const submitCodeHandler = (values: CodeBlockContent) => {
|
|
99
|
+
submitCode(values);
|
|
100
|
+
|
|
101
|
+
emit('change', props.model[props.name]);
|
|
102
|
+
};
|
|
103
|
+
</script>
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<MSelect
|
|
3
|
+
:model="model"
|
|
4
|
+
:name="name"
|
|
5
|
+
:size="size"
|
|
6
|
+
:prop="prop"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
:config="selectConfig"
|
|
9
|
+
:last-values="lastValues"
|
|
10
|
+
@change="changeHandler"
|
|
11
|
+
></MSelect>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { computed, inject } from 'vue';
|
|
16
|
+
|
|
17
|
+
import { FieldProps, MSelect, SelectConfig } from '@tmagic/form';
|
|
18
|
+
|
|
19
|
+
import { Services } from '../type';
|
|
20
|
+
|
|
21
|
+
defineOptions({
|
|
22
|
+
name: 'MEditorDataSourceSelect',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const emit = defineEmits(['change']);
|
|
26
|
+
|
|
27
|
+
const props = withDefaults(
|
|
28
|
+
defineProps<
|
|
29
|
+
FieldProps<{
|
|
30
|
+
type: 'data-source-select';
|
|
31
|
+
name: string;
|
|
32
|
+
text: string;
|
|
33
|
+
placeholder: string;
|
|
34
|
+
dataSourceType?: string;
|
|
35
|
+
}>
|
|
36
|
+
>(),
|
|
37
|
+
{
|
|
38
|
+
disabled: false,
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const { dataSourceService } = inject<Services>('services') || {};
|
|
43
|
+
|
|
44
|
+
const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
|
|
45
|
+
|
|
46
|
+
const selectConfig = computed<SelectConfig>(() => {
|
|
47
|
+
const { type, dataSourceType, ...config } = props.config;
|
|
48
|
+
return {
|
|
49
|
+
...config,
|
|
50
|
+
type: 'select',
|
|
51
|
+
valueKey: 'dataSourceId',
|
|
52
|
+
options: dataSources.value
|
|
53
|
+
.filter((ds) => !dataSourceType || ds.type === dataSourceType)
|
|
54
|
+
.map((ds) => ({
|
|
55
|
+
value: {
|
|
56
|
+
isBindDataSource: true,
|
|
57
|
+
dataSourceType: ds.type,
|
|
58
|
+
dataSourceId: ds.id,
|
|
59
|
+
},
|
|
60
|
+
text: ds.title || ds.id,
|
|
61
|
+
})),
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const changeHandler = (value: any) => {
|
|
66
|
+
emit('change', value);
|
|
67
|
+
};
|
|
68
|
+
</script>
|
|
@@ -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,9 +29,18 @@
|
|
|
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>
|
|
@@ -39,22 +53,16 @@ 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({
|
|
48
62
|
name: 'MEditorEventSelect',
|
|
49
63
|
});
|
|
50
64
|
|
|
51
|
-
const props = defineProps<
|
|
52
|
-
config: EventSelectConfig;
|
|
53
|
-
model: any;
|
|
54
|
-
prop: string;
|
|
55
|
-
name: string;
|
|
56
|
-
size: 'small' | 'default' | 'large';
|
|
57
|
-
}>();
|
|
65
|
+
const props = defineProps<FieldProps<EventSelectConfig>>();
|
|
58
66
|
|
|
59
67
|
const emit = defineEmits(['change']);
|
|
60
68
|
|
|
@@ -81,7 +89,7 @@ const actionTypeConfig = computed(() => {
|
|
|
81
89
|
const defaultActionTypeConfig = {
|
|
82
90
|
name: 'actionType',
|
|
83
91
|
text: '联动类型',
|
|
84
|
-
labelWidth: '
|
|
92
|
+
labelWidth: '80px',
|
|
85
93
|
type: 'select',
|
|
86
94
|
defaultValue: ActionType.COMP,
|
|
87
95
|
options: () => [
|
|
@@ -93,8 +101,15 @@ const actionTypeConfig = computed(() => {
|
|
|
93
101
|
{
|
|
94
102
|
text: '代码',
|
|
95
103
|
label: '代码',
|
|
104
|
+
disabled: !Object.keys(services?.codeBlockService.getCodeDsl() || {}).length,
|
|
96
105
|
value: ActionType.CODE,
|
|
97
106
|
},
|
|
107
|
+
{
|
|
108
|
+
text: '数据源',
|
|
109
|
+
label: '数据源',
|
|
110
|
+
disabled: !services?.dataSourceService.get('dataSources')?.filter((ds) => ds.methods?.length).length,
|
|
111
|
+
value: ActionType.DATA_SOURCE,
|
|
112
|
+
},
|
|
98
113
|
],
|
|
99
114
|
};
|
|
100
115
|
return { ...defaultActionTypeConfig, ...props.config.actionTypeConfig };
|
|
@@ -105,7 +120,7 @@ const targetCompConfig = computed(() => {
|
|
|
105
120
|
const defaultTargetCompConfig = {
|
|
106
121
|
name: 'to',
|
|
107
122
|
text: '联动组件',
|
|
108
|
-
labelWidth: '
|
|
123
|
+
labelWidth: '80px',
|
|
109
124
|
type: 'ui-select',
|
|
110
125
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
|
|
111
126
|
};
|
|
@@ -117,7 +132,7 @@ const compActionConfig = computed(() => {
|
|
|
117
132
|
const defaultCompActionConfig = {
|
|
118
133
|
name: 'method',
|
|
119
134
|
text: '动作',
|
|
120
|
-
labelWidth: '
|
|
135
|
+
labelWidth: '80px',
|
|
121
136
|
type: 'select',
|
|
122
137
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.COMP,
|
|
123
138
|
options: (mForm: FormState, { model }: any) => {
|
|
@@ -135,14 +150,27 @@ const compActionConfig = computed(() => {
|
|
|
135
150
|
|
|
136
151
|
// 代码联动配置
|
|
137
152
|
const codeActionConfig = computed(() => {
|
|
138
|
-
const defaultCodeActionConfig = {
|
|
153
|
+
const defaultCodeActionConfig: CodeSelectColConfig = {
|
|
139
154
|
type: 'code-select-col',
|
|
140
155
|
labelWidth: 0,
|
|
141
|
-
|
|
156
|
+
name: 'codeId',
|
|
157
|
+
disabled: () => !services?.codeBlockService.getEditStatus(),
|
|
158
|
+
display: (mForm, { model }) => model.actionType === ActionType.CODE,
|
|
142
159
|
};
|
|
143
160
|
return { ...defaultCodeActionConfig, ...props.config.codeActionConfig };
|
|
144
161
|
});
|
|
145
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
|
+
|
|
146
174
|
// 兼容旧的数据格式
|
|
147
175
|
const tableConfig = computed(() => ({
|
|
148
176
|
type: 'table',
|
|
@@ -188,7 +216,13 @@ const actionsConfig = computed(() => ({
|
|
|
188
216
|
name: 'actions',
|
|
189
217
|
expandAll: true,
|
|
190
218
|
enableToggleMode: false,
|
|
191
|
-
items: [
|
|
219
|
+
items: [
|
|
220
|
+
actionTypeConfig.value,
|
|
221
|
+
targetCompConfig.value,
|
|
222
|
+
compActionConfig.value,
|
|
223
|
+
codeActionConfig.value,
|
|
224
|
+
dataSourceActionConfig.value,
|
|
225
|
+
],
|
|
192
226
|
},
|
|
193
227
|
],
|
|
194
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,25 +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';
|
|
40
44
|
|
|
41
45
|
defineOptions({
|
|
42
46
|
name: 'MEditorKeyValue',
|
|
43
47
|
});
|
|
44
48
|
|
|
45
49
|
const props = withDefaults(
|
|
46
|
-
defineProps<
|
|
47
|
-
|
|
50
|
+
defineProps<
|
|
51
|
+
FieldProps<{
|
|
48
52
|
type: 'key-value';
|
|
49
53
|
name: string;
|
|
50
54
|
text: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
name: string;
|
|
54
|
-
prop: string;
|
|
55
|
-
disabled: boolean;
|
|
56
|
-
lastValues?: Record<string, any>;
|
|
57
|
-
size?: 'large' | 'default' | 'small';
|
|
58
|
-
}>(),
|
|
55
|
+
}>
|
|
56
|
+
>(),
|
|
59
57
|
{
|
|
60
58
|
disabled: false,
|
|
61
59
|
},
|
package/src/fields/UISelect.vue
CHANGED
|
@@ -1,13 +1,41 @@
|
|
|
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>
|
|
@@ -15,9 +43,11 @@
|
|
|
15
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
|
|
|
@@ -25,12 +55,7 @@ defineOptions({
|
|
|
25
55
|
name: 'MEditorUISelect',
|
|
26
56
|
});
|
|
27
57
|
|
|
28
|
-
const props = defineProps<
|
|
29
|
-
config: any;
|
|
30
|
-
model: any;
|
|
31
|
-
prop: string;
|
|
32
|
-
name: string;
|
|
33
|
-
}>();
|
|
58
|
+
const props = defineProps<FieldProps<any>>();
|
|
34
59
|
|
|
35
60
|
const emit = defineEmits(['change']);
|
|
36
61
|
|
|
@@ -77,6 +102,21 @@ const deleteHandler = () => {
|
|
|
77
102
|
mForm?.$emit('field-change', props.prop, '');
|
|
78
103
|
}
|
|
79
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
|
+
};
|
|
80
120
|
</script>
|
|
81
121
|
|
|
82
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
|
+
};
|