@tmagic/editor 1.3.4 → 1.3.6
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 +73 -51
- package/dist/tmagic-editor.js +1171 -1102
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +1188 -1119
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +17 -17
- package/src/Editor.vue +5 -0
- package/src/components/FloatingBox.vue +117 -0
- package/src/components/Tree.vue +5 -0
- package/src/components/TreeNode.vue +8 -2
- package/src/editorProps.ts +7 -0
- package/src/hooks/use-filter.ts +55 -0
- package/src/hooks/use-node-status.ts +48 -0
- package/src/hooks/use-stage.ts +1 -0
- package/src/initService.ts +28 -12
- package/src/layouts/sidebar/Sidebar.vue +7 -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/LayerPanel.vue +24 -7
- package/src/layouts/sidebar/layer/use-node-status.ts +8 -11
- package/src/layouts/workspace/viewer/NodeListMenu.vue +67 -128
- package/src/layouts/workspace/viewer/Stage.vue +2 -1
- package/src/layouts/workspace/viewer/ViewerMenu.vue +1 -6
- 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 +66 -30
- package/src/services/props.ts +70 -12
- package/src/services/storage.ts +23 -13
- package/src/services/ui.ts +4 -1
- package/src/theme/floating-box.scss +30 -0
- package/src/theme/layer-panel.scss +19 -0
- 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 +6 -3
- package/src/utils/compose.ts +25 -6
- package/src/utils/content-menu.ts +4 -5
- package/src/utils/editor.ts +12 -3
- package/src/utils/operator.ts +1 -2
- 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 +1 -1
- package/types/components/Tree.vue.d.ts +27 -8
- package/types/components/TreeNode.vue.d.ts +24 -7
- package/types/editorProps.d.ts +7 -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/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/layouts/CodeEditor.vue.d.ts +4 -1
- package/types/layouts/Framework.vue.d.ts +1 -1
- package/types/layouts/PropsPanel.vue.d.ts +10 -4
- package/types/layouts/sidebar/ComponentListPanel.vue.d.ts +1 -1
- package/types/layouts/sidebar/Sidebar.vue.d.ts +5 -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 +6 -2
- package/types/layouts/sidebar/layer/LayerPanel.vue.d.ts +1 -1
- package/types/layouts/sidebar/layer/use-click.d.ts +14 -5
- package/types/layouts/sidebar/layer/use-node-status.d.ts +3 -4
- package/types/layouts/workspace/Workspace.vue.d.ts +1 -1
- package/types/layouts/workspace/viewer/NodeListMenu.vue.d.ts +1 -14
- package/types/layouts/workspace/viewer/ViewerMenu.vue.d.ts +1 -1
- package/types/services/BaseService.d.ts +4 -1
- package/types/services/dep.d.ts +6 -5
- package/types/services/editor.d.ts +9 -3
- package/types/services/props.d.ts +25 -1
- package/types/services/storage.d.ts +7 -7
- package/types/type.d.ts +8 -6
- package/types/utils/compose.d.ts +1 -1
- package/types/utils/editor.d.ts +5 -1
- package/src/layouts/sidebar/layer/use-filter.ts +0 -59
- 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/viewer/NodeListMenuTitle.vue.d.ts +0 -15
|
@@ -1,57 +1,42 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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>
|
|
36
|
-
</div>
|
|
37
|
-
</div>
|
|
2
|
+
<Tree :data="codeList" :node-status-map="nodeStatusMap" @node-click="clickHandler">
|
|
3
|
+
<template #tree-node-label="{ data }">
|
|
4
|
+
<div
|
|
5
|
+
:class="{
|
|
6
|
+
code: data.type === 'code',
|
|
7
|
+
hook: data.type === 'key',
|
|
8
|
+
disabled: data.type === 'key' || data.type === 'code',
|
|
9
|
+
}"
|
|
10
|
+
>
|
|
11
|
+
{{ data.name }} {{ data.key ? `(${data.key})` : '' }}
|
|
38
12
|
</div>
|
|
39
13
|
</template>
|
|
40
|
-
|
|
14
|
+
|
|
15
|
+
<template #tree-node-tool="{ data }">
|
|
16
|
+
<TMagicTooltip v-if="data.type === 'code'" effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
|
|
17
|
+
<Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editCode(`${data.key}`)"></Icon>
|
|
18
|
+
</TMagicTooltip>
|
|
19
|
+
<TMagicTooltip v-if="data.type === 'code' && editable" effect="dark" content="删除" placement="bottom">
|
|
20
|
+
<Icon :icon="Close" class="edit-icon" @click.stop="deleteCode(`${data.key}`)"></Icon>
|
|
21
|
+
</TMagicTooltip>
|
|
22
|
+
<slot name="code-block-panel-tool" :id="data.key" :data="data"></slot>
|
|
23
|
+
</template>
|
|
24
|
+
</Tree>
|
|
41
25
|
</template>
|
|
42
26
|
|
|
43
27
|
<script lang="ts" setup>
|
|
44
|
-
import { computed, inject
|
|
28
|
+
import { computed, inject } from 'vue';
|
|
45
29
|
import { Close, Edit, View } from '@element-plus/icons-vue';
|
|
46
30
|
|
|
47
31
|
import { DepTargetType } from '@tmagic/dep';
|
|
48
|
-
import { tMagicMessage, tMagicMessageBox, TMagicTooltip
|
|
49
|
-
import type { Id } from '@tmagic/schema';
|
|
32
|
+
import { tMagicMessage, tMagicMessageBox, TMagicTooltip } from '@tmagic/design';
|
|
33
|
+
import type { Id, MNode } from '@tmagic/schema';
|
|
50
34
|
|
|
51
35
|
import Icon from '@editor/components/Icon.vue';
|
|
52
|
-
import
|
|
53
|
-
import
|
|
54
|
-
import {
|
|
36
|
+
import Tree from '@editor/components/Tree.vue';
|
|
37
|
+
import { useFilter } from '@editor/hooks/use-filter';
|
|
38
|
+
import { useNodeStatus } from '@editor/hooks/use-node-status';
|
|
39
|
+
import { type CodeBlockListSlots, CodeDeleteErrorType, type Services, type TreeNodeData } from '@editor/type';
|
|
55
40
|
|
|
56
41
|
defineSlots<CodeBlockListSlots>();
|
|
57
42
|
|
|
@@ -68,38 +53,49 @@ const emit = defineEmits<{
|
|
|
68
53
|
remove: [id: string];
|
|
69
54
|
}>();
|
|
70
55
|
|
|
71
|
-
const
|
|
56
|
+
const services = inject<Services>('services');
|
|
57
|
+
const { codeBlockService, depService, editorService } = services || {};
|
|
72
58
|
|
|
73
59
|
// 代码块列表
|
|
74
|
-
const codeList = computed(() =>
|
|
60
|
+
const codeList = computed<TreeNodeData[]>(() =>
|
|
75
61
|
Object.values(depService?.getTargets(DepTargetType.CODE_BLOCK) || {}).map((target) => {
|
|
76
62
|
// 组件节点
|
|
77
|
-
const compNodes = Object.entries(target.deps).map(([id, dep]) => ({
|
|
63
|
+
const compNodes: TreeNodeData[] = Object.entries(target.deps).map(([id, dep]) => ({
|
|
78
64
|
name: dep.name,
|
|
79
65
|
type: 'node',
|
|
80
|
-
id
|
|
81
|
-
|
|
66
|
+
id: `${target.id}_${id}`,
|
|
67
|
+
key: id,
|
|
68
|
+
items: dep.keys.map((key) => {
|
|
69
|
+
const data: TreeNodeData = { name: `${key}`, id: `${target.id}_${id}_${key}`, type: 'key' };
|
|
70
|
+
return data;
|
|
71
|
+
}),
|
|
82
72
|
}));
|
|
83
|
-
|
|
73
|
+
|
|
74
|
+
const data: TreeNodeData = {
|
|
84
75
|
id: target.id,
|
|
76
|
+
key: target.id,
|
|
85
77
|
name: target.name,
|
|
86
78
|
type: 'code',
|
|
87
79
|
codeBlockContent: codeBlockService?.getCodeContentById(target.id),
|
|
88
|
-
|
|
80
|
+
items: compNodes,
|
|
89
81
|
};
|
|
82
|
+
|
|
83
|
+
return data;
|
|
90
84
|
}),
|
|
91
85
|
);
|
|
92
|
-
// 默认展开组件层级的节点
|
|
93
|
-
const expandedKeys = computed(() => codeList.value.map((item) => item.id));
|
|
94
|
-
const editable = computed(() => codeBlockService?.getEditStatus());
|
|
95
86
|
|
|
96
|
-
const filterNode = (value: string, data:
|
|
87
|
+
const filterNode = (value: string, data: MNode): boolean => {
|
|
97
88
|
if (!value) {
|
|
98
89
|
return true;
|
|
99
90
|
}
|
|
100
|
-
return `${data.name}${data.id}`.toLocaleLowerCase().
|
|
91
|
+
return `${data.name}${data.id}`.toLocaleLowerCase().includes(value.toLocaleLowerCase());
|
|
101
92
|
};
|
|
102
93
|
|
|
94
|
+
const { nodeStatusMap } = useNodeStatus(codeList);
|
|
95
|
+
const { filterTextChangeHandler } = useFilter(codeList, nodeStatusMap, filterNode);
|
|
96
|
+
|
|
97
|
+
const editable = computed(() => codeBlockService?.getEditStatus());
|
|
98
|
+
|
|
103
99
|
// 选中组件
|
|
104
100
|
const selectComp = (compId: Id) => {
|
|
105
101
|
const stage = editorService?.get('stage');
|
|
@@ -107,11 +103,9 @@ const selectComp = (compId: Id) => {
|
|
|
107
103
|
stage?.select(compId);
|
|
108
104
|
};
|
|
109
105
|
|
|
110
|
-
const clickHandler = (
|
|
106
|
+
const clickHandler = (event: MouseEvent, data: any) => {
|
|
111
107
|
if (data.type === 'node') {
|
|
112
|
-
selectComp(data.
|
|
113
|
-
} else if (data.type === 'key') {
|
|
114
|
-
selectComp(node.parent.data.id);
|
|
108
|
+
selectComp(data.key);
|
|
115
109
|
}
|
|
116
110
|
};
|
|
117
111
|
|
|
@@ -122,7 +116,7 @@ const editCode = (id: string) => {
|
|
|
122
116
|
|
|
123
117
|
const deleteCode = async (id: string) => {
|
|
124
118
|
const currentCode = codeList.value.find((codeItem) => codeItem.id === id);
|
|
125
|
-
const existBinds = Boolean(currentCode?.
|
|
119
|
+
const existBinds = Boolean(currentCode?.items?.length);
|
|
126
120
|
const undeleteableList = codeBlockService?.getUndeletableList() || [];
|
|
127
121
|
if (!existBinds && !undeleteableList.includes(id)) {
|
|
128
122
|
await tMagicMessageBox.confirm('确定删除该代码块吗?', '提示', {
|
|
@@ -142,11 +136,7 @@ const deleteCode = async (id: string) => {
|
|
|
142
136
|
}
|
|
143
137
|
};
|
|
144
138
|
|
|
145
|
-
const tree = ref<InstanceType<typeof TMagicTree>>();
|
|
146
|
-
|
|
147
139
|
defineExpose({
|
|
148
|
-
filter
|
|
149
|
-
tree.value?.filter(val);
|
|
150
|
-
},
|
|
140
|
+
filter: filterTextChangeHandler,
|
|
151
141
|
});
|
|
152
142
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TMagicScrollbar class="m-editor-code-block-list m-editor-
|
|
2
|
+
<TMagicScrollbar class="m-editor-code-block-list m-editor-layer-panel">
|
|
3
3
|
<slot name="code-block-panel-header">
|
|
4
4
|
<div class="search-wrapper">
|
|
5
5
|
<SearchInput @search="filterTextChangeHandler"></SearchInput>
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
</template>
|
|
18
18
|
</CodeBlockList>
|
|
19
19
|
</TMagicScrollbar>
|
|
20
|
+
|
|
20
21
|
<!-- 代码块编辑区 -->
|
|
21
22
|
<CodeBlockEditor
|
|
22
23
|
v-if="codeConfig"
|
|
@@ -1,48 +1,40 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
>
|
|
13
|
-
<template #default="{ data }">
|
|
14
|
-
<div :id="data.id" class="list-container">
|
|
15
|
-
<div class="list-item">
|
|
16
|
-
<Icon v-if="data.type === 'code'" class="codeIcon" :icon="Coin"></Icon>
|
|
17
|
-
<Icon v-if="data.type === 'node'" class="compIcon" :icon="Aim"></Icon>
|
|
18
|
-
<span class="name" :class="{ code: data.type === 'ds', hook: data.type === 'key' }">{{
|
|
19
|
-
data.type === 'key' ? data.name : `${data.name}(${data.id})`
|
|
20
|
-
}}</span>
|
|
21
|
-
<!-- 右侧工具栏 -->
|
|
22
|
-
<div class="right-tool" v-if="data.type === 'ds'">
|
|
23
|
-
<TMagicTooltip effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
|
|
24
|
-
<Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editHandler(`${data.id}`)"></Icon>
|
|
25
|
-
</TMagicTooltip>
|
|
26
|
-
<TMagicTooltip v-if="editable" effect="dark" content="删除" placement="bottom">
|
|
27
|
-
<Icon :icon="Close" class="edit-icon" @click.stop="removeHandler(`${data.id}`)"></Icon>
|
|
28
|
-
</TMagicTooltip>
|
|
29
|
-
<slot name="data-source-panel-tool" :data="data"></slot>
|
|
30
|
-
</div>
|
|
31
|
-
</div>
|
|
2
|
+
<Tree :data="list" :node-status-map="nodeStatusMap" @node-click="clickHandler">
|
|
3
|
+
<template #tree-node-label="{ data }">
|
|
4
|
+
<div
|
|
5
|
+
:class="{
|
|
6
|
+
ds: data.type === 'ds',
|
|
7
|
+
hook: data.type === 'key',
|
|
8
|
+
disabled: data.type === 'key' || data.type === 'ds',
|
|
9
|
+
}"
|
|
10
|
+
>
|
|
11
|
+
{{ data.name }} {{ data.key ? `(${data.key})` : '' }}
|
|
32
12
|
</div>
|
|
33
13
|
</template>
|
|
34
|
-
|
|
14
|
+
<template #tree-node-tool="{ data }">
|
|
15
|
+
<TMagicTooltip v-if="data.type === 'ds'" effect="dark" :content="editable ? '编辑' : '查看'" placement="bottom">
|
|
16
|
+
<Icon :icon="editable ? Edit : View" class="edit-icon" @click.stop="editHandler(`${data.key}`)"></Icon>
|
|
17
|
+
</TMagicTooltip>
|
|
18
|
+
<TMagicTooltip v-if="data.type === 'ds' && editable" effect="dark" content="删除" placement="bottom">
|
|
19
|
+
<Icon :icon="Close" class="edit-icon" @click.stop="removeHandler(`${data.key}`)"></Icon>
|
|
20
|
+
</TMagicTooltip>
|
|
21
|
+
<slot name="data-source-panel-tool" :data="data"></slot>
|
|
22
|
+
</template>
|
|
23
|
+
</Tree>
|
|
35
24
|
</template>
|
|
36
25
|
|
|
37
26
|
<script lang="ts" setup>
|
|
38
|
-
import { computed, inject
|
|
39
|
-
import {
|
|
27
|
+
import { computed, inject } from 'vue';
|
|
28
|
+
import { Close, Edit, View } from '@element-plus/icons-vue';
|
|
40
29
|
|
|
41
30
|
import { DepTargetType } from '@tmagic/dep';
|
|
42
|
-
import { tMagicMessageBox, TMagicTooltip
|
|
43
|
-
import { DepData, Id } from '@tmagic/schema';
|
|
31
|
+
import { tMagicMessageBox, TMagicTooltip } from '@tmagic/design';
|
|
32
|
+
import { DepData, Id, MNode } from '@tmagic/schema';
|
|
44
33
|
|
|
45
34
|
import Icon from '@editor/components/Icon.vue';
|
|
35
|
+
import Tree from '@editor/components/Tree.vue';
|
|
36
|
+
import { useFilter } from '@editor/hooks/use-filter';
|
|
37
|
+
import { useNodeStatus } from '@editor/hooks/use-node-status';
|
|
46
38
|
import type { DataSourceListSlots, Services } from '@editor/type';
|
|
47
39
|
|
|
48
40
|
defineSlots<DataSourceListSlots>();
|
|
@@ -66,32 +58,39 @@ const dsDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE) |
|
|
|
66
58
|
const dsMethodDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_METHOD) || {});
|
|
67
59
|
const dsCondDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_COND) || {});
|
|
68
60
|
|
|
69
|
-
const getKeyTreeConfig = (dep: DepData[string], type?: string) =>
|
|
70
|
-
dep.keys.map((key) => ({
|
|
61
|
+
const getKeyTreeConfig = (dep: DepData[string], type?: string, parentKey?: Id) =>
|
|
62
|
+
dep.keys.map((key) => ({
|
|
63
|
+
name: key,
|
|
64
|
+
id: `${parentKey}_${key}`,
|
|
65
|
+
type: 'key',
|
|
66
|
+
isMethod: type === 'method',
|
|
67
|
+
isCond: type === 'cond',
|
|
68
|
+
}));
|
|
71
69
|
|
|
72
|
-
const getNodeTreeConfig = (id: string, dep: DepData[string], type?: string) => ({
|
|
70
|
+
const getNodeTreeConfig = (id: string, dep: DepData[string], type?: string, parentKey?: Id) => ({
|
|
73
71
|
name: dep.name,
|
|
74
72
|
type: 'node',
|
|
75
|
-
id
|
|
76
|
-
|
|
73
|
+
id: `${parentKey}_${id}`,
|
|
74
|
+
key: id,
|
|
75
|
+
items: getKeyTreeConfig(dep, type, `${parentKey}_${id}`),
|
|
77
76
|
});
|
|
78
77
|
|
|
79
78
|
/**
|
|
80
79
|
* 生成tree中依赖节点的数据
|
|
81
|
-
* @param
|
|
80
|
+
* @param items 节点
|
|
82
81
|
* @param deps 依赖
|
|
83
82
|
* @param type 依赖类型
|
|
84
83
|
*/
|
|
85
|
-
const mergeChildren = (
|
|
84
|
+
const mergeChildren = (dsId: Id, items: any[], deps: DepData, type?: string) => {
|
|
86
85
|
Object.entries(deps).forEach(([id, dep]) => {
|
|
87
86
|
// 已经生成过的节点
|
|
88
|
-
const nodeItem =
|
|
87
|
+
const nodeItem = items.find((item) => item.key === id);
|
|
89
88
|
// 节点存在,则追加依赖的key
|
|
90
89
|
if (nodeItem) {
|
|
91
|
-
nodeItem.
|
|
90
|
+
nodeItem.items = nodeItem.items.concat(getKeyTreeConfig(dep, type, nodeItem.key));
|
|
92
91
|
} else {
|
|
93
92
|
// 节点不存在,则生成
|
|
94
|
-
|
|
93
|
+
items.push(getNodeTreeConfig(id, dep, type, dsId));
|
|
95
94
|
}
|
|
96
95
|
});
|
|
97
96
|
};
|
|
@@ -102,21 +101,32 @@ const list = computed(() =>
|
|
|
102
101
|
const dsMethodDeps = dsMethodDep.value[ds.id]?.deps || {};
|
|
103
102
|
const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
|
|
104
103
|
|
|
105
|
-
const
|
|
104
|
+
const items: any[] = [];
|
|
106
105
|
// 数据源依赖分为三种类型:key/node、method、cond,是分开存储,这里将其合并展示
|
|
107
|
-
mergeChildren(
|
|
108
|
-
mergeChildren(
|
|
109
|
-
mergeChildren(
|
|
106
|
+
mergeChildren(ds.id, items, dsDeps);
|
|
107
|
+
mergeChildren(ds.id, items, dsMethodDeps, 'method');
|
|
108
|
+
mergeChildren(ds.id, items, dsCondDeps, 'cond');
|
|
110
109
|
|
|
111
110
|
return {
|
|
112
111
|
id: ds.id,
|
|
112
|
+
key: ds.id,
|
|
113
113
|
name: ds.title,
|
|
114
114
|
type: 'ds',
|
|
115
|
-
|
|
115
|
+
items,
|
|
116
116
|
};
|
|
117
117
|
}),
|
|
118
118
|
);
|
|
119
119
|
|
|
120
|
+
const filterNode = (value: string, data: MNode): boolean => {
|
|
121
|
+
if (!value) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
return `${data.name}${data.id}`.toLocaleLowerCase().includes(value.toLocaleLowerCase());
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
const { nodeStatusMap } = useNodeStatus(list);
|
|
128
|
+
const { filterTextChangeHandler } = useFilter(list, nodeStatusMap, filterNode);
|
|
129
|
+
|
|
120
130
|
const editHandler = (id: string) => {
|
|
121
131
|
emit('edit', id);
|
|
122
132
|
};
|
|
@@ -138,19 +148,13 @@ const selectComp = (compId: Id) => {
|
|
|
138
148
|
stage?.select(compId);
|
|
139
149
|
};
|
|
140
150
|
|
|
141
|
-
const clickHandler = (
|
|
151
|
+
const clickHandler = (event: MouseEvent, data: any) => {
|
|
142
152
|
if (data.type === 'node') {
|
|
143
|
-
selectComp(data.
|
|
144
|
-
} else if (data.type === 'key') {
|
|
145
|
-
selectComp(node.parent.data.id);
|
|
153
|
+
selectComp(data.key);
|
|
146
154
|
}
|
|
147
155
|
};
|
|
148
156
|
|
|
149
|
-
const tree = ref<InstanceType<typeof TMagicTree>>();
|
|
150
|
-
|
|
151
157
|
defineExpose({
|
|
152
|
-
filter
|
|
153
|
-
tree.value?.filter(val);
|
|
154
|
-
},
|
|
158
|
+
filter: filterTextChangeHandler,
|
|
155
159
|
});
|
|
156
160
|
</script>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<TMagicScrollbar class="data-source-list-panel m-editor-
|
|
2
|
+
<TMagicScrollbar class="data-source-list-panel m-editor-layer-panel">
|
|
3
3
|
<div class="search-wrapper">
|
|
4
4
|
<SearchInput @search="filterTextChangeHandler"></SearchInput>
|
|
5
5
|
<TMagicPopover v-if="editable" placement="right">
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
v-if="page && nodeStatusMap"
|
|
9
9
|
tabindex="-1"
|
|
10
10
|
ref="tree"
|
|
11
|
-
:data="
|
|
11
|
+
:data="nodeData"
|
|
12
12
|
:node-status-map="nodeStatusMap"
|
|
13
13
|
@node-dragover="handleDragOver"
|
|
14
14
|
@node-dragstart="handleDragStart"
|
|
@@ -18,14 +18,18 @@
|
|
|
18
18
|
@node-mouseenter="mouseenterHandler"
|
|
19
19
|
@node-click="nodeClickHandler"
|
|
20
20
|
>
|
|
21
|
+
<template #tree-node-content="{ data: nodeData }">
|
|
22
|
+
<slot name="layer-node-content" :data="nodeData"> </slot>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
21
25
|
<template #tree-node-tool="{ data: nodeData }">
|
|
22
26
|
<slot name="layer-node-tool" :data="nodeData">
|
|
23
27
|
<LayerNodeTool :data="nodeData"></LayerNodeTool>
|
|
24
28
|
</slot>
|
|
25
29
|
</template>
|
|
26
30
|
|
|
27
|
-
<template #tree-node-
|
|
28
|
-
<slot name="layer-node-
|
|
31
|
+
<template #tree-node-label="{ data: nodeData }">
|
|
32
|
+
<slot name="layer-node-label" :data="nodeData"></slot>
|
|
29
33
|
</template>
|
|
30
34
|
</Tree>
|
|
31
35
|
|
|
@@ -39,16 +43,17 @@
|
|
|
39
43
|
import { computed, inject, ref } from 'vue';
|
|
40
44
|
|
|
41
45
|
import { TMagicScrollbar } from '@tmagic/design';
|
|
46
|
+
import type { MNode } from '@tmagic/schema';
|
|
42
47
|
|
|
43
48
|
import SearchInput from '@editor/components/SearchInput.vue';
|
|
44
49
|
import Tree from '@editor/components/Tree.vue';
|
|
45
|
-
import {
|
|
50
|
+
import { useFilter } from '@editor/hooks/use-filter';
|
|
51
|
+
import { LayerPanelSlots, MenuButton, MenuComponent, Services, TreeNodeData } from '@editor/type';
|
|
46
52
|
|
|
47
53
|
import LayerMenu from './LayerMenu.vue';
|
|
48
54
|
import LayerNodeTool from './LayerNodeTool.vue';
|
|
49
55
|
import { useClick } from './use-click';
|
|
50
56
|
import { useDrag } from './use-drag';
|
|
51
|
-
import { useFilter } from './use-filter';
|
|
52
57
|
import { useKeybinding } from './use-keybinding';
|
|
53
58
|
import { useNodeStatus } from './use-node-status';
|
|
54
59
|
|
|
@@ -68,11 +73,23 @@ const editorService = services?.editorService;
|
|
|
68
73
|
const tree = ref<InstanceType<typeof Tree>>();
|
|
69
74
|
|
|
70
75
|
const page = computed(() => editorService?.get('page'));
|
|
76
|
+
const nodeData = computed<TreeNodeData[]>(() => (!page.value ? [] : [page.value]));
|
|
71
77
|
|
|
72
|
-
const { nodeStatusMap } = useNodeStatus(services
|
|
78
|
+
const { nodeStatusMap } = useNodeStatus(services);
|
|
73
79
|
const { isCtrlKeyDown } = useKeybinding(services, tree);
|
|
74
80
|
|
|
75
|
-
const
|
|
81
|
+
const filterNodeMethod = (v: string, data: MNode): boolean => {
|
|
82
|
+
let name = '';
|
|
83
|
+
if (data.name) {
|
|
84
|
+
name = data.name;
|
|
85
|
+
} else if (data.items) {
|
|
86
|
+
name = 'container';
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return `${data.id}${name}${data.type}`.includes(v);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const { filterTextChangeHandler } = useFilter(nodeData, nodeStatusMap, filterNodeMethod);
|
|
76
93
|
|
|
77
94
|
const collapseAllHandler = () => {
|
|
78
95
|
if (!page.value || !nodeStatusMap.value) return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed,
|
|
1
|
+
import { computed, ref, watch } from 'vue';
|
|
2
2
|
|
|
3
3
|
import type { Id, MNode, MPage } from '@tmagic/schema';
|
|
4
4
|
import { getNodePath } from '@tmagic/utils';
|
|
@@ -7,22 +7,18 @@ import { LayerNodeStatus, Services } from '@editor/type';
|
|
|
7
7
|
import { traverseNode } from '@editor/utils';
|
|
8
8
|
import { updateStatus } from '@editor/utils/tree';
|
|
9
9
|
|
|
10
|
-
const createPageNodeStatus = (
|
|
11
|
-
services: Services | undefined,
|
|
12
|
-
pageId: Id,
|
|
13
|
-
initalLayerNodeStatus?: Map<Id, LayerNodeStatus>,
|
|
14
|
-
) => {
|
|
10
|
+
const createPageNodeStatus = (page: MPage, initalLayerNodeStatus?: Map<Id, LayerNodeStatus>) => {
|
|
15
11
|
const map = new Map<Id, LayerNodeStatus>();
|
|
16
12
|
|
|
17
|
-
map.set(
|
|
13
|
+
map.set(page.id, {
|
|
18
14
|
visible: true,
|
|
19
15
|
expand: true,
|
|
20
16
|
selected: true,
|
|
21
17
|
draggable: false,
|
|
22
18
|
});
|
|
23
19
|
|
|
24
|
-
|
|
25
|
-
traverseNode(node, (node) => {
|
|
20
|
+
page.items.forEach((node: MNode) =>
|
|
21
|
+
traverseNode<MNode>(node, (node) => {
|
|
26
22
|
map.set(
|
|
27
23
|
node.id,
|
|
28
24
|
initalLayerNodeStatus?.get(node.id) || {
|
|
@@ -38,7 +34,8 @@ const createPageNodeStatus = (
|
|
|
38
34
|
return map;
|
|
39
35
|
};
|
|
40
36
|
|
|
41
|
-
export const useNodeStatus = (services: Services | undefined
|
|
37
|
+
export const useNodeStatus = (services: Services | undefined) => {
|
|
38
|
+
const page = computed(() => services?.editorService.get('page'));
|
|
42
39
|
const nodes = computed(() => services?.editorService.get('nodes') || []);
|
|
43
40
|
|
|
44
41
|
/** 所有页面的节点状态 */
|
|
@@ -57,7 +54,7 @@ export const useNodeStatus = (services: Services | undefined, page: ComputedRef<
|
|
|
57
54
|
return;
|
|
58
55
|
}
|
|
59
56
|
// 生成节点状态
|
|
60
|
-
nodeStatusMaps.value.set(page.id, createPageNodeStatus(
|
|
57
|
+
nodeStatusMaps.value.set(page.id, createPageNodeStatus(page, nodeStatusMaps.value.get(page.id)));
|
|
61
58
|
},
|
|
62
59
|
{
|
|
63
60
|
immediate: true,
|