@tmagic/editor 1.5.7 → 1.5.8

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 (72) hide show
  1. package/dist/style.css +17 -0
  2. package/dist/tmagic-editor.js +463 -470
  3. package/dist/tmagic-editor.umd.cjs +471 -469
  4. package/package.json +7 -7
  5. package/src/components/CodeBlockEditor.vue +4 -4
  6. package/src/components/FloatingBox.vue +4 -4
  7. package/src/components/ToolButton.vue +6 -4
  8. package/src/components/TreeNode.vue +2 -2
  9. package/src/fields/CodeSelect.vue +6 -6
  10. package/src/fields/CodeSelectCol.vue +5 -4
  11. package/src/fields/CondOpSelect.vue +5 -4
  12. package/src/fields/DataSourceFieldSelect/FieldSelect.vue +6 -5
  13. package/src/fields/DataSourceFieldSelect/Index.vue +4 -3
  14. package/src/fields/DataSourceFields.vue +3 -3
  15. package/src/fields/DataSourceInput.vue +4 -4
  16. package/src/fields/DataSourceMethodSelect.vue +8 -9
  17. package/src/fields/DataSourceMocks.vue +3 -3
  18. package/src/fields/DataSourceSelect.vue +6 -5
  19. package/src/fields/DisplayConds.vue +4 -4
  20. package/src/fields/EventSelect.vue +17 -23
  21. package/src/fields/PageFragmentSelect.vue +6 -5
  22. package/src/fields/UISelect.vue +16 -19
  23. package/src/hooks/index.ts +1 -0
  24. package/src/hooks/use-code-block-edit.ts +5 -10
  25. package/src/hooks/use-data-source-edit.ts +6 -6
  26. package/src/hooks/use-editor-content-height.ts +5 -5
  27. package/src/hooks/use-float-box.ts +5 -5
  28. package/src/hooks/use-next-float-box-position.ts +9 -9
  29. package/src/hooks/use-services.ts +13 -0
  30. package/src/hooks/use-stage.ts +2 -6
  31. package/src/layouts/AddPageBox.vue +3 -7
  32. package/src/layouts/Framework.vue +27 -27
  33. package/src/layouts/NavMenu.vue +16 -16
  34. package/src/layouts/page-bar/AddButton.vue +4 -7
  35. package/src/layouts/page-bar/PageBar.vue +10 -10
  36. package/src/layouts/page-bar/PageBarScrollContainer.vue +7 -8
  37. package/src/layouts/page-bar/PageList.vue +6 -8
  38. package/src/layouts/props-panel/FormPanel.vue +6 -4
  39. package/src/layouts/props-panel/PropsPanel.vue +39 -49
  40. package/src/layouts/props-panel/use-style-panel.ts +35 -19
  41. package/src/layouts/sidebar/ComponentListPanel.vue +5 -5
  42. package/src/layouts/sidebar/Sidebar.vue +15 -9
  43. package/src/layouts/sidebar/code-block/CodeBlockList.vue +13 -18
  44. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +4 -3
  45. package/src/layouts/sidebar/code-block/useContentMenu.ts +3 -3
  46. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +5 -5
  47. package/src/layouts/sidebar/data-source/DataSourceList.vue +13 -17
  48. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +6 -12
  49. package/src/layouts/sidebar/data-source/useContentMenu.ts +3 -3
  50. package/src/layouts/sidebar/layer/LayerMenu.vue +11 -8
  51. package/src/layouts/sidebar/layer/LayerNodeTool.vue +2 -6
  52. package/src/layouts/sidebar/layer/LayerPanel.vue +6 -12
  53. package/src/layouts/sidebar/layer/use-click.ts +16 -15
  54. package/src/layouts/sidebar/layer/use-drag.ts +6 -6
  55. package/src/layouts/sidebar/layer/use-keybinding.ts +6 -8
  56. package/src/layouts/sidebar/layer/use-node-status.ts +16 -7
  57. package/src/layouts/workspace/Breadcrumb.vue +8 -9
  58. package/src/layouts/workspace/Workspace.vue +4 -10
  59. package/src/layouts/workspace/viewer/NodeListMenu.vue +9 -8
  60. package/src/layouts/workspace/viewer/Stage.vue +24 -24
  61. package/src/layouts/workspace/viewer/StageOverlay.vue +15 -16
  62. package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -14
  63. package/src/services/dep.ts +23 -8
  64. package/src/services/ui.ts +6 -2
  65. package/src/theme/common/var.scss +1 -0
  66. package/src/theme/sidebar.scss +20 -1
  67. package/src/type.ts +3 -9
  68. package/src/utils/const.ts +11 -0
  69. package/src/utils/content-menu.ts +28 -30
  70. package/src/utils/idle-task.ts +11 -0
  71. package/src/utils/index.ts +1 -0
  72. package/types/index.d.ts +28 -10
@@ -20,9 +20,6 @@
20
20
  </template>
21
21
 
22
22
  <template #tree-node-tool="{ data }">
23
- <TMagicTag v-if="collecting && data.type === 'code'" type="info" size="small" style="margin-right: 5px"
24
- >依赖收集中</TMagicTag
25
- >
26
23
  <TMagicTooltip v-if="data.type === 'code'" effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
27
24
  <Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editCode(`${data.key}`)"></Icon>
28
25
  </TMagicTooltip>
@@ -35,18 +32,19 @@
35
32
  </template>
36
33
 
37
34
  <script lang="ts" setup>
38
- import { computed, inject } from 'vue';
35
+ import { computed } from 'vue';
39
36
  import { Close, Edit, View } from '@element-plus/icons-vue';
40
37
 
41
38
  import type { Id, MNode } from '@tmagic/core';
42
39
  import { DepTargetType } from '@tmagic/core';
43
- import { tMagicMessage, tMagicMessageBox, TMagicTag, TMagicTooltip } from '@tmagic/design';
40
+ import { tMagicMessage, tMagicMessageBox, TMagicTooltip } from '@tmagic/design';
44
41
 
45
42
  import Icon from '@editor/components/Icon.vue';
46
43
  import Tree from '@editor/components/Tree.vue';
47
44
  import { useFilter } from '@editor/hooks/use-filter';
48
45
  import { useNodeStatus } from '@editor/hooks/use-node-status';
49
- import { type CodeBlockListSlots, CodeDeleteErrorType, type Services, type TreeNodeData } from '@editor/type';
46
+ import { useServices } from '@editor/hooks/use-services';
47
+ import { type CodeBlockListSlots, CodeDeleteErrorType, type TreeNodeData } from '@editor/type';
50
48
 
51
49
  defineSlots<CodeBlockListSlots>();
52
50
 
@@ -66,19 +64,16 @@ const emit = defineEmits<{
66
64
  'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
67
65
  }>();
68
66
 
69
- const services = inject<Services>('services');
70
- const { codeBlockService, depService, editorService } = services || {};
71
-
72
- const collecting = computed(() => depService?.get('collecting'));
67
+ const { codeBlockService, depService, editorService } = useServices();
73
68
 
74
69
  // 代码块列表
75
70
  const codeList = computed<TreeNodeData[]>(() =>
76
- Object.entries(codeBlockService?.getCodeDsl() || {}).map(([codeId, code]) => {
77
- const target = depService?.getTarget(codeId, DepTargetType.CODE_BLOCK);
71
+ Object.entries(codeBlockService.getCodeDsl() || {}).map(([codeId, code]) => {
72
+ const target = depService.getTarget(codeId, DepTargetType.CODE_BLOCK);
78
73
 
79
74
  // 按页面分类显示
80
75
  const pageList: TreeNodeData[] =
81
- editorService?.get('root')?.items.map((page) => ({
76
+ editorService.get('root')?.items.map((page) => ({
82
77
  name: page.devconfig?.tabName || page.name,
83
78
  type: 'node',
84
79
  id: `${codeId}_${page.id}`,
@@ -108,7 +103,7 @@ const codeList = computed<TreeNodeData[]>(() =>
108
103
  key: codeId,
109
104
  name: code.name,
110
105
  type: 'code',
111
- codeBlockContent: codeBlockService?.getCodeContentById(codeId),
106
+ codeBlockContent: codeBlockService.getCodeContentById(codeId),
112
107
  // 只有一个页面不显示页面分类
113
108
  items: pageList.length > 1 ? pageList.filter((page) => page.items?.length) : pageList[0]?.items || [],
114
109
  };
@@ -127,12 +122,12 @@ const filterNode = (value: string, data: MNode): boolean => {
127
122
  const { nodeStatusMap } = useNodeStatus(codeList);
128
123
  const { filterTextChangeHandler } = useFilter(codeList, nodeStatusMap, filterNode);
129
124
 
130
- const editable = computed(() => codeBlockService?.getEditStatus());
125
+ const editable = computed(() => codeBlockService.getEditStatus());
131
126
 
132
127
  // 选中组件
133
128
  const selectComp = (compId: Id) => {
134
- const stage = editorService?.get('stage');
135
- editorService?.select(compId);
129
+ const stage = editorService.get('stage');
130
+ editorService.select(compId);
136
131
  stage?.select(compId);
137
132
  };
138
133
 
@@ -150,7 +145,7 @@ const editCode = (id: string) => {
150
145
  const deleteCode = async (id: string) => {
151
146
  const currentCode = codeList.value.find((codeItem) => codeItem.id === id);
152
147
  const existBinds = Boolean(currentCode?.items?.length);
153
- const undeleteableList = codeBlockService?.getUndeletableList() || [];
148
+ const undeleteableList = codeBlockService.getUndeletableList() || [];
154
149
  if (!existBinds && !undeleteableList.includes(id)) {
155
150
  await tMagicMessageBox.confirm('确定删除该代码块吗?', '提示', {
156
151
  confirmButtonText: '确定',
@@ -55,6 +55,7 @@ import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
55
55
  import ContentMenu from '@editor/components/ContentMenu.vue';
56
56
  import SearchInput from '@editor/components/SearchInput.vue';
57
57
  import { useCodeBlockEdit } from '@editor/hooks/use-code-block-edit';
58
+ import { useServices } from '@editor/hooks/use-services';
58
59
  import type {
59
60
  CodeBlockListPanelSlots,
60
61
  CodeDeleteErrorType,
@@ -62,7 +63,6 @@ import type {
62
63
  EventBus,
63
64
  MenuButton,
64
65
  MenuComponent,
65
- Services,
66
66
  } from '@editor/type';
67
67
 
68
68
  import CodeBlockList from './CodeBlockList.vue';
@@ -82,9 +82,10 @@ const props = defineProps<{
82
82
  }>();
83
83
 
84
84
  const eventBus = inject<EventBus>('eventBus');
85
- const { codeBlockService } = inject<Services>('services') || {};
86
85
 
87
- const editable = computed(() => codeBlockService?.getEditStatus());
86
+ const { codeBlockService } = useServices();
87
+
88
+ const editable = computed(() => codeBlockService.getEditStatus());
88
89
 
89
90
  const { codeBlockEditor, codeConfig, editCode, deleteCode, createCodeBlock, submitCodeBlockHandler } =
90
91
  useCodeBlockEdit(codeBlockService);
@@ -3,7 +3,7 @@ import { CopyDocument, Delete, Edit } from '@element-plus/icons-vue';
3
3
  import { cloneDeep } from 'lodash-es';
4
4
 
5
5
  import ContentMenu from '@editor/components/ContentMenu.vue';
6
- import type { EventBus, MenuButton, MenuComponent, Services, TreeNodeData } from '@editor/type';
6
+ import type { EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
7
7
 
8
8
  export const useContentMenu = (deleteCode: (id: string) => void) => {
9
9
  const eventBus = inject<EventBus>('eventBus');
@@ -16,7 +16,7 @@ export const useContentMenu = (deleteCode: (id: string) => void) => {
16
16
  type: 'button',
17
17
  text: '编辑',
18
18
  icon: Edit,
19
- display: (services) => services?.codeBlockService?.getEditStatus() ?? true,
19
+ display: ({ codeBlockService }) => codeBlockService.getEditStatus(),
20
20
  handler: () => {
21
21
  if (!selectId) {
22
22
  return;
@@ -29,7 +29,7 @@ export const useContentMenu = (deleteCode: (id: string) => void) => {
29
29
  type: 'button',
30
30
  text: '复制并粘贴至当前',
31
31
  icon: markRaw(CopyDocument),
32
- handler: async ({ codeBlockService }: Services) => {
32
+ handler: async ({ codeBlockService }) => {
33
33
  if (!selectId) {
34
34
  return;
35
35
  }
@@ -29,9 +29,9 @@ import { tMagicMessage } from '@tmagic/design';
29
29
  import { type ContainerChangeEventData, type FormConfig, MFormBox } from '@tmagic/form';
30
30
 
31
31
  import FloatingBox from '@editor/components/FloatingBox.vue';
32
- import { useEditorContentHeight } from '@editor/hooks';
32
+ import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
33
33
  import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
34
- import type { Services } from '@editor/type';
34
+ import { useServices } from '@editor/hooks/use-services';
35
35
 
36
36
  defineOptions({
37
37
  name: 'MEditorDataSourceConfigPanel',
@@ -50,7 +50,7 @@ const emit = defineEmits<{
50
50
  submit: [v: any, eventData: ContainerChangeEventData];
51
51
  }>();
52
52
 
53
- const services = inject<Services>('services');
53
+ const { uiService, dataSourceService } = useServices();
54
54
 
55
55
  const initValues = ref<Partial<DataSourceSchema>>({});
56
56
  const dataSourceConfig = ref<FormConfig>([]);
@@ -58,11 +58,11 @@ const dataSourceConfig = ref<FormConfig>([]);
58
58
  const { height: editorHeight } = useEditorContentHeight();
59
59
 
60
60
  const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
61
- const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(services?.uiService, parentFloating);
61
+ const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
62
62
 
63
63
  watchEffect(() => {
64
64
  initValues.value = props.values;
65
- dataSourceConfig.value = services?.dataSourceService.getFormConfig(initValues.value.type) || [];
65
+ dataSourceConfig.value = dataSourceService.getFormConfig(initValues.value.type);
66
66
  });
67
67
 
68
68
  const submitHandler = (values: any, data: ContainerChangeEventData) => {
@@ -19,9 +19,6 @@
19
19
  </div>
20
20
  </template>
21
21
  <template #tree-node-tool="{ data }">
22
- <TMagicTag v-if="collecting && data.type === 'ds'" type="info" size="small" style="margin-right: 5px"
23
- >依赖收集中</TMagicTag
24
- >
25
22
  <TMagicTooltip v-if="data.type === 'ds'" effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
26
23
  <Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editHandler(`${data.key}`)"></Icon>
27
24
  </TMagicTooltip>
@@ -34,17 +31,18 @@
34
31
  </template>
35
32
 
36
33
  <script lang="ts" setup>
37
- import { computed, inject } from 'vue';
34
+ import { computed } from 'vue';
38
35
  import { Close, Edit, View } from '@element-plus/icons-vue';
39
36
 
40
37
  import { DepData, DepTargetType, Id, MNode } from '@tmagic/core';
41
- import { TMagicTag, TMagicTooltip } from '@tmagic/design';
38
+ import { TMagicTooltip } from '@tmagic/design';
42
39
 
43
40
  import Icon from '@editor/components/Icon.vue';
44
41
  import Tree from '@editor/components/Tree.vue';
45
42
  import { useFilter } from '@editor/hooks/use-filter';
46
43
  import { useNodeStatus } from '@editor/hooks/use-node-status';
47
- import type { DataSourceListSlots, Services, TreeNodeData } from '@editor/type';
44
+ import { useServices } from '@editor/hooks/use-services';
45
+ import type { DataSourceListSlots, TreeNodeData } from '@editor/type';
48
46
 
49
47
  defineSlots<DataSourceListSlots>();
50
48
 
@@ -63,17 +61,15 @@ const emit = defineEmits<{
63
61
  'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
64
62
  }>();
65
63
 
66
- const { depService, editorService, dataSourceService } = inject<Services>('services') || {};
67
-
68
- const collecting = computed(() => depService?.get('collecting'));
64
+ const { depService, editorService, dataSourceService } = useServices();
69
65
 
70
- const editable = computed(() => dataSourceService?.get('editable') ?? true);
66
+ const editable = computed(() => dataSourceService.get('editable'));
71
67
 
72
- const dataSources = computed(() => dataSourceService?.get('dataSources') || []);
68
+ const dataSources = computed(() => dataSourceService.get('dataSources'));
73
69
 
74
- const dsDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE) || {});
75
- const dsMethodDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_METHOD) || {});
76
- const dsCondDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_COND) || {});
70
+ const dsDep = computed(() => depService.getTargets(DepTargetType.DATA_SOURCE));
71
+ const dsMethodDep = computed(() => depService.getTargets(DepTargetType.DATA_SOURCE_METHOD));
72
+ const dsCondDep = computed(() => depService.getTargets(DepTargetType.DATA_SOURCE_COND));
77
73
 
78
74
  const getKeyTreeConfig = (dep: DepData[string], type?: string, parentKey?: Id) =>
79
75
  dep.keys.map((key) => ({
@@ -122,7 +118,7 @@ const list = computed(() =>
122
118
  const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
123
119
 
124
120
  const items =
125
- editorService?.get('root')?.items.map((page) => ({
121
+ editorService.get('root')?.items.map((page) => ({
126
122
  name: page.devconfig?.tabName || page.name,
127
123
  type: 'node',
128
124
  id: `${ds.id}_${page.id}`,
@@ -166,8 +162,8 @@ const removeHandler = async (id: string) => {
166
162
 
167
163
  // 选中组件
168
164
  const selectComp = (compId: Id) => {
169
- const stage = editorService?.get('stage');
170
- editorService?.select(compId);
165
+ const stage = editorService.get('stage');
166
+ editorService.select(compId);
171
167
  stage?.select(compId);
172
168
  };
173
169
 
@@ -68,14 +68,8 @@ import ContentMenu from '@editor/components/ContentMenu.vue';
68
68
  import SearchInput from '@editor/components/SearchInput.vue';
69
69
  import ToolButton from '@editor/components/ToolButton.vue';
70
70
  import { useDataSourceEdit } from '@editor/hooks/use-data-source-edit';
71
- import type {
72
- CustomContentMenuFunction,
73
- DataSourceListSlots,
74
- EventBus,
75
- MenuButton,
76
- MenuComponent,
77
- Services,
78
- } from '@editor/type';
71
+ import { useServices } from '@editor/hooks/use-services';
72
+ import type { CustomContentMenuFunction, DataSourceListSlots, EventBus, MenuButton, MenuComponent } from '@editor/type';
79
73
 
80
74
  import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
81
75
  import DataSourceList from './DataSourceList.vue';
@@ -94,7 +88,7 @@ const props = defineProps<{
94
88
  }>();
95
89
 
96
90
  const eventBus = inject<EventBus>('eventBus');
97
- const { dataSourceService } = inject<Services>('services') || {};
91
+ const { dataSourceService } = useServices();
98
92
 
99
93
  const { editDialog, dataSourceValues, dialogTitle, editable, editHandler, submitDataSourceHandler } =
100
94
  useDataSourceEdit(dataSourceService);
@@ -103,7 +97,7 @@ const datasourceTypeList = computed(() =>
103
97
  [
104
98
  { text: '基础', type: 'base' },
105
99
  { text: 'HTTP', type: 'http' },
106
- ].concat(dataSourceService?.get('datasourceTypeList') ?? []),
100
+ ].concat(dataSourceService.get('datasourceTypeList')),
107
101
  );
108
102
 
109
103
  const addHandler = (type: string) => {
@@ -113,7 +107,7 @@ const addHandler = (type: string) => {
113
107
 
114
108
  dataSourceValues.value = mergeWith(
115
109
  { type, title: datasourceType?.text },
116
- dataSourceService?.getFormValue(type) || {},
110
+ dataSourceService.getFormValue(type),
117
111
  (objValue, srcValue) => {
118
112
  if (Array.isArray(srcValue)) {
119
113
  return srcValue;
@@ -133,7 +127,7 @@ const removeHandler = async (id: string) => {
133
127
  type: 'warning',
134
128
  });
135
129
 
136
- dataSourceService?.remove(id);
130
+ dataSourceService.remove(id);
137
131
  };
138
132
 
139
133
  const dataSourceList = ref<InstanceType<typeof DataSourceList>>();
@@ -3,7 +3,7 @@ import { CopyDocument, Delete, Edit } from '@element-plus/icons-vue';
3
3
  import { cloneDeep } from 'lodash-es';
4
4
 
5
5
  import ContentMenu from '@editor/components/ContentMenu.vue';
6
- import type { EventBus, MenuButton, MenuComponent, Services, TreeNodeData } from '@editor/type';
6
+ import type { EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
7
7
 
8
8
  export const useContentMenu = () => {
9
9
  const eventBus = inject<EventBus>('eventBus');
@@ -16,7 +16,7 @@ export const useContentMenu = () => {
16
16
  type: 'button',
17
17
  text: '编辑',
18
18
  icon: Edit,
19
- display: (services) => services?.dataSourceService?.get('editable') ?? true,
19
+ display: ({ dataSourceService }) => dataSourceService.get('editable'),
20
20
  handler: () => {
21
21
  if (!selectId) {
22
22
  return;
@@ -29,7 +29,7 @@ export const useContentMenu = () => {
29
29
  type: 'button',
30
30
  text: '复制并粘贴至当前',
31
31
  icon: markRaw(CopyDocument),
32
- handler: ({ dataSourceService }: Services) => {
32
+ handler: ({ dataSourceService }) => {
33
33
  if (!selectId) {
34
34
  return;
35
35
  }
@@ -3,14 +3,15 @@
3
3
  </template>
4
4
 
5
5
  <script lang="ts" setup>
6
- import { computed, inject, markRaw, useTemplateRef } from 'vue';
6
+ import { computed, markRaw, useTemplateRef } from 'vue';
7
7
  import { Files, Plus } from '@element-plus/icons-vue';
8
8
 
9
9
  import { isPage, isPageFragment } from '@tmagic/utils';
10
10
 
11
11
  import ContentMenu from '@editor/components/ContentMenu.vue';
12
+ import { useServices } from '@editor/hooks/use-services';
12
13
  import FolderMinusIcon from '@editor/icons/FolderMinusIcon.vue';
13
- import type { ComponentGroup, CustomContentMenuFunction, MenuButton, MenuComponent, Services } from '@editor/type';
14
+ import type { ComponentGroup, CustomContentMenuFunction, MenuButton, MenuComponent } from '@editor/type';
14
15
  import { useCopyMenu, useDeleteMenu, useMoveToMenu, usePasteMenu } from '@editor/utils/content-menu';
15
16
 
16
17
  defineOptions({
@@ -26,11 +27,13 @@ const emit = defineEmits<{
26
27
  'collapse-all': [];
27
28
  }>();
28
29
 
29
- const services = inject<Services>('services');
30
+ const services = useServices();
31
+ const { editorService, componentListService } = services;
32
+
30
33
  const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
31
- const node = computed(() => services?.editorService.get('node'));
32
- const nodes = computed(() => services?.editorService.get('nodes'));
33
- const componentList = computed(() => services?.componentListService.getList() || []);
34
+ const node = computed(() => editorService.get('node'));
35
+ const nodes = computed(() => editorService.get('nodes'));
36
+ const componentList = computed(() => componentListService.getList());
34
37
 
35
38
  const createMenuItems = (group: ComponentGroup): MenuButton[] =>
36
39
  group.items.map((component) => ({
@@ -38,7 +41,7 @@ const createMenuItems = (group: ComponentGroup): MenuButton[] =>
38
41
  type: 'button',
39
42
  icon: component.icon,
40
43
  handler: () => {
41
- services?.editorService.add({
44
+ editorService.add({
42
45
  name: component.text,
43
46
  type: component.type,
44
47
  ...(component.data || {}),
@@ -54,7 +57,7 @@ const getSubMenuData = computed<MenuButton[]>(() => {
54
57
  type: 'button',
55
58
  icon: Files,
56
59
  handler: () => {
57
- services?.editorService.add({
60
+ editorService.add({
58
61
  type: 'tab-pane',
59
62
  });
60
63
  },
@@ -6,24 +6,20 @@
6
6
  </template>
7
7
 
8
8
  <script setup lang="ts">
9
- import { inject } from 'vue';
10
9
  import { Hide, View } from '@element-plus/icons-vue';
11
10
 
12
11
  import type { MNode } from '@tmagic/core';
13
12
 
14
13
  import MIcon from '@editor/components/Icon.vue';
15
- import { Services } from '@editor/type';
14
+ import { useServices } from '@editor/hooks/use-services';
16
15
 
17
16
  const props = defineProps<{
18
17
  data: MNode;
19
18
  }>();
20
19
 
21
- const services = inject<Services>('services');
22
- const editorService = services?.editorService;
20
+ const { editorService } = useServices();
23
21
 
24
22
  const setNodeVisible = (visible: boolean) => {
25
- if (!editorService) return;
26
-
27
23
  editorService.update({
28
24
  id: props.data.id,
29
25
  visible,
@@ -47,7 +47,7 @@
47
47
  </template>
48
48
 
49
49
  <script setup lang="ts">
50
- import { computed, inject, useTemplateRef } from 'vue';
50
+ import { computed, useTemplateRef } from 'vue';
51
51
 
52
52
  import type { MNode } from '@tmagic/core';
53
53
  import { TMagicScrollbar } from '@tmagic/design';
@@ -55,14 +55,8 @@ import { TMagicScrollbar } from '@tmagic/design';
55
55
  import SearchInput from '@editor/components/SearchInput.vue';
56
56
  import Tree from '@editor/components/Tree.vue';
57
57
  import { useFilter } from '@editor/hooks/use-filter';
58
- import type {
59
- CustomContentMenuFunction,
60
- LayerPanelSlots,
61
- MenuButton,
62
- MenuComponent,
63
- Services,
64
- TreeNodeData,
65
- } from '@editor/type';
58
+ import { useServices } from '@editor/hooks/use-services';
59
+ import type { CustomContentMenuFunction, LayerPanelSlots, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
66
60
 
67
61
  import LayerMenu from './LayerMenu.vue';
68
62
  import LayerNodeTool from './LayerNodeTool.vue';
@@ -84,12 +78,12 @@ defineProps<{
84
78
  customContentMenu: CustomContentMenuFunction;
85
79
  }>();
86
80
 
87
- const services = inject<Services>('services');
88
- const editorService = services?.editorService;
81
+ const services = useServices();
82
+ const { editorService } = services;
89
83
 
90
84
  const treeRef = useTemplateRef<InstanceType<typeof Tree>>('tree');
91
85
 
92
- const page = computed(() => editorService?.get('page'));
86
+ const page = computed(() => editorService.get('page'));
93
87
  const nodeData = computed<TreeNodeData[]>(() => (!page.value ? [] : [page.value]));
94
88
 
95
89
  const { nodeStatusMap } = useNodeStatus(services);
@@ -4,18 +4,19 @@ import { throttle } from 'lodash-es';
4
4
  import { Id, MNode } from '@tmagic/core';
5
5
  import { isPage, isPageFragment } from '@tmagic/utils';
6
6
 
7
- import { LayerNodeStatus, Services, TreeNodeData, UI_SELECT_MODE_EVENT_NAME } from '@editor/type';
7
+ import type { LayerNodeStatus, Services, TreeNodeData } from '@editor/type';
8
+ import { UI_SELECT_MODE_EVENT_NAME } from '@editor/utils/const';
8
9
  import { updateStatus } from '@editor/utils/tree';
9
10
 
10
11
  import LayerMenu from './LayerMenu.vue';
11
12
 
12
13
  export const useClick = (
13
- services: Services | undefined,
14
+ { editorService, stageOverlayService, uiService }: Services,
14
15
  isCtrlKeyDown: Ref<boolean>,
15
16
  nodeStatusMap: ComputedRef<Map<Id, LayerNodeStatus> | undefined>,
16
17
  menuRef: ShallowRef<InstanceType<typeof LayerMenu> | null>,
17
18
  ) => {
18
- const isMultiSelect = computed(() => isCtrlKeyDown.value && !services?.editorService.get('disabledMultiSelect'));
19
+ const isMultiSelect = computed(() => isCtrlKeyDown.value && !editorService.get('disabledMultiSelect'));
19
20
 
20
21
  // 触发画布选中
21
22
  const select = async (data: MNode) => {
@@ -26,9 +27,9 @@ export const useClick = (
26
27
  if (isMultiSelect.value) {
27
28
  multiSelect(data);
28
29
  } else {
29
- await services?.editorService.select(data);
30
- services?.editorService.get('stage')?.select(data.id);
31
- services?.stageOverlayService.get('stage')?.select(data.id);
30
+ await editorService.select(data);
31
+ editorService.get('stage')?.select(data.id);
32
+ stageOverlayService.get('stage')?.select(data.id);
32
33
  }
33
34
  };
34
35
 
@@ -37,7 +38,7 @@ export const useClick = (
37
38
  return;
38
39
  }
39
40
 
40
- const nodes = services?.editorService.get('nodes') || [];
41
+ const nodes = editorService.get('nodes') || [];
41
42
 
42
43
  const newNodes: Id[] = [];
43
44
  let isCancel = false;
@@ -59,9 +60,9 @@ export const useClick = (
59
60
  newNodes.push(data.id);
60
61
  }
61
62
 
62
- await services?.editorService.multiSelect(newNodes);
63
- services?.editorService.get('stage')?.multiSelect(newNodes);
64
- services?.stageOverlayService.get('stage')?.multiSelect(newNodes);
63
+ await editorService.multiSelect(newNodes);
64
+ editorService.get('stage')?.multiSelect(newNodes);
65
+ stageOverlayService.get('stage')?.multiSelect(newNodes);
65
66
  };
66
67
 
67
68
  const throttleTime = 300;
@@ -75,15 +76,15 @@ export const useClick = (
75
76
 
76
77
  // 触发画布高亮
77
78
  const highlight = (data: TreeNodeData) => {
78
- services?.editorService?.highlight(data);
79
- services?.editorService?.get('stage')?.highlight(data.id);
80
- services?.stageOverlayService?.get('stage')?.highlight(data.id);
79
+ editorService.highlight(data);
80
+ editorService.get('stage')?.highlight(data.id);
81
+ stageOverlayService.get('stage')?.highlight(data.id);
81
82
  };
82
83
 
83
84
  const nodeClickHandler = (event: MouseEvent, data: TreeNodeData): void => {
84
85
  if (!nodeStatusMap?.value) return;
85
86
 
86
- if (services?.uiService.get('uiSelectMode')) {
87
+ if (uiService.get('uiSelectMode')) {
87
88
  document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: data }));
88
89
  return;
89
90
  }
@@ -107,7 +108,7 @@ export const useClick = (
107
108
  nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData): void {
108
109
  event.preventDefault();
109
110
 
110
- const nodes = services?.editorService.get('nodes') || [];
111
+ const nodes = editorService.get('nodes') || [];
111
112
  if (nodes.length < 2 || !nodes.includes(data)) {
112
113
  nodeClickHandler(event, data);
113
114
  }
@@ -42,7 +42,7 @@ const removeStatusClass = (el: HTMLElement | null) => {
42
42
  * dragover 属于目标节点
43
43
  * 这些方法并不是同一个dom事件触发的
44
44
  */
45
- export const useDrag = (services: Services | undefined) => {
45
+ export const useDrag = ({ editorService }: Services) => {
46
46
  const handleDragStart = (event: DragEvent) => {
47
47
  if (!event.dataTransfer || !event.target || !event.currentTarget) return;
48
48
 
@@ -144,12 +144,12 @@ export const useDrag = (services: Services | undefined) => {
144
144
 
145
145
  removeStatusClass(dragState.container);
146
146
 
147
- if (node && dragState.dragOverNodeId && dragState.dropType && services) {
147
+ if (node && dragState.dragOverNodeId && dragState.dropType) {
148
148
  if (dragState.dragOverNodeId === node.id) {
149
149
  return;
150
150
  }
151
151
 
152
- const targetInfo = services.editorService.getNodeInfo(dragState.dragOverNodeId, false);
152
+ const targetInfo = editorService.getNodeInfo(dragState.dragOverNodeId, false);
153
153
  const targetNode = targetInfo.node;
154
154
  let targetParent = targetInfo.parent;
155
155
 
@@ -168,12 +168,12 @@ export const useDrag = (services: Services | undefined) => {
168
168
  targetIndex += 1;
169
169
  }
170
170
 
171
- const selectedNodes = services.editorService.get('nodes');
171
+ const selectedNodes = editorService.get('nodes');
172
172
 
173
173
  if (selectedNodes.find((n) => `${n.id}` === `${node.id}`)) {
174
- services.editorService.dragTo(selectedNodes, targetParent, targetIndex);
174
+ editorService.dragTo(selectedNodes, targetParent, targetIndex);
175
175
  } else {
176
- services.editorService.dragTo([node], targetParent, targetIndex);
176
+ editorService.dragTo([node], targetParent, targetIndex);
177
177
  }
178
178
  }
179
179
 
@@ -5,11 +5,9 @@ import type { Services } from '@editor/type';
5
5
  import { KeyBindingContainerKey } from '@editor/utils/keybinding-config';
6
6
 
7
7
  export const useKeybinding = (
8
- services: Services | undefined,
8
+ { keybindingService }: Services,
9
9
  container: ShallowRef<InstanceType<typeof Tree> | null>,
10
10
  ) => {
11
- const keybindingService = services?.keybindingService;
12
-
13
11
  // 是否多选
14
12
  const isCtrlKeyDown = ref(false);
15
13
 
@@ -17,15 +15,15 @@ export const useKeybinding = (
17
15
  isCtrlKeyDown.value = false;
18
16
  };
19
17
 
20
- keybindingService?.registerCommand('layer-panel-global-keyup', () => {
18
+ keybindingService.registerCommand('layer-panel-global-keyup', () => {
21
19
  isCtrlKeyDown.value = false;
22
20
  });
23
21
 
24
- keybindingService?.registerCommand('layer-panel-global-keydown', () => {
22
+ keybindingService.registerCommand('layer-panel-global-keydown', () => {
25
23
  isCtrlKeyDown.value = true;
26
24
  });
27
25
 
28
- keybindingService?.register([
26
+ keybindingService.register([
29
27
  {
30
28
  command: 'layer-panel-global-keydown',
31
29
  keybinding: 'ctrl',
@@ -41,10 +39,10 @@ export const useKeybinding = (
41
39
  watchEffect(() => {
42
40
  if (container.value) {
43
41
  globalThis.addEventListener('blur', windowBlurHandler);
44
- keybindingService?.registerEl(KeyBindingContainerKey.LAYER_PANEL, container.value.$el);
42
+ keybindingService.registerEl(KeyBindingContainerKey.LAYER_PANEL, container.value.$el);
45
43
  } else {
46
44
  globalThis.removeEventListener('blur', windowBlurHandler);
47
- keybindingService?.unregisterEl(KeyBindingContainerKey.LAYER_PANEL);
45
+ keybindingService.unregisterEl(KeyBindingContainerKey.LAYER_PANEL);
48
46
  }
49
47
  });
50
48