@tmagic/editor 1.2.0-beta.9 → 1.2.1

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 (103) hide show
  1. package/dist/style.css +62 -34
  2. package/dist/{tmagic-editor.mjs → tmagic-editor.js} +1641 -1266
  3. package/dist/tmagic-editor.js.map +1 -0
  4. package/dist/{tmagic-editor.umd.js → tmagic-editor.umd.cjs} +1649 -1270
  5. package/dist/tmagic-editor.umd.cjs.map +1 -0
  6. package/package.json +16 -14
  7. package/src/Editor.vue +66 -40
  8. package/src/components/CodeDraftEditor.vue +137 -0
  9. package/src/components/ContentMenu.vue +1 -1
  10. package/src/components/FunctionEditor.vue +190 -0
  11. package/src/components/Icon.vue +1 -1
  12. package/src/{layouts → components}/Layout.vue +54 -15
  13. package/src/components/ScrollBar.vue +1 -1
  14. package/src/components/ScrollViewer.vue +10 -1
  15. package/src/components/ToolButton.vue +1 -1
  16. package/src/fields/Code.vue +1 -1
  17. package/src/fields/CodeLink.vue +1 -1
  18. package/src/fields/CodeSelect.vue +102 -99
  19. package/src/fields/UISelect.vue +3 -3
  20. package/src/index.ts +2 -1
  21. package/src/layouts/AddPageBox.vue +5 -2
  22. package/src/layouts/CodeEditor.vue +2 -3
  23. package/src/layouts/Framework.vue +12 -10
  24. package/src/layouts/NavMenu.vue +11 -8
  25. package/src/layouts/PropsPanel.vue +12 -9
  26. package/src/layouts/Resizer.vue +1 -1
  27. package/src/layouts/sidebar/ComponentListPanel.vue +2 -3
  28. package/src/layouts/sidebar/LayerMenu.vue +9 -7
  29. package/src/layouts/sidebar/LayerPanel.vue +130 -178
  30. package/src/layouts/sidebar/Sidebar.vue +110 -26
  31. package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +33 -118
  32. package/src/layouts/sidebar/code-block/CodeBlockList.vue +93 -126
  33. package/src/layouts/workspace/Breadcrumb.vue +6 -7
  34. package/src/layouts/workspace/PageBar.vue +3 -3
  35. package/src/layouts/workspace/PageBarScrollContainer.vue +5 -3
  36. package/src/layouts/workspace/Stage.vue +36 -18
  37. package/src/layouts/workspace/ViewerMenu.vue +16 -15
  38. package/src/layouts/workspace/Workspace.vue +9 -6
  39. package/src/services/BaseService.ts +11 -2
  40. package/src/services/codeBlock.ts +136 -146
  41. package/src/services/componentList.ts +7 -2
  42. package/src/services/editor.ts +161 -85
  43. package/src/services/events.ts +7 -2
  44. package/src/services/history.ts +8 -17
  45. package/src/services/props.ts +8 -3
  46. package/src/services/storage.ts +1 -0
  47. package/src/services/ui.ts +20 -10
  48. package/src/theme/code-block.scss +46 -23
  49. package/src/theme/component-list-panel.scss +8 -5
  50. package/src/type.ts +84 -63
  51. package/src/utils/config.ts +1 -1
  52. package/src/utils/editor.ts +17 -3
  53. package/src/utils/index.ts +2 -1
  54. package/src/utils/logger.ts +1 -1
  55. package/src/utils/operator.ts +12 -12
  56. package/src/utils/props.ts +3 -3
  57. package/src/utils/scroll-viewer.ts +18 -2
  58. package/src/utils/stage.ts +10 -9
  59. package/src/utils/undo-redo.ts +1 -1
  60. package/types/Editor.vue.d.ts +48 -28
  61. package/types/components/CodeDraftEditor.vue.d.ts +55 -0
  62. package/types/components/ContentMenu.vue.d.ts +11 -87
  63. package/types/components/FunctionEditor.vue.d.ts +60 -0
  64. package/types/components/Icon.vue.d.ts +4 -50
  65. package/types/{layouts → components}/Layout.vue.d.ts +12 -1
  66. package/types/components/ScrollBar.vue.d.ts +7 -65
  67. package/types/components/ScrollViewer.vue.d.ts +45 -1
  68. package/types/components/ToolButton.vue.d.ts +12 -78
  69. package/types/fields/Code.vue.d.ts +11 -77
  70. package/types/fields/CodeLink.vue.d.ts +12 -82
  71. package/types/fields/CodeSelect.vue.d.ts +13 -77
  72. package/types/fields/UISelect.vue.d.ts +7 -65
  73. package/types/index.d.ts +1 -0
  74. package/types/layouts/AddPageBox.vue.d.ts +1 -43
  75. package/types/layouts/CodeEditor.vue.d.ts +22 -130
  76. package/types/layouts/NavMenu.vue.d.ts +9 -69
  77. package/types/layouts/sidebar/LayerMenu.vue.d.ts +16 -48
  78. package/types/layouts/sidebar/LayerPanel.vue.d.ts +24 -7
  79. package/types/layouts/sidebar/Sidebar.vue.d.ts +10 -5
  80. package/types/layouts/sidebar/code-block/CodeBlockEditor.vue.d.ts +24 -6
  81. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +11 -5
  82. package/types/layouts/workspace/Breadcrumb.vue.d.ts +1 -43
  83. package/types/layouts/workspace/Stage.vue.d.ts +15 -43
  84. package/types/layouts/workspace/ViewerMenu.vue.d.ts +11 -66
  85. package/types/layouts/workspace/Workspace.vue.d.ts +25 -8
  86. package/types/services/BaseService.d.ts +2 -1
  87. package/types/services/codeBlock.d.ts +56 -47
  88. package/types/services/componentList.d.ts +1 -0
  89. package/types/services/editor.d.ts +10 -11
  90. package/types/services/events.d.ts +1 -0
  91. package/types/services/history.d.ts +5 -15
  92. package/types/services/props.d.ts +3 -2
  93. package/types/services/ui.d.ts +24 -24
  94. package/types/type.d.ts +70 -59
  95. package/types/utils/editor.d.ts +1 -0
  96. package/types/utils/index.d.ts +1 -0
  97. package/types/utils/operator.d.ts +1 -1
  98. package/types/utils/props.d.ts +1 -1
  99. package/types/utils/scroll-viewer.d.ts +5 -0
  100. package/dist/tmagic-editor.mjs.map +0 -1
  101. package/dist/tmagic-editor.umd.js.map +0 -1
  102. package/src/layouts/sidebar/TabPane.vue +0 -118
  103. package/types/layouts/sidebar/TabPane.vue.d.ts +0 -82
@@ -6,58 +6,142 @@
6
6
  type="card"
7
7
  tab-position="left"
8
8
  >
9
- <tab-pane v-for="(item, index) in data.items" :key="index" :data="item">
10
- <template #layer-panel-header v-if="item === 'layer'">
11
- <slot name="layer-panel-header"></slot>
9
+ <component :is="uiComponent.component" v-for="(config, index) in sideBarItems" :key="index" :name="config.text">
10
+ <template #label>
11
+ <div :key="config.text">
12
+ <MIcon v-if="config.icon" :icon="config.icon"></MIcon>
13
+ <div v-if="config.text" class="magic-editor-tab-panel-title">{{ config.text }}</div>
14
+ </div>
12
15
  </template>
13
16
 
14
- <template #layer-node-content="{ node, data }" v-if="item === 'layer'">
15
- <slot name="layer-node-content" :data="data" :node="node"></slot>
16
- </template>
17
+ <component v-if="config" :is="config.component" v-bind="config.props || {}" v-on="config?.listeners || {}">
18
+ <template
19
+ #component-list-panel-header
20
+ v-if="config.$key === 'component-list' || config.slots?.componentListPanelHeader"
21
+ >
22
+ <slot v-if="config.$key === 'component-list'" name="component-list-panel-header"></slot>
23
+ <component v-else-if="config.slots?.componentListPanelHeader" :is="config.slots.componentListPanelHeader" />
24
+ </template>
17
25
 
18
- <template #component-list-panel-header v-if="item === 'component-list'">
19
- <slot name="component-list-panel-header"></slot>
20
- </template>
26
+ <template
27
+ #component-list-item="{ component }"
28
+ v-if="config.$key === 'component-list' || config.slots?.componentListItem"
29
+ >
30
+ <slot v-if="config.$key === 'component-list'" name="component-list-item" :component="component"></slot>
31
+ <component
32
+ v-else-if="config.slots?.componentListItem"
33
+ :is="config.slots.componentListItem"
34
+ :component="component"
35
+ />
36
+ </template>
21
37
 
22
- <template #component-list-item="{ component }" v-if="item === 'component-list'">
23
- <slot name="component-list-item" :component="component"></slot>
24
- </template>
38
+ <template #layer-panel-header v-if="config.$key === 'layer' || config.slots?.layerPanelHeader">
39
+ <slot v-if="config.$key === 'layer'" name="layer-panel-header"></slot>
40
+ <component v-else-if="config.slots?.layerPanelHeader" :is="config.slots.layerPanelHeader" />
41
+ </template>
25
42
 
26
- <template #code-block-panel-header v-if="item === 'code-block'">
27
- <slot name="code-block-panel-header"></slot>
28
- </template>
43
+ <template #code-block-panel-header v-if="config.$key === 'code-block' || config.slots?.codeBlockPanelHeader">
44
+ <slot v-if="config.$key === 'code-block'" name="code-block-panel-header"></slot>
45
+ <component v-else-if="config.slots?.codeBlockPanelHeader" :is="config.slots.codeBlockPanelHeader" />
46
+ </template>
29
47
 
30
- <template #code-block-panel-tool="{ id, data }" v-if="item === 'code-block'">
31
- <slot name="code-block-panel-tool" :id="id" :data="data"></slot>
32
- </template>
48
+ <template
49
+ #code-block-panel-tool="{ id, data }"
50
+ v-if="config.$key === 'code-block' || config.slots?.codeBlockPanelTool"
51
+ >
52
+ <slot v-if="config.$key === 'code-block'" name="code-block-panel-tool" :id="id" :data="data"></slot>
53
+ <component v-else-if="config.slots?.codeBlockPanelTool" :is="config.slots.codeBlockPanelTool" />
54
+ </template>
33
55
 
34
- <template #code-block-edit-panel-header="{ id }" v-if="item === 'code-block'">
35
- <slot name="code-block-edit-panel-header" :id="id"></slot>
36
- </template>
37
- </tab-pane>
56
+ <template
57
+ #code-block-edit-panel-header="{ id }"
58
+ v-if="config.$key === 'code-block' || config.slots?.codeBlockEditPanelHeader"
59
+ >
60
+ <slot v-if="config.$key === 'code-block'" name="code-block-edit-panel-header" :id="id"></slot>
61
+ <component v-else-if="config.slots?.codeBlockEditPanelHeader" :is="config.slots.codeBlockEditPanelHeader" />
62
+ </template>
63
+
64
+ <template
65
+ #layer-node-content="{ data: nodeData, node }"
66
+ v-if="config.$key === 'layer' || config.slots?.layerNodeContent"
67
+ >
68
+ <slot v-if="config.$key === 'layer'" name="layer-node-content" :data="nodeData" :node="node"></slot>
69
+ <component
70
+ v-else-if="config.slots?.layerNodeContent"
71
+ :is="config.slots.layerNodeContent"
72
+ :data="nodeData"
73
+ :node="node"
74
+ />
75
+ </template>
76
+ </component>
77
+ </component>
38
78
  </TMagicTabs>
39
79
  </template>
40
80
 
41
- <script lang="ts" setup>
42
- import { ref, watch } from 'vue';
81
+ <script lang="ts" setup name="MEditorSidebar">
82
+ import { computed, ref, watch } from 'vue';
83
+ import { Coin, EditPen, Files } from '@element-plus/icons-vue';
43
84
 
44
- import { TMagicTabs } from '@tmagic/design';
85
+ import { getConfig, TMagicTabs } from '@tmagic/design';
45
86
 
87
+ import MIcon from '../../components/Icon.vue';
88
+ import type { MenuButton, MenuComponent, SideComponent, SideItem } from '../../type';
46
89
  import { SideBarData } from '../../type';
47
90
 
48
- import TabPane from './TabPane.vue';
91
+ import CodeBlockList from './code-block/CodeBlockList.vue';
92
+ import ComponentListPanel from './ComponentListPanel.vue';
93
+ import LayerPanel from './LayerPanel.vue';
49
94
 
50
95
  const props = withDefaults(
51
96
  defineProps<{
52
97
  data?: SideBarData;
98
+ layerContentMenu: (MenuButton | MenuComponent)[];
53
99
  }>(),
54
100
  {
55
101
  data: () => ({ type: 'tabs', status: '组件', items: ['component-list', 'layer', 'code-block'] }),
56
102
  },
57
103
  );
58
104
 
105
+ const uiComponent = getConfig('components').tabPane;
106
+
59
107
  const activeTabName = ref(props.data?.status);
60
108
 
109
+ const getItemConfig = (data: SideItem): SideComponent => {
110
+ const map: Record<string, SideComponent> = {
111
+ 'component-list': {
112
+ $key: 'component-list',
113
+ type: 'component',
114
+ icon: Coin,
115
+ text: '组件',
116
+ component: ComponentListPanel,
117
+ slots: {},
118
+ },
119
+ layer: {
120
+ $key: 'layer',
121
+ type: 'component',
122
+ icon: Files,
123
+ text: '已选组件',
124
+ props: {
125
+ layerContentMenu: props.layerContentMenu,
126
+ },
127
+ component: LayerPanel,
128
+ slots: {},
129
+ },
130
+ 'code-block': {
131
+ $key: 'code-block',
132
+ type: 'component',
133
+ icon: EditPen,
134
+ text: '代码编辑',
135
+ component: CodeBlockList,
136
+ slots: {},
137
+ },
138
+ };
139
+
140
+ return typeof data === 'string' ? map[data] : data;
141
+ };
142
+
143
+ const sideBarItems = computed(() => props.data.items.map((item) => getItemConfig(item)));
144
+
61
145
  watch(
62
146
  () => props.data.status,
63
147
  (status) => {
@@ -1,101 +1,54 @@
1
1
  <template>
2
2
  <TMagicDialog
3
- v-model="isShowCodeBlockEditor"
3
+ :model-value="true"
4
4
  class="code-editor-dialog"
5
5
  :title="currentTitle"
6
6
  :fullscreen="true"
7
- :before-close="saveAndClose"
7
+ :close-on-press-escape="false"
8
8
  :append-to-body="true"
9
+ :show-close="false"
9
10
  >
10
- <layout v-model:left="left" :min-left="45" class="code-editor-layout">
11
- <!-- 左侧列表 -->
12
- <template #left v-if="mode === CodeEditorMode.LIST">
13
- <TMagicTree
14
- v-if="!isEmpty(state.codeList)"
15
- class="side-tree"
16
- node-key="id"
17
- empty-text="暂无代码块"
18
- :data="state.codeList"
19
- :highlight-current="true"
20
- :current-node-key="state.codeList[0].id"
21
- @node-click="selectHandler"
22
- >
23
- <template #default="{ data }">
24
- <div :id="data.id" class="list-container">
25
- <div class="list-item">
26
- <div class="code-name">{{ data.name }}({{ data.id }})</div>
27
- </div>
28
- </div>
29
- </template>
30
- </TMagicTree>
31
- </template>
11
+ <Layout v-model:left="left" :min-left="45" class="code-editor-layout">
32
12
  <!-- 右侧区域 -->
33
13
  <template #center>
34
- <div
35
- v-if="!isEmpty(codeConfig)"
36
- :class="[
37
- mode === CodeEditorMode.LIST
38
- ? 'm-editor-code-block-editor-panel-list-mode'
39
- : 'm-editor-code-block-editor-panel',
40
- ]"
41
- >
14
+ <div v-if="!isEmpty(codeConfig)" class="m-editor-code-block-editor-panel">
42
15
  <slot name="code-block-edit-panel-header" :id="id"></slot>
43
- <TMagicCard shadow="never">
44
- <template #header>
45
- <div class="code-name-wrapper">
46
- <div class="code-name-label">代码块名称</div>
47
- <TMagicInput
48
- v-if="codeConfig"
49
- class="code-name-input"
50
- v-model="codeConfig.name"
51
- :disabled="!editable"
52
- />
53
- </div>
54
- </template>
55
- <div class="m-editor-wrapper">
56
- <magic-code-editor
57
- v-if="codeConfig"
58
- ref="codeEditor"
59
- class="m-editor-container"
60
- :init-values="`${codeConfig.content}`"
61
- @save="saveCode"
62
- :options="{
63
- tabSize: 2,
64
- fontSize: 16,
65
- formatOnPaste: true,
66
- readOnly: !editable,
67
- }"
68
- ></magic-code-editor>
69
- <div class="m-editor-content-bottom" v-if="editable">
70
- <TMagicButton type="primary" class="button" @click="saveCode">保存</TMagicButton>
71
- <TMagicButton type="primary" class="button" @click="saveAndClose">关闭</TMagicButton>
72
- </div>
73
- <div class="m-editor-content-bottom" v-else>
74
- <TMagicButton type="primary" class="button" @click="saveAndClose">关闭</TMagicButton>
75
- </div>
76
- </div>
77
- </TMagicCard>
16
+ <FunctionEditor
17
+ v-if="codeConfig"
18
+ :id="id"
19
+ :name="codeConfig.name"
20
+ :content="codeConfig.content"
21
+ :paramsColConfig="paramsColConfig"
22
+ :editable="!!editable"
23
+ :autoSaveDraft="true"
24
+ :codeOptions="codeOptions"
25
+ ></FunctionEditor>
78
26
  </div>
79
27
  </template>
80
- </layout>
28
+ </Layout>
81
29
  </TMagicDialog>
82
30
  </template>
83
31
 
84
- <script lang="ts" setup>
32
+ <script lang="ts" setup name="MEditorCodeBlockEditor">
85
33
  import { computed, inject, reactive, ref, watchEffect } from 'vue';
86
- import { forIn, isEmpty } from 'lodash-es';
87
- import type * as monaco from 'monaco-editor';
34
+ import { cloneDeep, forIn, isEmpty } from 'lodash-es';
88
35
 
89
- import { TMagicButton, TMagicCard, TMagicDialog, TMagicInput, tMagicMessage, TMagicTree } from '@tmagic/design';
36
+ import { TMagicDialog } from '@tmagic/design';
37
+ import { ColumnConfig } from '@tmagic/form';
38
+ import { CodeBlockContent } from '@tmagic/schema';
90
39
 
91
- import type { CodeBlockContent, CodeDslList, ListState, Services } from '../../../type';
92
- import { CodeEditorMode } from '../../../type';
93
- import MagicCodeEditor from '../../CodeEditor.vue';
94
- import Layout from '../../Layout.vue';
40
+ import FunctionEditor from '../../../components/FunctionEditor.vue';
41
+ import Layout from '../../../components/Layout.vue';
42
+ import type { ListState, Services } from '../../../type';
43
+ import { serializeConfig } from '../../../utils/editor';
95
44
 
96
45
  const services = inject<Services>('services');
46
+ const codeOptions = inject('codeOptions', {});
47
+
48
+ defineProps<{
49
+ paramsColConfig?: ColumnConfig;
50
+ }>();
97
51
 
98
- const codeEditor = ref<InstanceType<typeof MagicCodeEditor>>();
99
52
  const left = ref(200);
100
53
  const currentTitle = ref('');
101
54
  // 编辑器当前需展示的代码块内容
@@ -105,18 +58,15 @@ const state = reactive<ListState>({
105
58
  codeList: [],
106
59
  });
107
60
 
108
- // 是否展示代码编辑区
109
- const isShowCodeBlockEditor = computed(
110
- () => (codeConfig.value && services?.codeBlockService.getCodeEditorShowStatus()) || false,
111
- );
112
- const mode = computed(() => services?.codeBlockService.getMode());
113
61
  const id = computed(() => services?.codeBlockService.getId() || '');
114
62
  const editable = computed(() => services?.codeBlockService.getEditStatus());
115
63
  // 当前选中组件绑定的代码块id数组
116
64
  const selectedIds = computed(() => services?.codeBlockService.getCombineIds() || []);
117
65
 
118
66
  watchEffect(async () => {
119
- codeConfig.value = (await services?.codeBlockService.getCodeContentById(id.value)) || null;
67
+ codeConfig.value = cloneDeep(await services?.codeBlockService.getCodeContentById(id.value)) || null;
68
+ if (!codeConfig.value) return;
69
+ codeConfig.value.content = serializeConfig(codeConfig.value.content);
120
70
  });
121
71
 
122
72
  watchEffect(async () => {
@@ -131,39 +81,4 @@ watchEffect(async () => {
131
81
  });
132
82
  currentTitle.value = state.codeList[0]?.name || '';
133
83
  });
134
-
135
- // 保存代码
136
- const saveCode = async (): Promise<boolean> => {
137
- if (!codeEditor.value || !codeConfig.value || !editable.value) return true;
138
-
139
- try {
140
- // 代码内容
141
- const codeContent = (codeEditor.value.getEditor() as monaco.editor.IStandaloneCodeEditor)?.getValue();
142
- /* eslint no-eval: "off" */
143
- codeConfig.value.content = eval(codeContent);
144
- } catch (e: any) {
145
- tMagicMessage.error(e.stack);
146
- return false;
147
- }
148
- // 存入dsl
149
- await services?.codeBlockService.setCodeDslById(id.value, {
150
- name: codeConfig.value.name,
151
- content: codeConfig.value.content,
152
- });
153
- tMagicMessage.success('代码保存成功');
154
- return true;
155
- };
156
-
157
- // 保存并关闭
158
- const saveAndClose = async () => {
159
- const saveRes = await saveCode();
160
- if (saveRes) {
161
- await services?.codeBlockService.setCodeEditorShowStatus(false);
162
- }
163
- };
164
-
165
- const selectHandler = (data: CodeDslList) => {
166
- services?.codeBlockService.setId(data.id);
167
- currentTitle.value = data.name;
168
- };
169
84
  </script>