@tmagic/editor 1.0.0-beta.8 → 1.0.0-rc.10

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 (73) hide show
  1. package/README.md +1 -0
  2. package/dist/style.css +94 -45
  3. package/dist/tmagic-editor.es.js +1622 -2069
  4. package/dist/tmagic-editor.es.js.map +1 -1
  5. package/dist/tmagic-editor.umd.js +1621 -2071
  6. package/dist/tmagic-editor.umd.js.map +1 -1
  7. package/dist/types/src/Editor.vue.d.ts +50 -2
  8. package/dist/types/src/fields/Code.vue.d.ts +4 -4
  9. package/dist/types/src/fields/CodeLink.vue.d.ts +1 -3
  10. package/dist/types/src/index.d.ts +1 -0
  11. package/dist/types/src/layouts/CodeEditor.vue.d.ts +13 -4
  12. package/dist/types/src/layouts/Framework.vue.d.ts +15 -3
  13. package/dist/types/src/layouts/PropsPanel.vue.d.ts +4 -5
  14. package/dist/types/src/layouts/sidebar/ComponentListPanel.vue.d.ts +2 -1
  15. package/dist/types/src/layouts/sidebar/Sidebar.vue.d.ts +2 -3
  16. package/dist/types/src/layouts/sidebar/TabPane.vue.d.ts +14 -0
  17. package/dist/types/src/layouts/workspace/Workspace.vue.d.ts +5 -31
  18. package/dist/types/src/services/BaseService.d.ts +5 -2
  19. package/dist/types/src/services/editor.d.ts +16 -6
  20. package/dist/types/src/services/history.d.ts +2 -18
  21. package/dist/types/src/services/props.d.ts +8 -2
  22. package/dist/types/src/services/ui.d.ts +2 -0
  23. package/dist/types/src/type.d.ts +25 -9
  24. package/dist/types/src/utils/editor.d.ts +5 -10
  25. package/dist/types/src/utils/polyfills.d.ts +0 -0
  26. package/dist/types/src/utils/props.d.ts +8 -1
  27. package/package.json +35 -12
  28. package/src/Editor.vue +44 -9
  29. package/src/components/ContentMenu.vue +140 -0
  30. package/src/components/ScrollViewer.vue +1 -1
  31. package/src/components/ToolButton.vue +72 -31
  32. package/src/fields/UISelect.vue +14 -6
  33. package/src/index.ts +2 -0
  34. package/src/layouts/AddPageBox.vue +3 -1
  35. package/src/layouts/CodeEditor.vue +20 -13
  36. package/src/layouts/Framework.vue +20 -7
  37. package/src/layouts/PropsPanel.vue +5 -4
  38. package/src/layouts/sidebar/ComponentListPanel.vue +25 -3
  39. package/src/layouts/sidebar/LayerMenu.vue +93 -95
  40. package/src/layouts/sidebar/LayerPanel.vue +80 -59
  41. package/src/layouts/sidebar/Sidebar.vue +13 -52
  42. package/src/layouts/sidebar/TabPane.vue +68 -0
  43. package/src/layouts/workspace/PageBar.vue +145 -17
  44. package/src/layouts/workspace/Stage.vue +65 -91
  45. package/src/layouts/workspace/ViewerMenu.vue +122 -68
  46. package/src/layouts/workspace/Workspace.vue +125 -42
  47. package/src/services/BaseService.ts +71 -23
  48. package/src/services/editor.ts +231 -69
  49. package/src/services/history.ts +7 -0
  50. package/src/services/props.ts +64 -9
  51. package/src/services/ui.ts +35 -5
  52. package/src/theme/common/var.scss +3 -2
  53. package/src/theme/component-list-panel.scss +2 -0
  54. package/src/theme/content-menu.scss +33 -26
  55. package/src/theme/layer-panel.scss +10 -0
  56. package/src/theme/nav-menu.scss +6 -2
  57. package/src/theme/page-bar.scss +42 -2
  58. package/src/theme/props-panel.scss +19 -17
  59. package/src/theme/workspace.scss +4 -0
  60. package/src/type.ts +27 -9
  61. package/src/utils/editor.ts +37 -56
  62. package/src/utils/polyfills.ts +8 -0
  63. package/src/utils/props.ts +50 -8
  64. package/LICENSE +0 -5432
  65. package/dist/types/src/components/ToolButton.vue.d.ts +0 -35
  66. package/dist/types/src/fields/UISelect.vue.d.ts +0 -32
  67. package/dist/types/src/layouts/sidebar/LayerMenu.vue.d.ts +0 -31
  68. package/dist/types/src/layouts/sidebar/LayerPanel.vue.d.ts +0 -973
  69. package/dist/types/src/layouts/workspace/PageBar.vue.d.ts +0 -11
  70. package/dist/types/src/layouts/workspace/Stage.vue.d.ts +0 -192
  71. package/dist/types/src/layouts/workspace/ViewerMenu.vue.d.ts +0 -18
  72. package/tsconfig.json +0 -9
  73. package/vite.config.ts +0 -30
@@ -1,46 +1,33 @@
1
1
  <template>
2
- <div class="magic-editor-content-menu" ref="menu">
3
- <div>
4
- <div class="magic-editor-content-menu-item" @click="() => center()" v-if="canCenter">水平居中</div>
5
- <div class="magic-editor-content-menu-item" @click="() => copy()">复制</div>
6
- <div class="magic-editor-content-menu-item" @click="paste" v-if="canPaste">粘贴</div>
7
- <template v-if="canMoveZPos">
8
- <div class="separation"></div>
9
- <div class="magic-editor-content-menu-item" @click="topItem">上移一层</div>
10
- <div class="magic-editor-content-menu-item" @click="bottomItem">下移一层</div>
11
- <div class="magic-editor-content-menu-item" @click="top">置顶</div>
12
- <div class="magic-editor-content-menu-item" @click="bottom">置底</div>
13
- </template>
14
- <template v-if="canDelete">
15
- <div class="separation"></div>
16
- <div class="magic-editor-content-menu-item" @click="() => remove()">删除</div>
17
- </template>
18
- <div class="separation"></div>
19
- <div class="magic-editor-content-menu-item" @click="clearGuides">清空参考线</div>
20
- </div>
21
- </div>
2
+ <content-menu :menu-data="menuData" ref="menu"></content-menu>
22
3
  </template>
23
4
 
24
5
  <script lang="ts">
25
- import { computed, defineComponent, inject, onMounted, ref, watch } from 'vue';
6
+ import { computed, defineComponent, inject, markRaw, onMounted, reactive, ref, watch } from 'vue';
7
+ import { Bottom, Delete, DocumentCopy, Top } from '@element-plus/icons';
26
8
 
9
+ import { NodeType } from '@tmagic/schema';
27
10
  import type StageCore from '@tmagic/stage';
28
11
 
29
- import { LayerOffset, Layout, Services } from '@editor/type';
12
+ import ContentMenu from '@editor/components/ContentMenu.vue';
13
+ import { LayerOffset, Layout, MenuItem, Services } from '@editor/type';
30
14
  import { COPY_STORAGE_KEY } from '@editor/utils/editor';
31
15
 
32
16
  export default defineComponent({
33
- name: 'magic-editor-ui-viewer-menu',
17
+ components: { ContentMenu },
34
18
 
35
19
  setup() {
36
20
  const services = inject<Services>('services');
37
21
  const editorService = services?.editorService;
38
- const menu = ref<HTMLDivElement>();
22
+ const menu = ref<InstanceType<typeof ContentMenu>>();
39
23
  const canPaste = ref(false);
40
24
  const canCenter = ref(false);
41
25
 
42
26
  const node = computed(() => editorService?.get('node'));
43
27
  const parent = computed(() => editorService?.get('parent'));
28
+ const isPage = computed(() => node.value?.type === NodeType.PAGE);
29
+
30
+ const stageContentMenu = inject<MenuItem[]>('stageContentMenu', []);
44
31
 
45
32
  onMounted(() => {
46
33
  const data = globalThis.localStorage.getItem(COPY_STORAGE_KEY);
@@ -53,56 +40,123 @@ export default defineComponent({
53
40
  if (!parent.value || !editorService) return (canCenter.value = false);
54
41
  const layout = await editorService.getLayout(parent.value);
55
42
  canCenter.value =
56
- [Layout.ABSOLUTE, Layout.FIXED].includes(layout) && !['app', 'page', 'pop'].includes(`${node.value?.type}`);
43
+ [Layout.ABSOLUTE, Layout.FIXED].includes(layout) &&
44
+ ![NodeType.ROOT, NodeType.PAGE, 'pop'].includes(`${node.value?.type}`);
57
45
  },
58
46
  { immediate: true },
59
47
  );
60
48
 
61
49
  return {
62
50
  menu,
63
- canPaste,
64
-
65
- canDelete: computed(() => node.value?.type !== 'page'),
66
- canMoveZPos: computed(() => node.value?.type !== 'page'),
67
- canCenter,
68
-
69
- center() {
70
- node.value && editorService?.alignCenter(node.value);
71
- },
72
-
73
- copy() {
74
- node.value && editorService?.copy(node.value);
75
- canPaste.value = true;
76
- },
77
-
78
- paste() {
79
- const top = menu.value?.offsetTop || 0;
80
- const left = menu.value?.offsetLeft || 0;
81
- editorService?.paste({ left, top });
82
- },
83
-
84
- remove() {
85
- node.value && editorService?.remove(node.value);
86
- },
87
-
88
- top() {
89
- editorService?.moveLayer(LayerOffset.TOP);
90
- },
91
-
92
- bottom() {
93
- editorService?.moveLayer(LayerOffset.BOTTOM);
94
- },
95
-
96
- topItem() {
97
- editorService?.moveLayer(1);
98
- },
99
-
100
- bottomItem() {
101
- editorService?.moveLayer(-1);
102
- },
103
-
104
- clearGuides() {
105
- editorService?.get<StageCore>('stage').clearGuides();
51
+ menuData: reactive<MenuItem[]>([
52
+ {
53
+ type: 'button',
54
+ text: '水平居中',
55
+ display: () => canCenter.value,
56
+ handler: () => {
57
+ node.value && editorService?.alignCenter(node.value);
58
+ },
59
+ },
60
+ {
61
+ type: 'button',
62
+ text: '复制',
63
+ icon: markRaw(DocumentCopy),
64
+ handler: () => {
65
+ node.value && editorService?.copy(node.value);
66
+ canPaste.value = true;
67
+ },
68
+ },
69
+ {
70
+ type: 'button',
71
+ text: '粘贴',
72
+ display: () => canPaste.value,
73
+ handler: () => {
74
+ const stage = editorService?.get<StageCore>('stage');
75
+
76
+ const rect = menu.value?.$el.getBoundingClientRect();
77
+ const parentRect = stage?.container?.getBoundingClientRect();
78
+ let left = (rect?.left || 0) - (parentRect?.left || 0);
79
+ let top = (rect?.top || 0) - (parentRect?.top || 0);
80
+
81
+ if (node.value?.items && stage) {
82
+ const parentEl = stage.renderer.contentWindow?.document.getElementById(`${node.value.id}`);
83
+ const parentElRect = parentEl?.getBoundingClientRect();
84
+ left = left - (parentElRect?.left || 0);
85
+ top = top - (parentElRect?.top || 0);
86
+ }
87
+
88
+ editorService?.paste({ left, top });
89
+ },
90
+ },
91
+ {
92
+ type: 'divider',
93
+ direction: 'horizontal',
94
+ display: () => !isPage.value,
95
+ },
96
+ {
97
+ type: 'button',
98
+ text: '上移一层',
99
+ icon: markRaw(Top),
100
+ display: () => !isPage.value,
101
+ handler: () => {
102
+ editorService?.moveLayer(1);
103
+ },
104
+ },
105
+ {
106
+ type: 'button',
107
+ text: '下移一层',
108
+ icon: markRaw(Bottom),
109
+ display: () => !isPage.value,
110
+ handler: () => {
111
+ editorService?.moveLayer(-1);
112
+ },
113
+ },
114
+ {
115
+ type: 'button',
116
+ text: '置顶',
117
+ display: () => !isPage.value,
118
+ handler: () => {
119
+ editorService?.moveLayer(LayerOffset.TOP);
120
+ },
121
+ },
122
+ {
123
+ type: 'button',
124
+ text: '置底',
125
+ display: () => !isPage.value,
126
+ handler: () => {
127
+ editorService?.moveLayer(LayerOffset.BOTTOM);
128
+ },
129
+ },
130
+ {
131
+ type: 'divider',
132
+ direction: 'horizontal',
133
+ display: () => !isPage.value,
134
+ },
135
+ {
136
+ type: 'button',
137
+ text: '删除',
138
+ icon: Delete,
139
+ display: () => !isPage.value,
140
+ handler: () => {
141
+ node.value && editorService?.remove(node.value);
142
+ },
143
+ },
144
+ {
145
+ type: 'divider',
146
+ direction: 'horizontal',
147
+ },
148
+ {
149
+ type: 'button',
150
+ text: '清空参考线',
151
+ handler: () => {
152
+ editorService?.get<StageCore>('stage').clearGuides();
153
+ },
154
+ },
155
+ ...stageContentMenu,
156
+ ]),
157
+
158
+ show(e: MouseEvent) {
159
+ menu.value?.show(e);
106
160
  },
107
161
  };
108
162
  },
@@ -1,15 +1,6 @@
1
1
  <template>
2
- <div class="m-editor-workspace">
3
- <magic-stage
4
- :key="page?.id"
5
- :runtime-url="runtimeUrl"
6
- :render="render"
7
- :moveable-options="moveableOptions"
8
- :can-select="canSelect"
9
- @select="selectHandler"
10
- @update="updateNodeHandler"
11
- @sort="sortNodeHandler"
12
- ></magic-stage>
2
+ <div class="m-editor-workspace" tabindex="1" ref="workspace">
3
+ <magic-stage :key="page?.id"></magic-stage>
13
4
 
14
5
  <slot name="workspace-content"></slot>
15
6
 
@@ -21,11 +12,11 @@
21
12
  </template>
22
13
 
23
14
  <script lang="ts">
24
- import { computed, defineComponent, inject, PropType } from 'vue';
15
+ import { computed, defineComponent, inject, onMounted, onUnmounted, ref } from 'vue';
16
+ import KeyController from 'keycon';
25
17
 
26
- import type { MComponent, MContainer, MPage } from '@tmagic/schema';
27
- import type { MoveableOptions, SortEventData } from '@tmagic/stage';
28
- import StageCore from '@tmagic/stage';
18
+ import type { MNode, MPage } from '@tmagic/schema';
19
+ import { isPage } from '@tmagic/utils';
29
20
 
30
21
  import type { Services } from '@editor/type';
31
22
 
@@ -40,39 +31,131 @@ export default defineComponent({
40
31
  MagicStage,
41
32
  },
42
33
 
43
- props: {
44
- runtimeUrl: String,
45
-
46
- render: {
47
- type: Function as PropType<() => HTMLDivElement>,
48
- },
49
-
50
- moveableOptions: {
51
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
52
- },
53
-
54
- canSelect: {
55
- type: Function as PropType<(el: HTMLElement) => boolean | Promise<boolean>>,
56
- },
57
- },
58
-
59
34
  setup() {
60
35
  const services = inject<Services>('services');
36
+ const workspace = ref<HTMLDivElement>();
37
+ const node = computed(() => services?.editorService.get<MNode>('node'));
38
+ let keycon: KeyController;
61
39
 
62
- return {
63
- page: computed(() => services?.editorService.get<MPage>('page')),
40
+ const mouseenterHandler = () => {
41
+ workspace.value?.focus();
42
+ };
43
+
44
+ const mouseleaveHandler = () => {
45
+ workspace.value?.blur();
46
+ };
64
47
 
65
- selectHandler(el: HTMLElement) {
66
- services?.editorService.select(el.id);
67
- },
48
+ onMounted(() => {
49
+ workspace.value?.addEventListener('mouseenter', mouseenterHandler);
50
+ workspace.value?.addEventListener('mouseleave', mouseleaveHandler);
51
+
52
+ keycon = new KeyController(workspace.value);
53
+
54
+ const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
55
+
56
+ const ctrl = isMac ? 'meta' : 'ctrl';
57
+
58
+ keycon
59
+ .keyup('delete', (e) => {
60
+ e.inputEvent.preventDefault();
61
+ if (!node.value || isPage(node.value)) return;
62
+ services?.editorService.remove(node.value);
63
+ })
64
+ .keyup('backspace', (e) => {
65
+ e.inputEvent.preventDefault();
66
+ if (!node.value || isPage(node.value)) return;
67
+ services?.editorService.remove(node.value);
68
+ })
69
+ .keydown([ctrl, 'c'], (e) => {
70
+ e.inputEvent.preventDefault();
71
+ node.value && services?.editorService.copy(node.value);
72
+ })
73
+ .keydown([ctrl, 'v'], (e) => {
74
+ e.inputEvent.preventDefault();
75
+ node.value && services?.editorService.paste();
76
+ })
77
+ .keydown([ctrl, 'x'], (e) => {
78
+ e.inputEvent.preventDefault();
79
+ if (!node.value || isPage(node.value)) return;
80
+ services?.editorService.copy(node.value);
81
+ services?.editorService.remove(node.value);
82
+ })
83
+ .keydown([ctrl, 'z'], (e) => {
84
+ e.inputEvent.preventDefault();
85
+ services?.editorService.undo();
86
+ })
87
+ .keydown([ctrl, 'shift', 'z'], (e) => {
88
+ e.inputEvent.preventDefault();
89
+ services?.editorService.redo();
90
+ })
91
+ .keydown('up', (e) => {
92
+ e.inputEvent.preventDefault();
93
+ services?.editorService.move(0, -1);
94
+ })
95
+ .keydown('down', (e) => {
96
+ e.inputEvent.preventDefault();
97
+ services?.editorService.move(0, 1);
98
+ })
99
+ .keydown('left', (e) => {
100
+ e.inputEvent.preventDefault();
101
+ services?.editorService.move(-1, 0);
102
+ })
103
+ .keydown('right', (e) => {
104
+ e.inputEvent.preventDefault();
105
+ services?.editorService.move(1, 0);
106
+ })
107
+ .keydown([ctrl, 'up'], (e) => {
108
+ e.inputEvent.preventDefault();
109
+ services?.editorService.move(0, -10);
110
+ })
111
+ .keydown([ctrl, 'down'], (e) => {
112
+ e.inputEvent.preventDefault();
113
+ services?.editorService.move(0, 10);
114
+ })
115
+ .keydown([ctrl, 'left'], (e) => {
116
+ e.inputEvent.preventDefault();
117
+ services?.editorService.move(-10, 0);
118
+ })
119
+ .keydown([ctrl, 'right'], (e) => {
120
+ e.inputEvent.preventDefault();
121
+ services?.editorService.move(10, 0);
122
+ })
123
+ .keydown('tab', (e) => {
124
+ e.inputEvent.preventDefault();
125
+ services?.editorService.selectNextNode();
126
+ })
127
+ .keydown([ctrl, 'tab'], (e) => {
128
+ e.inputEvent.preventDefault();
129
+ services?.editorService.selectNextPage();
130
+ })
131
+ .keydown([ctrl, '='], (e) => {
132
+ e.inputEvent.preventDefault();
133
+ services?.uiService.zoom(0.1);
134
+ })
135
+ .keydown([ctrl, 'numpadplus'], (e) => {
136
+ e.inputEvent.preventDefault();
137
+ services?.uiService.zoom(0.1);
138
+ })
139
+ .keydown([ctrl, '-'], (e) => {
140
+ e.inputEvent.preventDefault();
141
+ services?.uiService.zoom(-0.1);
142
+ })
143
+ .keydown([ctrl, 'numpad-'], (e) => {
144
+ e.inputEvent.preventDefault();
145
+ services?.uiService.zoom(-0.1);
146
+ });
147
+ });
148
+
149
+ onUnmounted(() => {
150
+ workspace.value?.removeEventListener('mouseenter', mouseenterHandler);
151
+ workspace.value?.removeEventListener('mouseleave', mouseleaveHandler);
152
+ keycon.destroy();
153
+ });
68
154
 
69
- updateNodeHandler(node: MComponent | MContainer | MPage) {
70
- services?.editorService.update(node);
71
- },
155
+ return {
156
+ workspace,
72
157
 
73
- sortNodeHandler(ev: SortEventData) {
74
- services?.editorService.sort(ev.src, ev.dist);
75
- },
158
+ page: computed(() => services?.editorService.get<MPage>('page')),
76
159
  };
77
160
  },
78
161
  });
@@ -24,6 +24,46 @@ const methodName = (prefix: string, name: string) => `${prefix}${name[0].toUpper
24
24
 
25
25
  const isError = (error: any): boolean => Object.prototype.toString.call(error) === '[object Error]';
26
26
 
27
+ const doAction = async (
28
+ args: any[],
29
+ scope: any,
30
+ sourceMethod: any,
31
+ beforeMethodName: string,
32
+ afterMethodName: string,
33
+ fn: (args: any[], next?: Function | undefined) => Promise<void>,
34
+ ) => {
35
+ try {
36
+ let beforeArgs = args;
37
+
38
+ for (const beforeMethod of scope.pluginOptionsList[beforeMethodName]) {
39
+ let beforeReturnValue = (await beforeMethod(...beforeArgs)) || [];
40
+
41
+ if (isError(beforeReturnValue)) throw beforeReturnValue;
42
+
43
+ if (!Array.isArray(beforeReturnValue)) {
44
+ beforeReturnValue = [beforeReturnValue];
45
+ }
46
+
47
+ beforeArgs = beforeArgs.map((v: any, index: number) => {
48
+ if (typeof beforeReturnValue[index] === 'undefined') return v;
49
+ return beforeReturnValue[index];
50
+ });
51
+ }
52
+
53
+ let returnValue: any = await fn(beforeArgs, sourceMethod.bind(scope));
54
+
55
+ for (const afterMethod of scope.pluginOptionsList[afterMethodName]) {
56
+ returnValue = await afterMethod(returnValue, ...beforeArgs);
57
+
58
+ if (isError(returnValue)) throw returnValue;
59
+ }
60
+
61
+ return returnValue;
62
+ } catch (error) {
63
+ throw error;
64
+ }
65
+ };
66
+
27
67
  /**
28
68
  * 提供两种方式对Class进行扩展
29
69
  * 方法1:
@@ -51,7 +91,7 @@ const isError = (error: any): boolean => Object.prototype.toString.call(error) =
51
91
  * editorService.afterAdd();
52
92
  * }
53
93
  *
54
- * 调用时的参数会透传到before方法的参数中, 然后before的return 会作为原方法的参数和after的参数,after最后一个参数则是原方法的return值;
94
+ * 调用时的参数会透传到before方法的参数中, 然后before的return 会作为原方法的参数和after的参数,after第一个参数则是原方法的return值;
55
95
  * 如需终止后续方法调用可以return new Error();
56
96
  *
57
97
  * 方法2:
@@ -74,8 +114,10 @@ const isError = (error: any): boolean => Object.prototype.toString.call(error) =
74
114
  export default class extends EventEmitter {
75
115
  private pluginOptionsList: Record<string, Function[]> = {};
76
116
  private middleware: Record<string, Function[]> = {};
117
+ private taskList: (() => Promise<void>)[] = [];
118
+ private doingTask = false;
77
119
 
78
- constructor(methods: string[]) {
120
+ constructor(methods: string[] = [], serialMethods: string[] = []) {
79
121
  super();
80
122
 
81
123
  methods.forEach((propertyName: string) => {
@@ -93,32 +135,28 @@ export default class extends EventEmitter {
93
135
  const fn = compose(this.middleware[propertyName]);
94
136
  Object.defineProperty(scope, propertyName, {
95
137
  value: async (...args: any[]) => {
96
- let beforeArgs = args;
97
-
98
- for (const beforeMethod of this.pluginOptionsList[beforeMethodName]) {
99
- let beforeReturnValue = (await beforeMethod(...beforeArgs)) || [];
100
-
101
- if (isError(beforeReturnValue)) throw beforeReturnValue;
102
-
103
- if (!Array.isArray(beforeReturnValue)) {
104
- beforeReturnValue = [beforeReturnValue];
105
- }
106
-
107
- beforeArgs = beforeArgs.map((v: any, index: number) => {
108
- if (typeof beforeReturnValue[index] === 'undefined') return v;
109
- return beforeReturnValue[index];
110
- });
138
+ if (!serialMethods.includes(propertyName)) {
139
+ return doAction(args, scope, sourceMethod, beforeMethodName, afterMethodName, fn);
111
140
  }
112
141
 
113
- let returnValue = await fn(beforeArgs, sourceMethod.bind(scope));
114
-
115
- for (const afterMethod of this.pluginOptionsList[afterMethodName]) {
116
- returnValue = await afterMethod(...beforeArgs, returnValue);
142
+ // 由于async await,所以会出现函数执行到await时让出线程,导致执行顺序出错,例如调用了select(1) -> update -> select(2),这个时候就有可能出现update了2;
143
+ // 这里保证函数调用严格按顺序执行;
144
+ const promise = new Promise<any>((resolve, reject) => {
145
+ this.taskList.push(async () => {
146
+ try {
147
+ const value = await doAction(args, scope, sourceMethod, beforeMethodName, afterMethodName, fn);
148
+ resolve(value);
149
+ } catch (e) {
150
+ reject(e);
151
+ }
152
+ });
153
+ });
117
154
 
118
- if (isError(returnValue)) throw returnValue;
155
+ if (!this.doingTask) {
156
+ this.doTask();
119
157
  }
120
158
 
121
- return returnValue;
159
+ return promise;
122
160
  },
123
161
  });
124
162
  });
@@ -135,4 +173,14 @@ export default class extends EventEmitter {
135
173
  if (typeof method === 'function') this.pluginOptionsList[methodName].push(method);
136
174
  });
137
175
  }
176
+
177
+ private async doTask() {
178
+ this.doingTask = true;
179
+ let task = this.taskList.shift();
180
+ while (task) {
181
+ await task();
182
+ task = this.taskList.shift();
183
+ }
184
+ this.doingTask = false;
185
+ }
138
186
  }