@tmagic/editor 1.3.5 → 1.3.7
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/LICENSE +5432 -0
- package/dist/style.css +88 -62
- package/dist/tmagic-editor.js +2448 -2016
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +2453 -2019
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +23 -23
- package/src/Editor.vue +15 -7
- package/src/components/CodeBlockEditor.vue +2 -2
- package/src/components/ContentMenu.vue +5 -5
- package/src/components/FloatingBox.vue +117 -0
- package/src/components/ScrollBar.vue +2 -2
- package/src/components/ScrollViewer.vue +2 -2
- package/src/components/SplitView.vue +2 -2
- package/src/components/Tree.vue +5 -0
- package/src/components/TreeNode.vue +10 -4
- package/src/editorProps.ts +20 -3
- package/src/fields/PageFragmentSelect.vue +55 -0
- package/src/hooks/use-filter.ts +55 -0
- package/src/hooks/use-getso.ts +2 -2
- package/src/hooks/use-node-status.ts +48 -0
- package/src/hooks/use-stage.ts +19 -1
- package/src/index.ts +3 -0
- package/src/initService.ts +43 -17
- package/src/layouts/AddPageBox.vue +16 -4
- package/src/layouts/CodeEditor.vue +2 -2
- package/src/layouts/Framework.vue +17 -3
- package/src/layouts/PropsPanel.vue +2 -2
- package/src/layouts/page-bar/AddButton.vue +48 -0
- package/src/layouts/page-bar/PageBar.vue +158 -0
- package/src/layouts/{workspace → page-bar}/PageBarScrollContainer.vue +61 -35
- package/src/layouts/page-bar/SwitchTypeButton.vue +45 -0
- package/src/layouts/sidebar/Sidebar.vue +9 -2
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +55 -65
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +2 -1
- package/src/layouts/sidebar/data-source/DataSourceList.vue +63 -59
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +1 -1
- package/src/layouts/sidebar/layer/LayerMenu.vue +39 -27
- package/src/layouts/sidebar/layer/LayerPanel.vue +31 -8
- package/src/layouts/sidebar/layer/use-click.ts +5 -3
- package/src/layouts/sidebar/layer/use-keybinding.ts +8 -8
- package/src/layouts/sidebar/layer/use-node-status.ts +10 -13
- package/src/layouts/workspace/Workspace.vue +6 -7
- package/src/layouts/workspace/viewer/NodeListMenu.vue +68 -129
- package/src/layouts/workspace/viewer/Stage.vue +14 -6
- package/src/layouts/workspace/viewer/ViewerMenu.vue +94 -86
- package/src/services/BaseService.ts +63 -26
- package/src/services/codeBlock.ts +7 -1
- package/src/services/dep.ts +12 -8
- package/src/services/editor.ts +131 -64
- package/src/services/history.ts +6 -2
- package/src/services/keybinding.ts +48 -13
- package/src/services/props.ts +70 -12
- package/src/services/storage.ts +23 -13
- package/src/services/ui.ts +4 -1
- package/src/theme/code-block.scss +0 -16
- package/src/theme/floating-box.scss +30 -0
- package/src/theme/layer-panel.scss +19 -0
- package/src/theme/page-bar.scss +18 -1
- package/src/theme/stage.scss +24 -0
- package/src/theme/theme.scss +1 -1
- package/src/theme/tree.scss +12 -1
- package/src/type.ts +28 -10
- package/src/utils/compose.ts +25 -6
- package/src/utils/content-menu.ts +6 -7
- package/src/utils/editor.ts +34 -18
- package/src/utils/operator.ts +5 -6
- package/types/components/CodeBlockEditor.vue.d.ts +6 -2
- package/types/components/CodeParams.vue.d.ts +3 -1
- package/types/components/ContentMenu.vue.d.ts +13 -5
- package/types/components/FloatingBox.vue.d.ts +78 -0
- package/types/components/Resizer.vue.d.ts +6 -1
- package/types/components/ScrollBar.vue.d.ts +3 -1
- package/types/components/ScrollViewer.vue.d.ts +3 -3
- package/types/components/SearchInput.vue.d.ts +3 -1
- package/types/components/SplitView.vue.d.ts +8 -4
- package/types/components/ToolButton.vue.d.ts +3 -3
- package/types/components/Tree.vue.d.ts +27 -8
- package/types/components/TreeNode.vue.d.ts +24 -7
- package/types/editorProps.d.ts +16 -1
- package/types/fields/Code.vue.d.ts +6 -2
- package/types/fields/CodeLink.vue.d.ts +5 -3
- package/types/fields/CodeSelect.vue.d.ts +3 -1
- package/types/fields/CodeSelectCol.vue.d.ts +3 -1
- package/types/fields/DataSourceFieldSelect.vue.d.ts +3 -1
- package/types/fields/DataSourceFields.vue.d.ts +5 -3
- package/types/fields/DataSourceInput.vue.d.ts +8 -4
- package/types/fields/DataSourceMethodSelect.vue.d.ts +3 -1
- package/types/fields/DataSourceMethods.vue.d.ts +5 -3
- package/types/fields/DataSourceMocks.vue.d.ts +5 -3
- package/types/fields/DataSourceSelect.vue.d.ts +5 -3
- package/types/fields/EventSelect.vue.d.ts +3 -1
- package/types/fields/KeyValue.vue.d.ts +2 -2
- package/types/fields/PageFragmentSelect.vue.d.ts +31 -0
- package/types/fields/UISelect.vue.d.ts +3 -1
- package/types/hooks/use-code-block-edit.d.ts +14 -5
- package/types/hooks/use-data-source-method.d.ts +14 -5
- package/types/hooks/use-filter.d.ts +7 -0
- package/types/hooks/use-node-status.d.ts +6 -0
- package/types/index.d.ts +1 -0
- package/types/layouts/AddPageBox.vue.d.ts +14 -1
- package/types/layouts/CodeEditor.vue.d.ts +4 -1
- package/types/layouts/Framework.vue.d.ts +14 -1
- package/types/layouts/PropsPanel.vue.d.ts +19 -13
- package/types/layouts/{workspace/viewer/NodeListMenuTitle.vue.d.ts → page-bar/AddButton.vue.d.ts} +3 -2
- package/types/layouts/page-bar/PageBar.vue.d.ts +28 -0
- package/types/layouts/page-bar/PageBarScrollContainer.vue.d.ts +24 -0
- package/types/layouts/page-bar/SwitchTypeButton.vue.d.ts +20 -0
- package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
- package/types/layouts/sidebar/Sidebar.vue.d.ts +7 -5
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +9 -3
- package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +1 -1
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -1
- package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +8 -2
- package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +1 -1
- package/types/layouts/sidebar/layer/LayerMenu.vue.d.ts +26 -3
- package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +3 -1
- package/types/layouts/sidebar/layer/use-click.d.ts +37 -6
- package/types/layouts/sidebar/layer/use-keybinding.d.ts +1 -1
- package/types/layouts/sidebar/layer/use-node-status.d.ts +3 -4
- package/types/layouts/workspace/Workspace.vue.d.ts +3 -1
- package/types/layouts/workspace/viewer/NodeListMenu.vue.d.ts +1 -14
- package/types/layouts/workspace/viewer/Stage.vue.d.ts +2 -0
- package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +9 -1
- package/types/services/BaseService.d.ts +4 -1
- package/types/services/dataSource.d.ts +1 -0
- package/types/services/dep.d.ts +6 -5
- package/types/services/editor.d.ts +12 -5
- package/types/services/history.d.ts +3 -2
- package/types/services/keybinding.d.ts +21 -1
- package/types/services/props.d.ts +25 -1
- package/types/services/storage.d.ts +7 -7
- package/types/type.d.ts +32 -17
- package/types/utils/compose.d.ts +1 -1
- package/types/utils/editor.d.ts +14 -8
- package/src/layouts/sidebar/layer/use-filter.ts +0 -59
- package/src/layouts/workspace/PageBar.vue +0 -87
- package/src/layouts/workspace/viewer/NodeListMenuTitle.vue +0 -68
- package/src/theme/dep-list.scss +0 -59
- package/types/layouts/sidebar/layer/use-filter.d.ts +0 -7
- package/types/layouts/workspace/PageBar.vue.d.ts +0 -15
- package/types/layouts/workspace/PageBarScrollContainer.vue.d.ts +0 -9
package/src/hooks/use-stage.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed } from 'vue';
|
|
1
|
+
import { computed, watch } from 'vue';
|
|
2
2
|
|
|
3
3
|
import type { MNode } from '@tmagic/schema';
|
|
4
4
|
import StageCore, { GuidesType, RemoveEventData, SortEventData, UpdateEventData } from '@tmagic/stage';
|
|
@@ -31,6 +31,7 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
31
31
|
containerHighlightDuration: stageOptions.containerHighlightDuration,
|
|
32
32
|
containerHighlightType: stageOptions.containerHighlightType,
|
|
33
33
|
disabledDragStart: stageOptions.disabledDragStart,
|
|
34
|
+
renderType: stageOptions.renderType,
|
|
34
35
|
canSelect: (el, event, stop) => {
|
|
35
36
|
const elCanSelect = stageOptions.canSelect(el);
|
|
36
37
|
// 在组件联动过程中不能再往下选择,返回并触发 ui-select
|
|
@@ -43,13 +44,30 @@ export const useStage = (stageOptions: StageOptions) => {
|
|
|
43
44
|
},
|
|
44
45
|
moveableOptions: stageOptions.moveableOptions,
|
|
45
46
|
updateDragEl: stageOptions.updateDragEl,
|
|
47
|
+
guidesOptions: stageOptions.guidesOptions,
|
|
48
|
+
disabledMultiSelect: stageOptions.disabledMultiSelect,
|
|
46
49
|
});
|
|
47
50
|
|
|
51
|
+
watch(
|
|
52
|
+
() => editorService.get('disabledMultiSelect'),
|
|
53
|
+
(disabledMultiSelect) => {
|
|
54
|
+
if (disabledMultiSelect) {
|
|
55
|
+
stage.disableMultiSelect();
|
|
56
|
+
} else {
|
|
57
|
+
stage.enableMultiSelect();
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
|
|
48
62
|
stage.mask.setGuides([
|
|
49
63
|
getGuideLineFromCache(getGuideLineKey(H_GUIDE_LINE_STORAGE_KEY)),
|
|
50
64
|
getGuideLineFromCache(getGuideLineKey(V_GUIDE_LINE_STORAGE_KEY)),
|
|
51
65
|
]);
|
|
52
66
|
|
|
67
|
+
stage.on('page-el-update', () => {
|
|
68
|
+
editorService.set('stageLoading', false);
|
|
69
|
+
});
|
|
70
|
+
|
|
53
71
|
stage.on('select', (el: HTMLElement) => {
|
|
54
72
|
if (`${editorService.get('node')?.id}` === el.id && editorService.get('nodes').length === 1) return;
|
|
55
73
|
editorService.select(el.id);
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ import DataSourceMocks from './fields/DataSourceMocks.vue';
|
|
|
30
30
|
import DataSourceSelect from './fields/DataSourceSelect.vue';
|
|
31
31
|
import EventSelect from './fields/EventSelect.vue';
|
|
32
32
|
import KeyValue from './fields/KeyValue.vue';
|
|
33
|
+
import PageFragmentSelect from './fields/PageFragmentSelect.vue';
|
|
33
34
|
import uiSelect from './fields/UISelect.vue';
|
|
34
35
|
import CodeEditor from './layouts/CodeEditor.vue';
|
|
35
36
|
import { setConfig } from './utils/config';
|
|
@@ -79,6 +80,7 @@ export { default as LayoutContainer } from './components/SplitView.vue';
|
|
|
79
80
|
export { default as SplitView } from './components/SplitView.vue';
|
|
80
81
|
export { default as Resizer } from './components/Resizer.vue';
|
|
81
82
|
export { default as CodeBlockEditor } from './components/CodeBlockEditor.vue';
|
|
83
|
+
export { default as PageFragmentSelect } from './fields/PageFragmentSelect.vue';
|
|
82
84
|
|
|
83
85
|
const defaultInstallOpt: InstallOptions = {
|
|
84
86
|
// eslint-disable-next-line no-eval
|
|
@@ -108,5 +110,6 @@ export default {
|
|
|
108
110
|
app.component('m-fields-data-source-methods', DataSourceMethods);
|
|
109
111
|
app.component('m-fields-data-source-method-select', DataSourceMethodSelect);
|
|
110
112
|
app.component('m-fields-data-source-field-select', DataSourceFieldSelect);
|
|
113
|
+
app.component('m-fields-page-fragment-select', PageFragmentSelect);
|
|
111
114
|
},
|
|
112
115
|
};
|
package/src/initService.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { onBeforeUnmount, reactive, toRaw, watch } from 'vue';
|
|
2
2
|
import { cloneDeep } from 'lodash-es';
|
|
3
3
|
|
|
4
4
|
import type { EventOption } from '@tmagic/core';
|
|
5
|
-
import type { Target } from '@tmagic/dep';
|
|
6
5
|
import {
|
|
7
6
|
createCodeBlockTarget,
|
|
8
7
|
createDataSourceCondTarget,
|
|
9
8
|
createDataSourceMethodTarget,
|
|
10
9
|
createDataSourceTarget,
|
|
10
|
+
createRelatedCompTarget,
|
|
11
11
|
DepTargetType,
|
|
12
|
+
Target,
|
|
12
13
|
} from '@tmagic/dep';
|
|
13
|
-
import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage } from '@tmagic/schema';
|
|
14
|
+
import type { CodeBlockContent, DataSourceSchema, Id, MApp, MNode, MPage, MPageFragment } from '@tmagic/schema';
|
|
14
15
|
import { getNodes } from '@tmagic/utils';
|
|
15
16
|
|
|
16
17
|
import PropsPanel from './layouts/PropsPanel.vue';
|
|
@@ -46,6 +47,16 @@ export const initServiceState = (
|
|
|
46
47
|
},
|
|
47
48
|
);
|
|
48
49
|
|
|
50
|
+
watch(
|
|
51
|
+
() => props.disabledMultiSelect,
|
|
52
|
+
(disabledMultiSelect) => {
|
|
53
|
+
editorService.set('disabledMultiSelect', disabledMultiSelect || false);
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
immediate: true,
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
|
|
49
60
|
watch(
|
|
50
61
|
() => props.componentGroupList,
|
|
51
62
|
(componentGroupList) => componentGroupList && componentListService.setList(componentGroupList),
|
|
@@ -164,7 +175,7 @@ export const initServiceState = (
|
|
|
164
175
|
},
|
|
165
176
|
);
|
|
166
177
|
|
|
167
|
-
|
|
178
|
+
onBeforeUnmount(() => {
|
|
168
179
|
editorService.resetState();
|
|
169
180
|
historyService.resetState();
|
|
170
181
|
propsService.resetState();
|
|
@@ -186,7 +197,7 @@ export const initServiceEvents = (
|
|
|
186
197
|
return stage?.renderer.runtime?.getApp?.();
|
|
187
198
|
};
|
|
188
199
|
|
|
189
|
-
const
|
|
200
|
+
const updateDataSourceSchema = () => {
|
|
190
201
|
const root = editorService.get('root');
|
|
191
202
|
|
|
192
203
|
if (root?.dataSources) {
|
|
@@ -194,7 +205,7 @@ export const initServiceEvents = (
|
|
|
194
205
|
}
|
|
195
206
|
};
|
|
196
207
|
|
|
197
|
-
const
|
|
208
|
+
const updateNodeWhenDataSourceChange = (nodes: MNode[]) => {
|
|
198
209
|
const root = editorService.get('root');
|
|
199
210
|
const stage = editorService.get('stage');
|
|
200
211
|
|
|
@@ -210,7 +221,7 @@ export const initServiceEvents = (
|
|
|
210
221
|
app.dsl.dataSources = root.dataSources;
|
|
211
222
|
}
|
|
212
223
|
|
|
213
|
-
|
|
224
|
+
updateDataSourceSchema();
|
|
214
225
|
|
|
215
226
|
nodes.forEach((node) => {
|
|
216
227
|
const deps = Object.values(root.dataSourceDeps || {});
|
|
@@ -258,11 +269,11 @@ export const initServiceEvents = (
|
|
|
258
269
|
};
|
|
259
270
|
|
|
260
271
|
const depUpdateHandler = (node: MNode) => {
|
|
261
|
-
|
|
272
|
+
updateNodeWhenDataSourceChange([node]);
|
|
262
273
|
};
|
|
263
274
|
|
|
264
275
|
const collectedHandler = (nodes: MNode[]) => {
|
|
265
|
-
|
|
276
|
+
updateNodeWhenDataSourceChange(nodes);
|
|
266
277
|
};
|
|
267
278
|
|
|
268
279
|
depService.on('add-target', targetAddHandler);
|
|
@@ -291,7 +302,7 @@ export const initServiceEvents = (
|
|
|
291
302
|
depService.addTarget(createCodeBlockTarget(id, code));
|
|
292
303
|
});
|
|
293
304
|
|
|
294
|
-
|
|
305
|
+
dataSourceService.get('dataSources').forEach((ds) => {
|
|
295
306
|
initDataSourceDepTarget(ds);
|
|
296
307
|
});
|
|
297
308
|
|
|
@@ -339,7 +350,7 @@ export const initServiceEvents = (
|
|
|
339
350
|
};
|
|
340
351
|
|
|
341
352
|
// 由于历史记录变化是更新整个page,所以历史记录变化时,需要重新收集依赖
|
|
342
|
-
const historyChangeHandler = (page: MPage) => {
|
|
353
|
+
const historyChangeHandler = (page: MPage | MPageFragment) => {
|
|
343
354
|
depService.collect([page], true);
|
|
344
355
|
};
|
|
345
356
|
|
|
@@ -350,8 +361,8 @@ export const initServiceEvents = (
|
|
|
350
361
|
editorService.on('update', nodeUpdateHandler);
|
|
351
362
|
|
|
352
363
|
const codeBlockAddOrUpdateHandler = (id: Id, codeBlock: CodeBlockContent) => {
|
|
353
|
-
if (depService.hasTarget(id)) {
|
|
354
|
-
depService.getTarget(id)!.name = codeBlock.name;
|
|
364
|
+
if (depService.hasTarget(id, DepTargetType.CODE_BLOCK)) {
|
|
365
|
+
depService.getTarget(id, DepTargetType.CODE_BLOCK)!.name = codeBlock.name;
|
|
355
366
|
return;
|
|
356
367
|
}
|
|
357
368
|
|
|
@@ -359,7 +370,7 @@ export const initServiceEvents = (
|
|
|
359
370
|
};
|
|
360
371
|
|
|
361
372
|
const codeBlockRemoveHandler = (id: Id) => {
|
|
362
|
-
depService.removeTarget(id);
|
|
373
|
+
depService.removeTarget(id, DepTargetType.CODE_BLOCK);
|
|
363
374
|
};
|
|
364
375
|
|
|
365
376
|
codeBlockService.on('addOrUpdate', codeBlockAddOrUpdateHandler);
|
|
@@ -372,16 +383,26 @@ export const initServiceEvents = (
|
|
|
372
383
|
|
|
373
384
|
const dataSourceUpdateHandler = (config: DataSourceSchema) => {
|
|
374
385
|
const root = editorService.get('root');
|
|
386
|
+
removeDataSourceTarget(config.id);
|
|
387
|
+
initDataSourceDepTarget(config);
|
|
388
|
+
|
|
389
|
+
depService.collect(root?.items || [], true);
|
|
375
390
|
|
|
376
391
|
const targets = depService.getTargets(DepTargetType.DATA_SOURCE);
|
|
377
392
|
|
|
378
393
|
const nodes = getNodes(Object.keys(targets[config.id].deps), root?.items);
|
|
379
394
|
|
|
380
|
-
|
|
395
|
+
updateNodeWhenDataSourceChange(nodes);
|
|
396
|
+
};
|
|
397
|
+
|
|
398
|
+
const removeDataSourceTarget = (id: string) => {
|
|
399
|
+
depService.removeTarget(id, DepTargetType.DATA_SOURCE);
|
|
400
|
+
depService.removeTarget(id, DepTargetType.DATA_SOURCE_COND);
|
|
401
|
+
depService.removeTarget(id, DepTargetType.DATA_SOURCE_METHOD);
|
|
381
402
|
};
|
|
382
403
|
|
|
383
404
|
const dataSourceRemoveHandler = (id: string) => {
|
|
384
|
-
|
|
405
|
+
removeDataSourceTarget(id);
|
|
385
406
|
getApp()?.dataSourceManager?.removeDataSource(id);
|
|
386
407
|
};
|
|
387
408
|
|
|
@@ -389,7 +410,12 @@ export const initServiceEvents = (
|
|
|
389
410
|
dataSourceService.on('update', dataSourceUpdateHandler);
|
|
390
411
|
dataSourceService.on('remove', dataSourceRemoveHandler);
|
|
391
412
|
|
|
392
|
-
|
|
413
|
+
// 初始化复制组件相关的依赖收集器
|
|
414
|
+
if (props.collectorOptions && !depService.hasTarget(DepTargetType.RELATED_COMP_WHEN_COPY)) {
|
|
415
|
+
depService.addTarget(createRelatedCompTarget(props.collectorOptions));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
onBeforeUnmount(() => {
|
|
393
419
|
depService.off('add-target', targetAddHandler);
|
|
394
420
|
depService.off('remove-target', targetRemoveHandler);
|
|
395
421
|
depService.off('dep-update', depUpdateHandler);
|
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="m-editor-empty-panel">
|
|
3
3
|
<div class="m-editor-empty-content">
|
|
4
|
-
<div class="m-editor-empty-button" @click="clickHandler">
|
|
4
|
+
<div class="m-editor-empty-button" @click="clickHandler(NodeType.PAGE)">
|
|
5
5
|
<div>
|
|
6
6
|
<MIcon :icon="Plus"></MIcon>
|
|
7
7
|
</div>
|
|
8
8
|
<p>新增页面</p>
|
|
9
9
|
</div>
|
|
10
|
+
|
|
11
|
+
<div v-if="!disabledPageFragment" class="m-editor-empty-button" @click="clickHandler(NodeType.PAGE_FRAGMENT)">
|
|
12
|
+
<div>
|
|
13
|
+
<MIcon :icon="Plus"></MIcon>
|
|
14
|
+
</div>
|
|
15
|
+
<p>新增页面片</p>
|
|
16
|
+
</div>
|
|
10
17
|
</div>
|
|
11
18
|
</div>
|
|
12
19
|
</template>
|
|
@@ -25,9 +32,13 @@ defineOptions({
|
|
|
25
32
|
name: 'MEditorAddPageBox',
|
|
26
33
|
});
|
|
27
34
|
|
|
35
|
+
defineProps<{
|
|
36
|
+
disabledPageFragment: boolean;
|
|
37
|
+
}>();
|
|
38
|
+
|
|
28
39
|
const services = inject<Services>('services');
|
|
29
40
|
|
|
30
|
-
const clickHandler = () => {
|
|
41
|
+
const clickHandler = (type: NodeType.PAGE | NodeType.PAGE_FRAGMENT) => {
|
|
31
42
|
const { editorService } = services || {};
|
|
32
43
|
|
|
33
44
|
if (!editorService) return;
|
|
@@ -36,8 +47,9 @@ const clickHandler = () => {
|
|
|
36
47
|
if (!root) throw new Error('root 不能为空');
|
|
37
48
|
|
|
38
49
|
editorService.add({
|
|
39
|
-
type
|
|
40
|
-
name: generatePageNameByApp(root),
|
|
50
|
+
type,
|
|
51
|
+
name: generatePageNameByApp(root, type),
|
|
52
|
+
items: [],
|
|
41
53
|
});
|
|
42
54
|
};
|
|
43
55
|
</script>
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</template>
|
|
20
20
|
|
|
21
21
|
<script lang="ts" setup>
|
|
22
|
-
import {
|
|
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
25
|
import * as monaco from 'monaco-editor';
|
|
@@ -188,7 +188,7 @@ onMounted(async () => {
|
|
|
188
188
|
init();
|
|
189
189
|
});
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
onBeforeUnmount(() => {
|
|
192
192
|
resizeObserver.disconnect();
|
|
193
193
|
});
|
|
194
194
|
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
</slot>
|
|
12
12
|
|
|
13
13
|
<SplitView
|
|
14
|
+
v-loading="stageLoading"
|
|
15
|
+
element-loading-text="Runtime 加载中..."
|
|
14
16
|
v-else
|
|
15
17
|
ref="splitView"
|
|
16
18
|
class="m-editor-content"
|
|
@@ -29,13 +31,18 @@
|
|
|
29
31
|
</template>
|
|
30
32
|
|
|
31
33
|
<template #center>
|
|
32
|
-
<slot v-if="
|
|
34
|
+
<slot v-if="page" name="workspace"></slot>
|
|
33
35
|
<slot v-else name="empty">
|
|
34
|
-
<AddPageBox></AddPageBox>
|
|
36
|
+
<AddPageBox :disabled-page-fragment="disabledPageFragment"></AddPageBox>
|
|
35
37
|
</slot>
|
|
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>
|
|
36
43
|
</template>
|
|
37
44
|
|
|
38
|
-
<template v-if="
|
|
45
|
+
<template v-if="page" #right>
|
|
39
46
|
<TMagicScrollbar>
|
|
40
47
|
<slot name="props-panel"></slot>
|
|
41
48
|
</TMagicScrollbar>
|
|
@@ -56,6 +63,7 @@ import SplitView from '@editor/components/SplitView.vue';
|
|
|
56
63
|
import type { FrameworkSlots, GetColumnWidth, Services } from '@editor/type';
|
|
57
64
|
import { getConfig } from '@editor/utils/config';
|
|
58
65
|
|
|
66
|
+
import PageBar from './page-bar/PageBar.vue';
|
|
59
67
|
import AddPageBox from './AddPageBox.vue';
|
|
60
68
|
import CodeEditor from './CodeEditor.vue';
|
|
61
69
|
|
|
@@ -65,6 +73,10 @@ defineOptions({
|
|
|
65
73
|
name: 'MEditorFramework',
|
|
66
74
|
});
|
|
67
75
|
|
|
76
|
+
defineProps<{
|
|
77
|
+
disabledPageFragment: boolean;
|
|
78
|
+
}>();
|
|
79
|
+
|
|
68
80
|
const DEFAULT_LEFT_COLUMN_WIDTH = 310;
|
|
69
81
|
const DEFAULT_RIGHT_COLUMN_WIDTH = 480;
|
|
70
82
|
|
|
@@ -75,8 +87,10 @@ const content = ref<HTMLDivElement>();
|
|
|
75
87
|
const splitView = ref<InstanceType<typeof SplitView>>();
|
|
76
88
|
|
|
77
89
|
const root = computed(() => editorService?.get('root'));
|
|
90
|
+
const page = computed(() => editorService?.get('page'));
|
|
78
91
|
|
|
79
92
|
const pageLength = computed(() => editorService?.get('pageLength') || 0);
|
|
93
|
+
const stageLoading = computed(() => editorService?.get('stageLoading') || false);
|
|
80
94
|
const showSrc = computed(() => uiService?.get('showSrc'));
|
|
81
95
|
|
|
82
96
|
const LEFT_COLUMN_WIDTH_STORAGE_KEY = '$MagicEditorLeftColumnWidthData';
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
</template>
|
|
16
16
|
|
|
17
17
|
<script lang="ts" setup>
|
|
18
|
-
import { computed, getCurrentInstance, inject,
|
|
18
|
+
import { computed, getCurrentInstance, inject, onBeforeUnmount, onMounted, ref, watchEffect } from 'vue';
|
|
19
19
|
|
|
20
20
|
import { tMagicMessage } from '@tmagic/design';
|
|
21
21
|
import type { FormState, FormValue } from '@tmagic/form';
|
|
@@ -64,7 +64,7 @@ onMounted(() => {
|
|
|
64
64
|
emit('mounted', internalInstance);
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
onBeforeUnmount(() => {
|
|
68
68
|
services?.propsService.off('props-configs-change', init);
|
|
69
69
|
});
|
|
70
70
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
v-if="showAddPageButton"
|
|
4
|
+
id="m-editor-page-bar-add-icon"
|
|
5
|
+
class="m-editor-page-bar-item m-editor-page-bar-item-icon"
|
|
6
|
+
@click="addPage"
|
|
7
|
+
>
|
|
8
|
+
<Icon :icon="Plus"></Icon>
|
|
9
|
+
</div>
|
|
10
|
+
<div v-else style="width: 21px"></div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script setup lang="ts">
|
|
14
|
+
import { computed, inject, toRaw } from 'vue';
|
|
15
|
+
import { Plus } from '@element-plus/icons-vue';
|
|
16
|
+
|
|
17
|
+
import { NodeType } from '@tmagic/schema';
|
|
18
|
+
|
|
19
|
+
import Icon from '@editor/components/Icon.vue';
|
|
20
|
+
import type { Services } from '@editor/type';
|
|
21
|
+
import { generatePageNameByApp } from '@editor/utils/editor';
|
|
22
|
+
|
|
23
|
+
defineOptions({
|
|
24
|
+
name: 'MEditorPageBarAddButton',
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const props = defineProps<{
|
|
28
|
+
type: NodeType.PAGE | NodeType.PAGE_FRAGMENT;
|
|
29
|
+
}>();
|
|
30
|
+
|
|
31
|
+
const services = inject<Services>('services');
|
|
32
|
+
const uiService = services?.uiService;
|
|
33
|
+
const editorService = services?.editorService;
|
|
34
|
+
|
|
35
|
+
const showAddPageButton = computed(() => uiService?.get('showAddPageButton'));
|
|
36
|
+
|
|
37
|
+
const addPage = () => {
|
|
38
|
+
if (!editorService) return;
|
|
39
|
+
const root = toRaw(editorService.get('root'));
|
|
40
|
+
if (!root) throw new Error('root 不能为空');
|
|
41
|
+
const pageConfig = {
|
|
42
|
+
type: props.type,
|
|
43
|
+
name: generatePageNameByApp(root, props.type),
|
|
44
|
+
items: [],
|
|
45
|
+
};
|
|
46
|
+
editorService.add(pageConfig);
|
|
47
|
+
};
|
|
48
|
+
</script>
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="m-editor-page-bar-tabs">
|
|
3
|
+
<SwitchTypeButton v-if="!disabledPageFragment" v-model="active" />
|
|
4
|
+
|
|
5
|
+
<PageBarScrollContainer :type="active">
|
|
6
|
+
<template #prepend>
|
|
7
|
+
<AddButton :type="active"></AddButton>
|
|
8
|
+
</template>
|
|
9
|
+
|
|
10
|
+
<div
|
|
11
|
+
v-for="item in list"
|
|
12
|
+
class="m-editor-page-bar-item"
|
|
13
|
+
:key="item.id"
|
|
14
|
+
:class="{ active: page?.id === item.id }"
|
|
15
|
+
@click="switchPage(item.id)"
|
|
16
|
+
>
|
|
17
|
+
<div class="m-editor-page-bar-title">
|
|
18
|
+
<slot name="page-bar-title" :page="item">
|
|
19
|
+
<span :title="item.name">{{ item.name || item.id }}</span>
|
|
20
|
+
</slot>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<TMagicPopover popper-class="page-bar-popover" placement="top" :width="160" trigger="hover">
|
|
24
|
+
<div>
|
|
25
|
+
<slot name="page-bar-popover" :page="item">
|
|
26
|
+
<ToolButton
|
|
27
|
+
:data="{
|
|
28
|
+
type: 'button',
|
|
29
|
+
text: '复制',
|
|
30
|
+
icon: DocumentCopy,
|
|
31
|
+
handler: () => copy(item),
|
|
32
|
+
}"
|
|
33
|
+
></ToolButton>
|
|
34
|
+
<ToolButton
|
|
35
|
+
:data="{
|
|
36
|
+
type: 'button',
|
|
37
|
+
text: '删除',
|
|
38
|
+
icon: Delete,
|
|
39
|
+
handler: () => remove(item),
|
|
40
|
+
}"
|
|
41
|
+
></ToolButton>
|
|
42
|
+
</slot>
|
|
43
|
+
</div>
|
|
44
|
+
<template #reference>
|
|
45
|
+
<TMagicIcon class="m-editor-page-bar-menu-icon">
|
|
46
|
+
<CaretBottom></CaretBottom>
|
|
47
|
+
</TMagicIcon>
|
|
48
|
+
</template>
|
|
49
|
+
</TMagicPopover>
|
|
50
|
+
</div>
|
|
51
|
+
</PageBarScrollContainer>
|
|
52
|
+
</div>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<script lang="ts" setup>
|
|
56
|
+
import { computed, inject, ref, watch } from 'vue';
|
|
57
|
+
import { CaretBottom, Delete, DocumentCopy } from '@element-plus/icons-vue';
|
|
58
|
+
|
|
59
|
+
import { TMagicIcon, TMagicPopover } from '@tmagic/design';
|
|
60
|
+
import { Id, type MPage, type MPageFragment, NodeType } from '@tmagic/schema';
|
|
61
|
+
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
62
|
+
|
|
63
|
+
import ToolButton from '@editor/components/ToolButton.vue';
|
|
64
|
+
import type { Services } from '@editor/type';
|
|
65
|
+
import { getPageFragmentList, getPageList } from '@editor/utils';
|
|
66
|
+
|
|
67
|
+
import AddButton from './AddButton.vue';
|
|
68
|
+
import PageBarScrollContainer from './PageBarScrollContainer.vue';
|
|
69
|
+
import SwitchTypeButton from './SwitchTypeButton.vue';
|
|
70
|
+
|
|
71
|
+
defineOptions({
|
|
72
|
+
name: 'MEditorPageBar',
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
defineProps<{
|
|
76
|
+
disabledPageFragment: boolean;
|
|
77
|
+
}>();
|
|
78
|
+
|
|
79
|
+
const active = ref<NodeType.PAGE | NodeType.PAGE_FRAGMENT>(NodeType.PAGE);
|
|
80
|
+
|
|
81
|
+
const services = inject<Services>('services');
|
|
82
|
+
const editorService = services?.editorService;
|
|
83
|
+
|
|
84
|
+
const root = computed(() => editorService?.get('root'));
|
|
85
|
+
const page = computed(() => editorService?.get('page'));
|
|
86
|
+
const pageList = computed(() => getPageList(root.value));
|
|
87
|
+
const pageFragmentList = computed(() => getPageFragmentList(root.value));
|
|
88
|
+
|
|
89
|
+
const list = computed(() => (active.value === NodeType.PAGE ? pageList.value : pageFragmentList.value));
|
|
90
|
+
|
|
91
|
+
const activePage = ref<Id>('');
|
|
92
|
+
const activePageFragment = ref<Id>('');
|
|
93
|
+
|
|
94
|
+
watch(
|
|
95
|
+
page,
|
|
96
|
+
(page) => {
|
|
97
|
+
if (!page) {
|
|
98
|
+
if (active.value === NodeType.PAGE) {
|
|
99
|
+
activePage.value = '';
|
|
100
|
+
}
|
|
101
|
+
if (active.value === NodeType.PAGE_FRAGMENT) {
|
|
102
|
+
activePageFragment.value = '';
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (isPage(page)) {
|
|
108
|
+
activePage.value = page?.id;
|
|
109
|
+
if (active.value !== NodeType.PAGE) {
|
|
110
|
+
active.value = NodeType.PAGE;
|
|
111
|
+
}
|
|
112
|
+
} else if (isPageFragment(page)) {
|
|
113
|
+
activePageFragment.value = page?.id;
|
|
114
|
+
if (active.value !== NodeType.PAGE_FRAGMENT) {
|
|
115
|
+
active.value = NodeType.PAGE_FRAGMENT;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
immediate: true,
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
watch(active, (active) => {
|
|
125
|
+
if (active === NodeType.PAGE) {
|
|
126
|
+
if (!activePage.value) {
|
|
127
|
+
editorService?.selectRoot();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
switchPage(activePage.value);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (active === NodeType.PAGE_FRAGMENT) {
|
|
135
|
+
if (!activePageFragment.value) {
|
|
136
|
+
editorService?.selectRoot();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
switchPage(activePageFragment.value);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
const switchPage = (id: Id) => {
|
|
144
|
+
editorService?.select(id);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const copy = (node: MPage | MPageFragment) => {
|
|
148
|
+
node && editorService?.copy(node);
|
|
149
|
+
editorService?.paste({
|
|
150
|
+
left: 0,
|
|
151
|
+
top: 0,
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const remove = (node: MPage | MPageFragment) => {
|
|
156
|
+
editorService?.remove(node);
|
|
157
|
+
};
|
|
158
|
+
</script>
|