@tmagic/editor 1.3.16 → 1.4.0-beta.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 (116) hide show
  1. package/dist/style.css +11 -3
  2. package/dist/tmagic-editor.js +847 -523
  3. package/dist/tmagic-editor.umd.cjs +862 -538
  4. package/package.json +23 -21
  5. package/src/components/CodeBlockEditor.vue +50 -24
  6. package/src/components/FloatingBox.vue +53 -12
  7. package/src/fields/Code.vue +12 -10
  8. package/src/fields/CodeLink.vue +9 -9
  9. package/src/fields/CodeSelect.vue +7 -5
  10. package/src/fields/CodeSelectCol.vue +1 -1
  11. package/src/fields/DataSourceFieldSelect.vue +118 -27
  12. package/src/fields/DataSourceFields.vue +10 -3
  13. package/src/fields/DataSourceInput.vue +7 -7
  14. package/src/fields/DataSourceMethodSelect.vue +1 -1
  15. package/src/fields/DataSourceMethods.vue +3 -3
  16. package/src/fields/DataSourceMocks.vue +3 -3
  17. package/src/fields/DataSourceSelect.vue +6 -18
  18. package/src/fields/EventSelect.vue +1 -1
  19. package/src/fields/KeyValue.vue +8 -8
  20. package/src/fields/PageFragmentSelect.vue +1 -1
  21. package/src/fields/UISelect.vue +5 -5
  22. package/src/hooks/use-code-block-edit.ts +0 -1
  23. package/src/index.ts +2 -2
  24. package/src/layouts/NavMenu.vue +21 -2
  25. package/src/layouts/sidebar/Sidebar.vue +5 -0
  26. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +0 -1
  27. package/src/services/BaseService.ts +5 -2
  28. package/src/services/codeBlock.ts +14 -8
  29. package/src/services/dataSource.ts +39 -26
  30. package/src/services/editor.ts +46 -25
  31. package/src/services/events.ts +4 -4
  32. package/src/services/props.ts +44 -35
  33. package/src/services/stageOverlay.ts +14 -7
  34. package/src/services/storage.ts +14 -8
  35. package/src/services/ui.ts +20 -19
  36. package/src/theme/code-editor.scss +6 -0
  37. package/src/theme/floating-box.scss +2 -0
  38. package/src/theme/sidebar.scss +6 -3
  39. package/src/type.ts +81 -37
  40. package/src/utils/operator.ts +37 -39
  41. package/src/utils/props.ts +174 -37
  42. package/types/components/CodeBlockEditor.vue.d.ts +4 -4
  43. package/types/components/CodeParams.vue.d.ts +5 -5
  44. package/types/components/ContentMenu.vue.d.ts +12 -12
  45. package/types/components/FloatingBox.vue.d.ts +14 -12
  46. package/types/components/Icon.vue.d.ts +3 -3
  47. package/types/components/Resizer.vue.d.ts +3 -3
  48. package/types/components/ScrollBar.vue.d.ts +3 -3
  49. package/types/components/ScrollViewer.vue.d.ts +12 -12
  50. package/types/components/SearchInput.vue.d.ts +1 -1
  51. package/types/components/SplitView.vue.d.ts +11 -11
  52. package/types/components/ToolButton.vue.d.ts +13 -13
  53. package/types/components/Tree.vue.d.ts +24 -14
  54. package/types/components/TreeNode.vue.d.ts +22 -12
  55. package/types/fields/Code.vue.d.ts +14 -14
  56. package/types/fields/CodeLink.vue.d.ts +6 -10
  57. package/types/fields/CodeSelect.vue.d.ts +14 -14
  58. package/types/fields/CodeSelectCol.vue.d.ts +11 -11
  59. package/types/fields/DataSourceFieldSelect.vue.d.ts +11 -11
  60. package/types/fields/DataSourceFields.vue.d.ts +11 -11
  61. package/types/fields/DataSourceInput.vue.d.ts +14 -18
  62. package/types/fields/DataSourceMethodSelect.vue.d.ts +11 -11
  63. package/types/fields/DataSourceMethods.vue.d.ts +11 -11
  64. package/types/fields/DataSourceMocks.vue.d.ts +11 -11
  65. package/types/fields/DataSourceSelect.vue.d.ts +13 -26
  66. package/types/fields/EventSelect.vue.d.ts +3 -3
  67. package/types/fields/KeyValue.vue.d.ts +14 -18
  68. package/types/fields/PageFragmentSelect.vue.d.ts +11 -11
  69. package/types/fields/UISelect.vue.d.ts +8 -4
  70. package/types/hooks/use-code-block-edit.d.ts +51 -89
  71. package/types/hooks/use-data-source-method.d.ts +51 -89
  72. package/types/hooks/use-node-status.d.ts +6 -1
  73. package/types/icons/AppManageIcon.vue.d.ts +1 -1
  74. package/types/icons/CenterIcon.vue.d.ts +1 -1
  75. package/types/icons/CodeIcon.vue.d.ts +1 -1
  76. package/types/icons/FolderMinusIcon.vue.d.ts +1 -1
  77. package/types/icons/PinIcon.vue.d.ts +1 -1
  78. package/types/icons/PinnedIcon.vue.d.ts +1 -1
  79. package/types/layouts/AddPageBox.vue.d.ts +3 -3
  80. package/types/layouts/CodeEditor.vue.d.ts +12 -12
  81. package/types/layouts/Framework.vue.d.ts +9 -9
  82. package/types/layouts/NavMenu.vue.d.ts +11 -11
  83. package/types/layouts/PropsPanel.vue.d.ts +193 -243
  84. package/types/layouts/page-bar/AddButton.vue.d.ts +3 -3
  85. package/types/layouts/page-bar/PageBar.vue.d.ts +8 -8
  86. package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +8 -8
  87. package/types/layouts/page-bar/SwitchTypeButton.vue.d.ts +3 -3
  88. package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
  89. package/types/layouts/sidebar/Sidebar.vue.d.ts +12 -12
  90. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +10 -10
  91. package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +9 -9
  92. package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -3
  93. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +3 -3
  94. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +9 -9
  95. package/types/layouts/sidebar/layer/LayerMenu.vue.d.ts +11 -11
  96. package/types/layouts/sidebar/layer/LayerNodeTool.vue.d.ts +3 -3
  97. package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +9 -9
  98. package/types/layouts/sidebar/layer/use-click.d.ts +42 -76
  99. package/types/layouts/sidebar/layer/use-node-status.d.ts +6 -1
  100. package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -1
  101. package/types/layouts/workspace/Workspace.vue.d.ts +12 -12
  102. package/types/layouts/workspace/viewer/NodeListMenu.vue.d.ts +1 -1
  103. package/types/layouts/workspace/viewer/Stage.vue.d.ts +11 -11
  104. package/types/layouts/workspace/viewer/StageOverlay.vue.d.ts +1 -1
  105. package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +12 -12
  106. package/types/services/BaseService.d.ts +5 -2
  107. package/types/services/codeBlock.d.ts +8 -0
  108. package/types/services/dataSource.d.ts +9 -2
  109. package/types/services/editor.d.ts +8 -1
  110. package/types/services/props.d.ts +15 -22
  111. package/types/services/stageOverlay.d.ts +8 -1
  112. package/types/services/storage.d.ts +8 -0
  113. package/types/services/ui.d.ts +15 -9
  114. package/types/type.d.ts +50 -32
  115. package/types/utils/operator.d.ts +1 -1
  116. package/types/utils/props.d.ts +2 -13
@@ -24,14 +24,14 @@
24
24
  import { TMagicButton } from '@tmagic/design';
25
25
  import type { FieldProps } from '@tmagic/form';
26
26
  import type { CodeBlockContent } from '@tmagic/schema';
27
- import { MagicTable } from '@tmagic/table';
27
+ import { type ColumnConfig, MagicTable } from '@tmagic/table';
28
28
 
29
29
  import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
30
30
  import { useDataSourceMethod } from '@editor/hooks/use-data-source-method';
31
31
  import type { CodeParamStatement } from '@editor/type';
32
32
 
33
33
  defineOptions({
34
- name: 'MEditorDataSourceMethods',
34
+ name: 'MFieldsDataSourceMethods',
35
35
  });
36
36
 
37
37
  const props = withDefaults(
@@ -49,7 +49,7 @@ const emit = defineEmits(['change']);
49
49
 
50
50
  const { codeConfig, codeBlockEditor, createCode, editCode, deleteCode, submitCode } = useDataSourceMethod();
51
51
 
52
- const methodColumns = [
52
+ const methodColumns: ColumnConfig[] = [
53
53
  {
54
54
  label: '名称',
55
55
  prop: 'name',
@@ -26,14 +26,14 @@ import { computed, inject, ref } from 'vue';
26
26
  import { TMagicButton, tMagicMessageBox, TMagicSwitch } from '@tmagic/design';
27
27
  import { type FieldProps, type FormConfig, type FormState, MFormDrawer } from '@tmagic/form';
28
28
  import type { MockSchema } from '@tmagic/schema';
29
- import { MagicTable } from '@tmagic/table';
29
+ import { type ColumnConfig, MagicTable } from '@tmagic/table';
30
30
  import { getDefaultValueFromFields } from '@tmagic/utils';
31
31
 
32
32
  import CodeEditor from '@editor/layouts/CodeEditor.vue';
33
33
  import { Services } from '@editor/type';
34
34
 
35
35
  defineOptions({
36
- name: 'MEditorDataSourceMocks',
36
+ name: 'MFieldsDataSourceMocks',
37
37
  });
38
38
 
39
39
  const props = withDefaults(
@@ -117,7 +117,7 @@ const formConfig: FormConfig = [
117
117
  },
118
118
  ];
119
119
 
120
- const columns = [
120
+ const columns: ColumnConfig[] = [
121
121
  {
122
122
  type: 'expand',
123
123
  component: CodeEditor,
@@ -14,31 +14,19 @@
14
14
  <script setup lang="ts">
15
15
  import { computed, inject } from 'vue';
16
16
 
17
- import { FieldProps, MSelect, SelectConfig } from '@tmagic/form';
17
+ import { type FieldProps, MSelect, type SelectConfig } from '@tmagic/form';
18
18
 
19
- import { Services } from '../type';
19
+ import type { DataSourceSelect, Services } from '../type';
20
20
 
21
21
  defineOptions({
22
- name: 'MEditorDataSourceSelect',
22
+ name: 'MFieldsDataSourceSelect',
23
23
  });
24
24
 
25
25
  const emit = defineEmits(['change']);
26
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
- value?: 'id' | 'value';
36
- }>
37
- >(),
38
- {
39
- disabled: false,
40
- },
41
- );
27
+ const props = withDefaults(defineProps<FieldProps<DataSourceSelect>>(), {
28
+ disabled: false,
29
+ });
42
30
 
43
31
  const { dataSourceService } = inject<Services>('services') || {};
44
32
 
@@ -61,7 +61,7 @@ import { ActionType } from '@tmagic/schema';
61
61
  import type { CodeSelectColConfig, DataSourceMethodSelectConfig, EventSelectConfig, Services } from '@editor/type';
62
62
 
63
63
  defineOptions({
64
- name: 'MEditorEventSelect',
64
+ name: 'MFieldsEventSelect',
65
65
  });
66
66
 
67
67
  const props = defineProps<FieldProps<EventSelectConfig>>();
@@ -63,23 +63,23 @@ import { ref, watchEffect } from 'vue';
63
63
  import { Delete, Plus } from '@element-plus/icons-vue';
64
64
 
65
65
  import { TMagicButton, TMagicInput } from '@tmagic/design';
66
- import type { FieldProps } from '@tmagic/form';
66
+ import type { FieldProps, FormItem } from '@tmagic/form';
67
67
 
68
68
  import CodeIcon from '@editor/icons/CodeIcon.vue';
69
69
  import MagicCodeEditor from '@editor/layouts/CodeEditor.vue';
70
70
 
71
71
  defineOptions({
72
- name: 'MEditorKeyValue',
72
+ name: 'MFieldsKeyValue',
73
73
  });
74
74
 
75
75
  const props = withDefaults(
76
76
  defineProps<
77
- FieldProps<{
78
- type: 'key-value';
79
- name: string;
80
- text: string;
81
- advanced?: boolean;
82
- }>
77
+ FieldProps<
78
+ {
79
+ type: 'key-value';
80
+ advanced?: boolean;
81
+ } & FormItem
82
+ >
83
83
  >(),
84
84
  {
85
85
  disabled: false,
@@ -26,7 +26,7 @@ import Icon from '@editor/components/Icon.vue';
26
26
  import type { PageFragmentSelectConfig, Services } from '@editor/type';
27
27
 
28
28
  defineOptions({
29
- name: 'MEditorPageFragmentSelect',
29
+ name: 'MFieldsPageFragmentSelect',
30
30
  });
31
31
 
32
32
  const services = inject<Services>('services');
@@ -26,7 +26,7 @@
26
26
  :size="size"
27
27
  @click="selectNode(val)"
28
28
  @mouseenter="highlight(val)"
29
- @mouseleave="unhightlight"
29
+ @mouseleave="unhighlight"
30
30
  >{{ `${toName}_${val}` }}</TMagicButton
31
31
  >
32
32
  </TMagicTooltip>
@@ -46,16 +46,16 @@ import { Close, Delete } from '@element-plus/icons-vue';
46
46
  import { throttle } from 'lodash-es';
47
47
 
48
48
  import { TMagicButton, TMagicTooltip } from '@tmagic/design';
49
- import type { FieldProps, FormState } from '@tmagic/form';
49
+ import type { FieldProps, FormItem, FormState } from '@tmagic/form';
50
50
  import type { Id } from '@tmagic/schema';
51
51
 
52
52
  import { Services, UI_SELECT_MODE_EVENT_NAME } from '@editor/type';
53
53
 
54
54
  defineOptions({
55
- name: 'MEditorUISelect',
55
+ name: 'MFieldsUISelect',
56
56
  });
57
57
 
58
- const props = defineProps<FieldProps<any>>();
58
+ const props = defineProps<FieldProps<{ type: 'ui-select' } & FormItem>>();
59
59
 
60
60
  const emit = defineEmits(['change']);
61
61
 
@@ -115,7 +115,7 @@ const highlight = throttle((id: Id) => {
115
115
  services?.stageOverlayService.get('stage')?.highlight(id);
116
116
  }, 150);
117
117
 
118
- const unhightlight = () => {
118
+ const unhighlight = () => {
119
119
  services?.editorService.set('highlightNode', null);
120
120
  services?.editorService.get('stage')?.clearHighlight();
121
121
  services?.stageOverlayService.get('stage')?.clearHighlight();
@@ -54,7 +54,6 @@ export const useCodeBlockEdit = (codeBlockService?: CodeBlockService) => {
54
54
  codeId.value = id;
55
55
 
56
56
  await nextTick();
57
-
58
57
  codeBlockEditor.value?.show();
59
58
  };
60
59
 
package/src/index.ts CHANGED
@@ -96,11 +96,11 @@ export default {
96
96
  // eslint-disable-next-line no-param-reassign
97
97
  app.config.globalProperties.$TMAGIC_EDITOR = option;
98
98
  setConfig(option);
99
- app.component(Editor.name, Editor);
99
+ app.component(`${Editor.name || 'MEditor'}`, Editor);
100
+ app.component('magic-code-editor', CodeEditor);
100
101
  app.component('m-fields-ui-select', uiSelect);
101
102
  app.component('m-fields-code-link', CodeLink);
102
103
  app.component('m-fields-vs-code', Code);
103
- app.component('magic-code-editor', CodeEditor);
104
104
  app.component('m-fields-code-select', CodeSelect);
105
105
  app.component('m-fields-code-select-col', CodeSelectCol);
106
106
  app.component('m-fields-event-select', EventSelect);
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="m-editor-nav-menu" :style="{ height: `${height}px` }">
2
+ <div class="m-editor-nav-menu" :style="{ height: `${height}px` }" ref="navMenu">
3
3
  <div v-for="key in keys" :class="`menu-${key}`" :key="key" :style="`width: ${columnWidth?.[key]}px`">
4
4
  <ToolButton :data="item" v-for="(item, index) in buttons[key]" :key="index"></ToolButton>
5
5
  </div>
@@ -7,7 +7,7 @@
7
7
  </template>
8
8
 
9
9
  <script lang="ts" setup>
10
- import { computed, inject, markRaw } from 'vue';
10
+ import { computed, inject, markRaw, onBeforeUnmount, onMounted, ref } from 'vue';
11
11
  import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
12
12
 
13
13
  import { NodeType } from '@tmagic/schema';
@@ -178,4 +178,23 @@ const buttons = computed(() => {
178
178
  });
179
179
  return data;
180
180
  });
181
+
182
+ const resizeObserver = new ResizeObserver(() => {
183
+ const rect = navMenu.value?.getBoundingClientRect();
184
+ if (rect) {
185
+ uiService?.set('navMenuRect', {
186
+ left: rect.left,
187
+ top: rect.top,
188
+ width: rect.width,
189
+ height: rect.height,
190
+ });
191
+ }
192
+ });
193
+ const navMenu = ref<HTMLDivElement>();
194
+ onMounted(() => {
195
+ navMenu.value && resizeObserver.observe(navMenu.value);
196
+ });
197
+ onBeforeUnmount(() => {
198
+ resizeObserver.disconnect();
199
+ });
181
200
  </script>
@@ -204,6 +204,11 @@ const getItemConfig = (data: SideItem): SideComponent => {
204
204
  text: '代码编辑',
205
205
  component: CodeBlockListPanel,
206
206
  slots: {},
207
+ boxComponentConfig: {
208
+ props: {
209
+ slideType: 'box',
210
+ },
211
+ },
207
212
  },
208
213
  'data-source': {
209
214
  $key: 'data-source',
@@ -18,7 +18,6 @@
18
18
  </CodeBlockList>
19
19
  </TMagicScrollbar>
20
20
 
21
- <!-- 代码块编辑区 -->
22
21
  <CodeBlockEditor
23
22
  v-if="codeConfig"
24
23
  ref="codeBlockEditor"
@@ -103,7 +103,7 @@ const doAsyncAction = async (
103
103
  * 例如:
104
104
  * Class EditorService extends BaseService {
105
105
  * constructor() {
106
- * super(['add']);
106
+ * super([ { name: 'add', isAsync: true },]);
107
107
  * }
108
108
  * add(value) { return result; }
109
109
  * };
@@ -131,7 +131,7 @@ const doAsyncAction = async (
131
131
  * 例如:
132
132
  * Class EditorService extends BaseService {
133
133
  * constructor() {
134
- * super(['add']);
134
+ * super([ { name: 'add', isAsync: true },]);
135
135
  * }
136
136
  * add(value) { return result; }
137
137
  * };
@@ -194,6 +194,9 @@ export default class extends EventEmitter {
194
194
  });
195
195
  }
196
196
 
197
+ /**
198
+ * @deprecated 请使用usePlugin代替
199
+ */
197
200
  public use(options: Record<string, Function>) {
198
201
  Object.entries(options).forEach(([methodName, method]: [string, Function]) => {
199
202
  if (typeof method === 'function') this.middleware[methodName].push(method);
@@ -18,16 +18,24 @@
18
18
 
19
19
  import { reactive } from 'vue';
20
20
  import { keys, pick } from 'lodash-es';
21
+ import type { Writable } from 'type-fest';
21
22
 
22
23
  import type { ColumnConfig } from '@tmagic/form';
23
24
  import type { CodeBlockContent, CodeBlockDSL, Id } from '@tmagic/schema';
24
25
 
25
- import type { CodeState } from '@editor/type';
26
+ import type { AsyncHookPlugin, CodeState } from '@editor/type';
26
27
  import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
27
28
  import { getConfig } from '@editor/utils/config';
28
29
 
29
30
  import BaseService from './BaseService';
30
31
 
32
+ const canUsePluginMethods = {
33
+ async: ['setCodeDslById', 'setEditStatus', 'setCombineIds', 'setUndeleteableList', 'deleteCodeDslByIds'] as const,
34
+ sync: [],
35
+ };
36
+
37
+ type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
38
+
31
39
  class CodeBlock extends BaseService {
32
40
  private state = reactive<CodeState>({
33
41
  codeDsl: null,
@@ -38,13 +46,7 @@ class CodeBlock extends BaseService {
38
46
  });
39
47
 
40
48
  constructor() {
41
- super([
42
- { name: 'setCodeDslById', isAsync: true },
43
- { name: 'setEditStatus', isAsync: true },
44
- { name: 'setCombineIds', isAsync: true },
45
- { name: 'setUndeleteableList', isAsync: true },
46
- { name: 'deleteCodeDslByIds', isAsync: true },
47
- ]);
49
+ super(canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })));
48
50
  }
49
51
 
50
52
  /**
@@ -243,6 +245,10 @@ class CodeBlock extends BaseService {
243
245
  this.removeAllListeners();
244
246
  this.removeAllPlugins();
245
247
  }
248
+
249
+ public usePlugin(options: AsyncHookPlugin<AsyncMethodName, CodeBlock>): void {
250
+ super.usePlugin(options);
251
+ }
246
252
  }
247
253
 
248
254
  export type CodeBlockService = CodeBlock;
@@ -1,12 +1,13 @@
1
1
  import { reactive } from 'vue';
2
2
  import { cloneDeep } from 'lodash-es';
3
+ import { Writable } from 'type-fest';
3
4
 
4
5
  import type { EventOption } from '@tmagic/core';
5
6
  import type { FormConfig } from '@tmagic/form';
6
7
  import type { DataSourceSchema } from '@tmagic/schema';
7
- import { guid } from '@tmagic/utils';
8
+ import { guid, toLine } from '@tmagic/utils';
8
9
 
9
- import type { DatasourceTypeOption } from '@editor/type';
10
+ import type { DatasourceTypeOption, SyncHookPlugin } from '@editor/type';
10
11
  import { getFormConfig, getFormValue } from '@editor/utils/data-source';
11
12
 
12
13
  import BaseService from './BaseService';
@@ -22,6 +23,27 @@ interface State {
22
23
  }
23
24
 
24
25
  type StateKey = keyof State;
26
+
27
+ const canUsePluginMethods = {
28
+ async: [],
29
+ sync: [
30
+ 'getFormConfig',
31
+ 'setFormConfig',
32
+ 'getFormValue',
33
+ 'setFormValue',
34
+ 'getFormEvent',
35
+ 'setFormEvent',
36
+ 'getFormMethod',
37
+ 'setFormMethod',
38
+ 'add',
39
+ 'update',
40
+ 'remove',
41
+ 'createId',
42
+ ] as const,
43
+ };
44
+
45
+ type SyncMethodName = Writable<(typeof canUsePluginMethods)['sync']>;
46
+
25
47
  class DataSource extends BaseService {
26
48
  private state = reactive<State>({
27
49
  datasourceTypeList: [],
@@ -34,20 +56,7 @@ class DataSource extends BaseService {
34
56
  });
35
57
 
36
58
  constructor() {
37
- super([
38
- { name: 'getFormConfig', isAsync: false },
39
- { name: 'setFormConfig', isAsync: false },
40
- { name: 'getFormValue', isAsync: false },
41
- { name: 'setFormValue', isAsync: false },
42
- { name: 'getFormEvent', isAsync: false },
43
- { name: 'setFormEvent', isAsync: false },
44
- { name: 'getFormMethod', isAsync: false },
45
- { name: 'setFormMethod', isAsync: false },
46
- { name: 'add', isAsync: false },
47
- { name: 'update', isAsync: false },
48
- { name: 'remove', isAsync: false },
49
- { name: 'createId', isAsync: false },
50
- ]);
59
+ super(canUsePluginMethods.sync.map((methodName) => ({ name: methodName, isAsync: false })));
51
60
  }
52
61
 
53
62
  public set<K extends StateKey, T extends State[K]>(name: K, value: T) {
@@ -59,35 +68,35 @@ class DataSource extends BaseService {
59
68
  }
60
69
 
61
70
  public getFormConfig(type = 'base') {
62
- return getFormConfig(type, this.get('configs'));
71
+ return getFormConfig(toLine(type), this.get('configs'));
63
72
  }
64
73
 
65
74
  public setFormConfig(type: string, config: FormConfig) {
66
- this.get('configs')[type] = config;
75
+ this.get('configs')[toLine(type)] = config;
67
76
  }
68
77
 
69
78
  public getFormValue(type = 'base') {
70
- return getFormValue(type, this.get('values')[type]);
79
+ return getFormValue(toLine(type), this.get('values')[type]);
71
80
  }
72
81
 
73
82
  public setFormValue(type: string, value: Partial<DataSourceSchema>) {
74
- this.get('values')[type] = value;
83
+ this.get('values')[toLine(type)] = value;
75
84
  }
76
85
 
77
86
  public getFormEvent(type = 'base') {
78
- return this.get('events')[type] || [];
87
+ return this.get('events')[toLine(type)] || [];
79
88
  }
80
89
 
81
90
  public setFormEvent(type: string, value: EventOption[] = []) {
82
- this.get('events')[type] = value;
91
+ this.get('events')[toLine(type)] = value;
83
92
  }
84
93
 
85
94
  public getFormMethod(type = 'base') {
86
- return this.get('methods')[type] || [];
95
+ return this.get('methods')[toLine(type)] || [];
87
96
  }
88
97
 
89
98
  public setFormMethod(type: string, value: EventOption[] = []) {
90
- this.get('methods')[type] = value;
99
+ this.get('methods')[toLine(type)] = value;
91
100
  }
92
101
 
93
102
  public add(config: DataSourceSchema) {
@@ -123,6 +132,10 @@ class DataSource extends BaseService {
123
132
  this.emit('remove', id);
124
133
  }
125
134
 
135
+ public createId(): string {
136
+ return `ds_${guid()}`;
137
+ }
138
+
126
139
  public getDataSourceById(id: string) {
127
140
  return this.get('dataSources').find((ds) => ds.id === id);
128
141
  }
@@ -137,8 +150,8 @@ class DataSource extends BaseService {
137
150
  this.removeAllPlugins();
138
151
  }
139
152
 
140
- private createId(): string {
141
- return `ds_${guid()}`;
153
+ public usePlugin(options: SyncHookPlugin<SyncMethodName, DataSource>): void {
154
+ super.usePlugin(options);
142
155
  }
143
156
  }
144
157
 
@@ -18,6 +18,7 @@
18
18
 
19
19
  import { reactive, toRaw } from 'vue';
20
20
  import { cloneDeep, get, isObject, mergeWith, uniq } from 'lodash-es';
21
+ import { Writable } from 'type-fest';
21
22
 
22
23
  import { DepTargetType } from '@tmagic/dep';
23
24
  import type { Id, MApp, MComponent, MContainer, MNode, MPage, MPageFragment } from '@tmagic/schema';
@@ -29,7 +30,15 @@ import propsService from '@editor/services//props';
29
30
  import depService from '@editor/services/dep';
30
31
  import historyService from '@editor/services/history';
31
32
  import storageService, { Protocol } from '@editor/services/storage';
32
- import type { AddMNode, EditorNodeInfo, PastePosition, StepValue, StoreState, StoreStateKey } from '@editor/type';
33
+ import type {
34
+ AddMNode,
35
+ AsyncHookPlugin,
36
+ EditorNodeInfo,
37
+ PastePosition,
38
+ StepValue,
39
+ StoreState,
40
+ StoreStateKey,
41
+ } from '@editor/type';
33
42
  import { LayerOffset, Layout } from '@editor/type';
34
43
  import {
35
44
  change2Fixed,
@@ -46,6 +55,36 @@ import {
46
55
  } from '@editor/utils/editor';
47
56
  import { beforePaste, getAddParent } from '@editor/utils/operator';
48
57
 
58
+ const canUsePluginMethods = {
59
+ async: [
60
+ 'getLayout',
61
+ 'highlight',
62
+ 'select',
63
+ 'multiSelect',
64
+ 'doAdd',
65
+ 'add',
66
+ 'doRemove',
67
+ 'remove',
68
+ 'doUpdate',
69
+ 'update',
70
+ 'sort',
71
+ 'copy',
72
+ 'paste',
73
+ 'doPaste',
74
+ 'doAlignCenter',
75
+ 'alignCenter',
76
+ 'moveLayer',
77
+ 'moveToContainer',
78
+ 'dragTo',
79
+ 'undo',
80
+ 'redo',
81
+ 'move',
82
+ ] as const,
83
+ sync: [],
84
+ };
85
+
86
+ type AsyncMethodName = Writable<(typeof canUsePluginMethods)['async']>;
87
+
49
88
  class Editor extends BaseService {
50
89
  public state: StoreState = reactive({
51
90
  root: null,
@@ -65,29 +104,7 @@ class Editor extends BaseService {
65
104
 
66
105
  constructor() {
67
106
  super(
68
- [
69
- { name: 'getLayout', isAsync: true },
70
- { name: 'select', isAsync: true },
71
- { name: 'doAdd', isAsync: true },
72
- { name: 'add', isAsync: true },
73
- { name: 'doRemove', isAsync: true },
74
- { name: 'remove', isAsync: true },
75
- { name: 'doUpdate', isAsync: true },
76
- { name: 'update', isAsync: true },
77
- { name: 'sort', isAsync: true },
78
- { name: 'copy', isAsync: true },
79
- { name: 'paste', isAsync: true },
80
- { name: 'doPaste', isAsync: true },
81
- { name: 'doAlignCenter', isAsync: true },
82
- { name: 'alignCenter', isAsync: true },
83
- { name: 'moveLayer', isAsync: true },
84
- { name: 'moveToContainer', isAsync: true },
85
- { name: 'move', isAsync: true },
86
- { name: 'undo', isAsync: true },
87
- { name: 'redo', isAsync: true },
88
- { name: 'highlight', isAsync: true },
89
- { name: 'dragTo', isAsync: true },
90
- ],
107
+ canUsePluginMethods.async.map((methodName) => ({ name: methodName, isAsync: true })),
91
108
  // 需要注意循环依赖问题,如果函数间有相互调用的话,不能设置为串行调用
92
109
  ['select', 'update', 'moveLayer'],
93
110
  );
@@ -696,7 +713,7 @@ class Editor extends BaseService {
696
713
 
697
714
  public async doPaste(config: MNode[], position: PastePosition = {}): Promise<MNode[]> {
698
715
  propsService.clearRelateId();
699
- const pasteConfigs = await beforePaste(position, cloneDeep(config));
716
+ const pasteConfigs = beforePaste(position, cloneDeep(config));
700
717
  return pasteConfigs;
701
718
  }
702
719
 
@@ -985,6 +1002,10 @@ class Editor extends BaseService {
985
1002
  this.get('modifiedNodeIds').clear();
986
1003
  }
987
1004
 
1005
+ public usePlugin(options: AsyncHookPlugin<AsyncMethodName, Editor>): void {
1006
+ super.usePlugin(options);
1007
+ }
1008
+
988
1009
  private addModifiedNodeId(id: Id) {
989
1010
  if (!this.isHistoryStateChange) {
990
1011
  this.get('modifiedNodeIds').set(id, id);
@@ -55,11 +55,11 @@ class Events extends BaseService {
55
55
  }
56
56
 
57
57
  public setEvent(type: string, events: EventOption[]) {
58
- eventMap[type] = [...DEFAULT_EVENTS, ...events];
58
+ eventMap[toLine(type)] = [...DEFAULT_EVENTS, ...events];
59
59
  }
60
60
 
61
61
  public getEvent(type: string): EventOption[] {
62
- return cloneDeep(eventMap[type] || DEFAULT_EVENTS);
62
+ return cloneDeep(eventMap[toLine(type)] || DEFAULT_EVENTS);
63
63
  }
64
64
 
65
65
  public setMethods(methods: Record<string, EventOption[]>) {
@@ -69,11 +69,11 @@ class Events extends BaseService {
69
69
  }
70
70
 
71
71
  public setMethod(type: string, method: EventOption[]) {
72
- methodMap[type] = [...DEFAULT_METHODS, ...method];
72
+ methodMap[toLine(type)] = [...DEFAULT_METHODS, ...method];
73
73
  }
74
74
 
75
75
  public getMethod(type: string) {
76
- return cloneDeep(methodMap[type] || DEFAULT_METHODS);
76
+ return cloneDeep(methodMap[toLine(type)] || DEFAULT_METHODS);
77
77
  }
78
78
 
79
79
  public resetState() {