@tmagic/editor 1.3.0-alpha.8 → 1.3.0-beta.0

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 (124) hide show
  1. package/dist/style.css +82 -218
  2. package/dist/tmagic-editor.js +4985 -3999
  3. package/dist/tmagic-editor.js.map +1 -1
  4. package/dist/tmagic-editor.umd.cjs +5013 -4012
  5. package/dist/tmagic-editor.umd.cjs.map +1 -1
  6. package/package.json +15 -15
  7. package/src/Editor.vue +4 -5
  8. package/src/components/CodeBlockEditor.vue +257 -0
  9. package/src/components/CodeParams.vue +60 -0
  10. package/src/components/ContentMenu.vue +11 -3
  11. package/src/editorProps.ts +30 -5
  12. package/src/fields/Code.vue +23 -19
  13. package/src/fields/CodeLink.vue +6 -7
  14. package/src/fields/CodeSelect.vue +12 -9
  15. package/src/fields/CodeSelectCol.vue +70 -81
  16. package/src/fields/DataSourceFieldSelect.vue +47 -0
  17. package/src/fields/DataSourceFields.vue +28 -22
  18. package/src/fields/DataSourceInput.vue +21 -58
  19. package/src/fields/DataSourceMethodSelect.vue +136 -0
  20. package/src/fields/DataSourceMethods.vue +103 -0
  21. package/src/fields/DataSourceSelect.vue +68 -0
  22. package/src/fields/EventSelect.vue +53 -19
  23. package/src/fields/KeyValue.vue +9 -11
  24. package/src/fields/UISelect.vue +54 -14
  25. package/src/hooks/index.ts +21 -0
  26. package/src/hooks/use-code-block-edit.ts +84 -0
  27. package/src/hooks/use-data-source-method.ts +100 -0
  28. package/src/{utils/stage.ts → hooks/use-stage.ts} +4 -7
  29. package/src/icons/CenterIcon.vue +13 -0
  30. package/src/icons/CodeIcon.vue +0 -2
  31. package/src/icons/FolderMinusIcon.vue +22 -0
  32. package/src/index.ts +15 -0
  33. package/src/initService.ts +73 -16
  34. package/src/layouts/CodeEditor.vue +62 -10
  35. package/src/layouts/Framework.vue +7 -3
  36. package/src/layouts/PropsPanel.vue +8 -3
  37. package/src/layouts/sidebar/ComponentListPanel.vue +6 -9
  38. package/src/layouts/sidebar/LayerMenu.vue +20 -21
  39. package/src/layouts/sidebar/LayerNode.vue +40 -0
  40. package/src/layouts/sidebar/LayerPanel.vue +14 -5
  41. package/src/layouts/sidebar/Sidebar.vue +22 -36
  42. package/src/layouts/sidebar/code-block/CodeBlockList.vue +81 -119
  43. package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +64 -0
  44. package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +27 -47
  45. package/src/layouts/sidebar/data-source/DataSourceList.vue +145 -0
  46. package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +58 -69
  47. package/src/layouts/workspace/Stage.vue +13 -5
  48. package/src/layouts/workspace/ViewerMenu.vue +10 -35
  49. package/src/services/codeBlock.ts +18 -71
  50. package/src/services/dataSource.ts +16 -1
  51. package/src/services/dep.ts +23 -20
  52. package/src/services/editor.ts +46 -18
  53. package/src/services/props.ts +2 -2
  54. package/src/theme/code-block.scss +5 -117
  55. package/src/theme/code-editor.scss +27 -2
  56. package/src/theme/content-menu.scss +1 -1
  57. package/src/theme/data-source-methods.scss +13 -0
  58. package/src/theme/data-source.scss +11 -0
  59. package/src/theme/event.scss +15 -12
  60. package/src/theme/framework.scss +0 -3
  61. package/src/theme/layer-panel.scss +6 -0
  62. package/src/theme/layout.scss +4 -0
  63. package/src/theme/sidebar.scss +18 -60
  64. package/src/theme/theme.scss +1 -0
  65. package/src/type.ts +47 -7
  66. package/src/utils/content-menu.ts +92 -0
  67. package/src/utils/data-source/formConfigs/base.ts +28 -30
  68. package/src/utils/data-source/index.ts +65 -2
  69. package/src/utils/dep.ts +39 -7
  70. package/src/utils/index.ts +1 -1
  71. package/src/utils/props.ts +298 -189
  72. package/src/utils/undo-redo.ts +1 -1
  73. package/types/Editor.vue.d.ts +30 -6
  74. package/types/components/CodeBlockEditor.vue.d.ts +23 -0
  75. package/types/components/CodeParams.vue.d.ts +26 -0
  76. package/types/components/ContentMenu.vue.d.ts +2 -2
  77. package/types/components/ToolButton.vue.d.ts +3 -3
  78. package/types/editorProps.d.ts +19 -5
  79. package/types/fields/Code.vue.d.ts +24 -19
  80. package/types/fields/CodeLink.vue.d.ts +12 -21
  81. package/types/fields/CodeSelect.vue.d.ts +6 -17
  82. package/types/fields/CodeSelectCol.vue.d.ts +10 -14
  83. package/types/fields/DataSourceFieldSelect.vue.d.ts +29 -0
  84. package/types/fields/DataSourceFields.vue.d.ts +7 -18
  85. package/types/fields/DataSourceInput.vue.d.ts +10 -30
  86. package/types/fields/DataSourceMethodSelect.vue.d.ts +29 -0
  87. package/types/fields/DataSourceMethods.vue.d.ts +32 -0
  88. package/types/fields/DataSourceSelect.vue.d.ts +40 -0
  89. package/types/fields/EventSelect.vue.d.ts +2 -13
  90. package/types/fields/KeyValue.vue.d.ts +9 -24
  91. package/types/fields/UISelect.vue.d.ts +2 -11
  92. package/types/hooks/index.d.ts +3 -0
  93. package/types/{components/FunctionEditor.vue.d.ts → hooks/use-code-block-edit.d.ts} +31 -119
  94. package/types/hooks/use-data-source-method.d.ts +123 -0
  95. package/types/icons/CenterIcon.vue.d.ts +2 -0
  96. package/types/icons/FolderMinusIcon.vue.d.ts +2 -0
  97. package/types/index.d.ts +7 -0
  98. package/types/initService.d.ts +2 -2
  99. package/types/layouts/CodeEditor.vue.d.ts +10 -4
  100. package/types/layouts/PropsPanel.vue.d.ts +274 -2
  101. package/types/layouts/sidebar/LayerNode.vue.d.ts +16 -0
  102. package/types/layouts/sidebar/Sidebar.vue.d.ts +0 -3
  103. package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +4 -9
  104. package/types/layouts/sidebar/code-block/{CodeBlockEditor.vue.d.ts → CodeBlockListPanel.vue.d.ts} +9 -5
  105. package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -1
  106. package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +14 -0
  107. package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +1 -11
  108. package/types/services/codeBlock.d.ts +6 -37
  109. package/types/services/dataSource.d.ts +7 -1
  110. package/types/services/dep.d.ts +12 -21
  111. package/types/services/editor.d.ts +1 -1
  112. package/types/services/props.d.ts +10 -115
  113. package/types/type.d.ts +42 -7
  114. package/types/utils/content-menu.d.ts +7 -0
  115. package/types/utils/data-source/formConfigs/base.d.ts +1 -2
  116. package/types/utils/data-source/index.d.ts +5 -0
  117. package/types/utils/dep.d.ts +4 -2
  118. package/types/utils/index.d.ts +1 -1
  119. package/types/utils/props.d.ts +13 -102
  120. package/src/components/CodeDraftEditor.vue +0 -148
  121. package/src/components/FunctionEditor.vue +0 -197
  122. package/src/layouts/sidebar/code-block/CodeBlockEditor.vue +0 -100
  123. package/types/components/CodeDraftEditor.vue.d.ts +0 -61
  124. /package/types/{utils/stage.d.ts → hooks/use-stage.d.ts} +0 -0
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <div>
3
+ {{ `${data.name} (${data.id})` }}
4
+ </div>
5
+ <div class="layer-node-tool">
6
+ <template v-if="data.type !== 'page'">
7
+ <el-icon v-if="data.visible === false" @click.stop="setNodeVisible(true)" title="点击显示">
8
+ <Hide />
9
+ </el-icon>
10
+ <el-icon v-else @click.stop="setNodeVisible(false)" class="node-lock" title="点击隐藏">
11
+ <View />
12
+ </el-icon>
13
+ </template>
14
+ </div>
15
+ </template>
16
+
17
+ <script lang="ts" setup>
18
+ import { inject } from 'vue';
19
+ import { Hide, View } from '@element-plus/icons-vue';
20
+
21
+ import { MNode } from '@tmagic/schema';
22
+
23
+ import { Services } from '@editor/type';
24
+
25
+ const props = defineProps<{
26
+ data: MNode;
27
+ }>();
28
+
29
+ const services = inject<Services>('services');
30
+ const editorService = services?.editorService;
31
+
32
+ const setNodeVisible = (visible: boolean) => {
33
+ if (!editorService) return;
34
+
35
+ editorService.update({
36
+ id: props.data.id,
37
+ visible,
38
+ });
39
+ };
40
+ </script>
@@ -35,16 +35,14 @@
35
35
  <template #default="{ node, data }">
36
36
  <div class="cus-tree-node" :id="data.id" @mouseenter="highlightHandler(data)">
37
37
  <slot name="layer-node-content" :node="node" :data="data">
38
- <span>
39
- {{ `${data.name} (${data.id})` }}
40
- </span>
38
+ <LayerNode :data="data"></LayerNode>
41
39
  </slot>
42
40
  </div>
43
41
  </template>
44
42
  </TMagicTree>
45
43
 
46
44
  <Teleport to="body">
47
- <LayerMenu ref="menu" :layer-content-menu="layerContentMenu"></LayerMenu>
45
+ <LayerMenu ref="menu" :layer-content-menu="layerContentMenu" @collapse-all="collapseAllHandler"></LayerMenu>
48
46
  </Teleport>
49
47
  </TMagicScrollbar>
50
48
  </template>
@@ -63,6 +61,7 @@ import type { MenuButton, MenuComponent, Services } from '@editor/type';
63
61
  import { Layout } from '@editor/type';
64
62
 
65
63
  import LayerMenu from './LayerMenu.vue';
64
+ import LayerNode from './LayerNode.vue';
66
65
 
67
66
  defineOptions({
68
67
  name: 'MEditorLayerPanel',
@@ -157,7 +156,7 @@ const handleDragEnd = async (e: any) => {
157
156
  if (!tree.value) return;
158
157
  const { data: node } = e;
159
158
  const parent = editorService?.getParentById(node.id, false) as MContainer;
160
- const layout = await editorService?.getLayout(parent);
159
+ const layout = await editorService?.getLayout(parent, node);
161
160
  node.style.position = layout;
162
161
  if (layout === Layout.RELATIVE) {
163
162
  node.style.top = 0;
@@ -357,4 +356,14 @@ const contextmenu = async (event: MouseEvent, data: MNode): Promise<void> => {
357
356
 
358
357
  menu.value?.show(event);
359
358
  };
359
+
360
+ const collapseAllHandler = () => {
361
+ const page = editorService?.get('page');
362
+ if (!tree.value || !page) return;
363
+ const rootNode = tree.value.getNode(page.id);
364
+ rootNode.childNodes.forEach((node: any) => {
365
+ node.collapse();
366
+ handleCollapse(node.data);
367
+ });
368
+ };
360
369
  </script>
@@ -1,24 +1,23 @@
1
1
  <template>
2
- <component
3
- v-if="data.type === 'tabs' && data.items.length"
4
- v-model="activeTabName"
5
- class="m-editor-sidebar tmagic-design-tabs"
6
- v-bind="tabsComponent?.props({ type: 'card', tabPosition: 'left' }) || {}"
7
- :is="tabsComponent?.component || 'el-tabs'"
8
- >
9
- <component
2
+ <div class="m-editor-sidebar" v-if="data.type === 'tabs' && data.items.length">
3
+ <div class="m-editor-sidebar-header">
4
+ <div
5
+ class="m-editor-sidebar-header-item"
6
+ v-for="(config, index) in sideBarItems"
7
+ :key="config.$key ?? index"
8
+ :class="{ 'is-active': activeTabName === config.text }"
9
+ @click="activeTabName = config.text || `${index}`"
10
+ >
11
+ <MIcon v-if="config.icon" :icon="config.icon"></MIcon>
12
+ <div v-if="config.text" class="magic-editor-tab-panel-title">{{ config.text }}</div>
13
+ </div>
14
+ </div>
15
+ <div
16
+ class="m-editor-sidebar-content"
10
17
  v-for="(config, index) in sideBarItems"
11
- v-bind="tabPaneComponent?.props({ name: config.text, lazy: config.lazy }) || {}"
12
- :is="tabPaneComponent?.component || 'el-tab-pane'"
13
- :key="config.$key || index"
18
+ :key="config.$key ?? index"
19
+ v-show="activeTabName === config.text"
14
20
  >
15
- <template #label>
16
- <div :key="config.text">
17
- <MIcon v-if="config.icon" :icon="config.icon"></MIcon>
18
- <div v-if="config.text" class="magic-editor-tab-panel-title">{{ config.text }}</div>
19
- </div>
20
- </template>
21
-
22
21
  <component v-if="config" :is="config.component" v-bind="config.props || {}" v-on="config?.listeners || {}">
23
22
  <template
24
23
  #component-list-panel-header
@@ -58,14 +57,6 @@
58
57
  <component v-else-if="config.slots?.codeBlockPanelTool" :is="config.slots.codeBlockPanelTool" />
59
58
  </template>
60
59
 
61
- <template
62
- #code-block-edit-panel-header="{ id }"
63
- v-if="config.$key === 'code-block' || config.slots?.codeBlockEditPanelHeader"
64
- >
65
- <slot v-if="config.$key === 'code-block'" name="code-block-edit-panel-header" :id="id"></slot>
66
- <component v-else-if="config.slots?.codeBlockEditPanelHeader" :is="config.slots.codeBlockEditPanelHeader" />
67
- </template>
68
-
69
60
  <template
70
61
  #layer-node-content="{ data: nodeData, node }"
71
62
  v-if="config.$key === 'layer' || config.slots?.layerNodeContent"
@@ -79,21 +70,19 @@
79
70
  />
80
71
  </template>
81
72
  </component>
82
- </component>
83
- </component>
73
+ </div>
74
+ </div>
84
75
  </template>
85
76
 
86
- <script lang="ts" setup>
77
+ <script setup lang="ts">
87
78
  import { computed, ref, watch } from 'vue';
88
79
  import { Coin, EditPen, Goods, List } from '@element-plus/icons-vue';
89
80
 
90
- import { getConfig } from '@tmagic/design';
91
-
92
81
  import MIcon from '@editor/components/Icon.vue';
93
82
  import type { MenuButton, MenuComponent, SideComponent, SideItem } from '@editor/type';
94
83
  import { SideBarData } from '@editor/type';
95
84
 
96
- import CodeBlockList from './code-block/CodeBlockList.vue';
85
+ import CodeBlockListPanel from './code-block/CodeBlockListPanel.vue';
97
86
  import DataSourceListPanel from './data-source/DataSourceListPanel.vue';
98
87
  import ComponentListPanel from './ComponentListPanel.vue';
99
88
  import LayerPanel from './LayerPanel.vue';
@@ -112,9 +101,6 @@ const props = withDefaults(
112
101
  },
113
102
  );
114
103
 
115
- const tabPaneComponent = getConfig('components')?.tabPane;
116
- const tabsComponent = getConfig('components')?.tabs;
117
-
118
104
  const activeTabName = ref(props.data?.status);
119
105
 
120
106
  const getItemConfig = (data: SideItem): SideComponent => {
@@ -143,7 +129,7 @@ const getItemConfig = (data: SideItem): SideComponent => {
143
129
  type: 'component',
144
130
  icon: EditPen,
145
131
  text: '代码编辑',
146
- component: CodeBlockList,
132
+ component: CodeBlockListPanel,
147
133
  slots: {},
148
134
  },
149
135
  'data-source': {
@@ -1,75 +1,56 @@
1
1
  <template>
2
- <TMagicScrollbar class="m-editor-code-block-list m-editor-dep-list-panel">
3
- <slot name="code-block-panel-header">
4
- <div class="search-wrapper">
5
- <SearchInput @search="filterTextChangeHandler"></SearchInput>
6
- <TMagicButton class="create-code-button" type="primary" size="small" @click="createCodeBlock" v-if="editable"
7
- >新增</TMagicButton
8
- >
9
- </div>
10
- </slot>
11
-
12
- <!-- 代码块列表 -->
13
- <TMagicTree
14
- ref="tree"
15
- class="magic-editor-layer-tree"
16
- node-key="id"
17
- empty-text="暂无代码块"
18
- :default-expanded-keys="expandedKeys"
19
- :expand-on-click-node="false"
20
- :data="codeList"
21
- :props="treeProps"
22
- :highlight-current="true"
23
- :filter-node-method="filterNode"
24
- @node-click="clickHandler"
25
- >
26
- <template #default="{ data }">
27
- <div :id="data.id" class="list-container">
28
- <div class="list-item">
29
- <CodeIcon v-if="data.type === 'code'" class="codeIcon"></CodeIcon>
30
- <AppManageIcon v-if="data.type === 'node'" class="compIcon"></AppManageIcon>
31
- <span class="name" :class="{ code: data.type === 'code', hook: data.type === 'key' }"
32
- >{{ data.name }} ({{ data.id }})</span
33
- >
34
- <!-- 右侧工具栏 -->
35
- <div class="right-tool" v-if="data.type === 'code'">
36
- <TMagicTooltip effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
37
- <Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editCode(`${data.id}`)"></Icon>
38
- </TMagicTooltip>
39
- <TMagicTooltip effect="dark" content="删除" placement="bottom" v-if="editable">
40
- <Icon :icon="Close" class="edit-icon" @click.stop="deleteCode(`${data.id}`)"></Icon>
41
- </TMagicTooltip>
42
- <slot name="code-block-panel-tool" :id="data.id" :data="data.codeBlockContent"></slot>
43
- </div>
2
+ <TMagicTree
3
+ ref="tree"
4
+ class="magic-editor-layer-tree"
5
+ node-key="id"
6
+ empty-text="暂无代码块"
7
+ :default-expanded-keys="expandedKeys"
8
+ :expand-on-click-node="false"
9
+ :data="codeList"
10
+ :props="{
11
+ children: 'children',
12
+ label: 'name',
13
+ value: 'id',
14
+ }"
15
+ :highlight-current="true"
16
+ :filter-node-method="filterNode"
17
+ @node-click="clickHandler"
18
+ >
19
+ <template #default="{ data }">
20
+ <div :id="data.id" class="list-container">
21
+ <div class="list-item">
22
+ <CodeIcon v-if="data.type === 'code'" class="codeIcon"></CodeIcon>
23
+ <AppManageIcon v-if="data.type === 'node'" class="compIcon"></AppManageIcon>
24
+ <span class="name" :class="{ code: data.type === 'code', hook: data.type === 'key' }"
25
+ >{{ data.name }} ({{ data.id }})</span
26
+ >
27
+ <!-- 右侧工具栏 -->
28
+ <div class="right-tool" v-if="data.type === 'code'">
29
+ <TMagicTooltip effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
30
+ <Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editCode(data.id)"></Icon>
31
+ </TMagicTooltip>
32
+ <TMagicTooltip v-if="editable" effect="dark" content="删除" placement="bottom">
33
+ <Icon :icon="Close" class="edit-icon" @click.stop="deleteCode(`${data.id}`)"></Icon>
34
+ </TMagicTooltip>
35
+ <slot name="code-block-panel-tool" :id="data.id" :data="data.codeBlockContent"></slot>
44
36
  </div>
45
37
  </div>
46
- </template>
47
- </TMagicTree>
48
-
49
- <!-- 代码块编辑区 -->
50
- <CodeBlockEditor v-if="isShowCodeBlockEditor" :paramsColConfig="paramsColConfig">
51
- <template #code-block-edit-panel-header="{ id }">
52
- <slot name="code-block-edit-panel-header" :id="id"></slot>
53
- </template>
54
- </CodeBlockEditor>
55
- </TMagicScrollbar>
38
+ </div>
39
+ </template>
40
+ </TMagicTree>
56
41
  </template>
57
42
 
58
- <script setup lang="ts">
43
+ <script lang="ts" setup>
59
44
  import { computed, inject, ref } from 'vue';
60
45
  import { Close, Edit, View } from '@element-plus/icons-vue';
61
46
 
62
- import { TMagicButton, tMagicMessage, TMagicScrollbar, TMagicTooltip, TMagicTree } from '@tmagic/design';
63
- import { ColumnConfig } from '@tmagic/form';
64
- import { CodeBlockContent, Id } from '@tmagic/schema';
47
+ import { tMagicMessage, tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
48
+ import type { Id } from '@tmagic/schema';
65
49
 
66
50
  import Icon from '@editor/components/Icon.vue';
67
- import SearchInput from '@editor/components/SearchInput.vue';
68
51
  import AppManageIcon from '@editor/icons/AppManageIcon.vue';
69
52
  import CodeIcon from '@editor/icons/CodeIcon.vue';
70
- import { CodeDeleteErrorType, CodeDslItem, Services } from '@editor/type';
71
-
72
- import CodeBlockEditor from './CodeBlockEditor.vue';
53
+ import { CodeDeleteErrorType, CodeDslItem, DepTargetType, Services } from '@editor/type';
73
54
 
74
55
  defineOptions({
75
56
  name: 'MEditorCodeBlockList',
@@ -77,20 +58,18 @@ defineOptions({
77
58
 
78
59
  const props = defineProps<{
79
60
  customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
80
- paramsColConfig?: ColumnConfig;
81
61
  }>();
82
62
 
83
- const treeProps = {
84
- children: 'children',
85
- label: 'name',
86
- value: 'id',
87
- };
63
+ const emit = defineEmits<{
64
+ edit: [id: string];
65
+ remove: [id: string];
66
+ }>();
88
67
 
89
68
  const { codeBlockService, depService, editorService } = inject<Services>('services') || {};
90
69
 
91
70
  // 代码块列表
92
71
  const codeList = computed(() =>
93
- Object.values(depService?.targets['code-block'] || {}).map((target) => {
72
+ Object.values(depService?.getTargets(DepTargetType.CODE_BLOCK) || {}).map((target) => {
94
73
  // 组件节点
95
74
  const compNodes = Object.entries(target.deps).map(([id, dep]) => ({
96
75
  name: dep.name,
@@ -107,58 +86,10 @@ const codeList = computed(() =>
107
86
  };
108
87
  }),
109
88
  );
110
-
111
89
  // 默认展开组件层级的节点
112
90
  const expandedKeys = computed(() => codeList.value.map((item) => item.id));
113
-
114
91
  const editable = computed(() => codeBlockService?.getEditStatus());
115
92
 
116
- // 是否展示代码编辑区
117
- const isShowCodeBlockEditor = computed(() => codeBlockService?.getCodeEditorShowStatus() || false);
118
-
119
- // 新增代码块
120
- const createCodeBlock = async () => {
121
- if (!codeBlockService) {
122
- tMagicMessage.error('新增代码块失败');
123
- return;
124
- }
125
-
126
- const codeConfig: CodeBlockContent = {
127
- name: '代码块',
128
- content: `({app, params}) => {\n // place your code here\n}`,
129
- params: [],
130
- };
131
-
132
- const id = await codeBlockService.getUniqueId();
133
-
134
- await codeBlockService.setCodeDslById(id, codeConfig);
135
- codeBlockService.setCodeEditorContent(true, id);
136
- };
137
-
138
- // 编辑代码块
139
- const editCode = async (key: Id) => {
140
- codeBlockService?.setCodeEditorContent(true, key);
141
- };
142
-
143
- // 删除代码块
144
- const deleteCode = (key: Id) => {
145
- const currentCode = codeList.value.find((codeItem) => codeItem.id === key);
146
- const existBinds = Boolean(currentCode?.children.length);
147
- const undeleteableList = codeBlockService?.getUndeletableList() || [];
148
- if (!existBinds && !undeleteableList.includes(key)) {
149
- // 无绑定关系,且不在不可删除列表中
150
- codeBlockService?.deleteCodeDslByIds([key]);
151
- } else {
152
- if (typeof props.customError === 'function') {
153
- props.customError(key, existBinds ? CodeDeleteErrorType.BIND : CodeDeleteErrorType.UNDELETEABLE);
154
- } else {
155
- tMagicMessage.error('代码块删除失败');
156
- }
157
- }
158
- };
159
-
160
- const tree = ref<InstanceType<typeof TMagicTree>>();
161
-
162
93
  const filterNode = (value: string, data: CodeDslItem): boolean => {
163
94
  if (!value) {
164
95
  return true;
@@ -166,10 +97,6 @@ const filterNode = (value: string, data: CodeDslItem): boolean => {
166
97
  return `${data.name}${data.id}`.toLocaleLowerCase().indexOf(value.toLocaleLowerCase()) !== -1;
167
98
  };
168
99
 
169
- const filterTextChangeHandler = (val: string) => {
170
- tree.value?.filter(val);
171
- };
172
-
173
100
  // 选中组件
174
101
  const selectComp = (compId: Id) => {
175
102
  const stage = editorService?.get('stage');
@@ -184,4 +111,39 @@ const clickHandler = (data: any, node: any) => {
184
111
  selectComp(node.parent.data.id);
185
112
  }
186
113
  };
114
+
115
+ // 编辑代码块
116
+ const editCode = (id: string) => {
117
+ emit('edit', id);
118
+ };
119
+
120
+ const deleteCode = async (id: string) => {
121
+ const currentCode = codeList.value.find((codeItem) => codeItem.id === id);
122
+ const existBinds = Boolean(currentCode?.children.length);
123
+ const undeleteableList = codeBlockService?.getUndeletableList() || [];
124
+ if (!existBinds && !undeleteableList.includes(id)) {
125
+ await tMagicMessageBox.confirm('确定删除该代码块吗?', '提示', {
126
+ confirmButtonText: '确定',
127
+ cancelButtonText: '取消',
128
+ type: 'warning',
129
+ });
130
+
131
+ // 无绑定关系,且不在不可删除列表中
132
+ emit('remove', id);
133
+ } else {
134
+ if (typeof props.customError === 'function') {
135
+ props.customError(id, existBinds ? CodeDeleteErrorType.BIND : CodeDeleteErrorType.UNDELETEABLE);
136
+ } else {
137
+ tMagicMessage.error('代码块删除失败');
138
+ }
139
+ }
140
+ };
141
+
142
+ const tree = ref<InstanceType<typeof TMagicTree>>();
143
+
144
+ defineExpose({
145
+ filter(val: string) {
146
+ tree.value?.filter(val);
147
+ },
148
+ });
187
149
  </script>
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <TMagicScrollbar class="m-editor-code-block-list m-editor-dep-list-panel">
3
+ <slot name="code-block-panel-header">
4
+ <div class="search-wrapper">
5
+ <SearchInput @search="filterTextChangeHandler"></SearchInput>
6
+ <TMagicButton v-if="editable" class="create-code-button" type="primary" size="small" @click="createCodeBlock"
7
+ >新增</TMagicButton
8
+ >
9
+ <slot name="code-block-panel-search"></slot>
10
+ </div>
11
+ </slot>
12
+
13
+ <!-- 代码块列表 -->
14
+ <CodeBlockList ref="codeBlockList" :custom-error="customError" @edit="editCode" @remove="deleteCode">
15
+ <template #code-block-panel-tool="{ id, data }">
16
+ <slot name="code-block-panel-tool" :id="id" :data="data"></slot>
17
+ </template>
18
+ </CodeBlockList>
19
+
20
+ <!-- 代码块编辑区 -->
21
+ <CodeBlockEditor
22
+ v-if="codeConfig"
23
+ ref="codeBlockEditor"
24
+ :disabled="!editable"
25
+ :content="codeConfig"
26
+ @submit="submitCodeBlockHandler"
27
+ ></CodeBlockEditor>
28
+ </TMagicScrollbar>
29
+ </template>
30
+
31
+ <script setup lang="ts">
32
+ import { computed, inject, ref } from 'vue';
33
+
34
+ import { TMagicButton, TMagicScrollbar } from '@tmagic/design';
35
+ import type { Id } from '@tmagic/schema';
36
+
37
+ import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
38
+ import SearchInput from '@editor/components/SearchInput.vue';
39
+ import { useCodeBlockEdit } from '@editor/hooks/use-code-block-edit';
40
+ import type { CodeDeleteErrorType, Services } from '@editor/type';
41
+
42
+ import CodeBlockList from './CodeBlockList.vue';
43
+
44
+ defineOptions({
45
+ name: 'MEditorCodeBlockListPanel',
46
+ });
47
+
48
+ defineProps<{
49
+ customError?: (id: Id, errorType: CodeDeleteErrorType) => any;
50
+ }>();
51
+
52
+ const { codeBlockService } = inject<Services>('services') || {};
53
+
54
+ const editable = computed(() => codeBlockService?.getEditStatus());
55
+
56
+ const { codeBlockEditor, codeConfig, editCode, deleteCode, createCodeBlock, submitCodeBlockHandler } =
57
+ useCodeBlockEdit(codeBlockService);
58
+
59
+ const codeBlockList = ref<InstanceType<typeof CodeBlockList>>();
60
+
61
+ const filterTextChangeHandler = (val: string) => {
62
+ codeBlockList.value?.filter(val);
63
+ };
64
+ </script>
@@ -1,29 +1,24 @@
1
1
  <template>
2
- <TMagicDrawer
3
- v-model="visible"
2
+ <MFormDrawer
3
+ ref="fomDrawer"
4
+ label-width="80px"
5
+ :close-on-press-escape="false"
4
6
  :title="title"
5
- :close-on-press-escape="true"
6
- :append-to-body="true"
7
- :show-close="true"
8
- :close-on-click-modal="true"
9
- :size="size"
10
- >
11
- <MForm ref="form" :config="dataSourceConfig" :init-values="initValues" @change="changeHandler"></MForm>
12
-
13
- <template #footer>
14
- <div>
15
- <TMagicButton type="primary" @click="submitHandler">确定</TMagicButton>
16
- <TMagicButton @click="hide">关闭</TMagicButton>
17
- </div>
18
- </template>
19
- </TMagicDrawer>
7
+ :width="size"
8
+ :config="dataSourceConfig"
9
+ :values="initValues"
10
+ :disabled="disabled"
11
+ @submit="submitHandler"
12
+ @error="errorHandler"
13
+ ></MFormDrawer>
20
14
  </template>
21
15
 
22
16
  <script setup lang="ts">
23
17
  import { computed, inject, ref, watchEffect } from 'vue';
24
18
 
25
- import { TMagicButton, TMagicDrawer, tMagicMessage } from '@tmagic/design';
26
- import { MForm } from '@tmagic/form';
19
+ import { tMagicMessage } from '@tmagic/design';
20
+ import { FormConfig, MFormDrawer } from '@tmagic/form';
21
+ import { DataSourceSchema } from '@tmagic/schema';
27
22
 
28
23
  import type { Services } from '@editor/type';
29
24
 
@@ -34,55 +29,40 @@ defineOptions({
34
29
  const props = defineProps<{
35
30
  title?: string;
36
31
  values: any;
32
+ disabled: boolean;
37
33
  }>();
38
34
 
39
- const type = ref('base');
40
-
41
35
  const emit = defineEmits(['submit']);
42
36
 
43
37
  const services = inject<Services>('services');
44
38
 
45
39
  const size = computed(() => globalThis.document.body.clientWidth - (services?.uiService.get('columnWidth').left || 0));
46
40
 
47
- const dataSourceConfig = computed(() => services?.dataSourceService.getFormConfig(type.value) || []);
41
+ const fomDrawer = ref<InstanceType<typeof MFormDrawer>>();
48
42
 
49
- const form = ref<InstanceType<typeof MForm>>();
50
-
51
- const initValues = ref({});
43
+ const initValues = ref<Partial<DataSourceSchema>>({});
44
+ const dataSourceConfig = ref<FormConfig>([]);
52
45
 
53
46
  watchEffect(() => {
54
47
  initValues.value = props.values;
55
- type.value = props.values.type || 'base';
48
+ dataSourceConfig.value = services?.dataSourceService.getFormConfig(initValues.value.type) || [];
56
49
  });
57
50
 
58
- const changeHandler = (value: Record<string, any>) => {
59
- if (value.type === type.value) {
60
- return;
61
- }
62
- type.value = value.type || 'base';
63
- initValues.value = value;
51
+ const submitHandler = (values: any) => {
52
+ emit('submit', values);
64
53
  };
65
54
 
66
- const submitHandler = async () => {
67
- try {
68
- const values = await form.value?.submitForm();
69
- emit('submit', values);
70
- } catch (error: any) {
71
- tMagicMessage.error(error.message);
72
- }
73
- };
74
-
75
- const visible = ref(false);
76
-
77
- const hide = () => {
78
- visible.value = false;
55
+ const errorHandler = (error: any) => {
56
+ tMagicMessage.error(error.message);
79
57
  };
80
58
 
81
59
  defineExpose({
82
60
  show() {
83
- visible.value = true;
61
+ fomDrawer.value?.show();
84
62
  },
85
63
 
86
- hide,
64
+ hide() {
65
+ fomDrawer.value?.hide();
66
+ },
87
67
  });
88
68
  </script>