@tmagic/editor 1.3.13 → 1.3.15

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.
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3.13",
2
+ "version": "1.3.15",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -42,14 +42,14 @@
42
42
  "dependencies": {
43
43
  "@babel/core": "^7.18.0",
44
44
  "@element-plus/icons-vue": "^2.3.1",
45
- "@tmagic/core": "1.3.13",
46
- "@tmagic/dep": "1.3.13",
47
- "@tmagic/design": "1.3.13",
48
- "@tmagic/form": "1.3.13",
49
- "@tmagic/schema": "1.3.13",
50
- "@tmagic/stage": "1.3.13",
51
- "@tmagic/table": "1.3.13",
52
- "@tmagic/utils": "1.3.13",
45
+ "@tmagic/core": "1.3.15",
46
+ "@tmagic/dep": "1.3.15",
47
+ "@tmagic/design": "1.3.15",
48
+ "@tmagic/form": "1.3.15",
49
+ "@tmagic/schema": "1.3.15",
50
+ "@tmagic/stage": "1.3.15",
51
+ "@tmagic/table": "1.3.15",
52
+ "@tmagic/utils": "1.3.15",
53
53
  "buffer": "^6.0.3",
54
54
  "color": "^3.1.3",
55
55
  "emmet-monaco-es": "^5.3.0",
@@ -63,8 +63,8 @@
63
63
  "vue": "^3.3.8"
64
64
  },
65
65
  "peerDependencies": {
66
- "@tmagic/design": "1.3.13",
67
- "@tmagic/form": "1.3.13",
66
+ "@tmagic/design": "1.3.15",
67
+ "@tmagic/form": "1.3.15",
68
68
  "monaco-editor": "^0.41.0",
69
69
  "vue": "^3.3.8"
70
70
  },
@@ -39,7 +39,12 @@
39
39
  </template>
40
40
  </TMagicDropdown>
41
41
 
42
- <component v-else-if="data.type === 'component'" v-bind="data.props || {}" :is="data.component"></component>
42
+ <component
43
+ v-else-if="data.type === 'component'"
44
+ v-bind="data.props || {}"
45
+ v-on="(data as MenuComponent).listeners || {}"
46
+ :is="data.component"
47
+ ></component>
43
48
  </div>
44
49
  </template>
45
50
 
@@ -12,7 +12,8 @@ import { isEmpty } from 'lodash-es';
12
12
 
13
13
  import { TMagicCard } from '@tmagic/design';
14
14
  import type { FieldProps } from '@tmagic/form';
15
- import { HookType } from '@tmagic/schema';
15
+ import { FormState } from '@tmagic/form';
16
+ import { HookCodeType, HookType } from '@tmagic/schema';
16
17
 
17
18
  import type { Services } from '@editor/type';
18
19
 
@@ -38,13 +39,61 @@ const codeConfig = computed(() => ({
38
39
  name: 'hookData',
39
40
  enableToggleMode: false,
40
41
  expandAll: true,
41
- titleKey: 'codeId',
42
+ title: (mForm: FormState, { model, index }: any) => {
43
+ if (model.codeType === HookCodeType.DATA_SOURCE_METHOD) {
44
+ if (Array.isArray(model.codeId)) {
45
+ if (model.codeId.length < 2) {
46
+ return index;
47
+ }
48
+
49
+ const ds = services?.dataSourceService.getDataSourceById(model.codeId[0]);
50
+ return `${ds?.title} / ${model.codeId[1]}`;
51
+ }
52
+
53
+ return Array.isArray(model.codeId) ? model.codeId.join('/') : index;
54
+ }
55
+ return model.codeId || index;
56
+ },
42
57
  items: [
43
58
  {
44
- type: 'code-select-col',
45
- name: 'codeId',
46
- labelWidth: 0,
47
- disabled: () => !services?.codeBlockService.getEditStatus(),
59
+ type: 'row',
60
+ items: [
61
+ {
62
+ type: 'select',
63
+ name: 'codeType',
64
+ span: 8,
65
+ options: [
66
+ { value: HookCodeType.CODE, text: '代码块' },
67
+ { value: HookCodeType.DATA_SOURCE_METHOD, text: '数据源方法' },
68
+ ],
69
+ defaultValue: 'code',
70
+ onChange: (mForm: FormState, v: HookCodeType, { model }: any) => {
71
+ if (v === HookCodeType.DATA_SOURCE_METHOD) {
72
+ model.codeId = [];
73
+ } else {
74
+ model.codeId = '';
75
+ }
76
+
77
+ return v;
78
+ },
79
+ },
80
+ {
81
+ type: 'code-select-col',
82
+ name: 'codeId',
83
+ span: 16,
84
+ labelWidth: 0,
85
+ display: (mForm: FormState, { model }: any) => model.codeType !== HookCodeType.DATA_SOURCE_METHOD,
86
+ notEditable: () => !services?.codeBlockService.getEditStatus(),
87
+ },
88
+ {
89
+ type: 'data-source-method-select',
90
+ name: 'codeId',
91
+ span: 16,
92
+ labelWidth: 0,
93
+ display: (mForm: FormState, { model }: any) => model.codeType === HookCodeType.DATA_SOURCE_METHOD,
94
+ notEditable: () => !services?.dataSourceService.get('editable'),
95
+ },
96
+ ],
48
97
  },
49
98
  ],
50
99
  }));
@@ -10,13 +10,14 @@
10
10
  @change="onParamsChangeHandler"
11
11
  ></m-form-container>
12
12
  <!-- 查看/编辑按钮 -->
13
- <Icon v-if="model[name]" class="icon" :icon="!disabled ? Edit : View" @click="editCode(model[name])"></Icon>
13
+ <Icon v-if="model[name]" class="icon" :icon="!notEditable ? Edit : View" @click="editCode(model[name])"></Icon>
14
14
  </div>
15
15
 
16
16
  <!-- 参数填写框 -->
17
17
  <CodeParams
18
18
  v-if="paramsConfig.length"
19
19
  name="params"
20
+ :key="model[name]"
20
21
  :model="model"
21
22
  :size="size"
22
23
  :params-config="paramsConfig"
@@ -26,19 +27,19 @@
26
27
  <CodeBlockEditor
27
28
  ref="codeBlockEditor"
28
29
  v-if="codeConfig"
29
- :disabled="disabled"
30
+ :disabled="notEditable"
30
31
  :content="codeConfig"
31
32
  @submit="submitCodeBlockHandler"
32
33
  ></CodeBlockEditor>
33
34
  </div>
34
35
  </template>
35
36
 
36
- <script lang="ts" setup name="">
37
+ <script lang="ts" setup>
37
38
  import { computed, inject, ref, watch } from 'vue';
38
39
  import { Edit, View } from '@element-plus/icons-vue';
39
40
  import { isEmpty, map } from 'lodash-es';
40
41
 
41
- import { createValues, FieldProps } from '@tmagic/form';
42
+ import { createValues, type FieldProps, filterFunction, type FormState } from '@tmagic/form';
42
43
  import type { Id } from '@tmagic/schema';
43
44
 
44
45
  import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
@@ -51,9 +52,11 @@ defineOptions({
51
52
  name: 'MEditorCodeSelectCol',
52
53
  });
53
54
 
55
+ const mForm = inject<FormState | undefined>('mForm');
54
56
  const services = inject<Services>('services');
55
57
  const emit = defineEmits(['change']);
56
58
 
59
+ const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
57
60
  const props = withDefaults(defineProps<FieldProps<CodeSelectColConfig>>(), {
58
61
  disabled: false,
59
62
  });
@@ -91,6 +94,7 @@ watch(
91
94
  const selectConfig = {
92
95
  type: 'select',
93
96
  name: props.name,
97
+ disable: props.disabled,
94
98
  options: () => {
95
99
  if (codeDsl.value) {
96
100
  return map(codeDsl.value, (value, key) => ({
@@ -7,7 +7,12 @@
7
7
  :model="model"
8
8
  @change="onChangeHandler"
9
9
  ></m-form-container>
10
- <Icon v-if="model[name]" class="icon" :icon="!disabled ? Edit : View" @click="editCodeHandler"></Icon>
10
+ <Icon
11
+ v-if="model[name] && isCustomMethod"
12
+ class="icon"
13
+ :icon="!notEditable ? Edit : View"
14
+ @click="editCodeHandler"
15
+ ></Icon>
11
16
  </div>
12
17
 
13
18
  <CodeParams
@@ -23,7 +28,7 @@
23
28
  <CodeBlockEditor
24
29
  ref="codeBlockEditor"
25
30
  v-if="codeConfig"
26
- :disabled="disabled"
31
+ :disabled="notEditable"
27
32
  :content="codeConfig"
28
33
  @submit="submitCodeBlockHandler"
29
34
  ></CodeBlockEditor>
@@ -34,7 +39,7 @@
34
39
  import { computed, inject, ref } from 'vue';
35
40
  import { Edit, View } from '@element-plus/icons-vue';
36
41
 
37
- import { createValues, FieldProps } from '@tmagic/form';
42
+ import { createValues, type FieldProps, filterFunction, type FormState } from '@tmagic/form';
38
43
  import type { CodeBlockContent, Id } from '@tmagic/schema';
39
44
 
40
45
  import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
@@ -47,6 +52,7 @@ defineOptions({
47
52
  name: 'MEditorDataSourceMethodSelect',
48
53
  });
49
54
 
55
+ const mForm = inject<FormState | undefined>('mForm');
50
56
  const services = inject<Services>('services');
51
57
  const emit = defineEmits(['change']);
52
58
 
@@ -56,14 +62,24 @@ const props = withDefaults(defineProps<FieldProps<DataSourceMethodSelectConfig>>
56
62
  disabled: false,
57
63
  });
58
64
 
65
+ const notEditable = computed(() => filterFunction(mForm, props.config.notEditable, props));
66
+
59
67
  const dataSources = computed(() => dataSourceService?.get('dataSources'));
60
68
 
61
- const getParamItemsConfig = ([dataSourceId, medthodName]: [Id, string] = ['', '']): CodeParamStatement[] => {
69
+ const isCustomMethod = computed(() => {
70
+ const [id, name] = props.model[props.name];
71
+
72
+ const dataSource = dataSourceService?.getDataSourceById(id);
73
+
74
+ return Boolean(dataSource?.methods.find((method) => method.name === name));
75
+ });
76
+
77
+ const getParamItemsConfig = ([dataSourceId, methodName]: [Id, string] = ['', '']): CodeParamStatement[] => {
62
78
  if (!dataSourceId) return [];
63
79
 
64
80
  const paramStatements = dataSources.value
65
81
  ?.find((item) => item.id === dataSourceId)
66
- ?.methods?.find((item) => item.name === medthodName)?.params;
82
+ ?.methods?.find((item) => item.name === methodName)?.params;
67
83
 
68
84
  if (!paramStatements) return [];
69
85
 
@@ -107,6 +123,7 @@ const cascaderConfig = computed(() => ({
107
123
  type: 'cascader',
108
124
  name: props.name,
109
125
  options: methodsOptions.value,
126
+ disable: props.disabled,
110
127
  onChange: (formState: any, dataSourceMethod: [Id, string]) => {
111
128
  setParamsConfig(dataSourceMethod, formState);
112
129
 
@@ -171,7 +171,7 @@ const codeActionConfig = computed(() => {
171
171
  type: 'code-select-col',
172
172
  text: '代码块',
173
173
  name: 'codeId',
174
- disabled: () => !codeBlockService?.getEditStatus(),
174
+ notEditable: () => !codeBlockService?.getEditStatus(),
175
175
  display: (mForm, { model }) => model.actionType === ActionType.CODE,
176
176
  };
177
177
  return { ...defaultCodeActionConfig, ...props.config.codeActionConfig };
@@ -183,6 +183,7 @@ const dataSourceActionConfig = computed(() => {
183
183
  type: 'data-source-method-select',
184
184
  text: '数据源方法',
185
185
  name: 'dataSourceMethod',
186
+ notEditable: () => !services?.dataSourceService.get('editable'),
186
187
  display: (mForm, { model }) => model.actionType === ActionType.DATA_SOURCE,
187
188
  };
188
189
  return { ...defaultDataSourceActionConfig, ...props.config.dataSourceActionConfig };
@@ -1,124 +1,40 @@
1
- import { computed, ComputedRef, inject, nextTick, ref, watch } from 'vue';
2
- import Moveable from 'moveable';
1
+ import { computed, ComputedRef, ref, watch } from 'vue';
3
2
 
4
- import { type Services } from '@editor/type';
3
+ interface State {
4
+ status: boolean;
5
+ top: number;
6
+ left: number;
7
+ }
5
8
 
6
9
  export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
7
- const services = inject<Services>('services');
8
- const moveable = ref<Moveable>();
9
- const floatBox = ref<HTMLElement[]>();
10
-
11
- const floatBoxStates = computed(() => services?.uiService.get('floatBox'));
12
-
13
- const curKey = ref('');
14
- const target = computed(() =>
15
- floatBox.value
16
- ? floatBox.value.find((item) => item.classList.contains(`m-editor-float-box-${curKey.value}`))
17
- : undefined,
10
+ const floatBoxStates = ref<{
11
+ [key in (typeof slideKeys.value)[number]]: State;
12
+ }>(
13
+ slideKeys.value.reduce(
14
+ (total, cur) => ({
15
+ ...total,
16
+ [cur]: {
17
+ status: false,
18
+ top: 0,
19
+ left: 0,
20
+ },
21
+ }),
22
+ {},
23
+ ),
18
24
  );
19
25
 
20
26
  const showingBoxKeys = computed(() =>
21
- [...(floatBoxStates.value?.keys() ?? [])].filter((key) => floatBoxStates.value?.get(key)?.status),
27
+ Object.keys(floatBoxStates.value).filter((key) => floatBoxStates.value[key].status),
22
28
  );
23
-
24
29
  const isDraging = ref(false);
25
30
 
26
- const showFloatBox = async (key: string) => {
27
- const curBoxStatus = floatBoxStates.value?.get(curKey.value)?.status;
28
- if (curKey.value === key && curBoxStatus) return;
29
- curKey.value = key;
30
- setSlideState(key, {
31
- zIndex: getMaxZIndex() + 1,
32
- status: true,
33
- });
34
-
35
- await nextTick();
36
- if (moveable.value) {
37
- moveable.value.target = target.value;
38
- moveable.value.dragTarget = getDragTarget();
39
- moveable.value.updateRect();
40
- } else {
41
- initFloatBoxMoveable();
42
- }
43
- };
44
-
45
- const setSlideState = (key: string, data: Record<string, string | number | boolean>) => {
46
- const slideState = floatBoxStates.value?.get(key);
47
- if (!slideState) return;
48
- floatBoxStates.value?.set(key, {
49
- ...slideState,
50
- ...data,
51
- });
52
- };
53
-
54
- const getDragTarget = (key?: string) => `.m-editor-float-box-header-${key ?? curKey.value}`;
55
-
56
- const closeFloatBox = (key: string) => {
57
- setSlideState(key, {
58
- status: false,
59
- });
60
-
61
- // 如果只有一个,关掉后需要销毁moveable实例
62
- if (!floatBoxStates.value?.values) return;
63
- const keys = [...floatBoxStates.value?.keys()];
64
- const values = [...floatBoxStates.value?.values()];
65
- const lastFloatBoxLen = values.filter((state) => state.status).length;
66
- if (lastFloatBoxLen === 0) {
67
- moveable.value?.destroy();
68
- moveable.value = undefined;
69
- return;
70
- }
71
-
72
- // 如果关掉的 box 是最大的,需要选中下面的一层
73
- if (key === curKey.value) {
74
- // 查找显示的最大 zIndex 对应的 index
75
- const zIndexList = values.filter((item) => item.status).map((item) => item.zIndex);
76
- const maxZIndex = Math.max(...zIndexList);
77
- const key = keys.find((key) => floatBoxStates.value?.get(key)?.zIndex === maxZIndex);
78
- if (!key) return;
79
- showFloatBox(key);
80
- }
81
- };
82
-
83
- const getMaxZIndex = () => {
84
- if (!floatBoxStates.value?.values()) return 0;
85
- const list = [...floatBoxStates.value?.values()].map((state) => state.zIndex);
86
- return Math.max(...list) ?? 0;
87
- };
88
-
89
- const initFloatBoxMoveable = () => {
90
- const dragTarget = getDragTarget();
91
- moveable.value = new Moveable(document.body, {
92
- target: target.value,
93
- draggable: true,
94
- resizable: true,
95
- edge: true,
96
- keepRatio: false,
97
- origin: false,
98
- snappable: true,
99
- dragTarget,
100
- dragTargetSelf: false,
101
- linePadding: 10,
102
- controlPadding: 10,
103
- elementGuidelines: [...(floatBoxStates.value?.keys() ?? [])].map((key) => getDragTarget(key)),
104
- bounds: { left: 0, top: 0, right: 0, bottom: 0, position: 'css' },
105
- });
106
- moveable.value.on('drag', (e) => {
107
- e.target.style.transform = e.transform;
108
- });
109
- moveable.value.on('resize', (e) => {
110
- e.target.style.width = `${e.width}px`;
111
- e.target.style.height = `${e.height}px`;
112
- e.target.style.transform = e.drag.transform;
113
- });
114
- };
115
-
31
+ const dragstartHandler = () => (isDraging.value = true);
116
32
  const dragendHandler = (key: string, e: DragEvent) => {
117
- setSlideState(key, {
33
+ floatBoxStates.value[key] = {
118
34
  left: e.clientX,
119
35
  top: e.clientY,
120
- });
121
- showFloatBox(key);
36
+ status: true,
37
+ };
122
38
  isDraging.value = false;
123
39
  };
124
40
 
@@ -127,13 +43,17 @@ export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
127
43
  e.preventDefault();
128
44
  });
129
45
 
130
- const dragstartHandler = () => (isDraging.value = true);
131
-
132
- // 监听 slide 长度变化,更新 ui serice map
133
46
  watch(
134
47
  () => slideKeys.value,
135
48
  () => {
136
- services?.uiService.setFloatBox(slideKeys.value);
49
+ for (const key in slideKeys.value) {
50
+ if (floatBoxStates.value[key]) continue;
51
+ floatBoxStates.value[key] = {
52
+ status: false,
53
+ top: 0,
54
+ left: 0,
55
+ };
56
+ }
137
57
  },
138
58
  {
139
59
  deep: true,
@@ -142,12 +62,9 @@ export const useFloatBox = (slideKeys: ComputedRef<string[]>) => {
142
62
  );
143
63
 
144
64
  return {
145
- showFloatBox,
146
- closeFloatBox,
147
65
  dragstartHandler,
148
66
  dragendHandler,
149
67
  floatBoxStates,
150
- floatBox,
151
68
  showingBoxKeys,
152
69
  };
153
70
  };
@@ -123,7 +123,7 @@ watch(
123
123
 
124
124
  watch(active, (active) => {
125
125
  if (active === NodeType.PAGE) {
126
- if (!activePage.value) {
126
+ if (!activePage.value && !pageList.value.length) {
127
127
  editorService?.selectRoot();
128
128
  return;
129
129
  }
@@ -132,11 +132,12 @@ watch(active, (active) => {
132
132
  }
133
133
 
134
134
  if (active === NodeType.PAGE_FRAGMENT) {
135
- if (!activePageFragment.value) {
135
+ // 之前没有选中过页面片并且当前没有页面片
136
+ if (!activePageFragment.value && !pageFragmentList.value.length) {
136
137
  editorService?.selectRoot();
137
138
  return;
138
139
  }
139
- switchPage(activePageFragment.value);
140
+ switchPage(activePageFragment.value || pageFragmentList.value[0].id);
140
141
  }
141
142
  });
142
143
 
@@ -4,7 +4,7 @@
4
4
  <div
5
5
  class="m-editor-sidebar-header-item"
6
6
  v-for="(config, index) in sideBarItems"
7
- v-show="!floatBoxStates?.get(config.$key)?.status"
7
+ v-show="!floatBoxStates[config.$key]?.status"
8
8
  draggable="true"
9
9
  :key="config.$key ?? index"
10
10
  :class="{ 'is-active': activeTabName === config.text }"
@@ -23,7 +23,7 @@
23
23
  v-show="activeTabName === config.text"
24
24
  >
25
25
  <component
26
- v-if="config && !floatBoxStates?.get(config.$key)?.status"
26
+ v-if="config && !floatBoxStates[config.$key]?.status"
27
27
  :is="config.component"
28
28
  v-bind="config.props || {}"
29
29
  v-on="config?.listeners || {}"
@@ -96,43 +96,37 @@
96
96
  </div>
97
97
 
98
98
  <Teleport to="body">
99
- <div class="m-editor-float-box-list">
100
- <div
101
- v-for="(config, index) in sideBarItems"
99
+ <template v-for="(config, index) in sideBarItems">
100
+ <FloatingBox
102
101
  :key="config.$key ?? index"
103
- ref="floatBox"
104
- :class="['m-editor-float-box', `m-editor-float-box-${config.$key}`]"
105
- :style="{
106
- left: `${floatBoxStates?.get(config.$key)?.left}px`,
107
- top: `${floatBoxStates?.get(config.$key)?.top}px`,
108
- zIndex: floatBoxStates?.get(config.$key)?.zIndex,
102
+ v-if="floatBoxStates[config.$key]?.status"
103
+ v-model:visible="floatBoxStates[config.$key].status"
104
+ :title="config.text"
105
+ :position="{
106
+ left: floatBoxStates[config.$key].left,
107
+ top: floatBoxStates[config.$key].top,
109
108
  }"
110
- v-show="floatBoxStates?.get(config.$key)?.status"
111
109
  >
112
- <div
113
- :class="['m-editor-float-box-header', `m-editor-float-box-header-${config.$key}`]"
114
- @click="showFloatBox(config.$key)"
115
- >
116
- <div>{{ config.text }}</div>
117
- <MIcon class="m-editor-float-box-close" :icon="Close" @click.stop="closeFloatBox(config.$key)"></MIcon>
118
- </div>
119
- <div class="m-editor-float-box-body">
120
- <component
121
- v-if="config && floatBoxStates?.get(config.$key)?.status"
122
- :is="config.boxComponentConfig?.component || config.component"
123
- v-bind="config.boxComponentConfig?.props || config.props || {}"
124
- v-on="config?.listeners || {}"
125
- />
126
- </div>
127
- </div>
128
- </div>
110
+ <template #body>
111
+ <div class="m-editor-slide-list-box">
112
+ <component
113
+ v-if="config && floatBoxStates[config.$key].status"
114
+ :is="config.boxComponentConfig?.component || config.component"
115
+ v-bind="config.boxComponentConfig?.props || config.props || {}"
116
+ v-on="config?.listeners || {}"
117
+ />
118
+ </div>
119
+ </template>
120
+ </FloatingBox>
121
+ </template>
129
122
  </Teleport>
130
123
  </template>
131
124
 
132
125
  <script setup lang="ts">
133
126
  import { computed, inject, ref, watch } from 'vue';
134
- import { Close, Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
127
+ import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
135
128
 
129
+ import FloatingBox from '@editor/components/FloatingBox.vue';
136
130
  import MIcon from '@editor/components/Icon.vue';
137
131
  import { useFloatBox } from '@editor/hooks/use-float-box';
138
132
  import type {
@@ -200,11 +194,6 @@ const getItemConfig = (data: SideItem): SideComponent => {
200
194
  text: '代码编辑',
201
195
  component: CodeBlockListPanel,
202
196
  slots: {},
203
- boxComponentConfig: {
204
- props: {
205
- slideType: 'box',
206
- },
207
- },
208
197
  },
209
198
  'data-source': {
210
199
  $key: 'data-source',
@@ -213,11 +202,6 @@ const getItemConfig = (data: SideItem): SideComponent => {
213
202
  text: '数据源',
214
203
  component: DataSourceListPanel,
215
204
  slots: {},
216
- boxComponentConfig: {
217
- props: {
218
- slideType: 'box',
219
- },
220
- },
221
205
  },
222
206
  };
223
207
 
@@ -235,8 +219,7 @@ watch(
235
219
 
236
220
  const slideKeys = computed(() => sideBarItems.value.map((sideBarItem) => sideBarItem.$key));
237
221
 
238
- const { showFloatBox, closeFloatBox, dragstartHandler, dragendHandler, floatBoxStates, floatBox, showingBoxKeys } =
239
- useFloatBox(slideKeys);
222
+ const { dragstartHandler, dragendHandler, floatBoxStates, showingBoxKeys } = useFloatBox(slideKeys);
240
223
 
241
224
  watch(
242
225
  () => showingBoxKeys.value.length,
@@ -14,7 +14,7 @@
14
14
  @node-dragstart="handleDragStart"
15
15
  @node-dragleave="handleDragLeave"
16
16
  @node-dragend="handleDragEnd"
17
- @node-contextmenu="nodeContentmenuHandler"
17
+ @node-contextmenu="nodeContentMenuHandler"
18
18
  @node-mouseenter="mouseenterHandler"
19
19
  @node-click="nodeClickHandler"
20
20
  >
@@ -113,7 +113,7 @@ const { handleDragStart, handleDragEnd, handleDragLeave, handleDragOver } = useD
113
113
  const {
114
114
  menu,
115
115
  nodeClickHandler,
116
- nodeContentmenuHandler,
116
+ nodeContentMenuHandler,
117
117
  highlightHandler: mouseenterHandler,
118
118
  } = useClick(services, isCtrlKeyDown, nodeStatusMap);
119
119
  </script>
@@ -94,7 +94,7 @@ export const useClick = (
94
94
 
95
95
  nodeClickHandler,
96
96
 
97
- nodeContentmenuHandler(event: MouseEvent, data: TreeNodeData) {
97
+ nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData) {
98
98
  event.preventDefault();
99
99
 
100
100
  const nodes = services?.editorService.get('nodes') || [];
@@ -1,7 +1,7 @@
1
1
  import { computed, ref, watch } from 'vue';
2
2
 
3
3
  import type { Id, MNode, MPage, MPageFragment } from '@tmagic/schema';
4
- import { getNodePath } from '@tmagic/utils';
4
+ import { getNodePath, isPage, isPageFragment } from '@tmagic/utils';
5
5
 
6
6
  import { LayerNodeStatus, Services } from '@editor/type';
7
7
  import { traverseNode } from '@editor/utils';
@@ -48,13 +48,14 @@ export const useNodeStatus = (services: Services | undefined) => {
48
48
 
49
49
  // 切换页面或者新增页面,重新生成节点状态
50
50
  watch(
51
- page,
52
- (page) => {
53
- if (!page) {
51
+ () => page.value?.id,
52
+ (pageId) => {
53
+ if (!pageId) {
54
54
  return;
55
55
  }
56
+
56
57
  // 生成节点状态
57
- nodeStatusMaps.value.set(page.id, createPageNodeStatus(page, nodeStatusMaps.value.get(page.id)));
58
+ nodeStatusMaps.value.set(pageId, createPageNodeStatus(page.value!, nodeStatusMaps.value.get(pageId)));
58
59
  },
59
60
  {
60
61
  immediate: true,
@@ -85,6 +86,8 @@ export const useNodeStatus = (services: Services | undefined) => {
85
86
 
86
87
  services?.editorService.on('add', (newNodes: MNode[]) => {
87
88
  newNodes.forEach((node) => {
89
+ if (isPage(node) || isPageFragment(node)) return;
90
+
88
91
  traverseNode(node, (node: MNode) => {
89
92
  nodeStatusMap.value?.set(node.id, {
90
93
  visible: true,