@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.
Files changed (52) hide show
  1. package/dist/style.css +32 -0
  2. package/dist/tmagic-editor.js +949 -185
  3. package/dist/tmagic-editor.js.map +1 -1
  4. package/dist/tmagic-editor.umd.cjs +960 -194
  5. package/dist/tmagic-editor.umd.cjs.map +1 -1
  6. package/package.json +10 -9
  7. package/src/Editor.vue +2 -0
  8. package/src/components/CodeDraftEditor.vue +2 -2
  9. package/src/editorProps.ts +5 -0
  10. package/src/fields/CodeSelect.vue +1 -0
  11. package/src/fields/DataSourceFields.vue +178 -0
  12. package/src/fields/EventSelect.vue +1 -0
  13. package/src/fields/KeyValue.vue +93 -0
  14. package/src/index.ts +7 -0
  15. package/src/initService.ts +59 -3
  16. package/src/layouts/sidebar/LayerPanel.vue +2 -0
  17. package/src/layouts/sidebar/Sidebar.vue +14 -5
  18. package/src/layouts/sidebar/code-block/CodeBlockList.vue +7 -0
  19. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +84 -0
  20. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +130 -0
  21. package/src/services/codeBlock.ts +0 -2
  22. package/src/services/dataSource.ts +90 -0
  23. package/src/theme/data-source-fields.scss +13 -0
  24. package/src/theme/data-source.scss +17 -0
  25. package/src/theme/key-value.scss +13 -0
  26. package/src/theme/theme.scss +3 -0
  27. package/src/type.ts +3 -1
  28. package/src/utils/data-source/formConfigs/base.ts +32 -0
  29. package/src/utils/data-source/formConfigs/http.ts +50 -0
  30. package/src/utils/data-source/index.ts +31 -0
  31. package/src/utils/dep.ts +9 -1
  32. package/src/utils/props.ts +1 -0
  33. package/types/Editor.vue.d.ts +9 -0
  34. package/types/components/ContentMenu.vue.d.ts +2 -2
  35. package/types/components/ScrollViewer.vue.d.ts +1 -1
  36. package/types/editorProps.d.ts +4 -0
  37. package/types/fields/DataSourceFields.vue.d.ts +40 -0
  38. package/types/fields/KeyValue.vue.d.ts +50 -0
  39. package/types/index.d.ts +3 -0
  40. package/types/initService.d.ts +1 -1
  41. package/types/layouts/CodeEditor.vue.d.ts +1 -1
  42. package/types/layouts/sidebar/Sidebar.vue.d.ts +2 -2
  43. package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +22 -0
  44. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +12 -0
  45. package/types/services/dataSource.d.ts +25 -0
  46. package/types/services/props.d.ts +2 -3
  47. package/types/type.d.ts +3 -1
  48. package/types/utils/data-source/formConfigs/base.d.ts +3 -0
  49. package/types/utils/data-source/formConfigs/http.d.ts +3 -0
  50. package/types/utils/data-source/index.d.ts +2 -0
  51. package/types/utils/dep.d.ts +2 -1
  52. package/types/utils/props.d.ts +2 -3
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.15",
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.2.15",
50
- "@tmagic/design": "1.2.15",
51
- "@tmagic/form": "1.2.15",
52
- "@tmagic/schema": "1.2.15",
53
- "@tmagic/stage": "1.2.15",
54
- "@tmagic/utils": "1.2.15",
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.2.15",
67
- "@tmagic/form": "1.2.15",
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 type="primary" class="button" @click="close">关闭</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 type="primary" class="button" @click="close">关闭</TMagicButton>
22
+ <TMagicButton class="button" @click="close">关闭</TMagicButton>
23
23
  </div>
24
24
  </div>
25
25
  </template>
@@ -79,6 +79,11 @@ export default {
79
79
  default: () => ({}),
80
80
  },
81
81
 
82
+ dataScourceConfigs: {
83
+ type: Object as PropType<Record<string, FormConfig>>,
84
+ default: () => ({}),
85
+ },
86
+
82
87
  /** 画布中组件选中框的移动范围 */
83
88
  moveableOptions: {
84
89
  type: [Object, Function] as PropType<
@@ -35,6 +35,7 @@ const codeConfig = computed(() => ({
35
35
  items: [
36
36
  {
37
37
  type: 'code-select-col',
38
+ labelWidth: 0,
38
39
  },
39
40
  ],
40
41
  }));
@@ -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
  };
@@ -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 { createCodeBlockTarget } from './utils/dep';
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
  };
@@ -87,6 +87,8 @@ const clicked = ref(false);
87
87
 
88
88
  const treeProps = {
89
89
  children: 'items',
90
+ label: 'name',
91
+ value: 'id',
90
92
  disabled: (data: MNode) => Boolean(data.items?.length),
91
93
  class: (data: MNode) => {
92
94
  if (clicked.value || isPage(data)) return '';
@@ -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, Files } from '@element-plus/icons-vue';
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?: SideBarData;
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: Coin,
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: Files,
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
  // 代码块列表