@tmagic/editor 1.2.15 → 1.3.0-alpha.1
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 +32 -0
- package/dist/tmagic-editor.js +949 -185
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +960 -194
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +10 -9
- package/src/Editor.vue +2 -0
- package/src/components/CodeDraftEditor.vue +2 -2
- package/src/editorProps.ts +5 -0
- package/src/fields/CodeSelect.vue +1 -0
- package/src/fields/DataSourceFields.vue +178 -0
- package/src/fields/EventSelect.vue +1 -0
- package/src/fields/KeyValue.vue +93 -0
- package/src/index.ts +7 -0
- package/src/initService.ts +59 -3
- package/src/layouts/sidebar/LayerPanel.vue +2 -0
- package/src/layouts/sidebar/Sidebar.vue +14 -5
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +7 -0
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +84 -0
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +130 -0
- package/src/services/codeBlock.ts +0 -2
- package/src/services/dataSource.ts +90 -0
- package/src/theme/data-source-fields.scss +13 -0
- package/src/theme/data-source.scss +17 -0
- package/src/theme/key-value.scss +13 -0
- package/src/theme/theme.scss +3 -0
- package/src/type.ts +3 -1
- package/src/utils/data-source/formConfigs/base.ts +32 -0
- package/src/utils/data-source/formConfigs/http.ts +50 -0
- package/src/utils/data-source/index.ts +31 -0
- package/src/utils/dep.ts +9 -1
- package/src/utils/props.ts +1 -0
- package/types/Editor.vue.d.ts +9 -0
- package/types/components/ContentMenu.vue.d.ts +2 -2
- package/types/components/ScrollViewer.vue.d.ts +1 -1
- package/types/editorProps.d.ts +4 -0
- package/types/fields/DataSourceFields.vue.d.ts +40 -0
- package/types/fields/KeyValue.vue.d.ts +50 -0
- package/types/index.d.ts +3 -0
- package/types/initService.d.ts +1 -1
- package/types/layouts/CodeEditor.vue.d.ts +1 -1
- package/types/layouts/sidebar/Sidebar.vue.d.ts +2 -2
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +22 -0
- package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +12 -0
- package/types/services/dataSource.d.ts +25 -0
- package/types/services/props.d.ts +2 -3
- package/types/type.d.ts +3 -1
- package/types/utils/data-source/formConfigs/base.d.ts +3 -0
- package/types/utils/data-source/formConfigs/http.d.ts +3 -0
- package/types/utils/data-source/index.d.ts +2 -0
- package/types/utils/dep.d.ts +2 -1
- package/types/utils/props.d.ts +2 -3
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.3.0-alpha.1",
|
|
3
3
|
"name": "@tmagic/editor",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
@@ -46,12 +46,13 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@babel/core": "^7.18.0",
|
|
48
48
|
"@element-plus/icons-vue": "^2.0.9",
|
|
49
|
-
"@tmagic/core": "1.
|
|
50
|
-
"@tmagic/design": "1.
|
|
51
|
-
"@tmagic/form": "1.
|
|
52
|
-
"@tmagic/schema": "1.
|
|
53
|
-
"@tmagic/stage": "1.
|
|
54
|
-
"@tmagic/
|
|
49
|
+
"@tmagic/core": "1.3.0-alpha.1",
|
|
50
|
+
"@tmagic/design": "1.3.0-alpha.1",
|
|
51
|
+
"@tmagic/form": "1.3.0-alpha.1",
|
|
52
|
+
"@tmagic/schema": "1.3.0-alpha.1",
|
|
53
|
+
"@tmagic/stage": "1.3.0-alpha.1",
|
|
54
|
+
"@tmagic/table": "1.3.0-alpha.1",
|
|
55
|
+
"@tmagic/utils": "1.3.0-alpha.1",
|
|
55
56
|
"buffer": "^6.0.3",
|
|
56
57
|
"color": "^3.1.3",
|
|
57
58
|
"events": "^3.3.0",
|
|
@@ -63,8 +64,8 @@
|
|
|
63
64
|
"vue": "^3.2.37"
|
|
64
65
|
},
|
|
65
66
|
"peerDependencies": {
|
|
66
|
-
"@tmagic/design": "1.
|
|
67
|
-
"@tmagic/form": "1.
|
|
67
|
+
"@tmagic/design": "1.3.0-alpha.1",
|
|
68
|
+
"@tmagic/form": "1.3.0-alpha.1",
|
|
68
69
|
"monaco-editor": "^0.34.0",
|
|
69
70
|
"vue": "^3.2.37"
|
|
70
71
|
},
|
package/src/Editor.vue
CHANGED
|
@@ -73,6 +73,7 @@ import Sidebar from './layouts/sidebar/Sidebar.vue';
|
|
|
73
73
|
import Workspace from './layouts/workspace/Workspace.vue';
|
|
74
74
|
import codeBlockService from './services/codeBlock';
|
|
75
75
|
import componentListService from './services/componentList';
|
|
76
|
+
import dataSourceService from './services/dataSource';
|
|
76
77
|
import depService from './services/dep';
|
|
77
78
|
import editorService from './services/editor';
|
|
78
79
|
import eventsService from './services/events';
|
|
@@ -110,6 +111,7 @@ export default defineComponent({
|
|
|
110
111
|
storageService,
|
|
111
112
|
codeBlockService,
|
|
112
113
|
depService,
|
|
114
|
+
dataSourceService,
|
|
113
115
|
};
|
|
114
116
|
|
|
115
117
|
initServiceEvents(props, emit, services);
|
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
{{ isFullScreen ? '退出全屏' : '全屏' }}</TMagicButton
|
|
14
14
|
>
|
|
15
15
|
<TMagicButton type="primary" class="button" @click="saveAndClose">确认</TMagicButton>
|
|
16
|
-
<TMagicButton
|
|
16
|
+
<TMagicButton class="button" @click="close">关闭</TMagicButton>
|
|
17
17
|
</div>
|
|
18
18
|
<div class="m-editor-content-bottom" v-else>
|
|
19
19
|
<TMagicButton type="primary" class="button" @click="toggleFullScreen">
|
|
20
20
|
{{ isFullScreen ? '退出全屏' : '全屏' }}</TMagicButton
|
|
21
21
|
>
|
|
22
|
-
<TMagicButton
|
|
22
|
+
<TMagicButton class="button" @click="close">关闭</TMagicButton>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
25
25
|
</template>
|
package/src/editorProps.ts
CHANGED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-editor-data-source-fields">
|
|
3
|
+
<MagicTable :data="model[name]" :columns="filedColumns"></MagicTable>
|
|
4
|
+
|
|
5
|
+
<div class="m-editor-data-source-fields-footer">
|
|
6
|
+
<TMagicButton size="small" type="primary" :disabled="disabled" plain @click="newHandler()">添加</TMagicButton>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<MFormDialog
|
|
10
|
+
ref="addDialog"
|
|
11
|
+
:title="filedTitle"
|
|
12
|
+
:config="dataSourceFieldsConfig"
|
|
13
|
+
:values="fieldValues"
|
|
14
|
+
:parentValues="model[name]"
|
|
15
|
+
@submit="fieldChange"
|
|
16
|
+
></MFormDialog>
|
|
17
|
+
</div>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
import { ref } from 'vue';
|
|
22
|
+
|
|
23
|
+
import { TMagicButton, tMagicMessageBox } from '@tmagic/design';
|
|
24
|
+
import { FormConfig, FormState, MFormDialog } from '@tmagic/form';
|
|
25
|
+
import { MagicTable } from '@tmagic/table';
|
|
26
|
+
|
|
27
|
+
const props = withDefaults(
|
|
28
|
+
defineProps<{
|
|
29
|
+
config: {
|
|
30
|
+
type: 'data-source-fields';
|
|
31
|
+
};
|
|
32
|
+
model: any;
|
|
33
|
+
prop: string;
|
|
34
|
+
disabled: boolean;
|
|
35
|
+
name: string;
|
|
36
|
+
}>(),
|
|
37
|
+
{
|
|
38
|
+
disabled: false,
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
const emit = defineEmits(['change']);
|
|
43
|
+
|
|
44
|
+
const addDialog = ref<InstanceType<typeof MFormDialog>>();
|
|
45
|
+
const fieldValues = ref<Record<string, any>>({});
|
|
46
|
+
const filedTitle = ref('');
|
|
47
|
+
|
|
48
|
+
const newHandler = () => {
|
|
49
|
+
if (!addDialog.value) return;
|
|
50
|
+
fieldValues.value = {};
|
|
51
|
+
filedTitle.value = '新增属性';
|
|
52
|
+
addDialog.value.dialogVisible = true;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const fieldChange = ({ index, ...value }: Record<string, any>) => {
|
|
56
|
+
if (!addDialog.value) return;
|
|
57
|
+
|
|
58
|
+
if (index > -1) {
|
|
59
|
+
props.model[props.name][index] = value;
|
|
60
|
+
} else {
|
|
61
|
+
props.model[props.name].push(value);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
addDialog.value.dialogVisible = false;
|
|
65
|
+
|
|
66
|
+
emit('change', props.model[props.name]);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const filedColumns = [
|
|
70
|
+
{
|
|
71
|
+
label: '属性名称',
|
|
72
|
+
prop: 'title',
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
label: '属性key',
|
|
76
|
+
prop: 'name',
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: '属性描述',
|
|
80
|
+
prop: 'desc',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
label: '操作',
|
|
84
|
+
fixed: 'right',
|
|
85
|
+
actions: [
|
|
86
|
+
{
|
|
87
|
+
text: '编辑',
|
|
88
|
+
handler: (row: Record<string, any>, index: number) => {
|
|
89
|
+
if (!addDialog.value) return;
|
|
90
|
+
fieldValues.value = {
|
|
91
|
+
...row,
|
|
92
|
+
index,
|
|
93
|
+
};
|
|
94
|
+
filedTitle.value = `编辑${row.title}`;
|
|
95
|
+
addDialog.value.dialogVisible = true;
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
text: '删除',
|
|
100
|
+
buttonType: 'danger',
|
|
101
|
+
handler: async (row: Record<string, any>, index: number) => {
|
|
102
|
+
await tMagicMessageBox.confirm(`确定删除${row.title}(${row.name})?`, '提示');
|
|
103
|
+
props.model[props.name].splice(index, 1);
|
|
104
|
+
emit('change', props.model[props.name]);
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
const dataSourceFieldsConfig: FormConfig = [
|
|
112
|
+
{ name: 'index', type: 'hidden', filter: 'number', defaultValue: -1 },
|
|
113
|
+
{
|
|
114
|
+
name: 'type',
|
|
115
|
+
text: '数据类型',
|
|
116
|
+
type: 'select',
|
|
117
|
+
defaultValue: 'string',
|
|
118
|
+
options: [
|
|
119
|
+
{ text: '字符串', value: 'string' },
|
|
120
|
+
{ text: '数字', value: 'number' },
|
|
121
|
+
{ text: '布尔值', value: 'boolean' },
|
|
122
|
+
{ text: '对象', value: 'object' },
|
|
123
|
+
{ text: '数组', value: 'array' },
|
|
124
|
+
{ text: 'null', value: 'null' },
|
|
125
|
+
{ text: 'any', value: 'any' },
|
|
126
|
+
],
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: 'name',
|
|
130
|
+
text: '字段名称',
|
|
131
|
+
rules: [
|
|
132
|
+
{
|
|
133
|
+
required: true,
|
|
134
|
+
message: '请输入字段名称',
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
validator: ({ value, callback }, { model, parent }) => {
|
|
138
|
+
const index = parent.findIndex((item: Record<string, any>) => item.name === value);
|
|
139
|
+
if ((model.index === -1 && index > -1) || (model.index > -1 && index !== model.index)) {
|
|
140
|
+
return callback(`属性key(${value})已存在`);
|
|
141
|
+
}
|
|
142
|
+
callback();
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'title',
|
|
149
|
+
text: '展示名称',
|
|
150
|
+
rules: [
|
|
151
|
+
{
|
|
152
|
+
required: true,
|
|
153
|
+
message: '请输入展示名称',
|
|
154
|
+
},
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
name: 'description',
|
|
159
|
+
text: '描述',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'defaultValue',
|
|
163
|
+
text: '默认值',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'enable',
|
|
167
|
+
text: '是否可用',
|
|
168
|
+
type: 'switch',
|
|
169
|
+
defaultValue: true,
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
name: 'fields',
|
|
173
|
+
type: 'data-source-fields',
|
|
174
|
+
defaultValue: [],
|
|
175
|
+
display: (formState: FormState | undefined, { model }: any) => model.type === 'object',
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
</script>
|
|
@@ -132,6 +132,7 @@ const compActionConfig = computed(() => {
|
|
|
132
132
|
const codeActionConfig = computed(() => {
|
|
133
133
|
const defaultCodeActionConfig = {
|
|
134
134
|
type: 'code-select-col',
|
|
135
|
+
labelWidth: 0,
|
|
135
136
|
display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.CODE,
|
|
136
137
|
};
|
|
137
138
|
return { ...defaultCodeActionConfig, ...props.config.codeActionConfig };
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-fields-key-value">
|
|
3
|
+
<div class="m-fields-key-value-item" v-for="(item, index) in records" :key="index">
|
|
4
|
+
<TMagicInput
|
|
5
|
+
placeholder="key"
|
|
6
|
+
v-model="records[index][0]"
|
|
7
|
+
:disabled="disabled"
|
|
8
|
+
:size="size"
|
|
9
|
+
@change="keyChangeHandler"
|
|
10
|
+
></TMagicInput>
|
|
11
|
+
<span class="m-fileds-key-value-delimiter">:</span>
|
|
12
|
+
<TMagicInput
|
|
13
|
+
placeholder="value"
|
|
14
|
+
v-model="records[index][1]"
|
|
15
|
+
:disabled="disabled"
|
|
16
|
+
:size="size"
|
|
17
|
+
@change="valueChangeHandler"
|
|
18
|
+
></TMagicInput>
|
|
19
|
+
|
|
20
|
+
<TMagicButton
|
|
21
|
+
class="m-fileds-key-value-delete"
|
|
22
|
+
type="danger"
|
|
23
|
+
:size="size"
|
|
24
|
+
circle
|
|
25
|
+
plain
|
|
26
|
+
:icon="Delete"
|
|
27
|
+
@click="deleteHandler(index)"
|
|
28
|
+
></TMagicButton>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<TMagicButton type="primary" :size="size" plain :icon="Plus" @click="addHandler">添加</TMagicButton>
|
|
32
|
+
</div>
|
|
33
|
+
</template>
|
|
34
|
+
|
|
35
|
+
<script setup lang="ts">
|
|
36
|
+
import { ref, watchEffect } from 'vue';
|
|
37
|
+
import { Delete, Plus } from '@element-plus/icons-vue';
|
|
38
|
+
|
|
39
|
+
import { TMagicButton, TMagicInput } from '@tmagic/design';
|
|
40
|
+
|
|
41
|
+
const props = withDefaults(
|
|
42
|
+
defineProps<{
|
|
43
|
+
config: {
|
|
44
|
+
type: 'key-value';
|
|
45
|
+
name: string;
|
|
46
|
+
text: string;
|
|
47
|
+
};
|
|
48
|
+
model: Record<string, any>;
|
|
49
|
+
name: string;
|
|
50
|
+
prop: string;
|
|
51
|
+
disabled: boolean;
|
|
52
|
+
lastValues?: Record<string, any>;
|
|
53
|
+
size?: 'large' | 'default' | 'small';
|
|
54
|
+
}>(),
|
|
55
|
+
{
|
|
56
|
+
disabled: false,
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const emit = defineEmits<(e: 'change', value: Record<string, any>) => void>();
|
|
61
|
+
|
|
62
|
+
const records = ref<[string, string][]>([]);
|
|
63
|
+
|
|
64
|
+
watchEffect(() => {
|
|
65
|
+
records.value = Object.entries(props.model[props.name] || {});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const getValue = () => {
|
|
69
|
+
const record: Record<string, string> = {};
|
|
70
|
+
records.value.forEach(([key, value]) => {
|
|
71
|
+
if (key) {
|
|
72
|
+
record[key] = value;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
return record;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const keyChangeHandler = () => {
|
|
79
|
+
emit('change', getValue());
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const valueChangeHandler = () => {
|
|
83
|
+
emit('change', getValue());
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const addHandler = () => {
|
|
87
|
+
records.value.push(['', '']);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const deleteHandler = (index: number) => {
|
|
91
|
+
records.value.splice(index, 1);
|
|
92
|
+
};
|
|
93
|
+
</script>
|
package/src/index.ts
CHANGED
|
@@ -21,7 +21,9 @@ import Code from './fields/Code.vue';
|
|
|
21
21
|
import CodeLink from './fields/CodeLink.vue';
|
|
22
22
|
import CodeSelect from './fields/CodeSelect.vue';
|
|
23
23
|
import CodeSelectCol from './fields/CodeSelectCol.vue';
|
|
24
|
+
import DataSourceFields from './fields/DataSourceFields.vue';
|
|
24
25
|
import EventSelect from './fields/EventSelect.vue';
|
|
26
|
+
import KeyValue from './fields/KeyValue.vue';
|
|
25
27
|
import uiSelect from './fields/UISelect.vue';
|
|
26
28
|
import CodeEditor from './layouts/CodeEditor.vue';
|
|
27
29
|
import { setConfig } from './utils/config';
|
|
@@ -40,6 +42,7 @@ export { default as propsService } from './services/props';
|
|
|
40
42
|
export { default as historyService } from './services/history';
|
|
41
43
|
export { default as storageService } from './services/storage';
|
|
42
44
|
export { default as eventsService } from './services/events';
|
|
45
|
+
export { default as dataSourceService } from './services/dataSource';
|
|
43
46
|
export { default as uiService } from './services/ui';
|
|
44
47
|
export { default as codeBlockService } from './services/codeBlock';
|
|
45
48
|
export { default as depService } from './services/dep';
|
|
@@ -47,7 +50,9 @@ export { default as ComponentListPanel } from './layouts/sidebar/ComponentListPa
|
|
|
47
50
|
export { default as LayerPanel } from './layouts/sidebar/LayerPanel.vue';
|
|
48
51
|
export { default as CodeSelect } from './fields/CodeSelect.vue';
|
|
49
52
|
export { default as CodeSelectCol } from './fields/CodeSelectCol.vue';
|
|
53
|
+
export { default as DataSourceFields } from './fields/DataSourceFields.vue';
|
|
50
54
|
export { default as EventSelect } from './fields/EventSelect.vue';
|
|
55
|
+
export { default as KeyValue } from './fields/KeyValue.vue';
|
|
51
56
|
export { default as CodeBlockList } from './layouts/sidebar/code-block/CodeBlockList.vue';
|
|
52
57
|
export { default as PropsPanel } from './layouts/PropsPanel.vue';
|
|
53
58
|
export { default as ToolButton } from './components/ToolButton.vue';
|
|
@@ -74,5 +79,7 @@ export default {
|
|
|
74
79
|
app.component('m-fields-code-select', CodeSelect);
|
|
75
80
|
app.component('m-fields-code-select-col', CodeSelectCol);
|
|
76
81
|
app.component('m-fields-event-select', EventSelect);
|
|
82
|
+
app.component('m-fields-data-source-fields', DataSourceFields);
|
|
83
|
+
app.component('m-fields-key-value', KeyValue);
|
|
77
84
|
},
|
|
78
85
|
};
|
package/src/initService.ts
CHANGED
|
@@ -2,9 +2,10 @@ import type { ExtractPropTypes } from 'vue';
|
|
|
2
2
|
import { onUnmounted, toRaw, watch } from 'vue';
|
|
3
3
|
|
|
4
4
|
import type { EventOption } from '@tmagic/core';
|
|
5
|
-
import type { CodeBlockContent, Id, MApp, MNode, MPage } from '@tmagic/schema';
|
|
5
|
+
import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage } from '@tmagic/schema';
|
|
6
6
|
|
|
7
|
-
import {
|
|
7
|
+
import type { Target } from './services/dep';
|
|
8
|
+
import { createCodeBlockTarget, createDataSourceTarget } from './utils/dep';
|
|
8
9
|
import editorProps from './editorProps';
|
|
9
10
|
import type { Services } from './type';
|
|
10
11
|
|
|
@@ -107,8 +108,31 @@ export const initServiceState = (
|
|
|
107
108
|
export const initServiceEvents = (
|
|
108
109
|
props: Readonly<LooseRequired<Readonly<ExtractPropTypes<typeof editorProps>>>>,
|
|
109
110
|
emit: (event: 'props-panel-mounted' | 'update:modelValue', ...args: any[]) => void,
|
|
110
|
-
{ editorService, codeBlockService, depService }: Services,
|
|
111
|
+
{ editorService, codeBlockService, dataSourceService, depService }: Services,
|
|
111
112
|
) => {
|
|
113
|
+
const targetAddHandler = (target: Target) => {
|
|
114
|
+
if (target.type !== 'data-source') return;
|
|
115
|
+
|
|
116
|
+
const root = editorService.get('root');
|
|
117
|
+
if (!root) return;
|
|
118
|
+
|
|
119
|
+
if (!root.dataSourceDeps) {
|
|
120
|
+
root.dataSourceDeps = {};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
root.dataSourceDeps[target.id] = target.deps;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const targetRemoveHandler = (id: string | number) => {
|
|
127
|
+
const root = editorService.get('root');
|
|
128
|
+
if (!root?.dataSourceDeps) return;
|
|
129
|
+
|
|
130
|
+
delete root.dataSourceDeps[id];
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
depService.on('add-target', targetAddHandler);
|
|
134
|
+
depService.on('remove-target', targetRemoveHandler);
|
|
135
|
+
|
|
112
136
|
const rootChangeHandler = async (value: MApp, preValue?: MApp | null) => {
|
|
113
137
|
const nodeId = editorService.get('node')?.id || props.defaultSelected;
|
|
114
138
|
let node;
|
|
@@ -131,8 +155,10 @@ export const initServiceEvents = (
|
|
|
131
155
|
}
|
|
132
156
|
|
|
133
157
|
value.codeBlocks = value.codeBlocks || {};
|
|
158
|
+
value.dataSources = value.dataSources || [];
|
|
134
159
|
|
|
135
160
|
codeBlockService.setCodeDsl(value.codeBlocks);
|
|
161
|
+
dataSourceService.set('dataSources', value.dataSources);
|
|
136
162
|
|
|
137
163
|
depService.removeTargets('code-block');
|
|
138
164
|
|
|
@@ -140,10 +166,15 @@ export const initServiceEvents = (
|
|
|
140
166
|
depService.addTarget(createCodeBlockTarget(id, code));
|
|
141
167
|
});
|
|
142
168
|
|
|
169
|
+
value.dataSources.forEach((ds) => {
|
|
170
|
+
depService.addTarget(createDataSourceTarget(ds.id, ds));
|
|
171
|
+
});
|
|
172
|
+
|
|
143
173
|
if (value && Array.isArray(value.items)) {
|
|
144
174
|
depService.collect(value.items, true);
|
|
145
175
|
} else {
|
|
146
176
|
depService.clear();
|
|
177
|
+
delete value.dataSourceDeps;
|
|
147
178
|
}
|
|
148
179
|
};
|
|
149
180
|
|
|
@@ -185,7 +216,28 @@ export const initServiceEvents = (
|
|
|
185
216
|
codeBlockService.on('addOrUpdate', codeBlockAddOrUpdateHandler);
|
|
186
217
|
codeBlockService.on('remove', codeBlockRemoveHandler);
|
|
187
218
|
|
|
219
|
+
const dataSourceAddHandler = (config: DataSourceSchema) => {
|
|
220
|
+
depService.addTarget(createDataSourceTarget(config.id, config));
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const dataSourceUpdateHandler = (config: DataSourceSchema) => {
|
|
224
|
+
if (config.title) {
|
|
225
|
+
depService.getTarget(config.id)!.name = config.title;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
const dataSourceRemoveHandler = (id: string) => {
|
|
230
|
+
depService.removeTarget(id);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
dataSourceService.on('add', dataSourceAddHandler);
|
|
234
|
+
dataSourceService.on('update', dataSourceUpdateHandler);
|
|
235
|
+
dataSourceService.on('remove', dataSourceRemoveHandler);
|
|
236
|
+
|
|
188
237
|
onUnmounted(() => {
|
|
238
|
+
depService.off('add-target', targetAddHandler);
|
|
239
|
+
depService.off('remove-target', targetRemoveHandler);
|
|
240
|
+
|
|
189
241
|
editorService.off('history-change', historyChangeHandler);
|
|
190
242
|
editorService.off('root-change', rootChangeHandler);
|
|
191
243
|
editorService.off('add', nodeAddHandler);
|
|
@@ -194,5 +246,9 @@ export const initServiceEvents = (
|
|
|
194
246
|
|
|
195
247
|
codeBlockService.off('addOrUpdate', codeBlockAddOrUpdateHandler);
|
|
196
248
|
codeBlockService.off('remove', codeBlockRemoveHandler);
|
|
249
|
+
|
|
250
|
+
dataSourceService.off('add', dataSourceAddHandler);
|
|
251
|
+
dataSourceService.off('update', dataSourceUpdateHandler);
|
|
252
|
+
dataSourceService.off('remove', dataSourceRemoveHandler);
|
|
197
253
|
});
|
|
198
254
|
};
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
|
|
86
86
|
<script lang="ts" setup name="MEditorSidebar">
|
|
87
87
|
import { computed, ref, watch } from 'vue';
|
|
88
|
-
import { Coin, EditPen,
|
|
88
|
+
import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
|
|
89
89
|
|
|
90
90
|
import { getConfig } from '@tmagic/design';
|
|
91
91
|
|
|
@@ -94,16 +94,17 @@ import type { MenuButton, MenuComponent, SideComponent, SideItem } from '@editor
|
|
|
94
94
|
import { SideBarData } from '@editor/type';
|
|
95
95
|
|
|
96
96
|
import CodeBlockList from './code-block/CodeBlockList.vue';
|
|
97
|
+
import DataSourceListPanel from './data-source/DataSourceListPanel.vue';
|
|
97
98
|
import ComponentListPanel from './ComponentListPanel.vue';
|
|
98
99
|
import LayerPanel from './LayerPanel.vue';
|
|
99
100
|
|
|
100
101
|
const props = withDefaults(
|
|
101
102
|
defineProps<{
|
|
102
|
-
data
|
|
103
|
+
data: SideBarData;
|
|
103
104
|
layerContentMenu: (MenuButton | MenuComponent)[];
|
|
104
105
|
}>(),
|
|
105
106
|
{
|
|
106
|
-
data: () => ({ type: 'tabs', status: '组件', items: ['component-list', 'layer', 'code-block'] }),
|
|
107
|
+
data: () => ({ type: 'tabs', status: '组件', items: ['component-list', 'layer', 'code-block', 'data-source'] }),
|
|
107
108
|
},
|
|
108
109
|
);
|
|
109
110
|
|
|
@@ -117,7 +118,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
117
118
|
'component-list': {
|
|
118
119
|
$key: 'component-list',
|
|
119
120
|
type: 'component',
|
|
120
|
-
icon:
|
|
121
|
+
icon: Goods,
|
|
121
122
|
text: '组件',
|
|
122
123
|
component: ComponentListPanel,
|
|
123
124
|
slots: {},
|
|
@@ -125,7 +126,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
125
126
|
layer: {
|
|
126
127
|
$key: 'layer',
|
|
127
128
|
type: 'component',
|
|
128
|
-
icon:
|
|
129
|
+
icon: List,
|
|
129
130
|
text: '已选组件',
|
|
130
131
|
props: {
|
|
131
132
|
layerContentMenu: props.layerContentMenu,
|
|
@@ -141,6 +142,14 @@ const getItemConfig = (data: SideItem): SideComponent => {
|
|
|
141
142
|
component: CodeBlockList,
|
|
142
143
|
slots: {},
|
|
143
144
|
},
|
|
145
|
+
'data-source': {
|
|
146
|
+
$key: 'data-source',
|
|
147
|
+
type: 'component',
|
|
148
|
+
icon: Coin,
|
|
149
|
+
text: '数据源',
|
|
150
|
+
component: DataSourceListPanel,
|
|
151
|
+
slots: {},
|
|
152
|
+
},
|
|
144
153
|
};
|
|
145
154
|
|
|
146
155
|
return typeof data === 'string' ? map[data] : data;
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
:default-expanded-keys="expandedKeys"
|
|
19
19
|
:expand-on-click-node="false"
|
|
20
20
|
:data="codeList"
|
|
21
|
+
:props="treeProps"
|
|
21
22
|
:highlight-current="true"
|
|
22
23
|
:filter-node-method="filterNode"
|
|
23
24
|
@node-click="clickHandler"
|
|
@@ -75,6 +76,12 @@ const props = defineProps<{
|
|
|
75
76
|
paramsColConfig?: ColumnConfig;
|
|
76
77
|
}>();
|
|
77
78
|
|
|
79
|
+
const treeProps = {
|
|
80
|
+
children: 'children',
|
|
81
|
+
label: 'name',
|
|
82
|
+
value: 'id',
|
|
83
|
+
};
|
|
84
|
+
|
|
78
85
|
const { codeBlockService, depService, editorService } = inject<Services>('services') || {};
|
|
79
86
|
|
|
80
87
|
// 代码块列表
|