@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
|
@@ -9,10 +9,26 @@
|
|
|
9
9
|
@change="onParamsChangeHandler"
|
|
10
10
|
></m-form-container>
|
|
11
11
|
<!-- 查看/编辑按钮 -->
|
|
12
|
-
<Icon class="icon" :icon="
|
|
12
|
+
<Icon v-if="model[name]" class="icon" :icon="!disabled ? Edit : View" @click="editCode(model[name])"></Icon>
|
|
13
13
|
</div>
|
|
14
|
+
|
|
14
15
|
<!-- 参数填写框 -->
|
|
15
|
-
<
|
|
16
|
+
<CodeParams
|
|
17
|
+
v-if="paramsConfig.length"
|
|
18
|
+
name="params"
|
|
19
|
+
:model="model"
|
|
20
|
+
:size="size"
|
|
21
|
+
:params-config="paramsConfig"
|
|
22
|
+
@change="onParamsChangeHandler"
|
|
23
|
+
></CodeParams>
|
|
24
|
+
|
|
25
|
+
<CodeBlockEditor
|
|
26
|
+
ref="codeBlockEditor"
|
|
27
|
+
v-if="codeConfig"
|
|
28
|
+
:disabled="disabled"
|
|
29
|
+
:content="codeConfig"
|
|
30
|
+
@submit="submitCodeBlockHandler"
|
|
31
|
+
></CodeBlockEditor>
|
|
16
32
|
</div>
|
|
17
33
|
</template>
|
|
18
34
|
|
|
@@ -21,45 +37,61 @@ import { computed, inject, ref, watch } from 'vue';
|
|
|
21
37
|
import { Edit, View } from '@element-plus/icons-vue';
|
|
22
38
|
import { isEmpty, map } from 'lodash-es';
|
|
23
39
|
|
|
24
|
-
import { createValues,
|
|
25
|
-
import { Id } from '@tmagic/schema';
|
|
40
|
+
import { createValues, FieldProps } from '@tmagic/form';
|
|
41
|
+
import type { Id } from '@tmagic/schema';
|
|
26
42
|
|
|
43
|
+
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
|
44
|
+
import CodeParams from '@editor/components/CodeParams.vue';
|
|
27
45
|
import Icon from '@editor/components/Icon.vue';
|
|
28
|
-
import
|
|
46
|
+
import { useCodeBlockEdit } from '@editor/hooks/use-code-block-edit';
|
|
47
|
+
import type { CodeParamStatement, CodeSelectColConfig, Services } from '@editor/type';
|
|
29
48
|
|
|
30
49
|
defineOptions({
|
|
31
50
|
name: 'MEditorCodeSelectCol',
|
|
32
51
|
});
|
|
33
52
|
|
|
34
53
|
const services = inject<Services>('services');
|
|
35
|
-
const mForm = inject<FormState>('mForm');
|
|
36
54
|
const emit = defineEmits(['change']);
|
|
37
55
|
|
|
38
|
-
const props = withDefaults(
|
|
39
|
-
|
|
40
|
-
config: any;
|
|
41
|
-
model: any;
|
|
42
|
-
prop: string;
|
|
43
|
-
name: string;
|
|
44
|
-
size: 'small' | 'default' | 'large';
|
|
45
|
-
}>(),
|
|
46
|
-
{},
|
|
47
|
-
);
|
|
48
|
-
const codeDsl = computed(() => services?.codeBlockService.getCodeDsl());
|
|
49
|
-
const editable = computed(() => services?.codeBlockService.getEditStatus());
|
|
50
|
-
const codeParamsConfig = ref<FieldsetConfig>({
|
|
51
|
-
type: 'fieldset',
|
|
52
|
-
items: [],
|
|
53
|
-
legend: '参数',
|
|
54
|
-
labelWidth: '70px',
|
|
55
|
-
name: 'params',
|
|
56
|
-
display: false,
|
|
56
|
+
const props = withDefaults(defineProps<FieldProps<CodeSelectColConfig>>(), {
|
|
57
|
+
disabled: false,
|
|
57
58
|
});
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* 根据代码块id获取代码块参数配置
|
|
62
|
+
* @param codeId 代码块ID
|
|
63
|
+
*/
|
|
64
|
+
const getParamItemsConfig = (codeId?: Id): CodeParamStatement[] => {
|
|
65
|
+
if (!codeDsl.value || !codeId) return [];
|
|
66
|
+
|
|
67
|
+
const paramStatements = codeDsl.value[codeId]?.params;
|
|
68
|
+
|
|
69
|
+
if (isEmpty(paramStatements)) return [];
|
|
70
|
+
|
|
71
|
+
return paramStatements.map((paramState: CodeParamStatement) => ({
|
|
72
|
+
labelWidth: '100px',
|
|
73
|
+
text: paramState.name,
|
|
74
|
+
...paramState,
|
|
75
|
+
}));
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const codeDsl = computed(() => services?.codeBlockService.getCodeDsl());
|
|
79
|
+
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model[props.name]));
|
|
80
|
+
|
|
81
|
+
watch(
|
|
82
|
+
() => props.model[props.name],
|
|
83
|
+
(v, preV) => {
|
|
84
|
+
if (v !== preV) {
|
|
85
|
+
paramsConfig.value = getParamItemsConfig(v);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
);
|
|
89
|
+
|
|
58
90
|
const selectConfig = {
|
|
59
91
|
type: 'select',
|
|
60
92
|
text: '代码块',
|
|
61
|
-
name:
|
|
62
|
-
labelWidth: '
|
|
93
|
+
name: props.name,
|
|
94
|
+
labelWidth: '80px',
|
|
63
95
|
options: () => {
|
|
64
96
|
if (codeDsl.value) {
|
|
65
97
|
return map(codeDsl.value, (value, key) => ({
|
|
@@ -72,68 +104,25 @@ const selectConfig = {
|
|
|
72
104
|
},
|
|
73
105
|
onChange: (formState: any, codeId: Id, { model }: any) => {
|
|
74
106
|
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
};
|
|
107
|
+
paramsConfig.value = getParamItemsConfig(codeId);
|
|
78
108
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!codeDsl.value) return [];
|
|
85
|
-
const paramStatements = codeDsl.value[codeId]?.params;
|
|
86
|
-
if (isEmpty(paramStatements)) return [];
|
|
87
|
-
return paramStatements.map((paramState: CodeParamStatement) => ({
|
|
88
|
-
labelWidth: '100px',
|
|
89
|
-
text: paramState.name,
|
|
90
|
-
...paramState,
|
|
91
|
-
}));
|
|
92
|
-
};
|
|
109
|
+
if (paramsConfig.value.length) {
|
|
110
|
+
model.params = createValues(formState, paramsConfig.value, {}, model.params);
|
|
111
|
+
} else {
|
|
112
|
+
model.params = {};
|
|
113
|
+
}
|
|
93
114
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
* @param codeId 代码块ID
|
|
97
|
-
*/
|
|
98
|
-
const getCodeParamsConfig = (codeId: Id) => {
|
|
99
|
-
const paramsConfig = getParamItemsConfig(codeId);
|
|
100
|
-
// 如果参数没有填值,则使用createValues补全空值
|
|
101
|
-
if (!props.model.params || isEmpty(props.model.params)) {
|
|
102
|
-
props.model.params = {};
|
|
103
|
-
createValues(mForm, paramsConfig, {}, props.model.params);
|
|
104
|
-
}
|
|
105
|
-
codeParamsConfig.value = {
|
|
106
|
-
type: 'fieldset',
|
|
107
|
-
items: paramsConfig,
|
|
108
|
-
legend: '参数',
|
|
109
|
-
labelWidth: '70px',
|
|
110
|
-
name: 'params',
|
|
111
|
-
display: !isEmpty(paramsConfig),
|
|
112
|
-
};
|
|
115
|
+
return codeId;
|
|
116
|
+
},
|
|
113
117
|
};
|
|
114
118
|
|
|
115
119
|
/**
|
|
116
120
|
* 参数值修改更新
|
|
117
121
|
*/
|
|
118
|
-
const onParamsChangeHandler = () => {
|
|
122
|
+
const onParamsChangeHandler = (value: any) => {
|
|
123
|
+
props.model.params = value.params;
|
|
119
124
|
emit('change', props.model);
|
|
120
125
|
};
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
// TODO onchange在watch之前触发
|
|
124
|
-
watch(
|
|
125
|
-
() => props.model.codeId,
|
|
126
|
-
(codeId: Id) => {
|
|
127
|
-
if (!codeId) return;
|
|
128
|
-
getCodeParamsConfig(codeId);
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
immediate: true,
|
|
132
|
-
},
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
// 打开代码编辑框
|
|
136
|
-
const editCode = () => {
|
|
137
|
-
services?.codeBlockService.setCodeEditorContent(true, props.model.codeId);
|
|
138
|
-
};
|
|
127
|
+
const { codeBlockEditor, codeConfig, editCode, submitCodeBlockHandler } = useCodeBlockEdit(services?.codeBlockService);
|
|
139
128
|
</script>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<m-form-container
|
|
3
|
+
:config="{
|
|
4
|
+
...config,
|
|
5
|
+
...cascaderConfig,
|
|
6
|
+
}"
|
|
7
|
+
:model="model"
|
|
8
|
+
@change="onChangeHandler"
|
|
9
|
+
></m-form-container>
|
|
10
|
+
</template>
|
|
11
|
+
|
|
12
|
+
<script setup lang="ts">
|
|
13
|
+
import { computed, inject } from 'vue';
|
|
14
|
+
|
|
15
|
+
import type { FieldProps } from '@tmagic/form';
|
|
16
|
+
|
|
17
|
+
import type { DataSourceFieldSelectConfig, Services } from '@editor/type';
|
|
18
|
+
|
|
19
|
+
const services = inject<Services>('services');
|
|
20
|
+
const emit = defineEmits(['change']);
|
|
21
|
+
|
|
22
|
+
const props = withDefaults(defineProps<FieldProps<DataSourceFieldSelectConfig>>(), {
|
|
23
|
+
disabled: false,
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const dataSources = computed(() => services?.dataSourceService.get('dataSources'));
|
|
27
|
+
|
|
28
|
+
const cascaderConfig = {
|
|
29
|
+
type: 'cascader',
|
|
30
|
+
name: props.name,
|
|
31
|
+
options: () =>
|
|
32
|
+
dataSources.value
|
|
33
|
+
?.filter((ds) => ds.fields?.length)
|
|
34
|
+
?.map((ds) => ({
|
|
35
|
+
label: ds.title || ds.id,
|
|
36
|
+
value: ds.id,
|
|
37
|
+
children: ds.fields?.map((field) => ({
|
|
38
|
+
label: field.title,
|
|
39
|
+
value: field.name,
|
|
40
|
+
})),
|
|
41
|
+
})) || [],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const onChangeHandler = (value: any) => {
|
|
45
|
+
emit('change', value);
|
|
46
|
+
};
|
|
47
|
+
</script>
|
|
@@ -1,43 +1,44 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-data-source-fields">
|
|
3
|
-
<MagicTable :data="model[name]" :columns="
|
|
3
|
+
<MagicTable :data="model[name]" :columns="fieldColumns"></MagicTable>
|
|
4
4
|
|
|
5
5
|
<div class="m-editor-data-source-fields-footer">
|
|
6
6
|
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton>
|
|
7
7
|
</div>
|
|
8
8
|
|
|
9
|
-
<
|
|
9
|
+
<MFormDrawer
|
|
10
10
|
ref="addDialog"
|
|
11
|
+
label-width="80px"
|
|
11
12
|
:title="filedTitle"
|
|
12
13
|
:config="dataSourceFieldsConfig"
|
|
13
14
|
:values="fieldValues"
|
|
14
15
|
:parentValues="model[name]"
|
|
16
|
+
:disabled="disabled"
|
|
17
|
+
:width="width"
|
|
15
18
|
@submit="fieldChange"
|
|
16
|
-
></
|
|
19
|
+
></MFormDrawer>
|
|
17
20
|
</div>
|
|
18
21
|
</template>
|
|
19
22
|
|
|
20
23
|
<script setup lang="ts">
|
|
21
|
-
import { ref } from 'vue';
|
|
24
|
+
import { computed, inject, ref } from 'vue';
|
|
22
25
|
|
|
23
26
|
import { TMagicButton, tMagicMessageBox } from '@tmagic/design';
|
|
24
|
-
import { FormConfig, FormState,
|
|
27
|
+
import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form';
|
|
25
28
|
import { MagicTable } from '@tmagic/table';
|
|
26
29
|
|
|
30
|
+
import type { Services } from '@editor/type';
|
|
31
|
+
|
|
27
32
|
defineOptions({
|
|
28
33
|
name: 'MEditorDataSourceFields',
|
|
29
34
|
});
|
|
30
35
|
|
|
31
36
|
const props = withDefaults(
|
|
32
|
-
defineProps<
|
|
33
|
-
|
|
37
|
+
defineProps<
|
|
38
|
+
FieldProps<{
|
|
34
39
|
type: 'data-source-fields';
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
prop: string;
|
|
38
|
-
disabled: boolean;
|
|
39
|
-
name: string;
|
|
40
|
-
}>(),
|
|
40
|
+
}>
|
|
41
|
+
>(),
|
|
41
42
|
{
|
|
42
43
|
disabled: false,
|
|
43
44
|
},
|
|
@@ -45,32 +46,33 @@ const props = withDefaults(
|
|
|
45
46
|
|
|
46
47
|
const emit = defineEmits(['change']);
|
|
47
48
|
|
|
48
|
-
const
|
|
49
|
+
const services = inject<Services>('services');
|
|
50
|
+
|
|
51
|
+
const addDialog = ref<InstanceType<typeof MFormDrawer>>();
|
|
49
52
|
const fieldValues = ref<Record<string, any>>({});
|
|
50
53
|
const filedTitle = ref('');
|
|
51
54
|
|
|
55
|
+
const width = computed(() => globalThis.document.body.clientWidth - (services?.uiService.get('columnWidth').left || 0));
|
|
56
|
+
|
|
52
57
|
const newHandler = () => {
|
|
53
|
-
if (!addDialog.value) return;
|
|
54
58
|
fieldValues.value = {};
|
|
55
59
|
filedTitle.value = '新增属性';
|
|
56
|
-
addDialog.value
|
|
60
|
+
addDialog.value?.show();
|
|
57
61
|
};
|
|
58
62
|
|
|
59
63
|
const fieldChange = ({ index, ...value }: Record<string, any>) => {
|
|
60
|
-
if (!addDialog.value) return;
|
|
61
|
-
|
|
62
64
|
if (index > -1) {
|
|
63
65
|
props.model[props.name][index] = value;
|
|
64
66
|
} else {
|
|
65
67
|
props.model[props.name].push(value);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
|
-
addDialog.value
|
|
70
|
+
addDialog.value?.hide();
|
|
69
71
|
|
|
70
72
|
emit('change', props.model[props.name]);
|
|
71
73
|
};
|
|
72
74
|
|
|
73
|
-
const
|
|
75
|
+
const fieldColumns = [
|
|
74
76
|
{
|
|
75
77
|
label: '属性名称',
|
|
76
78
|
prop: 'title',
|
|
@@ -83,6 +85,10 @@ const filedColumns = [
|
|
|
83
85
|
label: '属性描述',
|
|
84
86
|
prop: 'desc',
|
|
85
87
|
},
|
|
88
|
+
{
|
|
89
|
+
label: '默认值',
|
|
90
|
+
prop: 'defaultValue',
|
|
91
|
+
},
|
|
86
92
|
{
|
|
87
93
|
label: '操作',
|
|
88
94
|
fixed: 'right',
|
|
@@ -90,13 +96,12 @@ const filedColumns = [
|
|
|
90
96
|
{
|
|
91
97
|
text: '编辑',
|
|
92
98
|
handler: (row: Record<string, any>, index: number) => {
|
|
93
|
-
if (!addDialog.value) return;
|
|
94
99
|
fieldValues.value = {
|
|
95
100
|
...row,
|
|
96
101
|
index,
|
|
97
102
|
};
|
|
98
103
|
filedTitle.value = `编辑${row.title}`;
|
|
99
|
-
addDialog.value
|
|
104
|
+
addDialog.value?.show();
|
|
100
105
|
},
|
|
101
106
|
},
|
|
102
107
|
{
|
|
@@ -161,6 +166,7 @@ const dataSourceFieldsConfig: FormConfig = [
|
|
|
161
166
|
{
|
|
162
167
|
name: 'description',
|
|
163
168
|
text: '描述',
|
|
169
|
+
type: 'textarea',
|
|
164
170
|
},
|
|
165
171
|
{
|
|
166
172
|
name: 'defaultValue',
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
"
|
|
17
17
|
style="width: 100%"
|
|
18
18
|
@blur="blurHandler"
|
|
19
|
-
@change="changeHandler"
|
|
20
19
|
@input="inputHandler"
|
|
21
20
|
@select="selectHandler"
|
|
22
21
|
>
|
|
@@ -48,36 +47,34 @@
|
|
|
48
47
|
import { computed, inject, nextTick, ref, watch } from 'vue';
|
|
49
48
|
import { Coin } from '@element-plus/icons-vue';
|
|
50
49
|
|
|
51
|
-
import {
|
|
50
|
+
import { getConfig, TMagicAutocomplete, TMagicTag } from '@tmagic/design';
|
|
51
|
+
import type { FieldProps } from '@tmagic/form';
|
|
52
52
|
import type { DataSchema, DataSourceSchema } from '@tmagic/schema';
|
|
53
53
|
|
|
54
54
|
import Icon from '@editor/components/Icon.vue';
|
|
55
55
|
import type { Services } from '@editor/type';
|
|
56
|
+
import { getDisplayField } from '@editor/utils/data-source';
|
|
56
57
|
|
|
57
58
|
defineOptions({
|
|
58
59
|
name: 'MEditorDataSourceInput',
|
|
59
60
|
});
|
|
60
61
|
|
|
61
62
|
const props = withDefaults(
|
|
62
|
-
defineProps<
|
|
63
|
-
|
|
63
|
+
defineProps<
|
|
64
|
+
FieldProps<{
|
|
64
65
|
type: 'data-source-input';
|
|
65
66
|
name: string;
|
|
66
67
|
text: string;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
name: string;
|
|
70
|
-
prop: string;
|
|
71
|
-
disabled: boolean;
|
|
72
|
-
lastValues?: Record<string, any>;
|
|
73
|
-
size?: FieldSize;
|
|
74
|
-
}>(),
|
|
68
|
+
}>
|
|
69
|
+
>(),
|
|
75
70
|
{
|
|
76
71
|
disabled: false,
|
|
77
72
|
},
|
|
78
73
|
);
|
|
79
74
|
|
|
80
|
-
const emit = defineEmits<
|
|
75
|
+
const emit = defineEmits<{
|
|
76
|
+
change: [value: string];
|
|
77
|
+
}>();
|
|
81
78
|
|
|
82
79
|
const { dataSourceService } = inject<Services>('services') || {};
|
|
83
80
|
|
|
@@ -90,49 +87,7 @@ const input = computed<HTMLInputElement>(() => autocomplete.value?.inputRef?.inp
|
|
|
90
87
|
const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
|
|
91
88
|
|
|
92
89
|
const setDisplayState = () => {
|
|
93
|
-
displayState.value =
|
|
94
|
-
|
|
95
|
-
const matches = state.value.matchAll(/\$\{([\s\S]+?)\}/g);
|
|
96
|
-
let index = 0;
|
|
97
|
-
for (const match of matches) {
|
|
98
|
-
if (typeof match.index === 'undefined') break;
|
|
99
|
-
|
|
100
|
-
displayState.value.push({
|
|
101
|
-
type: 'text',
|
|
102
|
-
value: state.value.substring(index, match.index),
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
let dsText = '';
|
|
106
|
-
let ds: DataSourceSchema | undefined;
|
|
107
|
-
let fields: DataSchema[] | undefined;
|
|
108
|
-
|
|
109
|
-
match[1].split('.').forEach((item, index) => {
|
|
110
|
-
if (index === 0) {
|
|
111
|
-
ds = dataSources.value.find((ds) => ds.id === item);
|
|
112
|
-
dsText += ds?.title || item;
|
|
113
|
-
fields = ds?.fields;
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const field = fields?.find((field) => field.name === item);
|
|
118
|
-
fields = field?.fields;
|
|
119
|
-
dsText += `.${field?.title || item}`;
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
displayState.value.push({
|
|
123
|
-
type: 'var',
|
|
124
|
-
value: dsText,
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
index = match.index + match[0].length;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (index < state.value.length) {
|
|
131
|
-
displayState.value.push({
|
|
132
|
-
type: 'text',
|
|
133
|
-
value: state.value.substring(index),
|
|
134
|
-
});
|
|
135
|
-
}
|
|
90
|
+
displayState.value = getDisplayField(dataSources.value, state.value);
|
|
136
91
|
};
|
|
137
92
|
|
|
138
93
|
watch(
|
|
@@ -155,6 +110,8 @@ const blurHandler = () => {
|
|
|
155
110
|
isFocused.value = false;
|
|
156
111
|
|
|
157
112
|
setDisplayState();
|
|
113
|
+
|
|
114
|
+
emit('change', state.value);
|
|
158
115
|
};
|
|
159
116
|
|
|
160
117
|
const changeHandler = (v: string) => {
|
|
@@ -246,17 +203,21 @@ const fieldQuerySearch = (
|
|
|
246
203
|
let result: DataSchema[] = [];
|
|
247
204
|
|
|
248
205
|
const dsKey = queryString.substring(leftAngleIndex + 1, dotIndex);
|
|
206
|
+
|
|
249
207
|
// 可能是xx.xx.xx,存在链式调用
|
|
250
208
|
const keys = dsKey.split('.');
|
|
209
|
+
|
|
251
210
|
// 最前的是数据源id
|
|
252
|
-
const
|
|
211
|
+
const dsId = keys.shift();
|
|
212
|
+
const ds = dataSources.value.find((ds) => ds.id === dsId);
|
|
253
213
|
if (!ds) {
|
|
214
|
+
cb([]);
|
|
254
215
|
return;
|
|
255
216
|
}
|
|
256
217
|
|
|
257
218
|
let fields = ds.fields || [];
|
|
258
219
|
|
|
259
|
-
//
|
|
220
|
+
// 后面这些是字段
|
|
260
221
|
let key = keys.shift();
|
|
261
222
|
while (key) {
|
|
262
223
|
for (const field of fields) {
|
|
@@ -354,5 +315,7 @@ const selectHandler = async ({ value, type }: { value: string; type: 'dataSource
|
|
|
354
315
|
newSelectionStart = dotIndex + suggestText.length + 1;
|
|
355
316
|
}
|
|
356
317
|
input.value?.setSelectionRange(newSelectionStart, newSelectionStart);
|
|
318
|
+
|
|
319
|
+
changeHandler(state.value);
|
|
357
320
|
};
|
|
358
321
|
</script>
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-fields-data-source-method-select">
|
|
3
|
+
<div class="data-source-method-select-container">
|
|
4
|
+
<m-form-container
|
|
5
|
+
class="select"
|
|
6
|
+
:config="cascaderConfig"
|
|
7
|
+
:model="model"
|
|
8
|
+
@change="onChangeHandler"
|
|
9
|
+
></m-form-container>
|
|
10
|
+
<Icon v-if="model[name]" class="icon" :icon="!disabled ? Edit : View" @click="editCodeHandler"></Icon>
|
|
11
|
+
</div>
|
|
12
|
+
|
|
13
|
+
<CodeParams
|
|
14
|
+
v-if="paramsConfig.length"
|
|
15
|
+
name="params"
|
|
16
|
+
:model="model"
|
|
17
|
+
:size="size"
|
|
18
|
+
:disabled="disabled"
|
|
19
|
+
:params-config="paramsConfig"
|
|
20
|
+
@change="onChangeHandler"
|
|
21
|
+
></CodeParams>
|
|
22
|
+
|
|
23
|
+
<CodeBlockEditor
|
|
24
|
+
ref="codeBlockEditor"
|
|
25
|
+
v-if="codeConfig"
|
|
26
|
+
:disabled="disabled"
|
|
27
|
+
:content="codeConfig"
|
|
28
|
+
@submit="submitCodeBlockHandler"
|
|
29
|
+
></CodeBlockEditor>
|
|
30
|
+
</div>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script lang="ts" setup name="">
|
|
34
|
+
import { computed, inject, ref } from 'vue';
|
|
35
|
+
import { Edit, View } from '@element-plus/icons-vue';
|
|
36
|
+
|
|
37
|
+
import { createValues, FieldProps } from '@tmagic/form';
|
|
38
|
+
import type { CodeBlockContent, Id } from '@tmagic/schema';
|
|
39
|
+
|
|
40
|
+
import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
|
41
|
+
import CodeParams from '@editor/components/CodeParams.vue';
|
|
42
|
+
import Icon from '@editor/components/Icon.vue';
|
|
43
|
+
import { useDataSourceMethod } from '@editor/hooks/use-data-source-method';
|
|
44
|
+
import type { CodeParamStatement, DataSourceMethodSelectConfig, Services } from '@editor/type';
|
|
45
|
+
|
|
46
|
+
defineOptions({
|
|
47
|
+
name: 'MEditorDataSourceMethodSelect',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const services = inject<Services>('services');
|
|
51
|
+
const emit = defineEmits(['change']);
|
|
52
|
+
|
|
53
|
+
const props = withDefaults(defineProps<FieldProps<DataSourceMethodSelectConfig>>(), {
|
|
54
|
+
disabled: false,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const dataSources = computed(() => services?.dataSourceService.get('dataSources'));
|
|
58
|
+
|
|
59
|
+
const getParamItemsConfig = ([dataSourceId, medthodName]: [Id, string] = ['', '']): CodeParamStatement[] => {
|
|
60
|
+
if (!dataSourceId) return [];
|
|
61
|
+
|
|
62
|
+
const paramStatements = dataSources.value
|
|
63
|
+
?.find((item) => item.id === dataSourceId)
|
|
64
|
+
?.methods?.find((item) => item.name === medthodName)?.params;
|
|
65
|
+
|
|
66
|
+
if (!paramStatements) return [];
|
|
67
|
+
|
|
68
|
+
return paramStatements.map((paramState: CodeParamStatement) => ({
|
|
69
|
+
labelWidth: '100px',
|
|
70
|
+
text: paramState.name,
|
|
71
|
+
...paramState,
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const paramsConfig = ref<CodeParamStatement[]>(getParamItemsConfig(props.model.dataSourceMethod));
|
|
76
|
+
|
|
77
|
+
const setParamsConfig = (dataSourceMethod: [Id, string], formState: any = {}) => {
|
|
78
|
+
// 通过下拉框选择的codeId变化后修正model的值,避免写入其他codeId的params
|
|
79
|
+
paramsConfig.value = dataSourceMethod ? getParamItemsConfig(dataSourceMethod) : [];
|
|
80
|
+
|
|
81
|
+
if (paramsConfig.value.length) {
|
|
82
|
+
props.model.params = createValues(formState, paramsConfig.value, {}, props.model.params);
|
|
83
|
+
} else {
|
|
84
|
+
props.model.params = {};
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const cascaderConfig = {
|
|
89
|
+
type: 'cascader',
|
|
90
|
+
text: '数据源方法',
|
|
91
|
+
name: props.name,
|
|
92
|
+
labelWidth: '80px',
|
|
93
|
+
options: () =>
|
|
94
|
+
dataSources.value
|
|
95
|
+
?.filter((ds) => ds.methods?.length)
|
|
96
|
+
?.map((ds) => ({
|
|
97
|
+
label: ds.title || ds.id,
|
|
98
|
+
value: ds.id,
|
|
99
|
+
children: ds.methods?.map((method) => ({
|
|
100
|
+
label: method.name,
|
|
101
|
+
value: method.name,
|
|
102
|
+
})),
|
|
103
|
+
})) || [],
|
|
104
|
+
onChange: (formState: any, dataSourceMethod: [Id, string]) => {
|
|
105
|
+
setParamsConfig(dataSourceMethod, formState);
|
|
106
|
+
|
|
107
|
+
return dataSourceMethod;
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 参数值修改更新
|
|
113
|
+
*/
|
|
114
|
+
const onChangeHandler = (value: any) => {
|
|
115
|
+
props.model.params = value.params;
|
|
116
|
+
emit('change', props.model);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const { codeBlockEditor, codeConfig, editCode, submitCode } = useDataSourceMethod();
|
|
120
|
+
|
|
121
|
+
const editCodeHandler = () => {
|
|
122
|
+
const [id, name] = props.model[props.name];
|
|
123
|
+
|
|
124
|
+
const dataSource = services?.dataSourceService.getDataSourceById(id);
|
|
125
|
+
|
|
126
|
+
if (!dataSource) return;
|
|
127
|
+
|
|
128
|
+
editCode(dataSource, name);
|
|
129
|
+
|
|
130
|
+
setParamsConfig([id, name]);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const submitCodeBlockHandler = (value: CodeBlockContent) => {
|
|
134
|
+
submitCode(value);
|
|
135
|
+
};
|
|
136
|
+
</script>
|