@tmagic/editor 1.5.7 → 1.5.8
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/dist/style.css +17 -0
- package/dist/tmagic-editor.js +463 -470
- package/dist/tmagic-editor.umd.cjs +471 -469
- package/package.json +7 -7
- package/src/components/CodeBlockEditor.vue +4 -4
- package/src/components/FloatingBox.vue +4 -4
- package/src/components/ToolButton.vue +6 -4
- package/src/components/TreeNode.vue +2 -2
- package/src/fields/CodeSelect.vue +6 -6
- package/src/fields/CodeSelectCol.vue +5 -4
- package/src/fields/CondOpSelect.vue +5 -4
- package/src/fields/DataSourceFieldSelect/FieldSelect.vue +6 -5
- package/src/fields/DataSourceFieldSelect/Index.vue +4 -3
- package/src/fields/DataSourceFields.vue +3 -3
- package/src/fields/DataSourceInput.vue +4 -4
- package/src/fields/DataSourceMethodSelect.vue +8 -9
- package/src/fields/DataSourceMocks.vue +3 -3
- package/src/fields/DataSourceSelect.vue +6 -5
- package/src/fields/DisplayConds.vue +4 -4
- package/src/fields/EventSelect.vue +17 -23
- package/src/fields/PageFragmentSelect.vue +6 -5
- package/src/fields/UISelect.vue +16 -19
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-code-block-edit.ts +5 -10
- package/src/hooks/use-data-source-edit.ts +6 -6
- package/src/hooks/use-editor-content-height.ts +5 -5
- package/src/hooks/use-float-box.ts +5 -5
- package/src/hooks/use-next-float-box-position.ts +9 -9
- package/src/hooks/use-services.ts +13 -0
- package/src/hooks/use-stage.ts +2 -6
- package/src/layouts/AddPageBox.vue +3 -7
- package/src/layouts/Framework.vue +27 -27
- package/src/layouts/NavMenu.vue +16 -16
- package/src/layouts/page-bar/AddButton.vue +4 -7
- package/src/layouts/page-bar/PageBar.vue +10 -10
- package/src/layouts/page-bar/PageBarScrollContainer.vue +7 -8
- package/src/layouts/page-bar/PageList.vue +6 -8
- package/src/layouts/props-panel/FormPanel.vue +6 -4
- package/src/layouts/props-panel/PropsPanel.vue +39 -49
- package/src/layouts/props-panel/use-style-panel.ts +35 -19
- package/src/layouts/sidebar/ComponentListPanel.vue +5 -5
- package/src/layouts/sidebar/Sidebar.vue +15 -9
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +13 -18
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +4 -3
- package/src/layouts/sidebar/code-block/useContentMenu.ts +3 -3
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +5 -5
- package/src/layouts/sidebar/data-source/DataSourceList.vue +13 -17
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +6 -12
- package/src/layouts/sidebar/data-source/useContentMenu.ts +3 -3
- package/src/layouts/sidebar/layer/LayerMenu.vue +11 -8
- package/src/layouts/sidebar/layer/LayerNodeTool.vue +2 -6
- package/src/layouts/sidebar/layer/LayerPanel.vue +6 -12
- package/src/layouts/sidebar/layer/use-click.ts +16 -15
- package/src/layouts/sidebar/layer/use-drag.ts +6 -6
- package/src/layouts/sidebar/layer/use-keybinding.ts +6 -8
- package/src/layouts/sidebar/layer/use-node-status.ts +16 -7
- package/src/layouts/workspace/Breadcrumb.vue +8 -9
- package/src/layouts/workspace/Workspace.vue +4 -10
- package/src/layouts/workspace/viewer/NodeListMenu.vue +9 -8
- package/src/layouts/workspace/viewer/Stage.vue +24 -24
- package/src/layouts/workspace/viewer/StageOverlay.vue +15 -16
- package/src/layouts/workspace/viewer/ViewerMenu.vue +15 -14
- package/src/services/dep.ts +23 -8
- package/src/services/ui.ts +6 -2
- package/src/theme/common/var.scss +1 -0
- package/src/theme/sidebar.scss +20 -1
- package/src/type.ts +3 -9
- package/src/utils/const.ts +11 -0
- package/src/utils/content-menu.ts +28 -30
- package/src/utils/idle-task.ts +11 -0
- package/src/utils/index.ts +1 -0
- package/types/index.d.ts +28 -10
|
@@ -20,9 +20,6 @@
|
|
|
20
20
|
</template>
|
|
21
21
|
|
|
22
22
|
<template #tree-node-tool="{ data }">
|
|
23
|
-
<TMagicTag v-if="collecting && data.type === 'code'" type="info" size="small" style="margin-right: 5px"
|
|
24
|
-
>依赖收集中</TMagicTag
|
|
25
|
-
>
|
|
26
23
|
<TMagicTooltip v-if="data.type === 'code'" effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
|
|
27
24
|
<Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editCode(`${data.key}`)"></Icon>
|
|
28
25
|
</TMagicTooltip>
|
|
@@ -35,18 +32,19 @@
|
|
|
35
32
|
</template>
|
|
36
33
|
|
|
37
34
|
<script lang="ts" setup>
|
|
38
|
-
import { computed
|
|
35
|
+
import { computed } from 'vue';
|
|
39
36
|
import { Close, Edit, View } from '@element-plus/icons-vue';
|
|
40
37
|
|
|
41
38
|
import type { Id, MNode } from '@tmagic/core';
|
|
42
39
|
import { DepTargetType } from '@tmagic/core';
|
|
43
|
-
import { tMagicMessage, tMagicMessageBox,
|
|
40
|
+
import { tMagicMessage, tMagicMessageBox, TMagicTooltip } from '@tmagic/design';
|
|
44
41
|
|
|
45
42
|
import Icon from '@editor/components/Icon.vue';
|
|
46
43
|
import Tree from '@editor/components/Tree.vue';
|
|
47
44
|
import { useFilter } from '@editor/hooks/use-filter';
|
|
48
45
|
import { useNodeStatus } from '@editor/hooks/use-node-status';
|
|
49
|
-
import {
|
|
46
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
47
|
+
import { type CodeBlockListSlots, CodeDeleteErrorType, type TreeNodeData } from '@editor/type';
|
|
50
48
|
|
|
51
49
|
defineSlots<CodeBlockListSlots>();
|
|
52
50
|
|
|
@@ -66,19 +64,16 @@ const emit = defineEmits<{
|
|
|
66
64
|
'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
|
|
67
65
|
}>();
|
|
68
66
|
|
|
69
|
-
const
|
|
70
|
-
const { codeBlockService, depService, editorService } = services || {};
|
|
71
|
-
|
|
72
|
-
const collecting = computed(() => depService?.get('collecting'));
|
|
67
|
+
const { codeBlockService, depService, editorService } = useServices();
|
|
73
68
|
|
|
74
69
|
// 代码块列表
|
|
75
70
|
const codeList = computed<TreeNodeData[]>(() =>
|
|
76
|
-
Object.entries(codeBlockService
|
|
77
|
-
const target = depService
|
|
71
|
+
Object.entries(codeBlockService.getCodeDsl() || {}).map(([codeId, code]) => {
|
|
72
|
+
const target = depService.getTarget(codeId, DepTargetType.CODE_BLOCK);
|
|
78
73
|
|
|
79
74
|
// 按页面分类显示
|
|
80
75
|
const pageList: TreeNodeData[] =
|
|
81
|
-
editorService
|
|
76
|
+
editorService.get('root')?.items.map((page) => ({
|
|
82
77
|
name: page.devconfig?.tabName || page.name,
|
|
83
78
|
type: 'node',
|
|
84
79
|
id: `${codeId}_${page.id}`,
|
|
@@ -108,7 +103,7 @@ const codeList = computed<TreeNodeData[]>(() =>
|
|
|
108
103
|
key: codeId,
|
|
109
104
|
name: code.name,
|
|
110
105
|
type: 'code',
|
|
111
|
-
codeBlockContent: codeBlockService
|
|
106
|
+
codeBlockContent: codeBlockService.getCodeContentById(codeId),
|
|
112
107
|
// 只有一个页面不显示页面分类
|
|
113
108
|
items: pageList.length > 1 ? pageList.filter((page) => page.items?.length) : pageList[0]?.items || [],
|
|
114
109
|
};
|
|
@@ -127,12 +122,12 @@ const filterNode = (value: string, data: MNode): boolean => {
|
|
|
127
122
|
const { nodeStatusMap } = useNodeStatus(codeList);
|
|
128
123
|
const { filterTextChangeHandler } = useFilter(codeList, nodeStatusMap, filterNode);
|
|
129
124
|
|
|
130
|
-
const editable = computed(() => codeBlockService
|
|
125
|
+
const editable = computed(() => codeBlockService.getEditStatus());
|
|
131
126
|
|
|
132
127
|
// 选中组件
|
|
133
128
|
const selectComp = (compId: Id) => {
|
|
134
|
-
const stage = editorService
|
|
135
|
-
editorService
|
|
129
|
+
const stage = editorService.get('stage');
|
|
130
|
+
editorService.select(compId);
|
|
136
131
|
stage?.select(compId);
|
|
137
132
|
};
|
|
138
133
|
|
|
@@ -150,7 +145,7 @@ const editCode = (id: string) => {
|
|
|
150
145
|
const deleteCode = async (id: string) => {
|
|
151
146
|
const currentCode = codeList.value.find((codeItem) => codeItem.id === id);
|
|
152
147
|
const existBinds = Boolean(currentCode?.items?.length);
|
|
153
|
-
const undeleteableList = codeBlockService
|
|
148
|
+
const undeleteableList = codeBlockService.getUndeletableList() || [];
|
|
154
149
|
if (!existBinds && !undeleteableList.includes(id)) {
|
|
155
150
|
await tMagicMessageBox.confirm('确定删除该代码块吗?', '提示', {
|
|
156
151
|
confirmButtonText: '确定',
|
|
@@ -55,6 +55,7 @@ import CodeBlockEditor from '@editor/components/CodeBlockEditor.vue';
|
|
|
55
55
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
56
56
|
import SearchInput from '@editor/components/SearchInput.vue';
|
|
57
57
|
import { useCodeBlockEdit } from '@editor/hooks/use-code-block-edit';
|
|
58
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
58
59
|
import type {
|
|
59
60
|
CodeBlockListPanelSlots,
|
|
60
61
|
CodeDeleteErrorType,
|
|
@@ -62,7 +63,6 @@ import type {
|
|
|
62
63
|
EventBus,
|
|
63
64
|
MenuButton,
|
|
64
65
|
MenuComponent,
|
|
65
|
-
Services,
|
|
66
66
|
} from '@editor/type';
|
|
67
67
|
|
|
68
68
|
import CodeBlockList from './CodeBlockList.vue';
|
|
@@ -82,9 +82,10 @@ const props = defineProps<{
|
|
|
82
82
|
}>();
|
|
83
83
|
|
|
84
84
|
const eventBus = inject<EventBus>('eventBus');
|
|
85
|
-
const { codeBlockService } = inject<Services>('services') || {};
|
|
86
85
|
|
|
87
|
-
const
|
|
86
|
+
const { codeBlockService } = useServices();
|
|
87
|
+
|
|
88
|
+
const editable = computed(() => codeBlockService.getEditStatus());
|
|
88
89
|
|
|
89
90
|
const { codeBlockEditor, codeConfig, editCode, deleteCode, createCodeBlock, submitCodeBlockHandler } =
|
|
90
91
|
useCodeBlockEdit(codeBlockService);
|
|
@@ -3,7 +3,7 @@ import { CopyDocument, Delete, Edit } from '@element-plus/icons-vue';
|
|
|
3
3
|
import { cloneDeep } from 'lodash-es';
|
|
4
4
|
|
|
5
5
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
6
|
-
import type { EventBus, MenuButton, MenuComponent,
|
|
6
|
+
import type { EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
|
|
7
7
|
|
|
8
8
|
export const useContentMenu = (deleteCode: (id: string) => void) => {
|
|
9
9
|
const eventBus = inject<EventBus>('eventBus');
|
|
@@ -16,7 +16,7 @@ export const useContentMenu = (deleteCode: (id: string) => void) => {
|
|
|
16
16
|
type: 'button',
|
|
17
17
|
text: '编辑',
|
|
18
18
|
icon: Edit,
|
|
19
|
-
display: (
|
|
19
|
+
display: ({ codeBlockService }) => codeBlockService.getEditStatus(),
|
|
20
20
|
handler: () => {
|
|
21
21
|
if (!selectId) {
|
|
22
22
|
return;
|
|
@@ -29,7 +29,7 @@ export const useContentMenu = (deleteCode: (id: string) => void) => {
|
|
|
29
29
|
type: 'button',
|
|
30
30
|
text: '复制并粘贴至当前',
|
|
31
31
|
icon: markRaw(CopyDocument),
|
|
32
|
-
handler: async ({ codeBlockService }
|
|
32
|
+
handler: async ({ codeBlockService }) => {
|
|
33
33
|
if (!selectId) {
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
@@ -29,9 +29,9 @@ import { tMagicMessage } from '@tmagic/design';
|
|
|
29
29
|
import { type ContainerChangeEventData, type FormConfig, MFormBox } from '@tmagic/form';
|
|
30
30
|
|
|
31
31
|
import FloatingBox from '@editor/components/FloatingBox.vue';
|
|
32
|
-
import { useEditorContentHeight } from '@editor/hooks';
|
|
32
|
+
import { useEditorContentHeight } from '@editor/hooks/use-editor-content-height';
|
|
33
33
|
import { useNextFloatBoxPosition } from '@editor/hooks/use-next-float-box-position';
|
|
34
|
-
import
|
|
34
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
35
35
|
|
|
36
36
|
defineOptions({
|
|
37
37
|
name: 'MEditorDataSourceConfigPanel',
|
|
@@ -50,7 +50,7 @@ const emit = defineEmits<{
|
|
|
50
50
|
submit: [v: any, eventData: ContainerChangeEventData];
|
|
51
51
|
}>();
|
|
52
52
|
|
|
53
|
-
const
|
|
53
|
+
const { uiService, dataSourceService } = useServices();
|
|
54
54
|
|
|
55
55
|
const initValues = ref<Partial<DataSourceSchema>>({});
|
|
56
56
|
const dataSourceConfig = ref<FormConfig>([]);
|
|
@@ -58,11 +58,11 @@ const dataSourceConfig = ref<FormConfig>([]);
|
|
|
58
58
|
const { height: editorHeight } = useEditorContentHeight();
|
|
59
59
|
|
|
60
60
|
const parentFloating = inject<Ref<HTMLDivElement | null>>('parentFloating', ref(null));
|
|
61
|
-
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(
|
|
61
|
+
const { boxPosition, calcBoxPosition } = useNextFloatBoxPosition(uiService, parentFloating);
|
|
62
62
|
|
|
63
63
|
watchEffect(() => {
|
|
64
64
|
initValues.value = props.values;
|
|
65
|
-
dataSourceConfig.value =
|
|
65
|
+
dataSourceConfig.value = dataSourceService.getFormConfig(initValues.value.type);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
68
|
const submitHandler = (values: any, data: ContainerChangeEventData) => {
|
|
@@ -19,9 +19,6 @@
|
|
|
19
19
|
</div>
|
|
20
20
|
</template>
|
|
21
21
|
<template #tree-node-tool="{ data }">
|
|
22
|
-
<TMagicTag v-if="collecting && data.type === 'ds'" type="info" size="small" style="margin-right: 5px"
|
|
23
|
-
>依赖收集中</TMagicTag
|
|
24
|
-
>
|
|
25
22
|
<TMagicTooltip v-if="data.type === 'ds'" effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
|
|
26
23
|
<Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editHandler(`${data.key}`)"></Icon>
|
|
27
24
|
</TMagicTooltip>
|
|
@@ -34,17 +31,18 @@
|
|
|
34
31
|
</template>
|
|
35
32
|
|
|
36
33
|
<script lang="ts" setup>
|
|
37
|
-
import { computed
|
|
34
|
+
import { computed } from 'vue';
|
|
38
35
|
import { Close, Edit, View } from '@element-plus/icons-vue';
|
|
39
36
|
|
|
40
37
|
import { DepData, DepTargetType, Id, MNode } from '@tmagic/core';
|
|
41
|
-
import {
|
|
38
|
+
import { TMagicTooltip } from '@tmagic/design';
|
|
42
39
|
|
|
43
40
|
import Icon from '@editor/components/Icon.vue';
|
|
44
41
|
import Tree from '@editor/components/Tree.vue';
|
|
45
42
|
import { useFilter } from '@editor/hooks/use-filter';
|
|
46
43
|
import { useNodeStatus } from '@editor/hooks/use-node-status';
|
|
47
|
-
import
|
|
44
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
45
|
+
import type { DataSourceListSlots, TreeNodeData } from '@editor/type';
|
|
48
46
|
|
|
49
47
|
defineSlots<DataSourceListSlots>();
|
|
50
48
|
|
|
@@ -63,17 +61,15 @@ const emit = defineEmits<{
|
|
|
63
61
|
'node-contextmenu': [event: MouseEvent, data: TreeNodeData];
|
|
64
62
|
}>();
|
|
65
63
|
|
|
66
|
-
const { depService, editorService, dataSourceService } =
|
|
67
|
-
|
|
68
|
-
const collecting = computed(() => depService?.get('collecting'));
|
|
64
|
+
const { depService, editorService, dataSourceService } = useServices();
|
|
69
65
|
|
|
70
|
-
const editable = computed(() => dataSourceService
|
|
66
|
+
const editable = computed(() => dataSourceService.get('editable'));
|
|
71
67
|
|
|
72
|
-
const dataSources = computed(() => dataSourceService
|
|
68
|
+
const dataSources = computed(() => dataSourceService.get('dataSources'));
|
|
73
69
|
|
|
74
|
-
const dsDep = computed(() => depService
|
|
75
|
-
const dsMethodDep = computed(() => depService
|
|
76
|
-
const dsCondDep = computed(() => depService
|
|
70
|
+
const dsDep = computed(() => depService.getTargets(DepTargetType.DATA_SOURCE));
|
|
71
|
+
const dsMethodDep = computed(() => depService.getTargets(DepTargetType.DATA_SOURCE_METHOD));
|
|
72
|
+
const dsCondDep = computed(() => depService.getTargets(DepTargetType.DATA_SOURCE_COND));
|
|
77
73
|
|
|
78
74
|
const getKeyTreeConfig = (dep: DepData[string], type?: string, parentKey?: Id) =>
|
|
79
75
|
dep.keys.map((key) => ({
|
|
@@ -122,7 +118,7 @@ const list = computed(() =>
|
|
|
122
118
|
const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
|
|
123
119
|
|
|
124
120
|
const items =
|
|
125
|
-
editorService
|
|
121
|
+
editorService.get('root')?.items.map((page) => ({
|
|
126
122
|
name: page.devconfig?.tabName || page.name,
|
|
127
123
|
type: 'node',
|
|
128
124
|
id: `${ds.id}_${page.id}`,
|
|
@@ -166,8 +162,8 @@ const removeHandler = async (id: string) => {
|
|
|
166
162
|
|
|
167
163
|
// 选中组件
|
|
168
164
|
const selectComp = (compId: Id) => {
|
|
169
|
-
const stage = editorService
|
|
170
|
-
editorService
|
|
165
|
+
const stage = editorService.get('stage');
|
|
166
|
+
editorService.select(compId);
|
|
171
167
|
stage?.select(compId);
|
|
172
168
|
};
|
|
173
169
|
|
|
@@ -68,14 +68,8 @@ import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
|
68
68
|
import SearchInput from '@editor/components/SearchInput.vue';
|
|
69
69
|
import ToolButton from '@editor/components/ToolButton.vue';
|
|
70
70
|
import { useDataSourceEdit } from '@editor/hooks/use-data-source-edit';
|
|
71
|
-
import
|
|
72
|
-
|
|
73
|
-
DataSourceListSlots,
|
|
74
|
-
EventBus,
|
|
75
|
-
MenuButton,
|
|
76
|
-
MenuComponent,
|
|
77
|
-
Services,
|
|
78
|
-
} from '@editor/type';
|
|
71
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
72
|
+
import type { CustomContentMenuFunction, DataSourceListSlots, EventBus, MenuButton, MenuComponent } from '@editor/type';
|
|
79
73
|
|
|
80
74
|
import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
|
|
81
75
|
import DataSourceList from './DataSourceList.vue';
|
|
@@ -94,7 +88,7 @@ const props = defineProps<{
|
|
|
94
88
|
}>();
|
|
95
89
|
|
|
96
90
|
const eventBus = inject<EventBus>('eventBus');
|
|
97
|
-
const { dataSourceService } =
|
|
91
|
+
const { dataSourceService } = useServices();
|
|
98
92
|
|
|
99
93
|
const { editDialog, dataSourceValues, dialogTitle, editable, editHandler, submitDataSourceHandler } =
|
|
100
94
|
useDataSourceEdit(dataSourceService);
|
|
@@ -103,7 +97,7 @@ const datasourceTypeList = computed(() =>
|
|
|
103
97
|
[
|
|
104
98
|
{ text: '基础', type: 'base' },
|
|
105
99
|
{ text: 'HTTP', type: 'http' },
|
|
106
|
-
].concat(dataSourceService
|
|
100
|
+
].concat(dataSourceService.get('datasourceTypeList')),
|
|
107
101
|
);
|
|
108
102
|
|
|
109
103
|
const addHandler = (type: string) => {
|
|
@@ -113,7 +107,7 @@ const addHandler = (type: string) => {
|
|
|
113
107
|
|
|
114
108
|
dataSourceValues.value = mergeWith(
|
|
115
109
|
{ type, title: datasourceType?.text },
|
|
116
|
-
dataSourceService
|
|
110
|
+
dataSourceService.getFormValue(type),
|
|
117
111
|
(objValue, srcValue) => {
|
|
118
112
|
if (Array.isArray(srcValue)) {
|
|
119
113
|
return srcValue;
|
|
@@ -133,7 +127,7 @@ const removeHandler = async (id: string) => {
|
|
|
133
127
|
type: 'warning',
|
|
134
128
|
});
|
|
135
129
|
|
|
136
|
-
dataSourceService
|
|
130
|
+
dataSourceService.remove(id);
|
|
137
131
|
};
|
|
138
132
|
|
|
139
133
|
const dataSourceList = ref<InstanceType<typeof DataSourceList>>();
|
|
@@ -3,7 +3,7 @@ import { CopyDocument, Delete, Edit } from '@element-plus/icons-vue';
|
|
|
3
3
|
import { cloneDeep } from 'lodash-es';
|
|
4
4
|
|
|
5
5
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
6
|
-
import type { EventBus, MenuButton, MenuComponent,
|
|
6
|
+
import type { EventBus, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
|
|
7
7
|
|
|
8
8
|
export const useContentMenu = () => {
|
|
9
9
|
const eventBus = inject<EventBus>('eventBus');
|
|
@@ -16,7 +16,7 @@ export const useContentMenu = () => {
|
|
|
16
16
|
type: 'button',
|
|
17
17
|
text: '编辑',
|
|
18
18
|
icon: Edit,
|
|
19
|
-
display: (
|
|
19
|
+
display: ({ dataSourceService }) => dataSourceService.get('editable'),
|
|
20
20
|
handler: () => {
|
|
21
21
|
if (!selectId) {
|
|
22
22
|
return;
|
|
@@ -29,7 +29,7 @@ export const useContentMenu = () => {
|
|
|
29
29
|
type: 'button',
|
|
30
30
|
text: '复制并粘贴至当前',
|
|
31
31
|
icon: markRaw(CopyDocument),
|
|
32
|
-
handler: ({ dataSourceService }
|
|
32
|
+
handler: ({ dataSourceService }) => {
|
|
33
33
|
if (!selectId) {
|
|
34
34
|
return;
|
|
35
35
|
}
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
</template>
|
|
4
4
|
|
|
5
5
|
<script lang="ts" setup>
|
|
6
|
-
import { computed,
|
|
6
|
+
import { computed, markRaw, useTemplateRef } from 'vue';
|
|
7
7
|
import { Files, Plus } from '@element-plus/icons-vue';
|
|
8
8
|
|
|
9
9
|
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
10
10
|
|
|
11
11
|
import ContentMenu from '@editor/components/ContentMenu.vue';
|
|
12
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
12
13
|
import FolderMinusIcon from '@editor/icons/FolderMinusIcon.vue';
|
|
13
|
-
import type { ComponentGroup, CustomContentMenuFunction, MenuButton, MenuComponent
|
|
14
|
+
import type { ComponentGroup, CustomContentMenuFunction, MenuButton, MenuComponent } from '@editor/type';
|
|
14
15
|
import { useCopyMenu, useDeleteMenu, useMoveToMenu, usePasteMenu } from '@editor/utils/content-menu';
|
|
15
16
|
|
|
16
17
|
defineOptions({
|
|
@@ -26,11 +27,13 @@ const emit = defineEmits<{
|
|
|
26
27
|
'collapse-all': [];
|
|
27
28
|
}>();
|
|
28
29
|
|
|
29
|
-
const services =
|
|
30
|
+
const services = useServices();
|
|
31
|
+
const { editorService, componentListService } = services;
|
|
32
|
+
|
|
30
33
|
const menuRef = useTemplateRef<InstanceType<typeof ContentMenu>>('menu');
|
|
31
|
-
const node = computed(() =>
|
|
32
|
-
const nodes = computed(() =>
|
|
33
|
-
const componentList = computed(() =>
|
|
34
|
+
const node = computed(() => editorService.get('node'));
|
|
35
|
+
const nodes = computed(() => editorService.get('nodes'));
|
|
36
|
+
const componentList = computed(() => componentListService.getList());
|
|
34
37
|
|
|
35
38
|
const createMenuItems = (group: ComponentGroup): MenuButton[] =>
|
|
36
39
|
group.items.map((component) => ({
|
|
@@ -38,7 +41,7 @@ const createMenuItems = (group: ComponentGroup): MenuButton[] =>
|
|
|
38
41
|
type: 'button',
|
|
39
42
|
icon: component.icon,
|
|
40
43
|
handler: () => {
|
|
41
|
-
|
|
44
|
+
editorService.add({
|
|
42
45
|
name: component.text,
|
|
43
46
|
type: component.type,
|
|
44
47
|
...(component.data || {}),
|
|
@@ -54,7 +57,7 @@ const getSubMenuData = computed<MenuButton[]>(() => {
|
|
|
54
57
|
type: 'button',
|
|
55
58
|
icon: Files,
|
|
56
59
|
handler: () => {
|
|
57
|
-
|
|
60
|
+
editorService.add({
|
|
58
61
|
type: 'tab-pane',
|
|
59
62
|
});
|
|
60
63
|
},
|
|
@@ -6,24 +6,20 @@
|
|
|
6
6
|
</template>
|
|
7
7
|
|
|
8
8
|
<script setup lang="ts">
|
|
9
|
-
import { inject } from 'vue';
|
|
10
9
|
import { Hide, View } from '@element-plus/icons-vue';
|
|
11
10
|
|
|
12
11
|
import type { MNode } from '@tmagic/core';
|
|
13
12
|
|
|
14
13
|
import MIcon from '@editor/components/Icon.vue';
|
|
15
|
-
import {
|
|
14
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
16
15
|
|
|
17
16
|
const props = defineProps<{
|
|
18
17
|
data: MNode;
|
|
19
18
|
}>();
|
|
20
19
|
|
|
21
|
-
const
|
|
22
|
-
const editorService = services?.editorService;
|
|
20
|
+
const { editorService } = useServices();
|
|
23
21
|
|
|
24
22
|
const setNodeVisible = (visible: boolean) => {
|
|
25
|
-
if (!editorService) return;
|
|
26
|
-
|
|
27
23
|
editorService.update({
|
|
28
24
|
id: props.data.id,
|
|
29
25
|
visible,
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
</template>
|
|
48
48
|
|
|
49
49
|
<script setup lang="ts">
|
|
50
|
-
import { computed,
|
|
50
|
+
import { computed, useTemplateRef } from 'vue';
|
|
51
51
|
|
|
52
52
|
import type { MNode } from '@tmagic/core';
|
|
53
53
|
import { TMagicScrollbar } from '@tmagic/design';
|
|
@@ -55,14 +55,8 @@ import { TMagicScrollbar } from '@tmagic/design';
|
|
|
55
55
|
import SearchInput from '@editor/components/SearchInput.vue';
|
|
56
56
|
import Tree from '@editor/components/Tree.vue';
|
|
57
57
|
import { useFilter } from '@editor/hooks/use-filter';
|
|
58
|
-
import
|
|
59
|
-
|
|
60
|
-
LayerPanelSlots,
|
|
61
|
-
MenuButton,
|
|
62
|
-
MenuComponent,
|
|
63
|
-
Services,
|
|
64
|
-
TreeNodeData,
|
|
65
|
-
} from '@editor/type';
|
|
58
|
+
import { useServices } from '@editor/hooks/use-services';
|
|
59
|
+
import type { CustomContentMenuFunction, LayerPanelSlots, MenuButton, MenuComponent, TreeNodeData } from '@editor/type';
|
|
66
60
|
|
|
67
61
|
import LayerMenu from './LayerMenu.vue';
|
|
68
62
|
import LayerNodeTool from './LayerNodeTool.vue';
|
|
@@ -84,12 +78,12 @@ defineProps<{
|
|
|
84
78
|
customContentMenu: CustomContentMenuFunction;
|
|
85
79
|
}>();
|
|
86
80
|
|
|
87
|
-
const services =
|
|
88
|
-
const editorService = services
|
|
81
|
+
const services = useServices();
|
|
82
|
+
const { editorService } = services;
|
|
89
83
|
|
|
90
84
|
const treeRef = useTemplateRef<InstanceType<typeof Tree>>('tree');
|
|
91
85
|
|
|
92
|
-
const page = computed(() => editorService
|
|
86
|
+
const page = computed(() => editorService.get('page'));
|
|
93
87
|
const nodeData = computed<TreeNodeData[]>(() => (!page.value ? [] : [page.value]));
|
|
94
88
|
|
|
95
89
|
const { nodeStatusMap } = useNodeStatus(services);
|
|
@@ -4,18 +4,19 @@ import { throttle } from 'lodash-es';
|
|
|
4
4
|
import { Id, MNode } from '@tmagic/core';
|
|
5
5
|
import { isPage, isPageFragment } from '@tmagic/utils';
|
|
6
6
|
|
|
7
|
-
import { LayerNodeStatus, Services, TreeNodeData
|
|
7
|
+
import type { LayerNodeStatus, Services, TreeNodeData } from '@editor/type';
|
|
8
|
+
import { UI_SELECT_MODE_EVENT_NAME } from '@editor/utils/const';
|
|
8
9
|
import { updateStatus } from '@editor/utils/tree';
|
|
9
10
|
|
|
10
11
|
import LayerMenu from './LayerMenu.vue';
|
|
11
12
|
|
|
12
13
|
export const useClick = (
|
|
13
|
-
|
|
14
|
+
{ editorService, stageOverlayService, uiService }: Services,
|
|
14
15
|
isCtrlKeyDown: Ref<boolean>,
|
|
15
16
|
nodeStatusMap: ComputedRef<Map<Id, LayerNodeStatus> | undefined>,
|
|
16
17
|
menuRef: ShallowRef<InstanceType<typeof LayerMenu> | null>,
|
|
17
18
|
) => {
|
|
18
|
-
const isMultiSelect = computed(() => isCtrlKeyDown.value && !
|
|
19
|
+
const isMultiSelect = computed(() => isCtrlKeyDown.value && !editorService.get('disabledMultiSelect'));
|
|
19
20
|
|
|
20
21
|
// 触发画布选中
|
|
21
22
|
const select = async (data: MNode) => {
|
|
@@ -26,9 +27,9 @@ export const useClick = (
|
|
|
26
27
|
if (isMultiSelect.value) {
|
|
27
28
|
multiSelect(data);
|
|
28
29
|
} else {
|
|
29
|
-
await
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
await editorService.select(data);
|
|
31
|
+
editorService.get('stage')?.select(data.id);
|
|
32
|
+
stageOverlayService.get('stage')?.select(data.id);
|
|
32
33
|
}
|
|
33
34
|
};
|
|
34
35
|
|
|
@@ -37,7 +38,7 @@ export const useClick = (
|
|
|
37
38
|
return;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
const nodes =
|
|
41
|
+
const nodes = editorService.get('nodes') || [];
|
|
41
42
|
|
|
42
43
|
const newNodes: Id[] = [];
|
|
43
44
|
let isCancel = false;
|
|
@@ -59,9 +60,9 @@ export const useClick = (
|
|
|
59
60
|
newNodes.push(data.id);
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
await
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
await editorService.multiSelect(newNodes);
|
|
64
|
+
editorService.get('stage')?.multiSelect(newNodes);
|
|
65
|
+
stageOverlayService.get('stage')?.multiSelect(newNodes);
|
|
65
66
|
};
|
|
66
67
|
|
|
67
68
|
const throttleTime = 300;
|
|
@@ -75,15 +76,15 @@ export const useClick = (
|
|
|
75
76
|
|
|
76
77
|
// 触发画布高亮
|
|
77
78
|
const highlight = (data: TreeNodeData) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
editorService.highlight(data);
|
|
80
|
+
editorService.get('stage')?.highlight(data.id);
|
|
81
|
+
stageOverlayService.get('stage')?.highlight(data.id);
|
|
81
82
|
};
|
|
82
83
|
|
|
83
84
|
const nodeClickHandler = (event: MouseEvent, data: TreeNodeData): void => {
|
|
84
85
|
if (!nodeStatusMap?.value) return;
|
|
85
86
|
|
|
86
|
-
if (
|
|
87
|
+
if (uiService.get('uiSelectMode')) {
|
|
87
88
|
document.dispatchEvent(new CustomEvent(UI_SELECT_MODE_EVENT_NAME, { detail: data }));
|
|
88
89
|
return;
|
|
89
90
|
}
|
|
@@ -107,7 +108,7 @@ export const useClick = (
|
|
|
107
108
|
nodeContentMenuHandler(event: MouseEvent, data: TreeNodeData): void {
|
|
108
109
|
event.preventDefault();
|
|
109
110
|
|
|
110
|
-
const nodes =
|
|
111
|
+
const nodes = editorService.get('nodes') || [];
|
|
111
112
|
if (nodes.length < 2 || !nodes.includes(data)) {
|
|
112
113
|
nodeClickHandler(event, data);
|
|
113
114
|
}
|
|
@@ -42,7 +42,7 @@ const removeStatusClass = (el: HTMLElement | null) => {
|
|
|
42
42
|
* dragover 属于目标节点
|
|
43
43
|
* 这些方法并不是同一个dom事件触发的
|
|
44
44
|
*/
|
|
45
|
-
export const useDrag = (
|
|
45
|
+
export const useDrag = ({ editorService }: Services) => {
|
|
46
46
|
const handleDragStart = (event: DragEvent) => {
|
|
47
47
|
if (!event.dataTransfer || !event.target || !event.currentTarget) return;
|
|
48
48
|
|
|
@@ -144,12 +144,12 @@ export const useDrag = (services: Services | undefined) => {
|
|
|
144
144
|
|
|
145
145
|
removeStatusClass(dragState.container);
|
|
146
146
|
|
|
147
|
-
if (node && dragState.dragOverNodeId && dragState.dropType
|
|
147
|
+
if (node && dragState.dragOverNodeId && dragState.dropType) {
|
|
148
148
|
if (dragState.dragOverNodeId === node.id) {
|
|
149
149
|
return;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
const targetInfo =
|
|
152
|
+
const targetInfo = editorService.getNodeInfo(dragState.dragOverNodeId, false);
|
|
153
153
|
const targetNode = targetInfo.node;
|
|
154
154
|
let targetParent = targetInfo.parent;
|
|
155
155
|
|
|
@@ -168,12 +168,12 @@ export const useDrag = (services: Services | undefined) => {
|
|
|
168
168
|
targetIndex += 1;
|
|
169
169
|
}
|
|
170
170
|
|
|
171
|
-
const selectedNodes =
|
|
171
|
+
const selectedNodes = editorService.get('nodes');
|
|
172
172
|
|
|
173
173
|
if (selectedNodes.find((n) => `${n.id}` === `${node.id}`)) {
|
|
174
|
-
|
|
174
|
+
editorService.dragTo(selectedNodes, targetParent, targetIndex);
|
|
175
175
|
} else {
|
|
176
|
-
|
|
176
|
+
editorService.dragTo([node], targetParent, targetIndex);
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
@@ -5,11 +5,9 @@ import type { Services } from '@editor/type';
|
|
|
5
5
|
import { KeyBindingContainerKey } from '@editor/utils/keybinding-config';
|
|
6
6
|
|
|
7
7
|
export const useKeybinding = (
|
|
8
|
-
|
|
8
|
+
{ keybindingService }: Services,
|
|
9
9
|
container: ShallowRef<InstanceType<typeof Tree> | null>,
|
|
10
10
|
) => {
|
|
11
|
-
const keybindingService = services?.keybindingService;
|
|
12
|
-
|
|
13
11
|
// 是否多选
|
|
14
12
|
const isCtrlKeyDown = ref(false);
|
|
15
13
|
|
|
@@ -17,15 +15,15 @@ export const useKeybinding = (
|
|
|
17
15
|
isCtrlKeyDown.value = false;
|
|
18
16
|
};
|
|
19
17
|
|
|
20
|
-
keybindingService
|
|
18
|
+
keybindingService.registerCommand('layer-panel-global-keyup', () => {
|
|
21
19
|
isCtrlKeyDown.value = false;
|
|
22
20
|
});
|
|
23
21
|
|
|
24
|
-
keybindingService
|
|
22
|
+
keybindingService.registerCommand('layer-panel-global-keydown', () => {
|
|
25
23
|
isCtrlKeyDown.value = true;
|
|
26
24
|
});
|
|
27
25
|
|
|
28
|
-
keybindingService
|
|
26
|
+
keybindingService.register([
|
|
29
27
|
{
|
|
30
28
|
command: 'layer-panel-global-keydown',
|
|
31
29
|
keybinding: 'ctrl',
|
|
@@ -41,10 +39,10 @@ export const useKeybinding = (
|
|
|
41
39
|
watchEffect(() => {
|
|
42
40
|
if (container.value) {
|
|
43
41
|
globalThis.addEventListener('blur', windowBlurHandler);
|
|
44
|
-
keybindingService
|
|
42
|
+
keybindingService.registerEl(KeyBindingContainerKey.LAYER_PANEL, container.value.$el);
|
|
45
43
|
} else {
|
|
46
44
|
globalThis.removeEventListener('blur', windowBlurHandler);
|
|
47
|
-
keybindingService
|
|
45
|
+
keybindingService.unregisterEl(KeyBindingContainerKey.LAYER_PANEL);
|
|
48
46
|
}
|
|
49
47
|
});
|
|
50
48
|
|