@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.
Files changed (124) hide show
  1. package/dist/style.css +82 -218
  2. package/dist/tmagic-editor.js +4985 -3999
  3. package/dist/tmagic-editor.js.map +1 -1
  4. package/dist/tmagic-editor.umd.cjs +5013 -4012
  5. package/dist/tmagic-editor.umd.cjs.map +1 -1
  6. package/package.json +15 -15
  7. package/src/Editor.vue +4 -5
  8. package/src/components/CodeBlockEditor.vue +257 -0
  9. package/src/components/CodeParams.vue +60 -0
  10. package/src/components/ContentMenu.vue +11 -3
  11. package/src/editorProps.ts +30 -5
  12. package/src/fields/Code.vue +23 -19
  13. package/src/fields/CodeLink.vue +6 -7
  14. package/src/fields/CodeSelect.vue +12 -9
  15. package/src/fields/CodeSelectCol.vue +70 -81
  16. package/src/fields/DataSourceFieldSelect.vue +47 -0
  17. package/src/fields/DataSourceFields.vue +28 -22
  18. package/src/fields/DataSourceInput.vue +21 -58
  19. package/src/fields/DataSourceMethodSelect.vue +136 -0
  20. package/src/fields/DataSourceMethods.vue +103 -0
  21. package/src/fields/DataSourceSelect.vue +68 -0
  22. package/src/fields/EventSelect.vue +53 -19
  23. package/src/fields/KeyValue.vue +9 -11
  24. package/src/fields/UISelect.vue +54 -14
  25. package/src/hooks/index.ts +21 -0
  26. package/src/hooks/use-code-block-edit.ts +84 -0
  27. package/src/hooks/use-data-source-method.ts +100 -0
  28. package/src/{utils/stage.ts → hooks/use-stage.ts} +4 -7
  29. package/src/icons/CenterIcon.vue +13 -0
  30. package/src/icons/CodeIcon.vue +0 -2
  31. package/src/icons/FolderMinusIcon.vue +22 -0
  32. package/src/index.ts +15 -0
  33. package/src/initService.ts +73 -16
  34. package/src/layouts/CodeEditor.vue +62 -10
  35. package/src/layouts/Framework.vue +7 -3
  36. package/src/layouts/PropsPanel.vue +8 -3
  37. package/src/layouts/sidebar/ComponentListPanel.vue +6 -9
  38. package/src/layouts/sidebar/LayerMenu.vue +20 -21
  39. package/src/layouts/sidebar/LayerNode.vue +40 -0
  40. package/src/layouts/sidebar/LayerPanel.vue +14 -5
  41. package/src/layouts/sidebar/Sidebar.vue +22 -36
  42. package/src/layouts/sidebar/code-block/CodeBlockList.vue +81 -119
  43. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +64 -0
  44. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +27 -47
  45. package/src/layouts/sidebar/data-source/DataSourceList.vue +145 -0
  46. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +58 -69
  47. package/src/layouts/workspace/Stage.vue +13 -5
  48. package/src/layouts/workspace/ViewerMenu.vue +10 -35
  49. package/src/services/codeBlock.ts +18 -71
  50. package/src/services/dataSource.ts +16 -1
  51. package/src/services/dep.ts +23 -20
  52. package/src/services/editor.ts +46 -18
  53. package/src/services/props.ts +2 -2
  54. package/src/theme/code-block.scss +5 -117
  55. package/src/theme/code-editor.scss +27 -2
  56. package/src/theme/content-menu.scss +1 -1
  57. package/src/theme/data-source-methods.scss +13 -0
  58. package/src/theme/data-source.scss +11 -0
  59. package/src/theme/event.scss +15 -12
  60. package/src/theme/framework.scss +0 -3
  61. package/src/theme/layer-panel.scss +6 -0
  62. package/src/theme/layout.scss +4 -0
  63. package/src/theme/sidebar.scss +18 -60
  64. package/src/theme/theme.scss +1 -0
  65. package/src/type.ts +47 -7
  66. package/src/utils/content-menu.ts +92 -0
  67. package/src/utils/data-source/formConfigs/base.ts +28 -30
  68. package/src/utils/data-source/index.ts +65 -2
  69. package/src/utils/dep.ts +39 -7
  70. package/src/utils/index.ts +1 -1
  71. package/src/utils/props.ts +298 -189
  72. package/src/utils/undo-redo.ts +1 -1
  73. package/types/Editor.vue.d.ts +30 -6
  74. package/types/components/CodeBlockEditor.vue.d.ts +23 -0
  75. package/types/components/CodeParams.vue.d.ts +26 -0
  76. package/types/components/ContentMenu.vue.d.ts +2 -2
  77. package/types/components/ToolButton.vue.d.ts +3 -3
  78. package/types/editorProps.d.ts +19 -5
  79. package/types/fields/Code.vue.d.ts +24 -19
  80. package/types/fields/CodeLink.vue.d.ts +12 -21
  81. package/types/fields/CodeSelect.vue.d.ts +6 -17
  82. package/types/fields/CodeSelectCol.vue.d.ts +10 -14
  83. package/types/fields/DataSourceFieldSelect.vue.d.ts +29 -0
  84. package/types/fields/DataSourceFields.vue.d.ts +7 -18
  85. package/types/fields/DataSourceInput.vue.d.ts +10 -30
  86. package/types/fields/DataSourceMethodSelect.vue.d.ts +29 -0
  87. package/types/fields/DataSourceMethods.vue.d.ts +32 -0
  88. package/types/fields/DataSourceSelect.vue.d.ts +40 -0
  89. package/types/fields/EventSelect.vue.d.ts +2 -13
  90. package/types/fields/KeyValue.vue.d.ts +9 -24
  91. package/types/fields/UISelect.vue.d.ts +2 -11
  92. package/types/hooks/index.d.ts +3 -0
  93. package/types/{components/FunctionEditor.vue.d.ts → hooks/use-code-block-edit.d.ts} +31 -119
  94. package/types/hooks/use-data-source-method.d.ts +123 -0
  95. package/types/icons/CenterIcon.vue.d.ts +2 -0
  96. package/types/icons/FolderMinusIcon.vue.d.ts +2 -0
  97. package/types/index.d.ts +7 -0
  98. package/types/initService.d.ts +2 -2
  99. package/types/layouts/CodeEditor.vue.d.ts +10 -4
  100. package/types/layouts/PropsPanel.vue.d.ts +274 -2
  101. package/types/layouts/sidebar/LayerNode.vue.d.ts +16 -0
  102. package/types/layouts/sidebar/Sidebar.vue.d.ts +0 -3
  103. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +4 -9
  104. package/types/layouts/sidebar/code-block/{CodeBlockEditor.vue.d.ts → CodeBlockListPanel.vue.d.ts} +9 -5
  105. package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -1
  106. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +14 -0
  107. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +1 -11
  108. package/types/services/codeBlock.d.ts +6 -37
  109. package/types/services/dataSource.d.ts +7 -1
  110. package/types/services/dep.d.ts +12 -21
  111. package/types/services/editor.d.ts +1 -1
  112. package/types/services/props.d.ts +10 -115
  113. package/types/type.d.ts +42 -7
  114. package/types/utils/content-menu.d.ts +7 -0
  115. package/types/utils/data-source/formConfigs/base.d.ts +1 -2
  116. package/types/utils/data-source/index.d.ts +5 -0
  117. package/types/utils/dep.d.ts +4 -2
  118. package/types/utils/index.d.ts +1 -1
  119. package/types/utils/props.d.ts +13 -102
  120. package/src/components/CodeDraftEditor.vue +0 -148
  121. package/src/components/FunctionEditor.vue +0 -197
  122. package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +0 -100
  123. package/types/components/CodeDraftEditor.vue.d.ts +0 -61
  124. /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="small" @click="addEvent()">添加事件</TMagicButton>
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 style="color: #f56c6c" text :icon="Delete" @click="removeEvent(index)"></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: '70px',
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: '70px',
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: '70px',
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
- display: (mForm: FormState, { model }: { model: Record<any, any> }) => model.actionType === ActionType.CODE,
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: [actionTypeConfig.value, targetCompConfig.value, compActionConfig.value, codeActionConfig.value],
219
+ items: [
220
+ actionTypeConfig.value,
221
+ targetCompConfig.value,
222
+ compActionConfig.value,
223
+ codeActionConfig.value,
224
+ dataSourceActionConfig.value,
225
+ ],
192
226
  },
193
227
  ],
194
228
  }));
@@ -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">添加</TMagicButton>
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
- config: {
50
+ defineProps<
51
+ FieldProps<{
48
52
  type: 'key-value';
49
53
  name: string;
50
54
  text: string;
51
- };
52
- model: Record<string, any>;
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
  },
@@ -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">取消</TMagicButton>
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 @click="startSelect" style="display: flex">
6
- <TMagicTooltip v-if="val" content="清除">
7
- <TMagicButton style="padding: 0" type="danger" :icon="Close" text @click.stop="deleteHandler"></TMagicButton>
8
- </TMagicTooltip>
9
- <TMagicTooltip :content="val ? toName + '_' + val : '点击此处选择'">
10
- <TMagicButton text style="padding: 0; margin: 0">{{ val ? toName + '_' + val : '点击此处选择' }}</TMagicButton>
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
+ };