@tmagic/editor 1.5.21 → 1.5.24

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.5.21",
2
+ "version": "1.5.24",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -50,33 +50,33 @@
50
50
  "buffer": "^6.0.3",
51
51
  "color": "^3.1.3",
52
52
  "deep-object-diff": "^1.1.9",
53
- "emmet-monaco-es": "^5.3.0",
53
+ "emmet-monaco-es": "^5.5.0",
54
54
  "events": "^3.3.0",
55
- "gesto": "^1.19.1",
55
+ "gesto": "^1.19.4",
56
56
  "keycon": "^1.4.0",
57
57
  "lodash-es": "^4.17.21",
58
58
  "moveable": "^0.53.0",
59
- "serialize-javascript": "^6.0.0",
60
- "sortablejs": "^1.15.2",
61
- "@tmagic/design": "1.5.21",
62
- "@tmagic/form": "1.5.21",
63
- "@tmagic/stage": "1.5.21",
64
- "@tmagic/utils": "1.5.21",
65
- "@tmagic/table": "1.5.21"
59
+ "serialize-javascript": "^6.0.2",
60
+ "sortablejs": "^1.15.6",
61
+ "@tmagic/form": "1.5.24",
62
+ "@tmagic/stage": "1.5.24",
63
+ "@tmagic/utils": "1.5.24",
64
+ "@tmagic/design": "1.5.24",
65
+ "@tmagic/table": "1.5.24"
66
66
  },
67
67
  "devDependencies": {
68
- "@types/events": "^3.0.0",
68
+ "@types/events": "^3.0.3",
69
69
  "@types/lodash-es": "^4.17.4",
70
- "@types/serialize-javascript": "^5.0.1",
70
+ "@types/serialize-javascript": "^5.0.4",
71
71
  "@types/sortablejs": "^1.15.8",
72
72
  "@vue/test-utils": "^2.4.6",
73
73
  "type-fest": "^4.10.3"
74
74
  },
75
75
  "peerDependencies": {
76
76
  "monaco-editor": "^0.48.0",
77
- "typescript": "*",
78
- "vue": ">=3.5.0",
79
- "@tmagic/core": "1.5.21"
77
+ "typescript": "^5.8.3",
78
+ "vue": "^3.5.17",
79
+ "@tmagic/core": "1.5.24"
80
80
  },
81
81
  "peerDependenciesMeta": {
82
82
  "typescript": {
package/src/Editor.vue CHANGED
@@ -97,6 +97,7 @@
97
97
  :extend-state="extendFormState"
98
98
  :disabled-show-src="disabledShowSrc"
99
99
  @mounted="propsPanelMountedHandler"
100
+ @unmounted="propsPanelUnmountedHandler"
100
101
  @form-error="propsPanelFormErrorHandler"
101
102
  @submit-error="propsPanelSubmitErrorHandler"
102
103
  >
@@ -163,6 +164,7 @@ defineOptions({
163
164
 
164
165
  const emit = defineEmits<{
165
166
  'props-panel-mounted': [instance: InstanceType<typeof FormPanel>];
167
+ 'props-panel-unmounted': [];
166
168
  'update:modelValue': [value: MApp | null];
167
169
  'props-form-error': [e: any];
168
170
  'props-submit-error': [e: any];
@@ -235,6 +237,9 @@ provide<EventBus>('eventBus', new EventEmitter());
235
237
  const propsPanelMountedHandler = (e: InstanceType<typeof FormPanel>) => {
236
238
  emit('props-panel-mounted', e);
237
239
  };
240
+ const propsPanelUnmountedHandler = () => {
241
+ emit('props-panel-unmounted');
242
+ };
238
243
 
239
244
  const propsPanelSubmitErrorHandler = (e: any) => {
240
245
  emit('props-submit-error', e);
@@ -32,20 +32,20 @@
32
32
  </FloatingBox>
33
33
 
34
34
  <Teleport to="body">
35
- <TMagicDialog title="查看修改" v-model="difVisible" fullscreen>
35
+ <TMagicDialog title="查看修改" v-model="difVisible" fullscreen destroy-on-close>
36
36
  <div style="display: flex; margin-bottom: 10px">
37
37
  <div style="flex: 1"><TMagicTag size="small" type="info">修改前</TMagicTag></div>
38
38
  <div style="flex: 1"><TMagicTag size="small" type="success">修改后</TMagicTag></div>
39
39
  </div>
40
40
 
41
41
  <CodeEditor
42
- v-if="difVisible"
43
42
  ref="magicVsEditor"
44
43
  type="diff"
45
44
  language="json"
45
+ :disabled-full-screen="true"
46
46
  :initValues="content.content"
47
47
  :modifiedValues="formBox?.form?.values.content"
48
- :style="`height: ${windowRect.height - 150}px`"
48
+ :height="`${windowRect.height - 150}px`"
49
49
  ></CodeEditor>
50
50
 
51
51
  <template #footer>
@@ -81,6 +81,10 @@ export interface EditorProps {
81
81
  disabledStageOverlay?: boolean;
82
82
  /** 禁用属性配置面板右下角显示源码的按钮 */
83
83
  disabledShowSrc?: boolean;
84
+ /** 禁用数据源 */
85
+ disabledDataSource?: boolean;
86
+ /** 禁用代码块 */
87
+ disabledCodeBlock?: boolean;
84
88
  /** 已选组件、代码编辑、数据源缩进配置 */
85
89
  treeIndent?: number;
86
90
  /** 已选组件、代码编辑、数据源子节点缩进增量配置 */
@@ -111,6 +115,8 @@ export const defaultEditorProps = {
111
115
  containerHighlightDuration: 800,
112
116
  containerHighlightType: ContainerHighlightType.DEFAULT,
113
117
  disabledShowSrc: false,
118
+ disabledDataSource: false,
119
+ disabledCodeBlock: false,
114
120
  componentGroupList: () => [],
115
121
  datasourceList: () => [],
116
122
  menu: () => ({ left: [], right: [] }),
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="m-fields-data-source-field-select">
3
3
  <FieldSelect
4
- v-if="showDataSourceFieldSelect || !config.fieldConfig"
4
+ v-if="!disabledDataSource && (showDataSourceFieldSelect || !config.fieldConfig)"
5
5
  :model-value="model[name]"
6
6
  :disabled="disabled"
7
7
  :size="size"
@@ -26,7 +26,11 @@
26
26
  @change="onChangeHandler"
27
27
  ></component>
28
28
 
29
- <TMagicTooltip v-if="config.fieldConfig" :disabled="showDataSourceFieldSelect" content="选择数据源">
29
+ <TMagicTooltip
30
+ v-if="config.fieldConfig && !disabledDataSource"
31
+ :disabled="showDataSourceFieldSelect"
32
+ content="选择数据源"
33
+ >
30
34
  <TMagicButton
31
35
  style="margin-left: 5px"
32
36
  :type="showDataSourceFieldSelect ? 'primary' : 'default'"
@@ -83,10 +87,11 @@ watch(
83
87
  },
84
88
  );
85
89
 
86
- const { dataSourceService } = useServices();
90
+ const { dataSourceService, propsService } = useServices();
87
91
  const mForm = inject<FormState | undefined>('mForm');
88
92
 
89
93
  const dataSources = computed(() => dataSourceService.get('dataSources') || []);
94
+ const disabledDataSource = computed(() => propsService.getDisabledDataSource());
90
95
 
91
96
  const type = computed((): string => {
92
97
  let type = props.config.fieldConfig?.type;
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="m-editor-data-source-fields">
3
- <MagicTable :data="model[name]" :columns="fieldColumns"></MagicTable>
3
+ <MagicTable :data="model[name]" :columns="fieldColumns" :border="true"></MagicTable>
4
4
 
5
5
  <div class="m-editor-data-source-fields-footer">
6
6
  <TMagicButton size="small" :disabled="disabled" plain @click="newFromJsonHandler()">快速添加</TMagicButton>
@@ -1,6 +1,14 @@
1
1
  <template>
2
+ <TMagicInput
3
+ v-if="disabledDataSource"
4
+ v-model="state"
5
+ :disabled="disabled"
6
+ :size="size"
7
+ :clearable="true"
8
+ @change="changeHandler"
9
+ ></TMagicInput>
2
10
  <component
3
- v-if="disabled || isFocused"
11
+ v-else-if="disabled || isFocused"
4
12
  :is="getDesignConfig('components')?.autocomplete.component || 'el-autocomplete'"
5
13
  class="tmagic-design-auto-complete"
6
14
  ref="autocomplete"
@@ -52,7 +60,7 @@ import { computed, nextTick, ref, useTemplateRef, watch } from 'vue';
52
60
  import { Coin } from '@element-plus/icons-vue';
53
61
 
54
62
  import type { DataSchema, DataSourceSchema } from '@tmagic/core';
55
- import { getDesignConfig, TMagicAutocomplete, TMagicTag } from '@tmagic/design';
63
+ import { getDesignConfig, TMagicAutocomplete, TMagicInput, TMagicTag } from '@tmagic/design';
56
64
  import type { DataSourceInputConfig, FieldProps } from '@tmagic/form';
57
65
  import { getKeysArray, isNumber } from '@tmagic/utils';
58
66
 
@@ -72,7 +80,7 @@ const emit = defineEmits<{
72
80
  change: [value: string];
73
81
  }>();
74
82
 
75
- const { dataSourceService } = useServices();
83
+ const { dataSourceService, propsService } = useServices();
76
84
 
77
85
  const autocompleteRef = useTemplateRef<InstanceType<typeof TMagicAutocomplete>>('autocomplete');
78
86
  const isFocused = ref(false);
@@ -81,6 +89,7 @@ const displayState = ref<{ value: string; type: 'var' | 'text' }[]>([]);
81
89
 
82
90
  const input = computed<HTMLInputElement>(() => autocompleteRef.value?.inputRef?.input);
83
91
  const dataSources = computed(() => dataSourceService.get('dataSources'));
92
+ const disabledDataSource = computed(() => propsService.getDisabledDataSource());
84
93
 
85
94
  const setDisplayState = () => {
86
95
  displayState.value = getDisplayField(dataSources.value, state.value);
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <div class="m-editor-data-source-methods">
3
- <MagicTable :data="model[name]" :columns="methodColumns"></MagicTable>
3
+ <MagicTable :data="model[name]" :columns="methodColumns" :border="true"></MagicTable>
4
4
 
5
5
  <div class="m-editor-data-source-methods-footer">
6
6
  <TMagicButton size="small" type="primary" :disabled="disabled" plain @click="createCodeHandler"
@@ -85,7 +85,7 @@ const emit = defineEmits<{
85
85
  change: [v: any, eventData?: ContainerChangeEventData];
86
86
  }>();
87
87
 
88
- const { editorService, dataSourceService, eventsService, codeBlockService } = useServices();
88
+ const { editorService, dataSourceService, eventsService, codeBlockService, propsService } = useServices();
89
89
 
90
90
  // 事件名称下拉框表单配置
91
91
  const eventNameConfig = computed(() => {
@@ -173,24 +173,39 @@ const actionTypeConfig = computed(() => {
173
173
  text: '联动类型',
174
174
  type: 'select',
175
175
  defaultValue: ActionType.COMP,
176
- options: () => [
177
- {
178
- text: '组件',
179
- label: '组件',
180
- value: ActionType.COMP,
181
- },
182
- {
183
- text: '代码',
184
- label: '代码',
185
- disabled: !Object.keys(codeBlockService.getCodeDsl() || {}).length,
186
- value: ActionType.CODE,
187
- },
188
- {
189
- text: '数据源',
190
- label: '数据源',
191
- value: ActionType.DATA_SOURCE,
192
- },
193
- ],
176
+ options: () => {
177
+ const o: {
178
+ text: string;
179
+ label: string;
180
+ value: string;
181
+ disabled?: boolean;
182
+ }[] = [
183
+ {
184
+ text: '组件',
185
+ label: '组件',
186
+ value: ActionType.COMP,
187
+ },
188
+ ];
189
+
190
+ if (!propsService.getDisabledCodeBlock()) {
191
+ o.push({
192
+ text: '代码',
193
+ label: '代码',
194
+ disabled: !Object.keys(codeBlockService.getCodeDsl() || {}).length,
195
+ value: ActionType.CODE,
196
+ });
197
+ }
198
+
199
+ if (!propsService.getDisabledDataSource()) {
200
+ o.push({
201
+ text: '数据源',
202
+ label: '数据源',
203
+ value: ActionType.DATA_SOURCE,
204
+ });
205
+ }
206
+
207
+ return o;
208
+ },
194
209
  };
195
210
  return { ...defaultActionTypeConfig, ...props.config.actionTypeConfig };
196
211
  });
@@ -12,6 +12,14 @@ const emit = defineEmits<{
12
12
  change: [v: string | StyleSchema, eventData: ContainerChangeEventData];
13
13
  }>();
14
14
 
15
+ const positionText: Record<string, string> = {
16
+ static: '不定位',
17
+ relative: '相对定位',
18
+ absolute: '绝对定位',
19
+ fixed: '固定定位',
20
+ sticky: '粘性定位',
21
+ };
22
+
15
23
  const config = {
16
24
  items: [
17
25
  {
@@ -21,9 +29,9 @@ const config = {
21
29
  type: 'data-source-field-select',
22
30
  fieldConfig: {
23
31
  type: 'select',
24
- options: ['static', 'relative', 'absolute', 'fixed', 'sticky'].map((item) => ({
32
+ options: Object.keys(positionText).map((item) => ({
25
33
  value: item,
26
- text: item,
34
+ text: `${item}(${positionText[item]})`,
27
35
  })),
28
36
  },
29
37
  },
@@ -32,10 +32,12 @@ export const useFilter = (
32
32
  const visible = filterIsMatch(text, node);
33
33
  if (visible && parents.length) {
34
34
  parents.forEach((parent) => {
35
- updateStatus(nodeStatusMap.value!, parent.id, {
36
- visible,
37
- expand: true,
38
- });
35
+ if (text || text.length) {
36
+ updateStatus(nodeStatusMap.value!, parent.id, {
37
+ visible,
38
+ expand: true,
39
+ });
40
+ }
39
41
  });
40
42
  }
41
43
 
@@ -45,6 +45,7 @@ export const useStage = (stageOptions: StageOptions) => {
45
45
  updateDragEl: stageOptions.updateDragEl,
46
46
  guidesOptions: stageOptions.guidesOptions,
47
47
  disabledMultiSelect: stageOptions.disabledMultiSelect,
48
+ disabledRule: stageOptions.disabledRule,
48
49
  });
49
50
 
50
51
  watch(
package/src/index.ts CHANGED
@@ -112,6 +112,9 @@ export { default as StyleSetter } from './fields/StyleSetter/Index.vue';
112
112
  const defaultInstallOpt: EditorInstallOptions = {
113
113
  // eslint-disable-next-line no-eval
114
114
  parseDSL: (dsl: string) => eval(dsl),
115
+ customCreateMonacoEditor: (monaco, codeEditorEl, options) => monaco.editor.create(codeEditorEl, options),
116
+ customCreateMonacoDiffEditor: (monaco, codeEditorEl, options) =>
117
+ monaco.editor.createDiffEditor(codeEditorEl, options),
115
118
  };
116
119
 
117
120
  export default {
@@ -1,4 +1,4 @@
1
- import { onBeforeUnmount, reactive, toRaw, watch } from 'vue';
1
+ import { nextTick, onBeforeUnmount, reactive, toRaw, watch } from 'vue';
2
2
  import { cloneDeep } from 'lodash-es';
3
3
 
4
4
  import type TMagicCore from '@tmagic/core';
@@ -21,9 +21,11 @@ import {
21
21
  NODE_CONDS_KEY,
22
22
  NodeType,
23
23
  Target,
24
+ updateNode,
24
25
  } from '@tmagic/core';
25
26
  import { ChangeRecord } from '@tmagic/form';
26
- import { getNodes, isPage, isValueIncludeDataSource } from '@tmagic/utils';
27
+ import StageCore from '@tmagic/stage';
28
+ import { getDepNodeIds, getNodes, isPage, isValueIncludeDataSource } from '@tmagic/utils';
27
29
 
28
30
  import PropsPanel from './layouts/PropsPanel.vue';
29
31
  import { isIncludeDataSource } from './utils/editor';
@@ -197,6 +199,22 @@ export const initServiceState = (
197
199
  },
198
200
  );
199
201
 
202
+ watch(
203
+ () => props.disabledCodeBlock,
204
+ (disabledCodeBlock) => propsService.setDisabledCodeBlock(disabledCodeBlock ?? false),
205
+ {
206
+ immediate: true,
207
+ },
208
+ );
209
+
210
+ watch(
211
+ () => props.disabledDataSource,
212
+ (disabledDataSource) => propsService.setDisabledDataSource(disabledDataSource ?? false),
213
+ {
214
+ immediate: true,
215
+ },
216
+ );
217
+
200
218
  onBeforeUnmount(() => {
201
219
  editorService.resetState();
202
220
  historyService.resetState();
@@ -217,14 +235,15 @@ export const initServiceEvents = (
217
235
  ) => {
218
236
  let getTMagicAppPrimise: Promise<TMagicCore | undefined> | null = null;
219
237
 
220
- const getTMagicApp = (): Promise<TMagicCore | undefined> => {
221
- const renderer = editorService.get('stage')?.renderer;
238
+ const getTMagicApp = async (): Promise<TMagicCore | undefined> => {
239
+ const stage = await getStage();
240
+ const { renderer } = stage;
222
241
  if (!renderer) {
223
- return Promise.resolve(void 0);
242
+ return void 0;
224
243
  }
225
244
 
226
245
  if (renderer.runtime) {
227
- return Promise.resolve(renderer.runtime.getApp?.());
246
+ return renderer.runtime.getApp?.();
228
247
  }
229
248
 
230
249
  if (getTMagicAppPrimise) {
@@ -328,6 +347,61 @@ export const initServiceEvents = (
328
347
  },
329
348
  );
330
349
 
350
+ const getStage = (): Promise<StageCore> => {
351
+ const stage = editorService.get('stage');
352
+ if (stage) {
353
+ return Promise.resolve(stage);
354
+ }
355
+
356
+ return new Promise<StageCore>((resolve) => {
357
+ const unWatch = watch(
358
+ () => editorService.get('stage'),
359
+ (stage) => {
360
+ if (stage) {
361
+ resolve(stage);
362
+ nextTick(() => {
363
+ unWatch();
364
+ });
365
+ }
366
+ },
367
+ );
368
+ });
369
+ };
370
+
371
+ const updateStageDsl = async (value: MApp | null) => {
372
+ const stage = await getStage();
373
+
374
+ const runtime = await stage.renderer?.getRuntime();
375
+ const app = await getTMagicApp();
376
+
377
+ if (!app?.dataSourceManager) {
378
+ runtime?.updateRootConfig?.(cloneDeep(toRaw(value))!);
379
+ }
380
+
381
+ const page = editorService.get('page');
382
+ const node = editorService.get('node');
383
+ page?.id && runtime?.updatePageId?.(page.id);
384
+ setTimeout(() => {
385
+ node && stage?.select(toRaw(node.id));
386
+ });
387
+
388
+ if (value) {
389
+ depService.clearIdleTasks();
390
+
391
+ const dsl = cloneDeep(toRaw(value));
392
+
393
+ await (typeof Worker === 'undefined' ? collectIdle(dsl.items, true) : depService.collectByWorker(dsl));
394
+
395
+ if (dsl.dataSources && dsl.dataSourceDeps && app?.dataSourceManager) {
396
+ for (const node of getNodes(getDepNodeIds(dsl.dataSourceDeps), dsl.items)) {
397
+ updateNode(app.dataSourceManager.compiledNode(node), dsl);
398
+ }
399
+ }
400
+
401
+ runtime?.updateRootConfig?.(dsl);
402
+ }
403
+ };
404
+
331
405
  const initDataSourceDepTarget = (ds: DataSourceSchema) => {
332
406
  depService.addTarget(createDataSourceTarget(ds, reactive({})));
333
407
  depService.addTarget(createDataSourceMethodTarget(ds, reactive({})));
@@ -354,11 +428,7 @@ export const initServiceEvents = (
354
428
  }
355
429
 
356
430
  if (Array.isArray(value.items)) {
357
- depService.clearIdleTasks();
358
-
359
- (typeof Worker === 'undefined' ? collectIdle(value.items, true) : depService.collectByWorker(value)).then(() => {
360
- updateStageNodes(value.items);
361
- });
431
+ updateStageDsl(value);
362
432
  } else {
363
433
  depService.clear();
364
434
  delete value.dataSourceDeps;
@@ -5,7 +5,12 @@
5
5
  :class="`magic-code-editor-wrapper${fullScreen ? ' full-screen' : ''}`"
6
6
  :style="!fullScreen && height ? `height: ${height}` : '100%'"
7
7
  >
8
- <TMagicButton class="magic-code-editor-full-screen-icon" circle size="small" @click="fullScreenHandler"
8
+ <TMagicButton
9
+ v-if="!disabledFullScreen"
10
+ class="magic-code-editor-full-screen-icon"
11
+ circle
12
+ size="small"
13
+ @click="fullScreenHandler"
9
14
  ><MIcon :icon="FullScreen"></MIcon
10
15
  ></TMagicButton>
11
16
  <div ref="codeEditor" class="magic-code-editor-content"></div>
@@ -15,7 +20,7 @@
15
20
  </template>
16
21
 
17
22
  <script lang="ts" setup>
18
- import { onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
23
+ import { nextTick, onBeforeUnmount, onMounted, ref, useTemplateRef, watch } from 'vue';
19
24
  import { FullScreen } from '@element-plus/icons-vue';
20
25
  import { throttle } from 'lodash-es';
21
26
  import serialize from 'serialize-javascript';
@@ -36,12 +41,11 @@ const props = withDefaults(
36
41
  modifiedValues?: any;
37
42
  type?: 'diff';
38
43
  language?: string;
39
- options?: {
40
- [key: string]: any;
41
- };
44
+ options?: monaco.editor.IStandaloneEditorConstructionOptions;
42
45
  height?: string;
43
46
  autoSave?: boolean;
44
47
  parse?: boolean;
48
+ disabledFullScreen?: boolean;
45
49
  }>(),
46
50
  {
47
51
  initValues: '',
@@ -51,6 +55,7 @@ const props = withDefaults(
51
55
  tabSize: 2,
52
56
  }),
53
57
  parse: false,
58
+ disabledFullScreen: false,
54
59
  },
55
60
  );
56
61
 
@@ -124,6 +129,10 @@ const getEditorValue = () =>
124
129
  const init = async () => {
125
130
  if (!codeEditorEl.value) return;
126
131
 
132
+ if (codeEditorEl.value.clientHeight === 0) {
133
+ await nextTick();
134
+ }
135
+
127
136
  const options = {
128
137
  value: values.value,
129
138
  language: props.language,
@@ -132,15 +141,13 @@ const init = async () => {
132
141
  };
133
142
 
134
143
  if (props.type === 'diff') {
135
- vsDiffEditor = monaco.editor.createDiffEditor(codeEditorEl.value, options);
144
+ vsDiffEditor = getEditorConfig('customCreateMonacoDiffEditor')(monaco, codeEditorEl.value, options);
136
145
  } else {
137
- vsEditor = monaco.editor.create(codeEditorEl.value, options);
146
+ vsEditor = getEditorConfig('customCreateMonacoEditor')(monaco, codeEditorEl.value, options);
138
147
  }
139
148
 
140
149
  setEditorValue(props.initValues, props.modifiedValues);
141
150
 
142
- loading.value = false;
143
-
144
151
  emit('initd', vsEditor);
145
152
 
146
153
  codeEditorEl.value.addEventListener('keydown', (e) => {
@@ -179,14 +186,33 @@ watch(
179
186
  },
180
187
  );
181
188
 
189
+ watch(
190
+ () => props.options,
191
+ (v) => {
192
+ vsEditor?.updateOptions(v);
193
+ vsDiffEditor?.updateOptions(v);
194
+ },
195
+ {
196
+ deep: true,
197
+ },
198
+ );
199
+
182
200
  onMounted(async () => {
183
201
  loading.value = true;
184
202
 
185
- init();
203
+ await init();
204
+
205
+ loading.value = false;
186
206
  });
187
207
 
188
208
  onBeforeUnmount(() => {
189
209
  resizeObserver.disconnect();
210
+
211
+ vsEditor?.dispose();
212
+ vsDiffEditor?.dispose();
213
+
214
+ vsEditor = null;
215
+ vsDiffEditor = null;
190
216
  });
191
217
 
192
218
  const fullScreen = ref(false);
@@ -78,6 +78,7 @@ const resizeObserver = new ResizeObserver(() => {
78
78
 
79
79
  onMounted(() => {
80
80
  pageBarEl.value && resizeObserver.observe(pageBarEl.value);
81
+ itemsContainerEl.value && resizeObserver.observe(itemsContainerEl.value);
81
82
  });
82
83
 
83
84
  onBeforeUnmount(() => {
@@ -136,7 +137,7 @@ watch(
136
137
  let beforeDragList: Id[] = [];
137
138
  const options = {
138
139
  ...{
139
- dataIdAttr: 'page-id', // 获取排序后的数据
140
+ dataIdAttr: 'data-page-id', // 获取排序后的数据
140
141
  onStart: async (event: SortableEvent) => {
141
142
  if (typeof props.pageBarSortOptions?.beforeStart === 'function') {
142
143
  await props.pageBarSortOptions.beforeStart(event, sortable);
@@ -42,7 +42,7 @@
42
42
  </template>
43
43
 
44
44
  <script setup lang="ts">
45
- import { computed, getCurrentInstance, inject, onMounted, ref, useTemplateRef, watchEffect } from 'vue';
45
+ import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, useTemplateRef, watchEffect } from 'vue';
46
46
  import { Document as DocumentIcon } from '@element-plus/icons-vue';
47
47
 
48
48
  import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
@@ -78,6 +78,7 @@ const emit = defineEmits<{
78
78
  'submit-error': [e: any];
79
79
  'form-error': [e: any];
80
80
  mounted: [internalInstance: any];
81
+ unmounted: [];
81
82
  }>();
82
83
 
83
84
  const services = useServices();
@@ -104,6 +105,10 @@ onMounted(() => {
104
105
  emit('mounted', internalInstance?.proxy);
105
106
  });
106
107
 
108
+ onUnmounted(() => {
109
+ emit('unmounted');
110
+ });
111
+
107
112
  const submit = async (v: FormValue, eventData: ContainerChangeEventData) => {
108
113
  try {
109
114
  const values = await configFormRef.value?.submitForm();
@@ -13,6 +13,7 @@
13
13
  @submit-error="errorHandler"
14
14
  @form-error="errorHandler"
15
15
  @mounted="mountedHandler"
16
+ @unmounted="unmountedHandler"
16
17
  ></FormPanel>
17
18
 
18
19
  <Resizer v-if="showStylePanel" @change="widthChange"></Resizer>
@@ -89,6 +90,7 @@ const emit = defineEmits<{
89
90
  'submit-error': [e: any];
90
91
  'form-error': [e: any];
91
92
  mounted: [internalInstance: InstanceType<typeof FormPanel>];
93
+ unmounted: [];
92
94
  }>();
93
95
 
94
96
  const { editorService, uiService, propsService, storageService } = useServices();
@@ -165,6 +167,10 @@ const mountedHandler = () => {
165
167
  }
166
168
  };
167
169
 
170
+ const unmountedHandler = () => {
171
+ emit('unmounted');
172
+ };
173
+
168
174
  const propsPanelEl = useTemplateRef('propsPanel');
169
175
  const propsPanelWidth = ref(
170
176
  storageService.getItem(PROPS_PANEL_WIDTH_STORAGE_KEY, { protocol: Protocol.NUMBER }) || 300,