@tmagic/editor 1.3.1 → 1.3.3
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 +50 -0
- package/dist/tmagic-editor.js +578 -574
- package/dist/tmagic-editor.js.map +1 -1
- package/dist/tmagic-editor.umd.cjs +590 -585
- package/dist/tmagic-editor.umd.cjs.map +1 -1
- package/package.json +15 -13
- package/src/components/CodeBlockEditor.vue +6 -4
- package/src/fields/DataSourceSelect.vue +15 -9
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-code-block-edit.ts +2 -0
- package/src/hooks/use-float-box.ts +153 -0
- package/src/index.ts +1 -0
- package/src/initService.ts +12 -11
- package/src/layouts/Framework.vue +10 -1
- package/src/layouts/sidebar/Sidebar.vue +90 -5
- package/src/layouts/sidebar/code-block/CodeBlockList.vue +2 -1
- package/src/layouts/sidebar/code-block/CodeBlockListPanel.vue +11 -10
- package/src/layouts/sidebar/data-source/DataSourceConfigPanel.vue +6 -4
- package/src/layouts/sidebar/data-source/DataSourceList.vue +9 -8
- package/src/layouts/sidebar/data-source/DataSourceListPanel.vue +15 -15
- package/src/layouts/sidebar/layer/use-drag.ts +4 -0
- package/src/layouts/sidebar/layer/use-node-status.ts +20 -15
- package/src/services/dataSource.ts +4 -0
- package/src/services/dep.ts +22 -284
- package/src/services/ui.ts +15 -0
- package/src/theme/code-block.scss +5 -0
- package/src/theme/floatbox.scss +48 -0
- package/src/theme/sidebar.scss +1 -0
- package/src/theme/theme.scss +1 -0
- package/src/type.ts +30 -20
- package/types/components/CodeBlockEditor.vue.d.ts +3 -0
- package/types/fields/DataSourceSelect.vue.d.ts +6 -4
- package/types/hooks/index.d.ts +1 -0
- package/types/hooks/use-code-block-edit.d.ts +26 -46
- package/types/hooks/use-data-source-method.d.ts +26 -46
- package/types/hooks/use-float-box.d.ts +15 -0
- package/types/index.d.ts +1 -0
- package/types/layouts/PropsPanel.vue.d.ts +92 -59
- package/types/layouts/sidebar/Sidebar.vue.d.ts +1 -2
- package/types/layouts/sidebar/code-block/CodeBlockList.vue.d.ts +1 -1
- package/types/layouts/sidebar/code-block/CodeBlockListPanel.vue.d.ts +3 -1
- package/types/layouts/sidebar/data-source/DataSourceConfigPanel.vue.d.ts +3 -0
- package/types/layouts/sidebar/data-source/DataSourceList.vue.d.ts +1 -1
- package/types/layouts/sidebar/data-source/DataSourceListPanel.vue.d.ts +15 -2
- package/types/layouts/sidebar/layer/use-click.d.ts +7 -46
- package/types/services/dataSource.d.ts +10 -2
- package/types/services/dep.d.ts +12 -112
- package/types/services/ui.d.ts +8 -0
- package/types/type.d.ts +23 -18
- package/src/utils/dep.ts +0 -81
- package/types/utils/dep.d.ts +0 -6
|
@@ -38,11 +38,12 @@
|
|
|
38
38
|
import { computed, inject, ref } from 'vue';
|
|
39
39
|
import { Aim, Close, Coin, Edit, View } from '@element-plus/icons-vue';
|
|
40
40
|
|
|
41
|
+
import { DepTargetType } from '@tmagic/dep';
|
|
41
42
|
import { tMagicMessageBox, TMagicTooltip, TMagicTree } from '@tmagic/design';
|
|
42
|
-
import {
|
|
43
|
+
import { DepData, Id } from '@tmagic/schema';
|
|
43
44
|
|
|
44
45
|
import Icon from '@editor/components/Icon.vue';
|
|
45
|
-
import {
|
|
46
|
+
import type { DataSourceListSlots, Services } from '@editor/type';
|
|
46
47
|
|
|
47
48
|
defineSlots<DataSourceListSlots>();
|
|
48
49
|
|
|
@@ -65,10 +66,10 @@ const dsDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE) |
|
|
|
65
66
|
const dsMethodDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_METHOD) || {});
|
|
66
67
|
const dsCondDep = computed(() => depService?.getTargets(DepTargetType.DATA_SOURCE_COND) || {});
|
|
67
68
|
|
|
68
|
-
const getKeyTreeConfig = (dep:
|
|
69
|
+
const getKeyTreeConfig = (dep: DepData[string], type?: string) =>
|
|
69
70
|
dep.keys.map((key) => ({ name: key, id: key, type: 'key', isMethod: type === 'method', isCond: type === 'cond' }));
|
|
70
71
|
|
|
71
|
-
const getNodeTreeConfig = (id: string, dep:
|
|
72
|
+
const getNodeTreeConfig = (id: string, dep: DepData[string], type?: string) => ({
|
|
72
73
|
name: dep.name,
|
|
73
74
|
type: 'node',
|
|
74
75
|
id,
|
|
@@ -81,7 +82,7 @@ const getNodeTreeConfig = (id: string, dep: Dep[string], type?: string) => ({
|
|
|
81
82
|
* @param deps 依赖
|
|
82
83
|
* @param type 依赖类型
|
|
83
84
|
*/
|
|
84
|
-
const mergeChildren = (children: any[], deps:
|
|
85
|
+
const mergeChildren = (children: any[], deps: DepData, type?: string) => {
|
|
85
86
|
Object.entries(deps).forEach(([id, dep]) => {
|
|
86
87
|
// 已经生成过的节点
|
|
87
88
|
const nodeItem = children.find((item) => item.id === id);
|
|
@@ -97,9 +98,9 @@ const mergeChildren = (children: any[], deps: Dep, type?: string) => {
|
|
|
97
98
|
|
|
98
99
|
const list = computed(() =>
|
|
99
100
|
dataSources.value.map((ds) => {
|
|
100
|
-
const dsDeps = dsDep.value[ds.id]
|
|
101
|
-
const dsMethodDeps = dsMethodDep.value[ds.id]
|
|
102
|
-
const dsCondDeps = dsCondDep.value[ds.id]
|
|
101
|
+
const dsDeps = dsDep.value[ds.id]?.deps || {};
|
|
102
|
+
const dsMethodDeps = dsMethodDep.value[ds.id]?.deps || {};
|
|
103
|
+
const dsCondDeps = dsCondDep.value[ds.id]?.deps || {};
|
|
103
104
|
|
|
104
105
|
const children: any[] = [];
|
|
105
106
|
// 数据源依赖分为三种类型:key/node、method、cond,是分开存储,这里将其合并展示
|
|
@@ -23,20 +23,16 @@
|
|
|
23
23
|
</div>
|
|
24
24
|
|
|
25
25
|
<!-- 数据源列表 -->
|
|
26
|
-
<DataSourceList @edit="editHandler" @remove="removeHandler">
|
|
27
|
-
<template #data-source-panel-tool="{ data }">
|
|
28
|
-
<slot name="data-source-panel-tool" :data="data"></slot>
|
|
29
|
-
</template>
|
|
30
|
-
</DataSourceList>
|
|
31
|
-
|
|
32
|
-
<DataSourceConfigPanel
|
|
33
|
-
ref="editDialog"
|
|
34
|
-
:disabled="!editable"
|
|
35
|
-
:values="dataSourceValues"
|
|
36
|
-
:title="dialogTitle"
|
|
37
|
-
@submit="submitDataSourceHandler"
|
|
38
|
-
></DataSourceConfigPanel>
|
|
26
|
+
<DataSourceList @edit="editHandler" @remove="removeHandler"></DataSourceList>
|
|
39
27
|
</TMagicScrollbar>
|
|
28
|
+
<DataSourceConfigPanel
|
|
29
|
+
ref="editDialog"
|
|
30
|
+
:disabled="!editable"
|
|
31
|
+
:values="dataSourceValues"
|
|
32
|
+
:title="dialogTitle"
|
|
33
|
+
:slideType="slideType"
|
|
34
|
+
@submit="submitDataSourceHandler"
|
|
35
|
+
></DataSourceConfigPanel>
|
|
40
36
|
</template>
|
|
41
37
|
|
|
42
38
|
<script setup lang="ts">
|
|
@@ -48,7 +44,7 @@ import type { DataSourceSchema } from '@tmagic/schema';
|
|
|
48
44
|
|
|
49
45
|
import SearchInput from '@editor/components/SearchInput.vue';
|
|
50
46
|
import ToolButton from '@editor/components/ToolButton.vue';
|
|
51
|
-
import type { DataSourceListSlots, Services } from '@editor/type';
|
|
47
|
+
import type { DataSourceListSlots, Services, SlideType } from '@editor/type';
|
|
52
48
|
|
|
53
49
|
import DataSourceConfigPanel from './DataSourceConfigPanel.vue';
|
|
54
50
|
import DataSourceList from './DataSourceList.vue';
|
|
@@ -59,6 +55,10 @@ defineOptions({
|
|
|
59
55
|
name: 'MEditorDataSourceListPanel',
|
|
60
56
|
});
|
|
61
57
|
|
|
58
|
+
defineProps<{
|
|
59
|
+
slideType?: SlideType;
|
|
60
|
+
}>();
|
|
61
|
+
|
|
62
62
|
const { dataSourceService } = inject<Services>('services') || {};
|
|
63
63
|
|
|
64
64
|
const editDialog = ref<InstanceType<typeof DataSourceConfigPanel>>();
|
|
@@ -102,7 +102,7 @@ const editHandler = (id: string) => {
|
|
|
102
102
|
...dataSourceService?.getDataSourceById(id),
|
|
103
103
|
};
|
|
104
104
|
|
|
105
|
-
dialogTitle.value =
|
|
105
|
+
dialogTitle.value = `编辑${dataSourceValues.value.title || ''}`;
|
|
106
106
|
|
|
107
107
|
editDialog.value.show();
|
|
108
108
|
};
|
|
@@ -121,6 +121,10 @@ export const useDrag = (services: Services | undefined) => {
|
|
|
121
121
|
removeStatusClass(dragState.container);
|
|
122
122
|
|
|
123
123
|
if (node && dragState.dragOverNodeId && dragState.dropType && services) {
|
|
124
|
+
if (dragState.dragOverNodeId === node.id) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
124
128
|
const targetInfo = services.editorService.getNodeInfo(dragState.dragOverNodeId, false);
|
|
125
129
|
const targetNode = targetInfo.node;
|
|
126
130
|
let targetParent = targetInfo.parent;
|
|
@@ -7,7 +7,11 @@ 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 = (
|
|
10
|
+
const createPageNodeStatus = (
|
|
11
|
+
services: Services | undefined,
|
|
12
|
+
pageId: Id,
|
|
13
|
+
initalLayerNodeStatus?: Map<Id, LayerNodeStatus>,
|
|
14
|
+
) => {
|
|
11
15
|
const map = new Map<Id, LayerNodeStatus>();
|
|
12
16
|
|
|
13
17
|
map.set(pageId, {
|
|
@@ -19,12 +23,15 @@ const createPageNodeStatus = (services: Services | undefined, pageId: Id) => {
|
|
|
19
23
|
|
|
20
24
|
services?.editorService.getNodeById(pageId)?.items.forEach((node: MNode) =>
|
|
21
25
|
traverseNode(node, (node) => {
|
|
22
|
-
map.set(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
map.set(
|
|
27
|
+
node.id,
|
|
28
|
+
initalLayerNodeStatus?.get(node.id) || {
|
|
29
|
+
visible: true,
|
|
30
|
+
expand: false,
|
|
31
|
+
selected: false,
|
|
32
|
+
draggable: true,
|
|
33
|
+
},
|
|
34
|
+
);
|
|
28
35
|
}),
|
|
29
36
|
);
|
|
30
37
|
|
|
@@ -42,17 +49,15 @@ export const useNodeStatus = (services: Services | undefined, page: ComputedRef<
|
|
|
42
49
|
page.value ? nodeStatusMaps.value.get(page.value.id) : new Map<Id, LayerNodeStatus>(),
|
|
43
50
|
);
|
|
44
51
|
|
|
45
|
-
//
|
|
52
|
+
// 切换页面或者新增页面,重新生成节点状态
|
|
46
53
|
watch(
|
|
47
|
-
|
|
48
|
-
(
|
|
49
|
-
|
|
50
|
-
if (!pageId || nodeStatusMaps.value.has(pageId)) {
|
|
54
|
+
page,
|
|
55
|
+
(page) => {
|
|
56
|
+
if (!page) {
|
|
51
57
|
return;
|
|
52
58
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
nodeStatusMaps.value.set(pageId, createPageNodeStatus(services, pageId));
|
|
59
|
+
// 生成节点状态
|
|
60
|
+
nodeStatusMaps.value.set(page.id, createPageNodeStatus(services, page.id, nodeStatusMaps.value.get(page.id)));
|
|
56
61
|
},
|
|
57
62
|
{
|
|
58
63
|
immediate: true,
|
|
@@ -82,6 +82,8 @@ class DataSource extends BaseService {
|
|
|
82
82
|
this.get('dataSources').push(newConfig);
|
|
83
83
|
|
|
84
84
|
this.emit('add', newConfig);
|
|
85
|
+
|
|
86
|
+
return newConfig;
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
public update(config: DataSourceSchema) {
|
|
@@ -92,6 +94,8 @@ class DataSource extends BaseService {
|
|
|
92
94
|
dataSources[index] = cloneDeep(config);
|
|
93
95
|
|
|
94
96
|
this.emit('update', config);
|
|
97
|
+
|
|
98
|
+
return config;
|
|
95
99
|
}
|
|
96
100
|
|
|
97
101
|
public remove(id: string) {
|
package/src/services/dep.ts
CHANGED
|
@@ -15,320 +15,58 @@
|
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
17
|
*/
|
|
18
|
-
import { EventEmitter } from 'events';
|
|
19
|
-
|
|
20
18
|
import { reactive } from 'vue';
|
|
21
19
|
|
|
22
|
-
import
|
|
23
|
-
import {
|
|
24
|
-
|
|
25
|
-
import { DepTargetType } from '@editor/type';
|
|
26
|
-
|
|
27
|
-
type IsTarget = (key: string | number, value: any) => boolean;
|
|
28
|
-
|
|
29
|
-
interface TargetOptions {
|
|
30
|
-
isTarget: IsTarget;
|
|
31
|
-
id: string | number;
|
|
32
|
-
/** 类型,数据源、代码块或其他 */
|
|
33
|
-
type?: DepTargetType | string;
|
|
34
|
-
name?: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
interface TargetList {
|
|
38
|
-
[type: DepTargetType | string]: {
|
|
39
|
-
[targetId: string | number]: Target;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* 需要收集依赖的目标
|
|
45
|
-
* 例如:一个代码块可以为一个目标
|
|
46
|
-
*/
|
|
47
|
-
export class Target extends EventEmitter {
|
|
48
|
-
/**
|
|
49
|
-
* 如何识别目标
|
|
50
|
-
*/
|
|
51
|
-
public isTarget: IsTarget;
|
|
52
|
-
/**
|
|
53
|
-
* 目标id,不可重复
|
|
54
|
-
* 例如目标是代码块,则为代码块id
|
|
55
|
-
*/
|
|
56
|
-
public id: string | number;
|
|
57
|
-
/**
|
|
58
|
-
* 目标名称,用于显示在依赖列表中
|
|
59
|
-
*/
|
|
60
|
-
public name?: string;
|
|
61
|
-
/**
|
|
62
|
-
* 不同的目标可以进行分类,例如代码块,数据源可以为两个不同的type
|
|
63
|
-
*/
|
|
64
|
-
public type: DepTargetType | string = DepTargetType.DEFAULT;
|
|
65
|
-
/**
|
|
66
|
-
* 依赖详情
|
|
67
|
-
* 实例:{ 'node_id': { name: 'node_name', keys: [ created, mounted ] } }
|
|
68
|
-
*/
|
|
69
|
-
public deps = reactive<Dep>({});
|
|
70
|
-
|
|
71
|
-
constructor(options: TargetOptions) {
|
|
72
|
-
super();
|
|
73
|
-
this.isTarget = options.isTarget;
|
|
74
|
-
this.id = options.id;
|
|
75
|
-
this.name = options.name;
|
|
76
|
-
if (options.type) {
|
|
77
|
-
this.type = options.type;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* 更新依赖
|
|
83
|
-
* @param node 节点配置
|
|
84
|
-
* @param key 哪个key配置了这个目标的id
|
|
85
|
-
*/
|
|
86
|
-
public updateDep(node: MNode, key: string | number) {
|
|
87
|
-
const dep = this.deps[node.id] || {
|
|
88
|
-
name: node.name,
|
|
89
|
-
keys: [],
|
|
90
|
-
};
|
|
20
|
+
import { DepTargetType, type Target, Watcher } from '@tmagic/dep';
|
|
21
|
+
import type { Id, MNode } from '@tmagic/schema';
|
|
91
22
|
|
|
92
|
-
|
|
93
|
-
dep.name = node.name;
|
|
94
|
-
}
|
|
23
|
+
import BaseService from './BaseService';
|
|
95
24
|
|
|
96
|
-
|
|
25
|
+
class Dep extends BaseService {
|
|
26
|
+
private watcher = new Watcher({ initialTargets: reactive({}) });
|
|
97
27
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
}
|
|
28
|
+
public removeTargets(type: string = DepTargetType.DEFAULT) {
|
|
29
|
+
this.watcher.removeTargets(type);
|
|
101
30
|
|
|
102
|
-
this.emit('
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* 删除依赖
|
|
107
|
-
* @param node 哪个节点的依赖需要移除,如果为空,则移除所有依赖
|
|
108
|
-
* @param key 节点下哪个key需要移除,如果为空,则移除改节点下的所有依赖key
|
|
109
|
-
* @returns void
|
|
110
|
-
*/
|
|
111
|
-
public removeDep(node?: MNode, key?: string | number) {
|
|
112
|
-
if (!node) {
|
|
113
|
-
Object.keys(this.deps).forEach((depKey) => {
|
|
114
|
-
delete this.deps[depKey];
|
|
115
|
-
});
|
|
116
|
-
this.emit('change');
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const dep = this.deps[node.id];
|
|
121
|
-
|
|
122
|
-
if (!dep) return;
|
|
123
|
-
|
|
124
|
-
if (key) {
|
|
125
|
-
const index = dep.keys.indexOf(key);
|
|
126
|
-
dep.keys.splice(index, 1);
|
|
127
|
-
|
|
128
|
-
if (dep.keys.length === 0) {
|
|
129
|
-
delete this.deps[node.id];
|
|
130
|
-
}
|
|
131
|
-
} else {
|
|
132
|
-
delete this.deps[node.id];
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
this.emit('change');
|
|
31
|
+
this.emit('remove-target');
|
|
136
32
|
}
|
|
137
33
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
* @param node 哪个节点
|
|
141
|
-
* @param key 哪个key
|
|
142
|
-
* @returns boolean
|
|
143
|
-
*/
|
|
144
|
-
public hasDep(node: MNode, key: string | number) {
|
|
145
|
-
const dep = this.deps[node.id];
|
|
146
|
-
|
|
147
|
-
return Boolean(dep?.keys.find((d) => d === key));
|
|
34
|
+
public getTargets(type: string = DepTargetType.DEFAULT) {
|
|
35
|
+
return this.watcher.getTargets(type);
|
|
148
36
|
}
|
|
149
37
|
|
|
150
|
-
public
|
|
151
|
-
this.
|
|
38
|
+
public getTarget(id: Id) {
|
|
39
|
+
return this.watcher.getTarget(id);
|
|
152
40
|
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export class Watcher extends EventEmitter {
|
|
156
|
-
private targets = reactive<TargetList>({});
|
|
157
41
|
|
|
158
|
-
/**
|
|
159
|
-
* 获取指定类型中的所有target
|
|
160
|
-
* @param type 分类
|
|
161
|
-
* @returns Target[]
|
|
162
|
-
*/
|
|
163
|
-
public getTargets(type: DepTargetType | string = DepTargetType.DEFAULT) {
|
|
164
|
-
return this.targets[type] || {};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* 添加新的目标
|
|
169
|
-
* @param target Target
|
|
170
|
-
*/
|
|
171
42
|
public addTarget(target: Target) {
|
|
172
|
-
|
|
173
|
-
this.targets[target.type] = targets;
|
|
174
|
-
targets[target.id] = target;
|
|
175
|
-
|
|
43
|
+
this.watcher.addTarget(target);
|
|
176
44
|
this.emit('add-target', target);
|
|
177
45
|
}
|
|
178
46
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
* @param id target id
|
|
182
|
-
* @returns Target
|
|
183
|
-
*/
|
|
184
|
-
public getTarget(id: string | number) {
|
|
185
|
-
const allTargets = Object.values(this.targets);
|
|
186
|
-
for (const targets of allTargets) {
|
|
187
|
-
if (targets[id]) {
|
|
188
|
-
return targets[id];
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* 判断是否存在指定id的target
|
|
195
|
-
* @param id target id
|
|
196
|
-
* @returns boolean
|
|
197
|
-
*/
|
|
198
|
-
public hasTarget(id: string | number) {
|
|
199
|
-
const allTargets = Object.values(this.targets);
|
|
200
|
-
for (const targets of allTargets) {
|
|
201
|
-
if (targets[id]) {
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return false;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* 删除指定id的target
|
|
211
|
-
* @param id target id
|
|
212
|
-
*/
|
|
213
|
-
public removeTarget(id: string | number) {
|
|
214
|
-
const allTargets = Object.values(this.targets);
|
|
215
|
-
for (const targets of allTargets) {
|
|
216
|
-
if (targets[id]) {
|
|
217
|
-
targets[id].destroy();
|
|
218
|
-
delete targets[id];
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
this.emit('remove-target');
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* 删除指定分类的所有target
|
|
227
|
-
* @param type 分类
|
|
228
|
-
* @returns void
|
|
229
|
-
*/
|
|
230
|
-
public removeTargets(type: DepTargetType | string = DepTargetType.DEFAULT) {
|
|
231
|
-
const targets = this.targets[type];
|
|
232
|
-
|
|
233
|
-
if (!targets) return;
|
|
234
|
-
|
|
235
|
-
for (const target of Object.values(targets)) {
|
|
236
|
-
target.destroy();
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
delete this.targets[type];
|
|
240
|
-
|
|
47
|
+
public removeTarget(id: Id) {
|
|
48
|
+
this.watcher.removeTarget(id);
|
|
241
49
|
this.emit('remove-target');
|
|
242
50
|
}
|
|
243
51
|
|
|
244
|
-
/**
|
|
245
|
-
* 删除所有target
|
|
246
|
-
*/
|
|
247
52
|
public clearTargets() {
|
|
248
|
-
|
|
249
|
-
delete this.targets[key];
|
|
250
|
-
});
|
|
53
|
+
this.watcher.clearTargets();
|
|
251
54
|
}
|
|
252
55
|
|
|
253
|
-
/**
|
|
254
|
-
* 收集依赖
|
|
255
|
-
* @param nodes 需要收集的节点
|
|
256
|
-
* @param deep 是否需要收集子节点
|
|
257
|
-
*/
|
|
258
56
|
public collect(nodes: MNode[], deep = false) {
|
|
259
|
-
|
|
260
|
-
Object.values(targets).forEach((target) => {
|
|
261
|
-
nodes.forEach((node) => {
|
|
262
|
-
// 先删除原有依赖,重新收集
|
|
263
|
-
target.removeDep(node);
|
|
264
|
-
this.collectItem(node, target, deep);
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
});
|
|
268
|
-
|
|
57
|
+
this.watcher.collect(nodes, deep);
|
|
269
58
|
this.emit('collected', nodes, deep);
|
|
270
59
|
}
|
|
271
60
|
|
|
272
|
-
/**
|
|
273
|
-
* 清除依赖
|
|
274
|
-
* @param nodes 需要清除依赖的节点
|
|
275
|
-
*/
|
|
276
61
|
public clear(nodes?: MNode[]) {
|
|
277
|
-
|
|
278
|
-
Object.values(this.targets).forEach((targets) => {
|
|
279
|
-
Object.values(targets).forEach((target) => {
|
|
280
|
-
if (nodes) {
|
|
281
|
-
nodes.forEach((node) => {
|
|
282
|
-
target.removeDep(node);
|
|
283
|
-
|
|
284
|
-
if (Array.isArray(node.items) && node.items.length && !clearedItemsNodeIds.includes(node.id)) {
|
|
285
|
-
clearedItemsNodeIds.push(node.id);
|
|
286
|
-
this.clear(node.items);
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
} else {
|
|
290
|
-
target.removeDep();
|
|
291
|
-
}
|
|
292
|
-
});
|
|
293
|
-
});
|
|
62
|
+
return this.watcher.clear(nodes);
|
|
294
63
|
}
|
|
295
64
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const doCollect = (key: string, value: any) => {
|
|
299
|
-
const keyIsItems = key === 'items';
|
|
300
|
-
const fullKey = prop ? `${prop}.${key}` : key;
|
|
301
|
-
|
|
302
|
-
if (target.isTarget(fullKey, value)) {
|
|
303
|
-
target.updateDep(node, fullKey);
|
|
304
|
-
this.emit('update-dep', node, fullKey);
|
|
305
|
-
} else if (!keyIsItems && Array.isArray(value)) {
|
|
306
|
-
value.forEach((item, index) => {
|
|
307
|
-
if (isObject(item)) {
|
|
308
|
-
collectTarget(item, `${fullKey}.${index}`);
|
|
309
|
-
}
|
|
310
|
-
});
|
|
311
|
-
} else if (isObject(value)) {
|
|
312
|
-
collectTarget(value, fullKey);
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
if (keyIsItems && deep && Array.isArray(value)) {
|
|
316
|
-
value.forEach((child) => {
|
|
317
|
-
this.collectItem(child, target, deep);
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
|
|
322
|
-
Object.entries(config).forEach(([key, value]) => {
|
|
323
|
-
if (typeof value === 'undefined' || value === '') return;
|
|
324
|
-
doCollect(key, value);
|
|
325
|
-
});
|
|
326
|
-
};
|
|
327
|
-
|
|
328
|
-
collectTarget(node);
|
|
65
|
+
public hasTarget(id: Id) {
|
|
66
|
+
return this.watcher.hasTarget(id);
|
|
329
67
|
}
|
|
330
68
|
}
|
|
331
69
|
|
|
332
|
-
export type DepService =
|
|
70
|
+
export type DepService = Dep;
|
|
333
71
|
|
|
334
|
-
export default new
|
|
72
|
+
export default new Dep();
|
package/src/services/ui.ts
CHANGED
|
@@ -44,6 +44,8 @@ const state = reactive<UiState>({
|
|
|
44
44
|
showRule: true,
|
|
45
45
|
propsPanelSize: 'small',
|
|
46
46
|
showAddPageButton: true,
|
|
47
|
+
floatBox: new Map(),
|
|
48
|
+
hideSlideBar: false,
|
|
47
49
|
});
|
|
48
50
|
|
|
49
51
|
class Ui extends BaseService {
|
|
@@ -95,6 +97,19 @@ class Ui extends BaseService {
|
|
|
95
97
|
return Math.min((width - 60) / stageWidth || 1, (height - 80) / stageHeight || 1);
|
|
96
98
|
}
|
|
97
99
|
|
|
100
|
+
public async setFloatBox(keys: string[]) {
|
|
101
|
+
const map = state.floatBox;
|
|
102
|
+
for (const key of keys) {
|
|
103
|
+
if (map.get(key)) continue;
|
|
104
|
+
map.set(key, {
|
|
105
|
+
status: false,
|
|
106
|
+
zIndex: 99,
|
|
107
|
+
top: 0,
|
|
108
|
+
left: 0,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
98
113
|
public resetState() {
|
|
99
114
|
this.set('showSrc', false);
|
|
100
115
|
this.set('uiSelectMode', false);
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
.m-editor-float-box-list {
|
|
2
|
+
.m-editor-float-box {
|
|
3
|
+
position: absolute;
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
width: auto;
|
|
7
|
+
height: 966px;
|
|
8
|
+
top: 240px;
|
|
9
|
+
left: 240px;
|
|
10
|
+
background: #fff;
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
z-index: 999;
|
|
13
|
+
max-width: auto;
|
|
14
|
+
min-width: auto;
|
|
15
|
+
max-height: auto;
|
|
16
|
+
min-height: auto;
|
|
17
|
+
border: 1px solid #eee;
|
|
18
|
+
box-shadow: 0 0 72px #ccc;
|
|
19
|
+
&-header {
|
|
20
|
+
display: flex;
|
|
21
|
+
align-items: center;
|
|
22
|
+
padding: 0 16px;
|
|
23
|
+
height: 44px;
|
|
24
|
+
border-bottom: 1px solid #d8dee8;
|
|
25
|
+
&:hover {
|
|
26
|
+
cursor: pointer;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
&-body {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex: 1;
|
|
32
|
+
width: 100%;
|
|
33
|
+
overflow: scroll;
|
|
34
|
+
> *:first-child {
|
|
35
|
+
min-width: 247px;
|
|
36
|
+
border-right: 1px solid #d8dee8;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
&-close {
|
|
41
|
+
position: absolute;
|
|
42
|
+
right: 16px;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
.moveable-resizable {
|
|
46
|
+
opacity: 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/theme/sidebar.scss
CHANGED