@tmagic/editor 1.2.0-beta.2 → 1.2.0-beta.21

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 (101) hide show
  1. package/dist/style.css +41 -28
  2. package/dist/{tmagic-editor.mjs → tmagic-editor.js} +1693 -1272
  3. package/dist/tmagic-editor.js.map +1 -0
  4. package/dist/{tmagic-editor.umd.js → tmagic-editor.umd.cjs} +1700 -1274
  5. package/dist/tmagic-editor.umd.cjs.map +1 -0
  6. package/package.json +16 -14
  7. package/src/Editor.vue +54 -37
  8. package/src/components/CodeDraftEditor.vue +145 -0
  9. package/src/components/ContentMenu.vue +4 -4
  10. package/src/components/FunctionEditor.vue +145 -0
  11. package/src/components/Icon.vue +7 -5
  12. package/src/components/Layout.vue +149 -0
  13. package/src/components/ScrollBar.vue +1 -1
  14. package/src/components/ScrollViewer.vue +10 -1
  15. package/src/components/ToolButton.vue +30 -15
  16. package/src/fields/Code.vue +1 -1
  17. package/src/fields/CodeLink.vue +1 -1
  18. package/src/fields/CodeSelect.vue +89 -110
  19. package/src/fields/UISelect.vue +9 -8
  20. package/src/index.ts +1 -0
  21. package/src/layouts/AddPageBox.vue +3 -2
  22. package/src/layouts/CodeEditor.vue +2 -3
  23. package/src/layouts/Framework.vue +62 -40
  24. package/src/layouts/NavMenu.vue +1 -1
  25. package/src/layouts/PropsPanel.vue +11 -13
  26. package/src/layouts/Resizer.vue +1 -1
  27. package/src/layouts/sidebar/ComponentListPanel.vue +15 -13
  28. package/src/layouts/sidebar/LayerMenu.vue +9 -7
  29. package/src/layouts/sidebar/LayerPanel.vue +277 -177
  30. package/src/layouts/sidebar/Sidebar.vue +113 -27
  31. package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +34 -85
  32. package/src/layouts/sidebar/code-block/CodeBlockList.vue +55 -89
  33. package/src/layouts/workspace/Breadcrumb.vue +32 -0
  34. package/src/layouts/workspace/PageBar.vue +12 -11
  35. package/src/layouts/workspace/PageBarScrollContainer.vue +1 -1
  36. package/src/layouts/workspace/Stage.vue +26 -9
  37. package/src/layouts/workspace/ViewerMenu.vue +11 -9
  38. package/src/layouts/workspace/Workspace.vue +10 -3
  39. package/src/services/BaseService.ts +6 -1
  40. package/src/services/codeBlock.ts +124 -125
  41. package/src/services/componentList.ts +6 -1
  42. package/src/services/editor.ts +43 -19
  43. package/src/services/events.ts +6 -1
  44. package/src/services/history.ts +7 -16
  45. package/src/services/props.ts +7 -2
  46. package/src/services/storage.ts +1 -0
  47. package/src/services/ui.ts +12 -0
  48. package/src/theme/breadcrumb.scss +6 -0
  49. package/src/theme/code-block.scss +30 -21
  50. package/src/theme/component-list-panel.scss +3 -7
  51. package/src/theme/layer-panel.scss +7 -2
  52. package/src/theme/theme.scss +1 -0
  53. package/src/type.ts +76 -50
  54. package/src/utils/editor.ts +9 -1
  55. package/src/utils/index.ts +1 -0
  56. package/src/utils/props.ts +2 -2
  57. package/src/utils/scroll-viewer.ts +18 -2
  58. package/src/utils/stage.ts +9 -2
  59. package/types/Editor.vue.d.ts +42 -29
  60. package/types/components/CodeDraftEditor.vue.d.ts +148 -0
  61. package/types/components/ContentMenu.vue.d.ts +1 -3
  62. package/types/components/FunctionEditor.vue.d.ts +120 -0
  63. package/types/components/Icon.vue.d.ts +1 -3
  64. package/types/{layouts → components}/Layout.vue.d.ts +12 -1
  65. package/types/components/ScrollBar.vue.d.ts +1 -3
  66. package/types/components/ScrollViewer.vue.d.ts +45 -1
  67. package/types/components/ToolButton.vue.d.ts +1 -3
  68. package/types/fields/Code.vue.d.ts +1 -3
  69. package/types/fields/CodeLink.vue.d.ts +1 -3
  70. package/types/fields/CodeSelect.vue.d.ts +10 -12
  71. package/types/fields/UISelect.vue.d.ts +1 -3
  72. package/types/index.d.ts +1 -0
  73. package/types/layouts/AddPageBox.vue.d.ts +1 -3
  74. package/types/layouts/CodeEditor.vue.d.ts +6 -15
  75. package/types/layouts/NavMenu.vue.d.ts +1 -3
  76. package/types/layouts/sidebar/LayerMenu.vue.d.ts +25 -9
  77. package/types/layouts/sidebar/LayerPanel.vue.d.ts +38 -886
  78. package/types/layouts/sidebar/Sidebar.vue.d.ts +10 -5
  79. package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +1 -1
  80. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +6 -5
  81. package/types/layouts/{sidebar/TabPane.vue.d.ts → workspace/Breadcrumb.vue.d.ts} +5 -43
  82. package/types/layouts/workspace/Stage.vue.d.ts +25 -8
  83. package/types/layouts/workspace/ViewerMenu.vue.d.ts +6 -3
  84. package/types/layouts/workspace/Workspace.vue.d.ts +23 -5
  85. package/types/services/BaseService.d.ts +2 -1
  86. package/types/services/codeBlock.d.ts +57 -36
  87. package/types/services/componentList.d.ts +1 -0
  88. package/types/services/editor.d.ts +5 -6
  89. package/types/services/events.d.ts +1 -0
  90. package/types/services/history.d.ts +5 -15
  91. package/types/services/props.d.ts +3 -2
  92. package/types/services/ui.d.ts +2 -1
  93. package/types/type.d.ts +64 -48
  94. package/types/utils/editor.d.ts +1 -0
  95. package/types/utils/index.d.ts +1 -0
  96. package/types/utils/props.d.ts +1 -1
  97. package/types/utils/scroll-viewer.d.ts +5 -0
  98. package/dist/tmagic-editor.mjs.map +0 -1
  99. package/dist/tmagic-editor.umd.js.map +0 -1
  100. package/src/layouts/Layout.vue +0 -100
  101. package/src/layouts/sidebar/TabPane.vue +0 -116
package/package.json CHANGED
@@ -1,18 +1,19 @@
1
1
  {
2
- "version": "1.2.0-beta.2",
2
+ "version": "1.2.0-beta.21",
3
3
  "name": "@tmagic/editor",
4
+ "type": "module",
4
5
  "sideEffects": [
5
6
  "dist/*",
6
7
  "src/theme/*"
7
8
  ],
8
- "main": "dist/tmagic-editor.umd.js",
9
- "module": "dist/tmagic-editor.mjs",
9
+ "main": "dist/tmagic-editor.umd.cjs",
10
+ "module": "dist/tmagic-editor.js",
10
11
  "style": "dist/style.css",
11
12
  "types": "types/index.d.ts",
12
13
  "exports": {
13
14
  ".": {
14
- "import": "./dist/tmagic-editor.mjs",
15
- "require": "./dist/tmagic-editor.umd.js"
15
+ "import": "./dist/tmagic-editor.js",
16
+ "require": "./dist/tmagic-editor.umd.cjs"
16
17
  },
17
18
  "./dist/style.css": {
18
19
  "import": "./dist/style.css",
@@ -45,14 +46,14 @@
45
46
  "dependencies": {
46
47
  "@babel/core": "^7.18.0",
47
48
  "@element-plus/icons-vue": "^2.0.9",
48
- "@tmagic/core": "1.2.0-beta.2",
49
- "@tmagic/form": "1.2.0-beta.2",
50
- "@tmagic/schema": "1.2.0-beta.2",
51
- "@tmagic/stage": "1.2.0-beta.2",
52
- "@tmagic/utils": "1.2.0-beta.2",
49
+ "@tmagic/core": "1.2.0-beta.21",
50
+ "@tmagic/design": "1.2.0-beta.21",
51
+ "@tmagic/form": "1.2.0-beta.21",
52
+ "@tmagic/schema": "1.2.0-beta.21",
53
+ "@tmagic/stage": "1.2.0-beta.21",
54
+ "@tmagic/utils": "1.2.0-beta.21",
53
55
  "buffer": "^6.0.3",
54
56
  "color": "^3.1.3",
55
- "element-plus": "^2.2.17",
56
57
  "events": "^3.3.0",
57
58
  "gesto": "^1.7.0",
58
59
  "keycon": "^1.1.2",
@@ -62,8 +63,8 @@
62
63
  "vue": "^3.2.37"
63
64
  },
64
65
  "peerDependencies": {
65
- "@tmagic/form": "1.2.0-beta.2",
66
- "element-plus": "^2.2.17",
66
+ "@tmagic/design": "1.2.0-beta.21",
67
+ "@tmagic/form": "1.2.0-beta.21",
67
68
  "monaco-editor": "^0.34.0",
68
69
  "vue": "^3.2.37"
69
70
  },
@@ -79,6 +80,7 @@
79
80
  "sass": "^1.35.1",
80
81
  "typescript": "^4.7.4",
81
82
  "vite": "^3.1.3",
82
- "vue-tsc": "^0.39.4"
83
+ "vite-plugin-vue-setup-extend": "^0.4.0",
84
+ "vue-tsc": "^1.0.10"
83
85
  }
84
86
  }
package/src/Editor.vue CHANGED
@@ -1,12 +1,12 @@
1
1
  <template>
2
- <framework :code-options="codeOptions">
2
+ <Framework :code-options="codeOptions">
3
3
  <template #nav>
4
- <slot name="nav" :editorService="editorService"><nav-menu :data="menu"></nav-menu></slot>
4
+ <slot name="nav" :editorService="editorService"><NavMenu :data="menu"></NavMenu></slot>
5
5
  </template>
6
6
 
7
7
  <template #sidebar>
8
8
  <slot name="sidebar" :editorService="editorService">
9
- <sidebar :data="sidebar">
9
+ <Sidebar :data="sidebar" :layer-content-menu="layerContentMenu">
10
10
  <template #layer-panel-header>
11
11
  <slot name="layer-panel-header"></slot>
12
12
  </template>
@@ -34,33 +34,33 @@
34
34
  <template #code-block-edit-panel-header="{ id }">
35
35
  <slot name="code-block-edit-panel-header" :id="id"></slot>
36
36
  </template>
37
- </sidebar>
37
+ </Sidebar>
38
38
  </slot>
39
39
  </template>
40
40
 
41
41
  <template #workspace>
42
42
  <slot name="workspace" :editorService="editorService">
43
- <workspace>
43
+ <Workspace :stage-content-menu="stageContentMenu">
44
44
  <template #stage><slot name="stage"></slot></template>
45
45
  <template #workspace-content><slot name="workspace-content" :editorService="editorService"></slot></template>
46
46
  <template #page-bar-title="{ page }"><slot name="page-bar-title" :page="page"></slot></template>
47
47
  <template #page-bar-popover="{ page }"><slot name="page-bar-popover" :page="page"></slot></template>
48
- </workspace>
48
+ </Workspace>
49
49
  </slot>
50
50
  </template>
51
51
 
52
52
  <template #props-panel>
53
53
  <slot name="props-panel">
54
- <props-panel @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
54
+ <PropsPanel @mounted="(instance: any) => $emit('props-panel-mounted', instance)">
55
55
  <template #props-panel-header>
56
56
  <slot name="props-panel-header"></slot>
57
57
  </template>
58
- </props-panel>
58
+ </PropsPanel>
59
59
  </slot>
60
60
  </template>
61
61
 
62
62
  <template #empty><slot name="empty" :editorService="editorService"></slot></template>
63
- </framework>
63
+ </Framework>
64
64
  </template>
65
65
 
66
66
  <script lang="ts">
@@ -69,8 +69,13 @@ import { defineComponent, onUnmounted, PropType, provide, reactive, toRaw, watch
69
69
  import { EventOption } from '@tmagic/core';
70
70
  import type { FormConfig } from '@tmagic/form';
71
71
  import type { MApp, MNode } from '@tmagic/schema';
72
- import type StageCore from '@tmagic/stage';
73
- import { CONTAINER_HIGHLIGHT_CLASS, ContainerHighlightType, MoveableOptions } from '@tmagic/stage';
72
+ import StageCore, {
73
+ CONTAINER_HIGHLIGHT_CLASS_NAME,
74
+ ContainerHighlightType,
75
+ CustomizeMoveableOptionsCallbackConfig,
76
+ MoveableOptions,
77
+ UpdateDragEl,
78
+ } from '@tmagic/stage';
74
79
 
75
80
  import Framework from './layouts/Framework.vue';
76
81
  import NavMenu from './layouts/NavMenu.vue';
@@ -117,25 +122,27 @@ export default defineComponent({
117
122
  type: Object as PropType<SideBarData>,
118
123
  },
119
124
 
125
+ /** 顶部工具栏配置 */
126
+ menu: {
127
+ type: Object as PropType<MenuBarData>,
128
+ default: () => ({ left: [], right: [] }),
129
+ },
130
+
131
+ /** 组件树右键菜单 */
120
132
  layerContentMenu: {
121
133
  type: Array as PropType<(MenuButton | MenuComponent)[]>,
122
134
  default: () => [],
123
135
  },
124
136
 
137
+ /** 画布右键菜单 */
125
138
  stageContentMenu: {
126
139
  type: Array as PropType<(MenuButton | MenuComponent)[]>,
127
140
  default: () => [],
128
141
  },
129
142
 
130
- /** 顶部工具栏配置 */
131
- menu: {
132
- type: Object as PropType<MenuBarData>,
133
- default: () => ({ left: [], right: [] }),
134
- },
135
-
136
143
  /** 中间工作区域中画布渲染的内容 */
137
144
  render: {
138
- type: Function as PropType<() => HTMLDivElement>,
145
+ type: Function as PropType<(stage: StageCore) => HTMLDivElement | Promise<HTMLDivElement>>,
139
146
  },
140
147
 
141
148
  /** 中间工作区域中画布通过iframe渲染时的页面url */
@@ -158,13 +165,15 @@ export default defineComponent({
158
165
 
159
166
  /** 组件联动事件选项列表 */
160
167
  eventMethodList: {
161
- type: Object,
168
+ type: Object as PropType<Record<string, { events: EventOption[]; methods: EventOption[] }>>,
162
169
  default: () => ({}),
163
170
  },
164
171
 
165
172
  /** 画布中组件选中框的移动范围 */
166
173
  moveableOptions: {
167
- type: [Object, Function] as PropType<MoveableOptions | ((core?: StageCore) => MoveableOptions)>,
174
+ type: [Object, Function] as PropType<
175
+ MoveableOptions | ((config?: CustomizeMoveableOptionsCallbackConfig) => MoveableOptions)
176
+ >,
168
177
  },
169
178
 
170
179
  /** 编辑器初始化时默认选中的组件ID */
@@ -184,7 +193,7 @@ export default defineComponent({
184
193
 
185
194
  containerHighlightClassName: {
186
195
  type: String,
187
- default: CONTAINER_HIGHLIGHT_CLASS,
196
+ default: CONTAINER_HIGHLIGHT_CLASS_NAME,
188
197
  },
189
198
 
190
199
  containerHighlightDuration: {
@@ -207,7 +216,7 @@ export default defineComponent({
207
216
  },
208
217
 
209
218
  updateDragEl: {
210
- type: Function as PropType<(el: HTMLDivElement, target: HTMLElement) => void>,
219
+ type: Function as PropType<UpdateDragEl>,
211
220
  },
212
221
  },
213
222
 
@@ -215,15 +224,25 @@ export default defineComponent({
215
224
 
216
225
  setup(props, { emit }) {
217
226
  editorService.on('root-change', (value) => {
218
- const node = editorService.get<MNode | null>('node');
219
- const nodeId = node?.id || props.defaultSelected;
220
- if (nodeId && node !== value) {
221
- editorService.select(nodeId);
222
- } else {
227
+ const nodeId = editorService.get<MNode | null>('node')?.id || props.defaultSelected;
228
+ let node;
229
+ if (nodeId) {
230
+ node = editorService.getNodeById(nodeId);
231
+ }
232
+
233
+ if (node && node !== value) {
234
+ editorService.select(node.id);
235
+ } else if (value?.items?.length) {
236
+ editorService.select(value.items[0]);
237
+ } else if (value?.id) {
223
238
  editorService.set('nodes', [value]);
239
+ editorService.set('parent', null);
240
+ editorService.set('page', null);
224
241
  }
225
242
 
226
- emit('update:modelValue', toRaw(editorService.get('root')));
243
+ if (toRaw(value) !== toRaw(editorService.get('root'))) {
244
+ emit('update:modelValue', value);
245
+ }
227
246
  });
228
247
 
229
248
  // 初始值变化,重新设置节点信息
@@ -297,13 +316,12 @@ export default defineComponent({
297
316
  );
298
317
 
299
318
  onUnmounted(() => {
300
- editorService.destroy();
301
- historyService.destroy();
302
- propsService.destroy();
303
- uiService.destroy();
304
- componentListService.destroy();
305
- storageService.destroy();
306
- codeBlockService.destroy();
319
+ editorService.resetState();
320
+ historyService.resetState();
321
+ propsService.resetState();
322
+ uiService.resetState();
323
+ componentListService.resetState();
324
+ codeBlockService.resetState();
307
325
  });
308
326
 
309
327
  const services: Services = {
@@ -319,8 +337,7 @@ export default defineComponent({
319
337
 
320
338
  provide('services', services);
321
339
 
322
- provide('layerContentMenu', props.layerContentMenu);
323
- provide('stageContentMenu', props.stageContentMenu);
340
+ provide('codeOptions', props.codeOptions);
324
341
  provide(
325
342
  'stageOptions',
326
343
  reactive({
@@ -0,0 +1,145 @@
1
+ <template>
2
+ <div class="m-editor-wrapper" :class="isFullScreen ? 'fullScreen' : 'normal'">
3
+ <magic-code-editor
4
+ ref="codeEditor"
5
+ class="m-editor-container"
6
+ :init-values="`${codeContent}`"
7
+ @save="saveCodeDraft"
8
+ :language="language"
9
+ :options="codeOptions"
10
+ ></magic-code-editor>
11
+ <div class="m-editor-content-bottom" v-if="editable">
12
+ <TMagicButton type="primary" class="button" @click="toggleFullScreen">
13
+ {{ isFullScreen ? '退出全屏' : '全屏' }}</TMagicButton
14
+ >
15
+ <TMagicButton type="primary" class="button" @click="saveCode">保存</TMagicButton>
16
+ <TMagicButton type="primary" class="button" @click="close">关闭</TMagicButton>
17
+ </div>
18
+ <div class="m-editor-content-bottom" v-else>
19
+ <TMagicButton type="primary" class="button" @click="toggleFullScreen">
20
+ {{ isFullScreen ? '退出全屏' : '全屏' }}</TMagicButton
21
+ >
22
+ <TMagicButton type="primary" class="button" @click="close">关闭</TMagicButton>
23
+ </div>
24
+ </div>
25
+ </template>
26
+ <script lang="ts" setup name="MEditorCodeDraftEditor">
27
+ import { computed, inject, ref, watchEffect } from 'vue';
28
+ import type * as monaco from 'monaco-editor';
29
+
30
+ import { TMagicButton, tMagicMessage, tMagicMessageBox } from '@tmagic/design';
31
+ import { Id } from '@tmagic/schema';
32
+ import { datetimeFormatter } from '@tmagic/utils';
33
+
34
+ import MagicCodeEditor from '../layouts/CodeEditor.vue';
35
+ import type { Services } from '../type';
36
+
37
+ const props = withDefaults(
38
+ defineProps<{
39
+ /** 代码id */
40
+ id: Id;
41
+ /** 代码内容 */
42
+ content: string;
43
+ /** 是否可编辑 */
44
+ editable?: boolean;
45
+ /** 是否自动保存草稿 */
46
+ autoSaveDraft?: boolean;
47
+ /** 编辑器参数 */
48
+ codeOptions?: Object;
49
+ /** 编辑器语言 */
50
+ language?: string;
51
+ }>(),
52
+ {
53
+ editable: true,
54
+ autoSaveDraft: true,
55
+ },
56
+ );
57
+ const emit = defineEmits(['save', 'close', 'saveAndClose']);
58
+
59
+ const services = inject<Services>('services');
60
+
61
+ const codeContent = ref<string>('');
62
+ const editorContent = ref<string>('');
63
+ const codeEditor = ref<InstanceType<typeof MagicCodeEditor>>();
64
+ // 原始代码内容
65
+ const originCodeContent = ref<string>('');
66
+ const isFullScreen = ref<boolean>(false);
67
+
68
+ const codeOptions = computed(() => ({
69
+ ...props.codeOptions,
70
+ readOnly: !props.editable,
71
+ }));
72
+
73
+ watchEffect(() => {
74
+ codeContent.value = props.content;
75
+ if (!originCodeContent.value) {
76
+ // 暂存原始的代码内容
77
+ originCodeContent.value = codeContent.value;
78
+ }
79
+ // 有草稿时展示上次保存的草稿内容
80
+ const codeDraft = services?.codeBlockService.getCodeDraft(props.id);
81
+ if (codeDraft) {
82
+ codeContent.value = codeDraft;
83
+ }
84
+ });
85
+
86
+ // 保存草稿
87
+ const saveCodeDraft = async (codeValue: string) => {
88
+ if (!props.autoSaveDraft) return;
89
+ if (originCodeContent.value === codeValue) {
90
+ // 没修改或改回原样 有草稿的话删除草稿
91
+ services?.codeBlockService.removeCodeDraft(props.id);
92
+ return;
93
+ }
94
+ services?.codeBlockService.setCodeDraft(props.id, codeValue);
95
+ tMagicMessage.success(`代码草稿保存成功 ${datetimeFormatter(new Date())}`);
96
+ };
97
+
98
+ // 保存代码
99
+ const saveCode = (): void => {
100
+ if (!codeEditor.value || !props.editable) return;
101
+ // 代码内容
102
+ editorContent.value = (codeEditor.value.getEditor() as monaco.editor.IStandaloneCodeEditor)?.getValue();
103
+ emit('save', editorContent.value);
104
+ };
105
+
106
+ // 保存并关闭
107
+ const saveAndClose = (): void => {
108
+ if (!codeEditor.value || !props.editable) return;
109
+ // 代码内容
110
+ editorContent.value = (codeEditor.value.getEditor() as monaco.editor.IStandaloneCodeEditor)?.getValue();
111
+ emit('saveAndClose', editorContent.value);
112
+ };
113
+
114
+ // 关闭弹窗
115
+ const close = async (): Promise<void> => {
116
+ const codeDraft = services?.codeBlockService.getCodeDraft(props.id);
117
+ if (codeDraft) {
118
+ tMagicMessageBox
119
+ .confirm('您有代码修改未保存,是否保存后再关闭?', '提示', {
120
+ confirmButtonText: '确认',
121
+ cancelButtonText: '取消',
122
+ type: 'warning',
123
+ })
124
+ .then(async () => {
125
+ // 保存之后再关闭
126
+ saveAndClose();
127
+ })
128
+ .catch(() => {
129
+ // 删除草稿 直接关闭
130
+ services?.codeBlockService.removeCodeDraft(props.id);
131
+ emit('close');
132
+ });
133
+ } else {
134
+ emit('close');
135
+ }
136
+ };
137
+
138
+ // 切换全屏
139
+ const toggleFullScreen = (): void => {
140
+ isFullScreen.value = !isFullScreen.value;
141
+ if (codeEditor.value) {
142
+ codeEditor.value.focus();
143
+ }
144
+ };
145
+ </script>
@@ -1,14 +1,14 @@
1
1
  <template>
2
- <div v-if="menuData.length && visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
2
+ <div v-if="menuData.length" v-show="visible" class="magic-editor-content-menu" ref="menu" :style="menuStyle">
3
3
  <div>
4
- <tool-button
4
+ <ToolButton
5
5
  v-for="(item, index) in menuData"
6
6
  event-type="mouseup"
7
7
  :data="item"
8
8
  :key="index"
9
9
  @mouseup="hide"
10
10
  @mouseenter="showSubMenu(item)"
11
- ></tool-button>
11
+ ></ToolButton>
12
12
  </div>
13
13
  <teleport to="body">
14
14
  <content-menu
@@ -22,7 +22,7 @@
22
22
  </div>
23
23
  </template>
24
24
 
25
- <script lang="ts" setup>
25
+ <script lang="ts" setup name="MEditorContentMenu">
26
26
  import { nextTick, onMounted, onUnmounted, ref } from 'vue';
27
27
 
28
28
  import { MenuButton, MenuComponent } from '../type';
@@ -0,0 +1,145 @@
1
+ <template>
2
+ <TMagicCard shadow="never">
3
+ <template #header>
4
+ <div class="code-name-wrapper">
5
+ <div class="code-name-label">代码块名称</div>
6
+ <TMagicInput class="code-name-input" v-model="codeName" :disabled="!editable" />
7
+ </div>
8
+ <div class="code-name-wrapper">
9
+ <div class="code-name-label">参数定义</div>
10
+ <m-form-table
11
+ style="width: 320px"
12
+ :config="tableConfig"
13
+ :model="tableModel"
14
+ :enableToggleMode="false"
15
+ name="params"
16
+ prop="params"
17
+ size="small"
18
+ >
19
+ </m-form-table>
20
+ </div>
21
+ </template>
22
+ <CodeDraftEditor
23
+ :id="id"
24
+ :content="codeContent"
25
+ :editable="editable"
26
+ :autoSaveDraft="autoSaveDraft"
27
+ :codeOptions="codeOptions"
28
+ language="javascript"
29
+ @save="saveCode"
30
+ @saveAndClose="saveAndClose"
31
+ @close="close"
32
+ ></CodeDraftEditor>
33
+ </TMagicCard>
34
+ </template>
35
+ <script lang="ts" setup name="MEditorFunctionEditor">
36
+ import { inject, provide, ref, watchEffect } from 'vue';
37
+
38
+ import { TMagicCard, TMagicInput, tMagicMessage } from '@tmagic/design';
39
+ import { CodeParam, Id } from '@tmagic/schema';
40
+
41
+ import type { Services } from '../type';
42
+
43
+ import CodeDraftEditor from './CodeDraftEditor.vue';
44
+
45
+ const tableConfig = {
46
+ border: true,
47
+ enableFullscreen: false,
48
+ name: 'params',
49
+ maxHeight: '150px',
50
+ items: [
51
+ {
52
+ type: 'text',
53
+ label: '参数名',
54
+ name: 'name',
55
+ },
56
+ ],
57
+ };
58
+
59
+ const props = withDefaults(
60
+ defineProps<{
61
+ id: Id;
62
+ name: string;
63
+ content: string;
64
+ editable?: boolean;
65
+ autoSaveDraft?: boolean;
66
+ codeOptions?: object;
67
+ }>(),
68
+ {
69
+ editable: true,
70
+ autoSaveDraft: true,
71
+ },
72
+ );
73
+
74
+ const emit = defineEmits(['change', 'field-input']);
75
+
76
+ const services = inject<Services>('services');
77
+
78
+ const codeName = ref<string>('');
79
+ const codeContent = ref<string>('');
80
+ const evalRes = ref(true);
81
+
82
+ provide('mForm', {
83
+ $emit: emit,
84
+ setField: () => {},
85
+ });
86
+
87
+ const tableModel = ref<{ params: CodeParam[] }>();
88
+ watchEffect(() => {
89
+ codeName.value = props.name;
90
+ codeContent.value = props.content;
91
+ });
92
+
93
+ const initTableModel = (): void => {
94
+ const codeDsl = services?.codeBlockService.getCodeDslSync();
95
+ if (!codeDsl) return;
96
+ tableModel.value = {
97
+ params: codeDsl[props.id]?.params || [],
98
+ };
99
+ };
100
+
101
+ initTableModel();
102
+
103
+ // 保存前钩子
104
+ const beforeSave = (codeValue: string): boolean => {
105
+ try {
106
+ // eval检测js代码是否存在语法错误
107
+ // eslint-disable-next-line no-eval
108
+ eval(codeValue);
109
+ return true;
110
+ } catch (e: any) {
111
+ tMagicMessage.error(e.stack);
112
+ return false;
113
+ }
114
+ };
115
+
116
+ // 保存代码
117
+ const saveCode = async (codeValue: string): Promise<void> => {
118
+ if (!props.editable) return;
119
+ evalRes.value = beforeSave(codeValue);
120
+ if (evalRes.value) {
121
+ // 存入dsl
122
+ await services?.codeBlockService.setCodeDslById(props.id, {
123
+ name: codeName.value,
124
+ content: codeValue,
125
+ params: tableModel.value?.params || [],
126
+ });
127
+ tMagicMessage.success('代码保存成功');
128
+ // 删除草稿
129
+ services?.codeBlockService.removeCodeDraft(props.id);
130
+ }
131
+ };
132
+
133
+ // 保存并关闭
134
+ const saveAndClose = async (codeValue: string): Promise<void> => {
135
+ await saveCode(codeValue);
136
+ if (evalRes.value) {
137
+ close();
138
+ }
139
+ };
140
+
141
+ // 关闭弹窗
142
+ const close = (): void => {
143
+ services?.codeBlockService.setCodeEditorShowStatus(false);
144
+ };
145
+ </script>
@@ -1,16 +1,18 @@
1
1
  <template>
2
- <el-icon v-if="!icon" class="magic-editor-icon"><Edit></Edit></el-icon>
3
- <el-icon v-else-if="typeof icon === 'string' && icon.startsWith('http')" class="magic-editor-icon"
2
+ <TMagicIcon v-if="!icon" class="magic-editor-icon"><Edit></Edit></TMagicIcon>
3
+ <TMagicIcon v-else-if="typeof icon === 'string' && icon.startsWith('http')" class="magic-editor-icon"
4
4
  ><img :src="icon"
5
- /></el-icon>
5
+ /></TMagicIcon>
6
6
  <i v-else-if="typeof icon === 'string'" class="magic-editor-icon" :class="icon"></i>
7
- <el-icon v-else class="magic-editor-icon"><component :is="toRaw(icon)"></component></el-icon>
7
+ <TMagicIcon v-else class="magic-editor-icon"><component :is="toRaw(icon)"></component></TMagicIcon>
8
8
  </template>
9
9
 
10
- <script lang="ts" setup>
10
+ <script lang="ts" setup name="MEditorIcon">
11
11
  import { toRaw } from 'vue';
12
12
  import { Edit } from '@element-plus/icons-vue';
13
13
 
14
+ import { TMagicIcon } from '@tmagic/design';
15
+
14
16
  defineProps<{
15
17
  icon?: any;
16
18
  }>();