centaline-data-driven-v3 0.1.40 → 0.1.42
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/centaline-data-driven-v3.umd.js +96 -96
- package/package.json +1 -1
- package/src/components/web/Form.vue +275 -19
- package/src/components/web/Tree/Tree.vue +766 -176
- package/src/components/web/TreeList.vue +2 -2
- package/src/loader/src/SearchScreen.js +1 -1
- package/src/main.js +5 -4
- package/src/utils/request.js +5 -6
- package/src/views/Form.vue +2 -2
- package/src/views/SearchList.vue +5 -2
- package/src/views/Tree.vue +9 -3
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div id="ct-tree" class="ct-tree" oncontextmenu="event.preventDefault()" style="overflow:auto;" v-loading="loading"
|
|
3
3
|
:style="{ height: props.treeHeight - 10 + 'px' }">
|
|
4
|
-
<el-tree class="tree-line" :props="defaultProps" :
|
|
5
|
-
|
|
6
|
-
current-node-key="currentNodeKey">
|
|
7
|
-
|
|
4
|
+
<el-tree class="tree-line" :props="defaultProps" :expand-on-click-node="false" @node-click="handleNodeClick"
|
|
5
|
+
:filter-node-method="filterNode" lazy :load="loadNode" ref="refTree" @node-contextmenu="rightClick"
|
|
6
|
+
node-key="code" current-node-key="currentNodeKey" :default-expanded-keys="defaultExpandedKeys">
|
|
8
7
|
<template #default="{ node, data }">
|
|
9
|
-
<span>
|
|
10
|
-
<
|
|
8
|
+
<span class="node_content">
|
|
9
|
+
<el-icon class="node-icon" :class="{ 'is-leaf': node.isLeaf }">
|
|
10
|
+
<Document v-if="node.isLeaf" :size="14" />
|
|
11
|
+
<Folder v-else-if="!node.expanded" :size="14" />
|
|
12
|
+
<FolderOpened v-else :size="14" />
|
|
13
|
+
</el-icon>
|
|
14
|
+
<span style="" :ref="(el: refItem) => handleSetInputMap(el, data)">{{
|
|
11
15
|
data.name }}</span>
|
|
12
16
|
<span @click.stop>
|
|
13
17
|
<el-popover placement="right" :virtual-ref="nodeRef" virtual-triggering
|
|
14
|
-
:visible="((data.code == currentData.code && menuVisible &&
|
|
18
|
+
:visible="((data.code == currentData.code && menuVisible && allowedRoutes?.length > 0))">
|
|
15
19
|
<div class="box-menu">
|
|
16
|
-
<template v-for="(item, index) in
|
|
20
|
+
<template v-for="(item, index) in allowedRoutes">
|
|
17
21
|
<div class="opertion" @click="routerClickHandler(item)">
|
|
18
22
|
<div>
|
|
19
23
|
<img v-if="item.imgUrl" :src="item.imgUrl" alt="" />
|
|
@@ -22,22 +26,21 @@
|
|
|
22
26
|
</div>
|
|
23
27
|
</template>
|
|
24
28
|
</div>
|
|
25
|
-
|
|
26
29
|
</el-popover>
|
|
27
30
|
</span>
|
|
28
31
|
</span>
|
|
29
32
|
</template>
|
|
30
33
|
</el-tree>
|
|
31
|
-
|
|
32
|
-
|
|
33
34
|
</div>
|
|
34
35
|
</template>
|
|
36
|
+
|
|
35
37
|
<script setup lang="ts">
|
|
36
|
-
import { ref, nextTick, ComponentPublicInstance, onBeforeUnmount } from 'vue'
|
|
38
|
+
import { ref, nextTick, ComponentPublicInstance, onBeforeUnmount, computed, watch } from 'vue'
|
|
37
39
|
import common from '../../../utils/common'
|
|
38
40
|
import { RouterClickHandler } from '../../../utils/mixins';
|
|
39
41
|
import Enum from '../../../utils/Enum'
|
|
40
42
|
import Tree from '../../../loader/src/Tree';
|
|
43
|
+
|
|
41
44
|
type refItem = Element | ComponentPublicInstance | null;
|
|
42
45
|
|
|
43
46
|
const emit = defineEmits(['loaded'])
|
|
@@ -54,8 +57,15 @@ const props = defineProps({
|
|
|
54
57
|
apiParam: {
|
|
55
58
|
type: Object,
|
|
56
59
|
default: () => { },
|
|
60
|
+
},
|
|
61
|
+
// 新增:是否默认展开两级
|
|
62
|
+
expandTwoLevels: {
|
|
63
|
+
type: Boolean,
|
|
64
|
+
default: true
|
|
57
65
|
}
|
|
58
66
|
})
|
|
67
|
+
|
|
68
|
+
const lazy = ref(true)
|
|
59
69
|
const refTree = ref()
|
|
60
70
|
const rootNode = ref();
|
|
61
71
|
const rootResolve = ref();
|
|
@@ -69,15 +79,30 @@ const defaultProps = ref({
|
|
|
69
79
|
})
|
|
70
80
|
const searchStatus = ref([])
|
|
71
81
|
const screenPara = ref(props.apiParam);
|
|
72
|
-
const menuVisible = ref(false)
|
|
73
|
-
const currentData = ref({ code: "" })
|
|
74
|
-
const currentNode = ref(null)
|
|
75
|
-
const loading = ref(false)
|
|
82
|
+
const menuVisible = ref(false)
|
|
83
|
+
const currentData = ref({ code: "" })
|
|
84
|
+
const currentNode = ref(null)
|
|
85
|
+
const loading = ref(false)
|
|
76
86
|
|
|
77
87
|
const model = ref(null)
|
|
78
88
|
const nodeRef = ref()
|
|
79
89
|
const retryCount = ref(0);
|
|
80
90
|
const treeNodeRefMap = ref({});
|
|
91
|
+
const allowedRoutes = ref([]);
|
|
92
|
+
|
|
93
|
+
// 默认展开的节点key数组
|
|
94
|
+
const defaultExpandedKeys = ref([])
|
|
95
|
+
// 是否已设置默认展开
|
|
96
|
+
const hasSetDefaultExpand = ref(false)
|
|
97
|
+
// 是否是搜索状态
|
|
98
|
+
const isSearching = ref(false)
|
|
99
|
+
|
|
100
|
+
// 全量数据缓存
|
|
101
|
+
const fullTreeData = ref([])
|
|
102
|
+
|
|
103
|
+
// 新增:缓存所有节点的Map,用于快速查找
|
|
104
|
+
const nodeCodeMap = ref(new Map())
|
|
105
|
+
|
|
81
106
|
/** 动态设置Input Ref */
|
|
82
107
|
const handleSetInputMap = (el: refItem, item) => {
|
|
83
108
|
if (el) {
|
|
@@ -93,11 +118,100 @@ onBeforeUnmount(() => {
|
|
|
93
118
|
}
|
|
94
119
|
})
|
|
95
120
|
|
|
96
|
-
|
|
121
|
+
// 递归获取前两级节点的key
|
|
122
|
+
function getFirstTwoLevelKeys(nodes, level = 0, result = []) {
|
|
123
|
+
if (!nodes || nodes.length === 0 || level >= 1) {
|
|
124
|
+
return result;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
nodes.forEach(node => {
|
|
128
|
+
if (node.code) {
|
|
129
|
+
result.push(node.code);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (level < 1 && node.children && node.children.length > 0) {
|
|
133
|
+
getFirstTwoLevelKeys(node.children, level + 1, result);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// 递归获取所有节点的key(用于搜索时全展开)
|
|
141
|
+
function getAllNodeKeys(nodes, result = []) {
|
|
142
|
+
if (!nodes || nodes.length === 0) {
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
nodes.forEach(node => {
|
|
147
|
+
if (node.code) {
|
|
148
|
+
result.push(node.code);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (node.children && node.children.length > 0) {
|
|
152
|
+
getAllNodeKeys(node.children, result);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// 设置默认展开节点
|
|
160
|
+
function setDefaultExpandedNodes() {
|
|
161
|
+
if (!props.expandTwoLevels || !fullTreeData.value.length) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (isSearching.value) {
|
|
166
|
+
const allKeys = getAllNodeKeys(fullTreeData.value);
|
|
167
|
+
defaultExpandedKeys.value = allKeys;
|
|
168
|
+
} else {
|
|
169
|
+
defaultExpandedKeys.value = getFirstTwoLevelKeys(fullTreeData.value);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
hasSetDefaultExpand.value = true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// 新增:构建节点Map,便于快速查找
|
|
176
|
+
function buildNodeCodeMap(nodes) {
|
|
177
|
+
const map = new Map();
|
|
178
|
+
|
|
179
|
+
function traverse(nodeList) {
|
|
180
|
+
nodeList.forEach(node => {
|
|
181
|
+
if (node.code) {
|
|
182
|
+
map.set(node.code, node);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (node.children && node.children.length > 0) {
|
|
186
|
+
traverse(node.children);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
traverse(nodes);
|
|
192
|
+
return map;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// 新增:复制节点(深拷贝)
|
|
196
|
+
function cloneNode(node) {
|
|
197
|
+
const cloned = { ...node };
|
|
198
|
+
cloned.children = [];
|
|
199
|
+
return cloned;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// 搜索(查询条件调用)
|
|
97
203
|
function search(m) {
|
|
204
|
+
const hasValidSearchConditions = checkHasValidSearchConditions(m);
|
|
205
|
+
|
|
206
|
+
isSearching.value = hasValidSearchConditions;
|
|
98
207
|
screenPara.value = m;
|
|
208
|
+
|
|
209
|
+
if (!lazy.value) {
|
|
210
|
+
filterFullTreeData(screenPara.value);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
99
214
|
if (searchStatus.value.length == 0) {
|
|
100
|
-
// 重置计数器
|
|
101
215
|
retryCount.value = 0
|
|
102
216
|
if (qrtimer.value) clearTimeout(qrtimer.value);
|
|
103
217
|
searchStatus.value.push('a');
|
|
@@ -116,47 +230,465 @@ function search(m) {
|
|
|
116
230
|
}, 200);
|
|
117
231
|
}
|
|
118
232
|
}
|
|
119
|
-
|
|
233
|
+
|
|
234
|
+
// 检查是否有有效的搜索条件
|
|
235
|
+
function checkHasValidSearchConditions(filter) {
|
|
236
|
+
if (!filter) return false;
|
|
237
|
+
|
|
238
|
+
let searchConditions = [];
|
|
239
|
+
|
|
240
|
+
if (filter?.searchData?.fields) {
|
|
241
|
+
searchConditions = filter.searchData.fields;
|
|
242
|
+
} else if (filter?.fields) {
|
|
243
|
+
searchConditions = filter.fields;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const validConditions = filterValidConditions(searchConditions);
|
|
247
|
+
return validConditions && validConditions.length > 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
// 过滤掉 operation 为 1 的条件
|
|
253
|
+
function filterValidConditions(conditions) {
|
|
254
|
+
if (!conditions || !Array.isArray(conditions)) return [];
|
|
255
|
+
|
|
256
|
+
return conditions.filter(condition => {
|
|
257
|
+
return condition.operation !== 1;
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// 判断节点是否匹配所有搜索条件
|
|
262
|
+
function nodeMatchesAllConditions(node, conditions) {
|
|
263
|
+
const validConditions = filterValidConditions(conditions);
|
|
264
|
+
|
|
265
|
+
if (!validConditions || validConditions.length === 0) return true;
|
|
266
|
+
|
|
267
|
+
return validConditions.every(condition => {
|
|
268
|
+
const { fieldName1, operation, searchValue1, searchValue2, searchDataType } = condition;
|
|
269
|
+
let nodeValue = node[fieldName1];
|
|
270
|
+
|
|
271
|
+
if (nodeValue === undefined) {
|
|
272
|
+
const mappedField = Object.keys(node).find(key =>
|
|
273
|
+
key.toLowerCase() === fieldName1.toLowerCase()
|
|
274
|
+
);
|
|
275
|
+
if (mappedField) {
|
|
276
|
+
nodeValue = node[mappedField];
|
|
277
|
+
} else {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const strNodeValue = String(nodeValue || '').toLowerCase();
|
|
283
|
+
const strSearchValue = String(searchValue1 || '').toLowerCase();
|
|
284
|
+
|
|
285
|
+
switch (operation) {
|
|
286
|
+
case 2:
|
|
287
|
+
return strNodeValue === strSearchValue;
|
|
288
|
+
case 3:
|
|
289
|
+
return strNodeValue !== strSearchValue;
|
|
290
|
+
case 4:
|
|
291
|
+
return Number(nodeValue) > Number(searchValue1);
|
|
292
|
+
case 5:
|
|
293
|
+
return Number(nodeValue) >= Number(searchValue1);
|
|
294
|
+
case 6:
|
|
295
|
+
return Number(nodeValue) < Number(searchValue1);
|
|
296
|
+
case 7:
|
|
297
|
+
return Number(nodeValue) <= Number(searchValue1);
|
|
298
|
+
case 8:
|
|
299
|
+
return strNodeValue.includes(strSearchValue);
|
|
300
|
+
case 9:
|
|
301
|
+
return strNodeValue.startsWith(strSearchValue);
|
|
302
|
+
case 10:
|
|
303
|
+
return strNodeValue.endsWith(strSearchValue);
|
|
304
|
+
case 11:
|
|
305
|
+
return !strNodeValue.includes(strSearchValue);
|
|
306
|
+
case 12:
|
|
307
|
+
try {
|
|
308
|
+
const regex = new RegExp(searchValue1, 'i');
|
|
309
|
+
return regex.test(nodeValue);
|
|
310
|
+
} catch (e) {
|
|
311
|
+
console.warn('正则表达式错误:', e);
|
|
312
|
+
return false;
|
|
313
|
+
}
|
|
314
|
+
case 13:
|
|
315
|
+
if (!searchValue1) return false;
|
|
316
|
+
try {
|
|
317
|
+
const values = searchValue1.split(',').map(v => v.trim().toLowerCase());
|
|
318
|
+
return values.includes(strNodeValue);
|
|
319
|
+
} catch (e) {
|
|
320
|
+
console.warn('解析IN条件错误:', e);
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
case 14:
|
|
324
|
+
if (!searchValue1) return true;
|
|
325
|
+
try {
|
|
326
|
+
const values = searchValue1.split(',').map(v => v.trim().toLowerCase());
|
|
327
|
+
return !values.includes(strNodeValue);
|
|
328
|
+
} catch (e) {
|
|
329
|
+
console.warn('解析NotIN条件错误:', e);
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
default:
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// 修改:构建完整的过滤树,保持原始层级结构
|
|
339
|
+
function buildFilteredTreeWithOriginalHierarchy(matchedNodes) {
|
|
340
|
+
if (!matchedNodes || matchedNodes.length === 0) {
|
|
341
|
+
return [];
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const resultMap = new Map();
|
|
345
|
+
const rootNodes = [];
|
|
346
|
+
|
|
347
|
+
// 第一步:创建所有匹配节点的副本
|
|
348
|
+
matchedNodes.forEach(node => {
|
|
349
|
+
if (!resultMap.has(node.code)) {
|
|
350
|
+
const clonedNode = cloneNode(node);
|
|
351
|
+
resultMap.set(node.code, clonedNode);
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
// 第二步:为每个匹配节点建立完整的父子关系链
|
|
356
|
+
matchedNodes.forEach(matchedNode => {
|
|
357
|
+
// 从全量数据中查找该节点的完整路径
|
|
358
|
+
const fullNode = nodeCodeMap.value.get(matchedNode.code);
|
|
359
|
+
if (!fullNode) return;
|
|
360
|
+
|
|
361
|
+
// 递归向上查找父节点链
|
|
362
|
+
function findParentChain(currentNode, chain = []) {
|
|
363
|
+
chain.unshift(currentNode.code);
|
|
364
|
+
|
|
365
|
+
// 在全量数据中查找父节点
|
|
366
|
+
const parentCode = findParentCodeInFullTree(currentNode.code);
|
|
367
|
+
if (parentCode) {
|
|
368
|
+
const parentNode = nodeCodeMap.value.get(parentCode);
|
|
369
|
+
if (parentNode) {
|
|
370
|
+
findParentChain(parentNode, chain);
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return chain;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
const parentChain = findParentChain(fullNode);
|
|
378
|
+
|
|
379
|
+
// 构建完整的树结构
|
|
380
|
+
for (let i = 0; i < parentChain.length; i++) {
|
|
381
|
+
const currentCode = parentChain[i];
|
|
382
|
+
|
|
383
|
+
// 如果节点已经存在,跳过
|
|
384
|
+
if (resultMap.has(currentCode)) {
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// 从全量数据中获取节点
|
|
389
|
+
const originalNode = nodeCodeMap.value.get(currentCode);
|
|
390
|
+
if (!originalNode) continue;
|
|
391
|
+
|
|
392
|
+
// 创建节点副本
|
|
393
|
+
const clonedNode = cloneNode(originalNode);
|
|
394
|
+
resultMap.set(currentCode, clonedNode);
|
|
395
|
+
|
|
396
|
+
// 如果是根节点,添加到根节点数组
|
|
397
|
+
if (i === 0) {
|
|
398
|
+
// 检查是否已经存在于根节点中
|
|
399
|
+
const existingRoot = rootNodes.find(n => n.code === currentCode);
|
|
400
|
+
if (!existingRoot) {
|
|
401
|
+
rootNodes.push(clonedNode);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// 连接到父节点
|
|
406
|
+
if (i > 0) {
|
|
407
|
+
const parentCode = parentChain[i - 1];
|
|
408
|
+
const parentNode = resultMap.get(parentCode);
|
|
409
|
+
|
|
410
|
+
if (parentNode) {
|
|
411
|
+
// 检查是否已经包含该子节点
|
|
412
|
+
const existingChild = parentNode.children.find(child => child.code === currentCode);
|
|
413
|
+
if (!existingChild) {
|
|
414
|
+
parentNode.children.push(clonedNode);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// 最后,确保当前匹配节点连接到其父节点
|
|
421
|
+
const parentCode = findParentCodeInFullTree(matchedNode.code);
|
|
422
|
+
if (parentCode && resultMap.has(parentCode)) {
|
|
423
|
+
const parentNode = resultMap.get(parentCode);
|
|
424
|
+
const currentNode = resultMap.get(matchedNode.code);
|
|
425
|
+
|
|
426
|
+
if (parentNode && currentNode) {
|
|
427
|
+
// 检查是否已经包含该子节点
|
|
428
|
+
const existingChild = parentNode.children.find(child => child.code === matchedNode.code);
|
|
429
|
+
if (!existingChild) {
|
|
430
|
+
parentNode.children.push(currentNode);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// 第三步:清理根节点,确保它们没有重复的父节点
|
|
437
|
+
const finalRootNodes = [];
|
|
438
|
+
const usedNodes = new Set();
|
|
439
|
+
|
|
440
|
+
function isNodeUsedInTree(node) {
|
|
441
|
+
for (const root of rootNodes) {
|
|
442
|
+
if (isNodeInChildren(root, node.code)) {
|
|
443
|
+
return true;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
rootNodes.forEach(rootNode => {
|
|
450
|
+
// 如果这个节点已经是其他节点的子节点,则不作为根节点
|
|
451
|
+
if (!isNodeUsedInTree(rootNode)) {
|
|
452
|
+
finalRootNodes.push(rootNode);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
return finalRootNodes;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// 新增:在全量树中查找父节点code
|
|
460
|
+
function findParentCodeInFullTree(nodeCode) {
|
|
461
|
+
function findParent(nodes, targetCode, parentCode = null) {
|
|
462
|
+
for (const node of nodes) {
|
|
463
|
+
if (node.code === targetCode) {
|
|
464
|
+
return parentCode;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (node.children && node.children.length > 0) {
|
|
468
|
+
const found = findParent(node.children, targetCode, node.code);
|
|
469
|
+
if (found !== null) {
|
|
470
|
+
return found;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return findParent(fullTreeData.value, nodeCode);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// 新增:检查节点是否在子树中
|
|
481
|
+
function isNodeInChildren(parentNode, targetCode) {
|
|
482
|
+
if (parentNode.code === targetCode) {
|
|
483
|
+
return false; // 不检查自身
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (!parentNode.children || parentNode.children.length === 0) {
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
for (const child of parentNode.children) {
|
|
491
|
+
if (child.code === targetCode) {
|
|
492
|
+
return true;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (isNodeInChildren(child, targetCode)) {
|
|
496
|
+
return true;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
// 修改:过滤全量树数据,保持原始层级
|
|
504
|
+
function filterFullTreeData(filter) {
|
|
505
|
+
if (!fullTreeData.value.length) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
loading.value = true;
|
|
510
|
+
try {
|
|
511
|
+
let searchConditions = [];
|
|
512
|
+
|
|
513
|
+
if (filter?.searchData?.fields) {
|
|
514
|
+
searchConditions = filter.searchData.fields;
|
|
515
|
+
} else if (filter?.fields) {
|
|
516
|
+
searchConditions = filter.fields;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const validConditions = filterValidConditions(searchConditions);
|
|
520
|
+
|
|
521
|
+
if (!validConditions || validConditions.length === 0) {
|
|
522
|
+
refTree.value.store.setData(fullTreeData.value);
|
|
523
|
+
loading.value = false;
|
|
524
|
+
isSearching.value = false;
|
|
525
|
+
hasSetDefaultExpand.value = false;
|
|
526
|
+
defaultExpandedKeys.value = [];
|
|
527
|
+
|
|
528
|
+
// 先收起所有节点
|
|
529
|
+
if (refTree.value && refTree.value.store) {
|
|
530
|
+
Object.values(refTree.value.store.nodesMap).forEach((node: any) => {
|
|
531
|
+
if (node) {
|
|
532
|
+
node.expanded = false;
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
setDefaultExpandedNodes();
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// 递归查找所有匹配的节点
|
|
542
|
+
const findMatchedNodes = (nodes, result = []) => {
|
|
543
|
+
nodes.forEach(node => {
|
|
544
|
+
const nodeMatches = nodeMatchesAllConditions(node, validConditions);
|
|
545
|
+
|
|
546
|
+
if (nodeMatches) {
|
|
547
|
+
result.push(node);
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (node.children && node.children.length > 0) {
|
|
551
|
+
findMatchedNodes(node.children, result);
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
return result;
|
|
555
|
+
};
|
|
556
|
+
|
|
557
|
+
const matchedNodes = findMatchedNodes(fullTreeData.value);
|
|
558
|
+
|
|
559
|
+
// 构建保持原始层级的过滤树
|
|
560
|
+
let filteredData = [];
|
|
561
|
+
if (matchedNodes.length > 0) {
|
|
562
|
+
filteredData = buildFilteredTreeWithOriginalHierarchy(matchedNodes);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// 设置过滤后的数据
|
|
566
|
+
refTree.value.store.setData(filteredData);
|
|
567
|
+
|
|
568
|
+
// 搜索状态时展开所有节点
|
|
569
|
+
if (filteredData.length > 0 && isSearching.value) {
|
|
570
|
+
const allKeys = getAllNodeKeys(filteredData);
|
|
571
|
+
defaultExpandedKeys.value = allKeys;
|
|
572
|
+
|
|
573
|
+
nextTick(() => {
|
|
574
|
+
if (refTree.value && refTree.value.store) {
|
|
575
|
+
Object.values(refTree.value.store.nodesMap).forEach((node: any) => {
|
|
576
|
+
if (node) {
|
|
577
|
+
node.expanded = true;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
}
|
|
581
|
+
});
|
|
582
|
+
|
|
583
|
+
// 默认选中第一个可选节点
|
|
584
|
+
const findFirstSelectableNode = (nodes) => {
|
|
585
|
+
for (const node of nodes) {
|
|
586
|
+
if (!node.children || node.children.length === 0) {
|
|
587
|
+
return node;
|
|
588
|
+
}
|
|
589
|
+
const childResult = findFirstSelectableNode(node.children);
|
|
590
|
+
if (childResult) return childResult;
|
|
591
|
+
}
|
|
592
|
+
return nodes[0];
|
|
593
|
+
};
|
|
594
|
+
|
|
595
|
+
const firstNode = findFirstSelectableNode(filteredData);
|
|
596
|
+
if (firstNode && firstNode.code) {
|
|
597
|
+
nextTick(() => {
|
|
598
|
+
refTree.value.setCurrentKey(firstNode.code);
|
|
599
|
+
handleNodeClick(firstNode, true);
|
|
600
|
+
});
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
} catch (error) {
|
|
605
|
+
console.error('过滤树数据失败:', error);
|
|
606
|
+
} finally {
|
|
607
|
+
loading.value = false;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// 修改:加载节点,保存节点Map
|
|
120
612
|
function loadNode(node, resolve) {
|
|
613
|
+
|
|
614
|
+
if (!lazy.value) {
|
|
615
|
+
const nodeData = node.data;
|
|
616
|
+
resolve(nodeData.children)
|
|
617
|
+
return;
|
|
618
|
+
}
|
|
619
|
+
|
|
121
620
|
if (node.level === 0) {
|
|
122
621
|
loading.value = true;
|
|
123
622
|
rootNode.value = node
|
|
124
623
|
rootResolve.value = resolve;
|
|
624
|
+
|
|
125
625
|
return SearchTree(screenPara.value || undefined).then(data => {
|
|
126
626
|
loading.value = false;
|
|
127
|
-
|
|
128
|
-
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
const { tree, hasAnyLeaf } = buildDeptTreeByField(data.rows, data.source.content.columns || [], {
|
|
630
|
+
pathKey: 'deptPath',
|
|
631
|
+
separator: '.'
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
// 缓存全量数据并构建节点Map
|
|
635
|
+
if (hasAnyLeaf) {
|
|
636
|
+
fullTreeData.value = tree;
|
|
637
|
+
nodeCodeMap.value = buildNodeCodeMap(tree);
|
|
638
|
+
resolve(tree);
|
|
639
|
+
if (props.expandTwoLevels) {
|
|
640
|
+
nextTick(() => {
|
|
641
|
+
hasSetDefaultExpand.value = false;
|
|
642
|
+
setDefaultExpandedNodes();
|
|
643
|
+
});
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
else {
|
|
647
|
+
resolve(data.rows);
|
|
648
|
+
}
|
|
649
|
+
lazy.value = !hasAnyLeaf;
|
|
650
|
+
|
|
651
|
+
load(data, true);
|
|
652
|
+
}).catch(error => {
|
|
653
|
+
loading.value = false;
|
|
654
|
+
console.error('加载树数据失败:', error);
|
|
129
655
|
});
|
|
130
656
|
}
|
|
131
|
-
|
|
657
|
+
|
|
658
|
+
if (node.level >= 1 && lazy.value) {
|
|
132
659
|
let fields = model.value.searchData("code", node.data.code, 9, 3);
|
|
133
660
|
let filter = {
|
|
134
661
|
"searchData": {
|
|
135
|
-
// 先保留searchData的其他属性
|
|
136
662
|
...(screenPara.value?.searchData || {}),
|
|
137
|
-
// 再合并fields数组(将两个数组合并,而不是覆盖)
|
|
138
663
|
fields: [
|
|
139
664
|
...fields.fields,
|
|
140
665
|
...(screenPara.value?.searchData?.fields || [])
|
|
141
666
|
]
|
|
142
667
|
}
|
|
143
|
-
};
|
|
668
|
+
};
|
|
669
|
+
|
|
144
670
|
return SearchTree(filter).then(data => {
|
|
145
671
|
loading.value = false;
|
|
146
672
|
resolve(data.rows);
|
|
147
|
-
load(data, false)
|
|
673
|
+
load(data, false);
|
|
674
|
+
}).catch(error => {
|
|
675
|
+
loading.value = false;
|
|
676
|
+
console.error('加载子节点失败:', error);
|
|
148
677
|
});
|
|
149
678
|
}
|
|
150
679
|
}
|
|
151
|
-
|
|
152
|
-
|
|
680
|
+
|
|
681
|
+
// 加载数据
|
|
682
|
+
async function load(data, flagRootNode) {
|
|
153
683
|
model.value = data;
|
|
154
684
|
if (searchStatus.value.length > 0) {
|
|
155
685
|
searchStatus.value = searchStatus.value.slice(1)
|
|
156
686
|
}
|
|
687
|
+
|
|
157
688
|
loading.value = false;
|
|
158
689
|
menuVisible.value = false;
|
|
159
|
-
|
|
690
|
+
|
|
691
|
+
if (flagRootNode) {
|
|
160
692
|
if (model.value.rows && model.value.rows[0]) {
|
|
161
693
|
handleNodeClick(model.value.rows[0], true);
|
|
162
694
|
}
|
|
@@ -167,17 +699,77 @@ async function load(data, firstLoad) {
|
|
|
167
699
|
});
|
|
168
700
|
}
|
|
169
701
|
}
|
|
170
|
-
//查询数据
|
|
171
|
-
function SearchTree(m) {
|
|
172
702
|
|
|
703
|
+
// 查询数据
|
|
704
|
+
function SearchTree(m) {
|
|
173
705
|
return new Promise((resolve, reject) => {
|
|
174
706
|
if (typeof props.api !== 'undefined') {
|
|
175
|
-
|
|
176
|
-
|
|
707
|
+
Tree.loadSearchTreeApi(props.api, m)
|
|
708
|
+
.then(resolve)
|
|
709
|
+
.catch(reject);
|
|
710
|
+
} else {
|
|
711
|
+
reject(new Error('API未定义'));
|
|
177
712
|
}
|
|
178
713
|
});
|
|
179
714
|
}
|
|
180
|
-
|
|
715
|
+
|
|
716
|
+
// 重置树到全量数据
|
|
717
|
+
function resetTree() {
|
|
718
|
+
isSearching.value = false;
|
|
719
|
+
if (fullTreeData.value.length > 0) {
|
|
720
|
+
refTree.value.store.setData(fullTreeData.value);
|
|
721
|
+
hasSetDefaultExpand.value = false;
|
|
722
|
+
defaultExpandedKeys.value = [];
|
|
723
|
+
|
|
724
|
+
if (fullTreeData.value[0] && fullTreeData.value[0].code) {
|
|
725
|
+
nextTick(() => {
|
|
726
|
+
if (refTree.value && refTree.value.store) {
|
|
727
|
+
Object.values(refTree.value.store.nodesMap).forEach((node: any) => {
|
|
728
|
+
if (node) {
|
|
729
|
+
node.expanded = false;
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
refTree.value.setCurrentKey(fullTreeData.value[0].code);
|
|
735
|
+
handleNodeClick(fullTreeData.value[0], true);
|
|
736
|
+
setDefaultExpandedNodes();
|
|
737
|
+
});
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
// 清除搜索条件
|
|
743
|
+
function clearSearch() {
|
|
744
|
+
screenPara.value = {};
|
|
745
|
+
isSearching.value = false;
|
|
746
|
+
|
|
747
|
+
defaultExpandedKeys.value = [];
|
|
748
|
+
hasSetDefaultExpand.value = false;
|
|
749
|
+
|
|
750
|
+
if (fullTreeData.value.length > 0) {
|
|
751
|
+
refTree.value.store.setData(fullTreeData.value);
|
|
752
|
+
|
|
753
|
+
nextTick(() => {
|
|
754
|
+
if (refTree.value && refTree.value.store) {
|
|
755
|
+
Object.values(refTree.value.store.nodesMap).forEach((node: any) => {
|
|
756
|
+
if (node) {
|
|
757
|
+
node.expanded = false;
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
setDefaultExpandedNodes();
|
|
763
|
+
|
|
764
|
+
if (fullTreeData.value[0] && fullTreeData.value[0].code) {
|
|
765
|
+
refTree.value.setCurrentKey(fullTreeData.value[0].code);
|
|
766
|
+
handleNodeClick(fullTreeData.value[0], true);
|
|
767
|
+
}
|
|
768
|
+
});
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
//节点点击事件
|
|
181
773
|
function handleNodeClick(data, formType) {
|
|
182
774
|
closeMenu();
|
|
183
775
|
if (data && formType) {
|
|
@@ -194,33 +786,41 @@ function handleNodeClick(data, formType) {
|
|
|
194
786
|
})
|
|
195
787
|
model.value.requestAction(rowRouter.action, SearchData, function (rowdata) {
|
|
196
788
|
var newdata = common.deepClone(data);
|
|
789
|
+
delete newdata.children;
|
|
790
|
+
|
|
197
791
|
if (rowdata) {
|
|
198
|
-
newdata.rowRouter = rowdata
|
|
792
|
+
newdata.rowRouter = rowdata;
|
|
199
793
|
}
|
|
200
794
|
newdata.title = model.value.source?.content?.title || '';
|
|
201
795
|
emit('loaded', newdata);
|
|
202
796
|
});
|
|
203
797
|
}
|
|
204
798
|
}
|
|
799
|
+
|
|
205
800
|
//右键菜单
|
|
206
|
-
function rightClick(event, object, Node) {
|
|
801
|
+
function rightClick(event, object, Node) {
|
|
207
802
|
nodeRef.value = treeNodeRefMap.value[`node_Ref_${object.code}`]
|
|
208
803
|
|
|
209
804
|
currentData.value = object
|
|
210
805
|
currentNode.value = Node
|
|
211
806
|
let actionIndex = 0;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
807
|
+
|
|
808
|
+
allowedRoutes.value = (model.value.actionRouter || []).filter(v => {
|
|
809
|
+
const val = currentData.value[v.rightField]
|
|
810
|
+
const hit = val == '1' || val === undefined || val === null;
|
|
811
|
+
return hit;
|
|
812
|
+
})
|
|
813
|
+
|
|
814
|
+
allowedRoutes.value?.forEach(() => {
|
|
815
|
+
menuVisible.value = true
|
|
816
|
+
actionIndex += 1
|
|
817
|
+
})
|
|
818
|
+
|
|
220
819
|
if (menuVisible.value) {
|
|
221
|
-
document.addEventListener('click', closeMenu)
|
|
820
|
+
document.addEventListener('click', closeMenu)
|
|
222
821
|
}
|
|
223
822
|
}
|
|
823
|
+
|
|
224
824
|
//关闭菜单
|
|
225
825
|
function closeMenu() {
|
|
226
826
|
menuVisible.value = false;
|
|
@@ -228,6 +828,7 @@ function closeMenu() {
|
|
|
228
828
|
currentData.value = { ...currentData.value, code: "" }
|
|
229
829
|
document.removeEventListener('click', closeMenu)
|
|
230
830
|
}
|
|
831
|
+
|
|
231
832
|
// 菜单路由
|
|
232
833
|
function routerClickHandler(field) {
|
|
233
834
|
var submitData = {};
|
|
@@ -238,48 +839,48 @@ function routerClickHandler(field) {
|
|
|
238
839
|
|
|
239
840
|
RouterClickHandler(field, submitData, null, model.value, 'tree', function (newData) {
|
|
240
841
|
switch (field.actionType) {
|
|
241
|
-
case Enum.ActionType.Delete
|
|
242
|
-
case Enum.ActionType.CloseTabThenDelete
|
|
243
|
-
removeNode(newData)
|
|
842
|
+
case Enum.ActionType.Delete:
|
|
843
|
+
case Enum.ActionType.CloseTabThenDelete:
|
|
844
|
+
removeNode(newData);
|
|
244
845
|
break;
|
|
245
|
-
case Enum.ActionType.New
|
|
246
|
-
case Enum.ActionType.CloseTabThenNew
|
|
247
|
-
addNode(newData)
|
|
846
|
+
case Enum.ActionType.New:
|
|
847
|
+
case Enum.ActionType.CloseTabThenNew:
|
|
848
|
+
addNode(newData)
|
|
248
849
|
break;
|
|
249
|
-
case Enum.ActionType.Update
|
|
250
|
-
case Enum.ActionType.CloseTabThenUpdate
|
|
251
|
-
updateNode(newData)
|
|
850
|
+
case Enum.ActionType.Update:
|
|
851
|
+
case Enum.ActionType.CloseTabThenUpdate:
|
|
852
|
+
updateNode(newData)
|
|
252
853
|
break;
|
|
253
854
|
default:
|
|
254
855
|
break;
|
|
255
856
|
}
|
|
256
|
-
|
|
257
857
|
})
|
|
258
858
|
}
|
|
859
|
+
|
|
259
860
|
//删除树节点
|
|
260
861
|
function removeNode(newData) {
|
|
261
862
|
getNextClickNode()
|
|
262
863
|
refTree.value.remove(currentNode.value);
|
|
263
864
|
}
|
|
865
|
+
|
|
264
866
|
//新增树节点
|
|
265
867
|
function addNode(newData) {
|
|
266
868
|
refTree.value.append(newData, currentNode.value)
|
|
267
869
|
handleNodeClick(newData, true)
|
|
268
870
|
}
|
|
871
|
+
|
|
269
872
|
//修改树节点
|
|
270
873
|
function updateNode(newData) {
|
|
271
|
-
|
|
272
874
|
for (let key in newData) {
|
|
273
|
-
|
|
274
875
|
if (typeof newData[key] === 'object') {
|
|
275
876
|
currentData.value[key] = { ...currentData.value[key], ...newData[key] }
|
|
276
877
|
} else {
|
|
277
878
|
currentData.value[key] = newData[key];
|
|
278
879
|
}
|
|
279
|
-
|
|
280
880
|
}
|
|
281
881
|
handleNodeClick(newData, true)
|
|
282
882
|
}
|
|
883
|
+
|
|
283
884
|
function getNextClickNode() {
|
|
284
885
|
const node = refTree.value.getNode(currentData.value.code);
|
|
285
886
|
let data = {};
|
|
@@ -292,9 +893,106 @@ function getNextClickNode() {
|
|
|
292
893
|
}
|
|
293
894
|
handleNodeClick(data, true)
|
|
294
895
|
}
|
|
295
|
-
|
|
896
|
+
|
|
897
|
+
/** 过滤节点(全量数据模式下使用) */
|
|
898
|
+
function filterNode(value, data) {
|
|
899
|
+
if (!value) return true
|
|
900
|
+
return data.name.toLowerCase().includes(value.toLowerCase())
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
function buildDeptTreeByField(flatList, fieldDefine, opt = {}) {
|
|
904
|
+
const {
|
|
905
|
+
pathKey = 'path',
|
|
906
|
+
separator = '.',
|
|
907
|
+
sortKey = 'path'
|
|
908
|
+
} = opt;
|
|
909
|
+
|
|
910
|
+
const keepFields = fieldDefine
|
|
911
|
+
.filter(f => f.visible && f.isDataField)
|
|
912
|
+
.sort((a, b) => a.trOrder - b.trOrder)
|
|
913
|
+
.map(f => f.fieldName);
|
|
914
|
+
|
|
915
|
+
const createNode = (tplItem, path) => {
|
|
916
|
+
const node = { children: [] };
|
|
917
|
+
|
|
918
|
+
for (const key in tplItem) {
|
|
919
|
+
if (key !== 'children') {
|
|
920
|
+
node[key] = tplItem[key];
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
node[pathKey] = path;
|
|
925
|
+
return node;
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
const root = [];
|
|
929
|
+
const nodeMap = new Map();
|
|
930
|
+
|
|
931
|
+
for (const item of flatList) {
|
|
932
|
+
|
|
933
|
+
if (!item[pathKey]) {
|
|
934
|
+
break;
|
|
935
|
+
}
|
|
936
|
+
const path = item[pathKey];
|
|
937
|
+
const levels = path.split(separator);
|
|
938
|
+
|
|
939
|
+
let curPath = '';
|
|
940
|
+
let parentPath = '';
|
|
941
|
+
|
|
942
|
+
levels.forEach((lvl, idx) => {
|
|
943
|
+
curPath = idx === 0 ? lvl : `${parentPath}${separator}${lvl}`;
|
|
944
|
+
let curNode = nodeMap.get(curPath);
|
|
945
|
+
|
|
946
|
+
if (!curNode) {
|
|
947
|
+
curNode = createNode(item, curPath);
|
|
948
|
+
nodeMap.set(curPath, curNode);
|
|
949
|
+
|
|
950
|
+
if (idx === 0) {
|
|
951
|
+
root.push(curNode);
|
|
952
|
+
} else {
|
|
953
|
+
const pNode = nodeMap.get(parentPath);
|
|
954
|
+
if (pNode) {
|
|
955
|
+
pNode.children.push(curNode);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
parentPath = curPath;
|
|
960
|
+
});
|
|
961
|
+
|
|
962
|
+
const lastNode = nodeMap.get(path);
|
|
963
|
+
for (const key in item) {
|
|
964
|
+
if (key !== 'children') {
|
|
965
|
+
lastNode[key] = item[key];
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
for (const node of nodeMap.values()) {
|
|
971
|
+
if (node.children && node.children.length > 0) {
|
|
972
|
+
node.children.sort((a, b) => {
|
|
973
|
+
const aVal = a[sortKey] || '';
|
|
974
|
+
const bVal = b[sortKey] || '';
|
|
975
|
+
return String(aVal).localeCompare(String(bVal));
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
node.isLeaf = node.children.length === 0;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
root.sort((a, b) => {
|
|
982
|
+
const aVal = a[sortKey] || '';
|
|
983
|
+
const bVal = b[sortKey] || '';
|
|
984
|
+
return String(aVal).localeCompare(String(bVal));
|
|
985
|
+
});
|
|
986
|
+
|
|
987
|
+
const hasAnyLeaf = [...nodeMap.values()].some(n => n.isLeaf == false);
|
|
988
|
+
return { tree: root, hasAnyLeaf };
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// 暴露方法
|
|
296
992
|
defineExpose({
|
|
297
|
-
search
|
|
993
|
+
search,
|
|
994
|
+
resetTree,
|
|
995
|
+
clearSearch
|
|
298
996
|
})
|
|
299
997
|
</script>
|
|
300
998
|
|
|
@@ -310,7 +1008,6 @@ defineExpose({
|
|
|
310
1008
|
|
|
311
1009
|
.ct-tree::-webkit-scrollbar-thumb {
|
|
312
1010
|
background-color: #bebebe;
|
|
313
|
-
/* 设置滚动条滑块颜色 */
|
|
314
1011
|
height: 5px;
|
|
315
1012
|
border-radius: 4px;
|
|
316
1013
|
display: block;
|
|
@@ -319,7 +1016,6 @@ defineExpose({
|
|
|
319
1016
|
.ct-tree::-webkit-scrollbar {
|
|
320
1017
|
width: 6px;
|
|
321
1018
|
height: 6px;
|
|
322
|
-
/* 设置滚动条高度 */
|
|
323
1019
|
background-color: #f1f1f1;
|
|
324
1020
|
display: block;
|
|
325
1021
|
}
|
|
@@ -347,121 +1043,14 @@ defineExpose({
|
|
|
347
1043
|
padding-right: 2px !important;
|
|
348
1044
|
}
|
|
349
1045
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
height: 100%;
|
|
354
|
-
width: 1px;
|
|
355
|
-
position: absolute;
|
|
356
|
-
left: 27px;
|
|
357
|
-
top: -1px;
|
|
358
|
-
border-width: 1px;
|
|
359
|
-
border-left: 1px dashed #52627C;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
.tree-line .el-tree-node:before:last-child {
|
|
363
|
-
top: -35px;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
.el-tree-node__children .el-tree-node::before {
|
|
367
|
-
content: "";
|
|
368
|
-
height: 100%;
|
|
369
|
-
width: 1px;
|
|
370
|
-
position: absolute;
|
|
371
|
-
left: 27px;
|
|
372
|
-
top: -2px;
|
|
373
|
-
border-width: 1px;
|
|
374
|
-
border-left: 1px dashed #52627C;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/* 当前最后一个接点的竖线高度 */
|
|
378
|
-
.el-tree-node:last-child::before {
|
|
379
|
-
height: 15px;
|
|
380
|
-
/*可以自己调整 */
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
/* 横线 */
|
|
384
|
-
.el-tree-node::after {
|
|
385
|
-
content: "";
|
|
386
|
-
width: 12px;
|
|
387
|
-
height: 20px;
|
|
388
|
-
position: absolute;
|
|
389
|
-
left: 27px;
|
|
390
|
-
top: 12px;
|
|
391
|
-
right: 2px;
|
|
392
|
-
border-width: 1px;
|
|
393
|
-
border-top: 1px dashed #52627C;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
.el-tree:first-child .el-tree-node:before {
|
|
397
|
-
/* height: 46px;可以自己调整 */
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
.el-tree-node__expand-icon {
|
|
401
|
-
font-size: 16px;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
/* 去掉顶层虚线 */
|
|
405
|
-
.tree>.el-tree-node:first-child::after {
|
|
406
|
-
border-top: none;
|
|
1046
|
+
.node_content {
|
|
1047
|
+
display: flex;
|
|
1048
|
+
align-items: center;
|
|
407
1049
|
}
|
|
408
1050
|
|
|
409
|
-
.
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
.tree>.is-leaf {
|
|
414
|
-
color: transparent;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
.el-tree .el-tree-node__expand-icon.expanded {
|
|
418
|
-
-webkit-transform: rotate(0deg);
|
|
419
|
-
transform: rotate(0deg);
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
.el-tree .el-tree-node__expand-icon.expanded {
|
|
423
|
-
-webkit-transform: rotate(0deg);
|
|
424
|
-
transform: rotate(0deg);
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
.el-tree .el-tree-node__expand-icon {
|
|
429
|
-
background: url("@/assets/images/node-collapse.png") no-repeat;
|
|
430
|
-
content: '';
|
|
431
|
-
display: block;
|
|
432
|
-
width: 12px;
|
|
433
|
-
height: 12px;
|
|
434
|
-
font-size: 12px;
|
|
435
|
-
background-size: 10px;
|
|
436
|
-
|
|
437
|
-
color: transparent;
|
|
438
|
-
background-position: left 6px top 6px;
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
/*
|
|
442
|
-
//有子节点 且已展开*/
|
|
443
|
-
.el-tree .el-tree-node__expand-icon.expanded {
|
|
444
|
-
background: url("@/assets/images/node-expand.png") no-repeat;
|
|
445
|
-
content: '';
|
|
446
|
-
display: block;
|
|
447
|
-
width: 12px;
|
|
448
|
-
height: 12px;
|
|
449
|
-
font-size: 12px;
|
|
450
|
-
background-size: 10px;
|
|
451
|
-
|
|
452
|
-
color: transparent;
|
|
453
|
-
background-position: left 6px top 6px;
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/* //没有子节点*/
|
|
457
|
-
.el-tree .el-tree-node__expand-icon.is-leaf::before {
|
|
458
|
-
background: transparent no-repeat 0 3px;
|
|
459
|
-
content: '';
|
|
460
|
-
display: block;
|
|
461
|
-
width: 12px;
|
|
462
|
-
height: 12px;
|
|
463
|
-
font-size: 12px;
|
|
464
|
-
background-size: 10px;
|
|
1051
|
+
.node-icon {
|
|
1052
|
+
margin-right: 5px;
|
|
1053
|
+
color: var(--el-color-warning);
|
|
465
1054
|
}
|
|
466
1055
|
|
|
467
1056
|
.box-menu {
|
|
@@ -481,5 +1070,6 @@ defineExpose({
|
|
|
481
1070
|
|
|
482
1071
|
.box-menu .opertion:hover {
|
|
483
1072
|
color: var(--btnHoverRed);
|
|
1073
|
+
background-color: var(--el-fill-color-light);
|
|
484
1074
|
}
|
|
485
|
-
</style>
|
|
1075
|
+
</style>
|