@tmagic/editor 1.3.7 → 1.3.9

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.7",
2
+ "version": "1.3.9",
3
3
  "name": "@tmagic/editor",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -42,16 +42,17 @@
42
42
  "dependencies": {
43
43
  "@babel/core": "^7.18.0",
44
44
  "@element-plus/icons-vue": "^2.3.1",
45
- "@tmagic/core": "1.3.7",
46
- "@tmagic/dep": "1.3.7",
47
- "@tmagic/design": "1.3.7",
48
- "@tmagic/form": "1.3.7",
49
- "@tmagic/schema": "1.3.7",
50
- "@tmagic/stage": "1.3.7",
51
- "@tmagic/table": "1.3.7",
52
- "@tmagic/utils": "1.3.7",
45
+ "@tmagic/core": "1.3.9",
46
+ "@tmagic/dep": "1.3.9",
47
+ "@tmagic/design": "1.3.9",
48
+ "@tmagic/form": "1.3.9",
49
+ "@tmagic/schema": "1.3.9",
50
+ "@tmagic/stage": "1.3.9",
51
+ "@tmagic/table": "1.3.9",
52
+ "@tmagic/utils": "1.3.9",
53
53
  "buffer": "^6.0.3",
54
54
  "color": "^3.1.3",
55
+ "emmet-monaco-es": "^5.3.0",
55
56
  "events": "^3.3.0",
56
57
  "gesto": "^1.19.1",
57
58
  "keycon": "^1.4.0",
@@ -62,8 +63,8 @@
62
63
  "vue": "^3.3.8"
63
64
  },
64
65
  "peerDependencies": {
65
- "@tmagic/design": "1.3.7",
66
- "@tmagic/form": "1.3.7",
66
+ "@tmagic/design": "1.3.9",
67
+ "@tmagic/form": "1.3.9",
67
68
  "monaco-editor": "^0.41.0",
68
69
  "vue": "^3.3.8"
69
70
  },
package/src/Editor.vue CHANGED
@@ -70,6 +70,8 @@
70
70
  <PropsPanel
71
71
  :extend-state="extendFormState"
72
72
  @mounted="(instance: any) => $emit('props-panel-mounted', instance)"
73
+ @form-error="(e: any) => $emit('props-form-error', e)"
74
+ @submit-error="(e: any) => $emit('props-submit-error', e)"
73
75
  >
74
76
  <template #props-panel-header>
75
77
  <slot name="props-panel-header"></slot>
@@ -88,6 +90,7 @@
88
90
  <slot name="footer"></slot>
89
91
  </template>
90
92
 
93
+ <template #page-bar><slot name="page-bar"></slot></template>
91
94
  <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
92
95
  <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
93
96
  </Framework>
@@ -136,6 +139,8 @@ defineOptions({
136
139
  const emit = defineEmits<{
137
140
  'props-panel-mounted': [instance: InstanceType<typeof PropsPanel>];
138
141
  'update:modelValue': [value: MApp | null];
142
+ 'props-form-error': [e: any];
143
+ 'props-submit-error': [e: any];
139
144
  }>();
140
145
 
141
146
  const props = withDefaults(defineProps<EditorProps>(), defaultEditorProps);
@@ -15,7 +15,7 @@
15
15
  </template>
16
16
  </TreeNode>
17
17
  </template>
18
- <div v-else>
18
+ <div v-else class="m-editor-tree-empty">
19
19
  <p>{{ emptyText }}</p>
20
20
  </div>
21
21
  </div>
@@ -9,16 +9,20 @@
9
9
  :size="size"
10
10
  @change="changeHandler"
11
11
  ></m-form-container>
12
+ <!-- 编辑按钮 -->
13
+ <Icon v-if="model[name]" class="icon" :icon="Edit" @click="editPageFragment(model[name])"></Icon>
12
14
  </div>
13
15
  </div>
14
16
  </template>
15
17
 
16
18
  <script lang="ts" setup>
17
19
  import { computed, inject } from 'vue';
20
+ import { Edit } from '@element-plus/icons-vue';
18
21
 
19
22
  import { FieldProps } from '@tmagic/form';
20
- import { NodeType } from '@tmagic/schema';
23
+ import { Id, NodeType } from '@tmagic/schema';
21
24
 
25
+ import Icon from '@editor/components/Icon.vue';
22
26
  import type { PageFragmentSelectConfig, Services } from '@editor/type';
23
27
 
24
28
  defineOptions({
@@ -41,8 +45,8 @@ const selectConfig = {
41
45
  options: () => {
42
46
  if (pageList.value) {
43
47
  return pageList.value.map((item) => ({
44
- text: `${item.name}(${item.id})`,
45
- label: `${item.name}(${item.id})`,
48
+ text: `${item.devconfig?.tabName || item.title || item.name}(${item.id})`,
49
+ label: `${item.devconfig?.tabName || item.title || item.name}(${item.id})`,
46
50
  value: item.id,
47
51
  }));
48
52
  }
@@ -52,4 +56,8 @@ const selectConfig = {
52
56
  const changeHandler = async () => {
53
57
  emit('change', props.model[props.name]);
54
58
  };
59
+
60
+ const editPageFragment = (id: Id) => {
61
+ services?.editorService.select(id);
62
+ };
55
63
  </script>
@@ -22,12 +22,12 @@
22
22
  import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
23
23
  import { FullScreen } from '@element-plus/icons-vue';
24
24
  import { throttle } from 'lodash-es';
25
- import * as monaco from 'monaco-editor';
26
25
  import serialize from 'serialize-javascript';
27
26
 
28
27
  import { TMagicButton } from '@tmagic/design';
29
28
 
30
29
  import { getConfig } from '@editor/utils/config';
30
+ import monaco from '@editor/utils/monaco-editor';
31
31
 
32
32
  defineOptions({
33
33
  name: 'MEditorCodeEditor',
@@ -36,10 +36,12 @@
36
36
  <AddPageBox :disabled-page-fragment="disabledPageFragment"></AddPageBox>
37
37
  </slot>
38
38
 
39
- <PageBar :disabled-page-fragment="disabledPageFragment">
40
- <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
41
- <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
42
- </PageBar>
39
+ <slot name="page-bar">
40
+ <PageBar :disabled-page-fragment="disabledPageFragment">
41
+ <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
42
+ <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
43
+ </PageBar>
44
+ </slot>
43
45
  </template>
44
46
 
45
47
  <template v-if="page" #right>
@@ -10,6 +10,7 @@
10
10
  :config="curFormConfig"
11
11
  :extend-state="extendState"
12
12
  @change="submit"
13
+ @error="errorHandler"
13
14
  ></MForm>
14
15
  </div>
15
16
  </template>
@@ -17,7 +18,6 @@
17
18
  <script lang="ts" setup>
18
19
  import { computed, getCurrentInstance, inject, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue';
19
20
 
20
- import { tMagicMessage } from '@tmagic/design';
21
21
  import type { FormState, FormValue } from '@tmagic/form';
22
22
  import { MForm } from '@tmagic/form';
23
23
 
@@ -33,7 +33,7 @@ defineProps<{
33
33
  extendState?: (state: FormState) => Record<string, any> | Promise<Record<string, any>>;
34
34
  }>();
35
35
 
36
- const emit = defineEmits(['mounted']);
36
+ const emit = defineEmits(['mounted', 'submit-error', 'form-error']);
37
37
 
38
38
  const internalInstance = getCurrentInstance();
39
39
  const values = ref<FormValue>({});
@@ -79,11 +79,13 @@ const submit = async () => {
79
79
  const values = await configForm.value?.submitForm();
80
80
  services?.editorService.update(values);
81
81
  } catch (e: any) {
82
- console.error(e);
83
- tMagicMessage.closeAll();
84
- tMagicMessage.error(e.message);
82
+ emit('submit-error', e);
85
83
  }
86
84
  };
87
85
 
86
+ const errorHandler = (e: any) => {
87
+ emit('form-error', e);
88
+ };
89
+
88
90
  defineExpose({ configForm, submit });
89
91
  </script>
@@ -33,6 +33,23 @@ class DataSource extends BaseService {
33
33
  methods: {},
34
34
  });
35
35
 
36
+ constructor() {
37
+ super([
38
+ { name: 'getFormConfig', isAsync: false },
39
+ { name: 'setFormConfig', isAsync: false },
40
+ { name: 'getFormValue', isAsync: false },
41
+ { name: 'setFormValue', isAsync: false },
42
+ { name: 'getFormEvent', isAsync: false },
43
+ { name: 'setFormEvent', isAsync: false },
44
+ { name: 'getFormMethod', isAsync: false },
45
+ { name: 'setFormMethod', isAsync: false },
46
+ { name: 'add', isAsync: false },
47
+ { name: 'update', isAsync: false },
48
+ { name: 'remove', isAsync: false },
49
+ { name: 'createId', isAsync: false },
50
+ ]);
51
+ }
52
+
36
53
  public set<K extends StateKey, T extends State[K]>(name: K, value: T) {
37
54
  this.state[name] = value;
38
55
  }
@@ -62,6 +62,10 @@ class Dep extends BaseService {
62
62
  return this.watcher.clear(nodes);
63
63
  }
64
64
 
65
+ public clearByType(type: DepTargetType, nodes?: MNode[]) {
66
+ return this.watcher.clearByType(type, nodes);
67
+ }
68
+
65
69
  public hasTarget(id: Id, type: string = DepTargetType.DEFAULT) {
66
70
  return this.watcher.hasTarget(id, type);
67
71
  }
@@ -644,7 +644,7 @@ class Editor extends BaseService {
644
644
  public copyWithRelated(config: MNode | MNode[]): void {
645
645
  const copyNodes: MNode[] = Array.isArray(config) ? config : [config];
646
646
  // 关联的组件也一并复制
647
- depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY)?.removeDep();
647
+ depService.clearByType(DepTargetType.RELATED_COMP_WHEN_COPY);
648
648
  depService.collect(copyNodes, true, DepTargetType.RELATED_COMP_WHEN_COPY);
649
649
  const customTarget = depService.getTarget(
650
650
  DepTargetType.RELATED_COMP_WHEN_COPY,
@@ -775,17 +775,23 @@ class Editor extends BaseService {
775
775
  const layout = await this.getLayout(parent, node);
776
776
  const isRelative = layout === Layout.RELATIVE;
777
777
 
778
- brothers.splice(index, 1);
779
-
778
+ let offsetIndex: number;
780
779
  if (offset === LayerOffset.TOP) {
781
- brothers.splice(isRelative ? 0 : brothers.length, 0, node);
780
+ offsetIndex = isRelative ? 0 : brothers.length;
782
781
  } else if (offset === LayerOffset.BOTTOM) {
783
- brothers.splice(isRelative ? brothers.length : 0, 0, node);
782
+ offsetIndex = isRelative ? brothers.length : 0;
784
783
  } else {
785
- brothers.splice(index + (isRelative ? -offset : offset), 0, node);
784
+ offsetIndex = index + (isRelative ? -offset : offset);
786
785
  }
787
786
 
787
+ if ((offsetIndex > 0 && offsetIndex > brothers.length) || offsetIndex < 0) {
788
+ return;
789
+ }
790
+ brothers.splice(index, 1);
791
+ brothers.splice(offsetIndex, 0, node);
792
+
788
793
  const grandparent = this.getParentById(parent.id);
794
+
789
795
  this.get('stage')?.update({
790
796
  config: cloneDeep(toRaw(parent)),
791
797
  parentId: grandparent?.id,
@@ -794,6 +800,8 @@ class Editor extends BaseService {
794
800
 
795
801
  this.addModifiedNodeId(parent.id);
796
802
  this.pushHistoryState();
803
+
804
+ this.emit('move-layer', offset);
797
805
  }
798
806
 
799
807
  /**
@@ -17,12 +17,12 @@
17
17
  */
18
18
 
19
19
  import { reactive } from 'vue';
20
- import { cloneDeep, get, mergeWith, set } from 'lodash-es';
20
+ import { cloneDeep, mergeWith } from 'lodash-es';
21
21
 
22
22
  import { DepTargetType } from '@tmagic/dep';
23
23
  import type { FormConfig } from '@tmagic/form';
24
24
  import type { Id, MComponent, MNode } from '@tmagic/schema';
25
- import { guid, toLine } from '@tmagic/utils';
25
+ import { getValueByKeyPath, guid, setValueByKeyPath, toLine } from '@tmagic/utils';
26
26
 
27
27
  import depService from '@editor/services/dep';
28
28
  import editorService from '@editor/services/editor';
@@ -194,17 +194,22 @@ class Props extends BaseService {
194
194
  public replaceRelateId(originConfigs: MNode[], targetConfigs: MNode[]) {
195
195
  const relateIdMap = this.getRelateIdMap();
196
196
  if (Object.keys(relateIdMap).length === 0) return;
197
+
197
198
  const target = depService.getTarget(DepTargetType.RELATED_COMP_WHEN_COPY, DepTargetType.RELATED_COMP_WHEN_COPY);
198
199
  if (!target) return;
200
+
199
201
  originConfigs.forEach((config: MNode) => {
200
202
  const newId = relateIdMap[config.id];
201
203
  const targetConfig = targetConfigs.find((targetConfig) => targetConfig.id === newId);
204
+
202
205
  if (!targetConfig) return;
206
+
203
207
  target.deps[config.id]?.keys?.forEach((fullKey) => {
204
- const relateOriginId = get(config, fullKey);
208
+ const relateOriginId = getValueByKeyPath(fullKey, config);
205
209
  const relateTargetId = relateIdMap[relateOriginId];
206
210
  if (!relateTargetId) return;
207
- set(targetConfig, fullKey, relateTargetId);
211
+
212
+ setValueByKeyPath(fullKey, relateTargetId, targetConfig);
208
213
  });
209
214
  });
210
215
  }
@@ -0,0 +1,14 @@
1
+ .m-fields-page-fragment-select {
2
+ width: 100%;
3
+ .page-fragment-select-container {
4
+ width: 100%;
5
+ display: flex;
6
+ align-items: center;
7
+ .select {
8
+ flex: 1;
9
+ }
10
+ .icon {
11
+ margin-left: 10px;
12
+ }
13
+ }
14
+ }
@@ -24,3 +24,4 @@
24
24
  @import "./floatbox.scss";
25
25
  @import "./tree.scss";
26
26
  @import "./floating-box.scss";
27
+ @import "./page-fragment-select.scss";
@@ -80,4 +80,10 @@
80
80
  }
81
81
  }
82
82
  }
83
+
84
+ .m-editor-tree-empty {
85
+ text-align: center;
86
+ color: #909399;
87
+ font-size: 14px;
88
+ }
83
89
  }
package/src/type.ts CHANGED
@@ -54,6 +54,7 @@ export interface FrameworkSlots {
54
54
  workspace(props: {}): any;
55
55
  'props-panel'(props: {}): any;
56
56
  'footer'(props: {}): any;
57
+ 'page-bar'(props: {}): any;
57
58
  'page-bar-title'(props: { page: MPage | MPageFragment }): any;
58
59
  'page-bar-popover'(props: { page: MPage | MPageFragment }): any;
59
60
  }
@@ -0,0 +1,8 @@
1
+ import { emmetCSS, emmetHTML } from 'emmet-monaco-es';
2
+ import * as monaco from 'monaco-editor';
3
+
4
+ // 注册emmet插件
5
+ emmetHTML(monaco);
6
+ emmetCSS(monaco, ['css', 'scss']);
7
+
8
+ export default monaco;
@@ -1,4 +1,4 @@
1
- import * as monaco from 'monaco-editor';
1
+ import monaco from '../utils/monaco-editor';
2
2
  declare const _default: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<{
3
3
  initValues?: any;
4
4
  modifiedValues?: any;
@@ -36,6 +36,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
36
36
  readonly popperClass?: string | undefined;
37
37
  readonly extendState?: ((state: FormState) => Record<string, any> | Promise<Record<string, any>>) | undefined;
38
38
  onChange?: ((...args: any[]) => any) | undefined;
39
+ onError?: ((...args: any[]) => any) | undefined;
39
40
  "onField-input"?: ((...args: any[]) => any) | undefined;
40
41
  "onField-change"?: ((...args: any[]) => any) | undefined;
41
42
  } & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & Readonly<import("vue").ExtractPropTypes<{
@@ -100,6 +101,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
100
101
  };
101
102
  }>> & {
102
103
  onChange?: ((...args: any[]) => any) | undefined;
104
+ onError?: ((...args: any[]) => any) | undefined;
103
105
  "onField-input"?: ((...args: any[]) => any) | undefined;
104
106
  "onField-change"?: ((...args: any[]) => any) | undefined;
105
107
  }, "labelWidth" | "disabled" | "height" | "config" | "initValues" | "lastValues" | "isCompare" | "parentValues" | "stepActive" | "inline" | "labelPosition" | "keyProp">;
@@ -114,7 +116,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
114
116
  }>;
115
117
  $root: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null;
116
118
  $parent: import("vue").ComponentPublicInstance<{}, {}, {}, {}, {}, {}, {}, {}, false, import("vue").ComponentOptionsBase<any, any, any, any, any, any, any, any, any, {}, {}, string, {}>, {}, {}> | null;
117
- $emit: ((event: "change", ...args: any[]) => void) & ((event: "field-input", ...args: any[]) => void) & ((event: "field-change", ...args: any[]) => void);
119
+ $emit: ((event: "change", ...args: any[]) => void) & ((event: "error", ...args: any[]) => void) & ((event: "field-input", ...args: any[]) => void) & ((event: "field-change", ...args: any[]) => void);
118
120
  $el: any;
119
121
  $options: import("vue").ComponentOptionsBase<Readonly<import("vue").ExtractPropTypes<{
120
122
  labelWidth: {
@@ -178,6 +180,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
178
180
  };
179
181
  }>> & {
180
182
  onChange?: ((...args: any[]) => any) | undefined;
183
+ onError?: ((...args: any[]) => any) | undefined;
181
184
  "onField-input"?: ((...args: any[]) => any) | undefined;
182
185
  "onField-change"?: ((...args: any[]) => any) | undefined;
183
186
  }, {
@@ -190,6 +193,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
190
193
  submitForm: (native?: boolean | undefined) => Promise<any>;
191
194
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
192
195
  change: (...args: any[]) => void;
196
+ error: (...args: any[]) => void;
193
197
  "field-input": (...args: any[]) => void;
194
198
  "field-change": (...args: any[]) => void;
195
199
  }, string, {
@@ -287,6 +291,7 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
287
291
  };
288
292
  }>> & {
289
293
  onChange?: ((...args: any[]) => any) | undefined;
294
+ onError?: ((...args: any[]) => any) | undefined;
290
295
  "onField-input"?: ((...args: any[]) => any) | undefined;
291
296
  "onField-change"?: ((...args: any[]) => any) | undefined;
292
297
  } & import("vue").ShallowUnwrapRef<{
@@ -301,10 +306,14 @@ declare const _default: __VLS_WithTemplateSlots<import("vue").DefineComponent<__
301
306
  submit: () => Promise<void>;
302
307
  }, unknown, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
303
308
  mounted: (...args: any[]) => void;
309
+ "submit-error": (...args: any[]) => void;
310
+ "form-error": (...args: any[]) => void;
304
311
  }, string, import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps, Readonly<import("vue").ExtractPropTypes<__VLS_TypePropsToRuntimeProps<{
305
312
  extendState?: ((state: FormState) => Record<string, any> | Promise<Record<string, any>>) | undefined;
306
313
  }>>> & {
307
314
  onMounted?: ((...args: any[]) => any) | undefined;
315
+ "onSubmit-error"?: ((...args: any[]) => any) | undefined;
316
+ "onForm-error"?: ((...args: any[]) => any) | undefined;
308
317
  }, {}, {}>, Readonly<PropsPanelSlots>>;
309
318
  export default _default;
310
319
  type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
@@ -15,6 +15,7 @@ interface State {
15
15
  type StateKey = keyof State;
16
16
  declare class DataSource extends BaseService {
17
17
  private state;
18
+ constructor();
18
19
  set<K extends StateKey, T extends State[K]>(name: K, value: T): void;
19
20
  get<K extends StateKey>(name: K): State[K];
20
21
  getFormConfig(type?: string): FormConfig;
@@ -14,6 +14,7 @@ declare class Dep extends BaseService {
14
14
  clearTargets(): void;
15
15
  collect(nodes: MNode[], deep?: boolean, type?: DepTargetType): void;
16
16
  clear(nodes?: MNode[]): void;
17
+ clearByType(type: DepTargetType, nodes?: MNode[]): void;
17
18
  hasTarget(id: Id, type?: string): boolean;
18
19
  hasSpecifiedTypeTarget(type?: string): boolean;
19
20
  }
package/types/type.d.ts CHANGED
@@ -26,6 +26,7 @@ export interface FrameworkSlots {
26
26
  workspace(props: {}): any;
27
27
  'props-panel'(props: {}): any;
28
28
  'footer'(props: {}): any;
29
+ 'page-bar'(props: {}): any;
29
30
  'page-bar-title'(props: {
30
31
  page: MPage | MPageFragment;
31
32
  }): any;
@@ -0,0 +1,2 @@
1
+ import * as monaco from 'monaco-editor';
2
+ export default monaco;