@handaotech-design/bom 0.0.40 → 0.0.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/es/components/bom-tree/index.vue +314 -71
- package/dist/es/components/bom-tree-view/index.d.ts +3 -0
- package/dist/es/components/bom-tree-view/index.js +10 -0
- package/dist/es/components/bom-tree-view/index.vue +420 -0
- package/dist/es/components/bom-workbench/index.vue +11 -1
- package/dist/es/utils/bom.d.ts +5 -1
- package/dist/es/utils/bom.js +55 -10
- package/dist/lib/components/bom-tree/index.vue +314 -71
- package/dist/lib/components/bom-tree-view/index.d.ts +3 -0
- package/dist/lib/components/bom-tree-view/index.js +29 -0
- package/dist/lib/components/bom-tree-view/index.vue +420 -0
- package/dist/lib/components/bom-workbench/index.vue +11 -1
- package/dist/lib/utils/bom.d.ts +5 -1
- package/dist/lib/utils/bom.js +55 -14
- package/dist/style.css +4 -1
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { nextTick, onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue'
|
|
2
|
+
import { computed, nextTick, onBeforeUnmount, onMounted, ref, toRefs, watch } from 'vue'
|
|
3
3
|
import type { TreeProps } from 'ant-design-vue'
|
|
4
4
|
import { Dropdown, Tree } from 'ant-design-vue'
|
|
5
5
|
import { watchDebounced } from '@vueuse/shared'
|
|
@@ -8,7 +8,8 @@ import type { DataNode } from 'ant-design-vue/es/vc-tree-select/interface'
|
|
|
8
8
|
import type { EventDataNode } from 'ant-design-vue/es/tree'
|
|
9
9
|
import { MoreOutlined } from '@ant-design/icons-vue'
|
|
10
10
|
import HdGrayInput from '../gray-input'
|
|
11
|
-
import type { BomTreeConfig } from '../../models'
|
|
11
|
+
import type { BomNode, BomTreeConfig } from '../../models'
|
|
12
|
+
import { convertBomDataToTree } from '../../utils'
|
|
12
13
|
|
|
13
14
|
const props = withDefaults(defineProps<Props>(), {
|
|
14
15
|
maintainable: false,
|
|
@@ -29,22 +30,40 @@ interface Props {
|
|
|
29
30
|
config: BomTreeConfig
|
|
30
31
|
maintainable?: boolean
|
|
31
32
|
shouldSelect?: (node: DataNode) => Promise<boolean>
|
|
33
|
+
keyNodeMap: Map<string, any>
|
|
34
|
+
firstSelectableKey?: string
|
|
35
|
+
loadData?: (node: BomNode, eventNode?: EventDataNode) => Promise<DataNode[]>
|
|
32
36
|
}
|
|
33
37
|
|
|
38
|
+
const localTreeData = ref<DataNode[]>(props.treeData || [])
|
|
34
39
|
const expandedKeys = ref<(string | number)[]>([])
|
|
35
40
|
const searchValue = ref<string>('')
|
|
36
41
|
const autoExpandParent = ref<boolean>(true)
|
|
37
|
-
const { treeData: _treeData } = toRefs(props)
|
|
38
|
-
const filteredTreeData = ref<TreeProps['treeData']>([])
|
|
39
42
|
const treeContainerHeight = ref<number>(0)
|
|
40
43
|
const treeContainerId = 'treeContainer'
|
|
44
|
+
const treeContainerRef = ref<HTMLElement | null>(null)
|
|
45
|
+
const treeRef = ref<any>(null)
|
|
41
46
|
let keyToNodeMap = new Map<string, TreeNodeWithMeta>()
|
|
42
47
|
const selectedKeys = ref<string[]>([])
|
|
48
|
+
const MAX_ROOT = 200
|
|
49
|
+
const fullRootKeys = computed(() => (localTreeData.value || []).map(node => node.key as string))
|
|
50
|
+
const visibleRootKeys = ref<Set<string>>(new Set())
|
|
51
|
+
const displayTreeData = computed(() => {
|
|
52
|
+
if (!localTreeData.value) {
|
|
53
|
+
return []
|
|
54
|
+
}
|
|
55
|
+
return localTreeData.value.filter(node => visibleRootKeys.value.has(node.key as string))
|
|
56
|
+
})
|
|
43
57
|
const isPreservingTreeState = ref<boolean>(false)
|
|
58
|
+
const isAutoLoadingRoots = ref(false)
|
|
59
|
+
const searchMatches = ref<string[]>([])
|
|
60
|
+
const currentMatchIndex = ref(0)
|
|
44
61
|
const initTreeState = () => {
|
|
45
62
|
searchValue.value = ''
|
|
46
63
|
selectedKeys.value = []
|
|
47
64
|
expandedKeys.value = []
|
|
65
|
+
searchMatches.value = []
|
|
66
|
+
currentMatchIndex.value = 0
|
|
48
67
|
}
|
|
49
68
|
|
|
50
69
|
const onExpand = (keys: Key[]) => {
|
|
@@ -53,66 +72,87 @@ const onExpand = (keys: Key[]) => {
|
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
const updateTreeContainerHeight = () => {
|
|
56
|
-
const treeContainer = document.getElementById(treeContainerId)
|
|
75
|
+
const treeContainer = treeContainerRef.value || document.getElementById(treeContainerId)
|
|
57
76
|
if (treeContainer) {
|
|
58
77
|
treeContainerHeight.value = treeContainer.clientHeight
|
|
59
78
|
}
|
|
60
79
|
}
|
|
61
80
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
if (!_.isEmpty(node.children)) {
|
|
73
|
-
traverse(node.children, [...parentKeys, node.key as string])
|
|
74
|
-
}
|
|
75
|
-
}
|
|
81
|
+
// 获取直接父节点的 key
|
|
82
|
+
const getParentKeys = (key: string): string[] | undefined => {
|
|
83
|
+
const treeNode = keyToNodeMap.get(key)
|
|
84
|
+
return treeNode?.parentKeys || []
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const ensureRootVisibleByKey = (key?: string) => {
|
|
88
|
+
if (!key) {
|
|
89
|
+
return
|
|
76
90
|
}
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
const parentKeys = getParentKeys(key)
|
|
92
|
+
const rootKey = parentKeys?.[0] ?? key
|
|
93
|
+
if (!rootKey || visibleRootKeys.value.has(rootKey)) {
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
const next = new Set(visibleRootKeys.value)
|
|
97
|
+
next.add(rootKey)
|
|
98
|
+
visibleRootKeys.value = next
|
|
79
99
|
}
|
|
80
100
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
result.push({ ...node })
|
|
85
|
-
return result
|
|
86
|
-
}
|
|
87
|
-
if (Array.isArray(node.children)) {
|
|
88
|
-
const children = node.children.reduce(getNodes, [])
|
|
89
|
-
if (!_.isEmpty(children)) {
|
|
90
|
-
result.push({ ...node, children })
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
return result
|
|
101
|
+
async function locateNodeByKey(targetKey: string) {
|
|
102
|
+
if (!targetKey) {
|
|
103
|
+
return
|
|
94
104
|
}
|
|
95
|
-
|
|
105
|
+
ensureRootVisibleByKey(targetKey)
|
|
106
|
+
const parentKeys = getParentKeys(targetKey) || []
|
|
107
|
+
expandedKeys.value = Array.from(new Set([
|
|
108
|
+
...expandedKeys.value,
|
|
109
|
+
...parentKeys,
|
|
110
|
+
]))
|
|
111
|
+
await nextTick()
|
|
112
|
+
await nextTick()
|
|
113
|
+
treeRef.value?.scrollTo?.({
|
|
114
|
+
key: targetKey,
|
|
115
|
+
align: 'top',
|
|
116
|
+
})
|
|
117
|
+
focusNode(targetKey)
|
|
96
118
|
}
|
|
97
119
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
120
|
+
const scrollToMatch = async (index: number) => {
|
|
121
|
+
if (!searchMatches.value.length) {
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
const total = searchMatches.value.length
|
|
125
|
+
const normalized = ((index % total) + total) % total
|
|
126
|
+
currentMatchIndex.value = normalized
|
|
127
|
+
const targetKey = searchMatches.value[normalized]
|
|
128
|
+
await locateNodeByKey(targetKey)
|
|
102
129
|
}
|
|
103
130
|
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
if (!firstNode) {
|
|
131
|
+
const focusPreviousMatch = () => {
|
|
132
|
+
if (!searchMatches.value.length) {
|
|
107
133
|
return
|
|
108
134
|
}
|
|
135
|
+
scrollToMatch(currentMatchIndex.value - 1)
|
|
136
|
+
}
|
|
109
137
|
|
|
138
|
+
const focusNextMatch = () => {
|
|
139
|
+
if (!searchMatches.value.length) {
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
scrollToMatch(currentMatchIndex.value + 1)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const selectFirstSelectableNode = (preserveExpanded = false) => {
|
|
146
|
+
if (!props.firstSelectableKey) {
|
|
147
|
+
return
|
|
148
|
+
}
|
|
110
149
|
nextTick(() => {
|
|
111
|
-
|
|
150
|
+
ensureRootVisibleByKey(props.firstSelectableKey)
|
|
151
|
+
const parentKeys = getParentKeys(props.firstSelectableKey!) as string[]
|
|
112
152
|
expandedKeys.value = preserveExpanded
|
|
113
153
|
? Array.from(new Set([...expandedKeys.value, ...parentKeys])) // 取并集
|
|
114
154
|
: parentKeys
|
|
115
|
-
selectedKeys.value = [
|
|
155
|
+
selectedKeys.value = [props.firstSelectableKey!]
|
|
116
156
|
})
|
|
117
157
|
}
|
|
118
158
|
|
|
@@ -123,6 +163,7 @@ const onSelected = async (keys: Key[], { node }: { node: EventDataNode }) => {
|
|
|
123
163
|
}
|
|
124
164
|
const key = node?.dataRef?.key
|
|
125
165
|
if (key) {
|
|
166
|
+
ensureRootVisibleByKey(key as string)
|
|
126
167
|
selectedKeys.value = [key as string]
|
|
127
168
|
}
|
|
128
169
|
else {
|
|
@@ -142,10 +183,14 @@ onBeforeUnmount(() => {
|
|
|
142
183
|
})
|
|
143
184
|
|
|
144
185
|
watch(
|
|
145
|
-
() =>
|
|
186
|
+
() => localTreeData.value,
|
|
146
187
|
async () => {
|
|
147
|
-
|
|
148
|
-
|
|
188
|
+
keyToNodeMap = props.keyNodeMap
|
|
189
|
+
const visibleSet = new Set<string>()
|
|
190
|
+
;(localTreeData.value || []).slice(0, MAX_ROOT).forEach((node) => {
|
|
191
|
+
visibleSet.add(node.key as string)
|
|
192
|
+
})
|
|
193
|
+
visibleRootKeys.value = visibleSet
|
|
149
194
|
initTreeState()
|
|
150
195
|
if (!isPreservingTreeState.value) {
|
|
151
196
|
selectFirstSelectableNode(true)
|
|
@@ -157,30 +202,34 @@ watch(
|
|
|
157
202
|
)
|
|
158
203
|
|
|
159
204
|
watchDebounced(
|
|
160
|
-
searchValue, (value: string) => {
|
|
161
|
-
let expanded: any[]
|
|
205
|
+
searchValue, async (value: string) => {
|
|
206
|
+
let expanded: any[] = []
|
|
162
207
|
if (_.isEmpty(value)) {
|
|
208
|
+
searchMatches.value = []
|
|
209
|
+
currentMatchIndex.value = 0
|
|
163
210
|
expanded = getParentKeys(selectedKeys.value[0]) || []
|
|
164
|
-
filteredTreeData.value = _treeData.value
|
|
165
211
|
}
|
|
166
212
|
else {
|
|
167
|
-
const
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
213
|
+
const matchedParents: string[][] = []
|
|
214
|
+
const matches: string[] = []
|
|
215
|
+
for (const node of keyToNodeMap.values()) {
|
|
216
|
+
if (hasSearchMatch((node as any).title)) {
|
|
217
|
+
const key = node.key as string
|
|
218
|
+
matches.push(key)
|
|
219
|
+
ensureRootVisibleByKey(key)
|
|
220
|
+
matchedParents.push(getParentKeys(key) || [])
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
searchMatches.value = matches
|
|
224
|
+
currentMatchIndex.value = matches.length ? 0 : 0
|
|
225
|
+
expanded = matchedParents.flat()
|
|
179
226
|
}
|
|
180
227
|
expandedKeys.value = expanded
|
|
181
|
-
nextTick(
|
|
182
|
-
|
|
183
|
-
|
|
228
|
+
await nextTick()
|
|
229
|
+
expandedKeys.value = _.uniq(expanded.flat(1)) as any as string[]
|
|
230
|
+
if (!_.isEmpty(value) && searchMatches.value.length) {
|
|
231
|
+
await scrollToMatch(currentMatchIndex.value)
|
|
232
|
+
}
|
|
184
233
|
}, { debounce: 500 })
|
|
185
234
|
|
|
186
235
|
watch(
|
|
@@ -219,6 +268,7 @@ async function updateTreeWithPreservedState(updateDataFn: () => Promise<void>) {
|
|
|
219
268
|
expandedKeys.value = prevExpanded.filter(key => keyToNodeMap.has(key as string))
|
|
220
269
|
|
|
221
270
|
if (prevSelected && keyToNodeMap.has(prevSelected)) {
|
|
271
|
+
ensureRootVisibleByKey(prevSelected)
|
|
222
272
|
selectedKeys.value = [prevSelected]
|
|
223
273
|
}
|
|
224
274
|
else {
|
|
@@ -241,35 +291,156 @@ defineExpose({
|
|
|
241
291
|
getParentKeys,
|
|
242
292
|
getDepth,
|
|
243
293
|
})
|
|
294
|
+
|
|
295
|
+
const canLoadMoreRoot = computed(() => visibleRootKeys.value.size < fullRootKeys.value.length)
|
|
296
|
+
const loadMoreRoot = () => {
|
|
297
|
+
if (!fullRootKeys.value.length) {
|
|
298
|
+
return
|
|
299
|
+
}
|
|
300
|
+
const currentSize = visibleRootKeys.value.size
|
|
301
|
+
if (currentSize >= fullRootKeys.value.length) {
|
|
302
|
+
return
|
|
303
|
+
}
|
|
304
|
+
const next = new Set(visibleRootKeys.value)
|
|
305
|
+
fullRootKeys.value.slice(currentSize, currentSize + MAX_ROOT).forEach((key) => {
|
|
306
|
+
next.add(key)
|
|
307
|
+
})
|
|
308
|
+
visibleRootKeys.value = next
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
const maybeAutoLoadMoreRoot = () => {
|
|
312
|
+
if (isAutoLoadingRoots.value || !canLoadMoreRoot.value) {
|
|
313
|
+
return
|
|
314
|
+
}
|
|
315
|
+
const container = treeContainerRef.value
|
|
316
|
+
if (!container) {
|
|
317
|
+
return
|
|
318
|
+
}
|
|
319
|
+
const nearBottom = container.scrollTop + container.clientHeight >= container.scrollHeight - 80
|
|
320
|
+
if (!nearBottom) {
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
isAutoLoadingRoots.value = true
|
|
324
|
+
loadMoreRoot()
|
|
325
|
+
requestAnimationFrame(() => {
|
|
326
|
+
isAutoLoadingRoots.value = false
|
|
327
|
+
})
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const handleTreeScroll = _.throttle(maybeAutoLoadMoreRoot, 300)
|
|
331
|
+
|
|
332
|
+
async function _loadData(node: EventDataNode) {
|
|
333
|
+
if (!props.loadData) {
|
|
334
|
+
return
|
|
335
|
+
}
|
|
336
|
+
if (node.children && node.children.length) {
|
|
337
|
+
return
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
const children: DataNode[] = await props.loadData(node.dataRef as BomNode, node)
|
|
341
|
+
|
|
342
|
+
if (children.length) {
|
|
343
|
+
children.forEach(item => item.key = node.key + (item.key ?? item.id) as string)
|
|
344
|
+
const { treeData, nodeMap } = convertBomDataToTree(children as any, props.config.nodeConfig.rule) as any
|
|
345
|
+
nodeMap.entries().forEach(([key, value]: any[]) => {
|
|
346
|
+
keyToNodeMap.set(key as string, {
|
|
347
|
+
...value,
|
|
348
|
+
parentKeys: [...(getParentKeys(node.key as string) || []), node.key as string],
|
|
349
|
+
})
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
node.dataRef!.children = treeData
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
node.isLeaf = true
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function focusNode(key: string) {
|
|
360
|
+
// 1. 用 antd Tree 自带滚动
|
|
361
|
+
treeRef.value?.scrollTo({ key, align: 'center' })
|
|
362
|
+
|
|
363
|
+
// 2. 下一帧再找 DOM,避免滚动未完成
|
|
364
|
+
requestAnimationFrame(() => {
|
|
365
|
+
const el = document.querySelector(
|
|
366
|
+
`.tree-node-tittle[data-key="${key}"]`,
|
|
367
|
+
) as HTMLElement | null
|
|
368
|
+
|
|
369
|
+
if (!el) {
|
|
370
|
+
return
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// 3. 触发一次可感知的焦点动画
|
|
374
|
+
el.classList.remove('focus-flash')
|
|
375
|
+
// eslint-disable-next-line no-void
|
|
376
|
+
void el.offsetWidth
|
|
377
|
+
el.classList.add('focus-flash')
|
|
378
|
+
|
|
379
|
+
setTimeout(() => {
|
|
380
|
+
el.classList.remove('focus-flash')
|
|
381
|
+
}, 2400)
|
|
382
|
+
})
|
|
383
|
+
}
|
|
244
384
|
</script>
|
|
245
385
|
|
|
246
386
|
<template>
|
|
247
387
|
<div class="flex flex-col h-100%">
|
|
248
388
|
<div class="search-box">
|
|
249
389
|
<HdGrayInput
|
|
250
|
-
v-model:value="searchValue"
|
|
390
|
+
v-model:value.trim="searchValue"
|
|
251
391
|
:placeholder="props.config?.filter?.placeholder || '输入关键词进行筛选(如名称/编号)'"
|
|
252
392
|
class="search-input"
|
|
253
393
|
>
|
|
254
394
|
<template #prefix>
|
|
255
395
|
<div class="i-icon-search w-16px h-16px" />
|
|
256
396
|
</template>
|
|
397
|
+
<template #suffix>
|
|
398
|
+
<div v-if="searchValue" class="match-hint mr-8px font-size-12px">
|
|
399
|
+
{{ searchMatches.length ? currentMatchIndex + 1 : 0 }} / {{ searchMatches.length }}
|
|
400
|
+
</div>
|
|
401
|
+
<div v-if="searchValue" class="match-nav" :class="{ 'is-disabled': !searchMatches.length }">
|
|
402
|
+
<div
|
|
403
|
+
class="match-nav-btn mr-4px"
|
|
404
|
+
:class="{ disabled: !searchMatches.length }"
|
|
405
|
+
@click.stop.prevent="focusPreviousMatch"
|
|
406
|
+
>
|
|
407
|
+
↑
|
|
408
|
+
</div>
|
|
409
|
+
<div
|
|
410
|
+
class="match-nav-btn"
|
|
411
|
+
:class="{ disabled: !searchMatches.length }"
|
|
412
|
+
@click.stop.prevent="focusNextMatch"
|
|
413
|
+
>
|
|
414
|
+
↓
|
|
415
|
+
</div>
|
|
416
|
+
</div>
|
|
417
|
+
</template>
|
|
257
418
|
</HdGrayInput>
|
|
258
419
|
</div>
|
|
259
|
-
<div
|
|
260
|
-
|
|
420
|
+
<div
|
|
421
|
+
:id="treeContainerId"
|
|
422
|
+
ref="treeContainerRef"
|
|
423
|
+
class="flex-grow tree-wrapper mt-12px"
|
|
424
|
+
>
|
|
425
|
+
<div v-if="!_.isEmpty(displayTreeData)">
|
|
261
426
|
<a-tree
|
|
427
|
+
ref="treeRef"
|
|
262
428
|
:height="treeContainerHeight"
|
|
429
|
+
:tree-data="displayTreeData"
|
|
263
430
|
:expanded-keys="expandedKeys"
|
|
264
431
|
:auto-expand-parent="autoExpandParent"
|
|
265
|
-
:tree-data="filteredTreeData"
|
|
266
432
|
:block-node="true"
|
|
267
433
|
:selected-keys="selectedKeys"
|
|
434
|
+
:load-data="_loadData"
|
|
435
|
+
@scroll="handleTreeScroll"
|
|
268
436
|
@expand="onExpand"
|
|
269
437
|
@select="onSelected"
|
|
270
438
|
>
|
|
271
439
|
<template #title="{ title, dataRef }">
|
|
272
|
-
<div
|
|
440
|
+
<div
|
|
441
|
+
:class="`tree-node-tittle flex items-center ${dataRef.selectable ? 'selectable' : 'not-selectable'}`"
|
|
442
|
+
:data-key="dataRef.key"
|
|
443
|
+
>
|
|
273
444
|
<div
|
|
274
445
|
v-if="!!dataRef.icon"
|
|
275
446
|
class="icon w-20px h-20px mr-4px min-w-20px"
|
|
@@ -305,7 +476,7 @@ defineExpose({
|
|
|
305
476
|
</template>
|
|
306
477
|
</a-tree>
|
|
307
478
|
</div>
|
|
308
|
-
<div v-show="_.isEmpty(
|
|
479
|
+
<div v-show="_.isEmpty(displayTreeData)" class="w-100% h-100% flex justify-center items-center">
|
|
309
480
|
<span>暂无数据</span>
|
|
310
481
|
</div>
|
|
311
482
|
</div>
|
|
@@ -313,6 +484,7 @@ defineExpose({
|
|
|
313
484
|
</template>
|
|
314
485
|
|
|
315
486
|
<style scoped>
|
|
487
|
+
@charset "UTF-8";
|
|
316
488
|
.tree-wrapper {
|
|
317
489
|
background-color: #fff;
|
|
318
490
|
min-height: 0;
|
|
@@ -322,6 +494,12 @@ defineExpose({
|
|
|
322
494
|
padding: 0 16px;
|
|
323
495
|
}
|
|
324
496
|
|
|
497
|
+
:deep(.match-nav) .ant-btn:hover, :deep(.match-nav) .ant-btn:focus {
|
|
498
|
+
color: #1E3B9D;
|
|
499
|
+
border-color: #1E3B9D;
|
|
500
|
+
background: #fff;
|
|
501
|
+
}
|
|
502
|
+
|
|
325
503
|
:deep(.ant-tree-list) .ant-tree-treenode-motion {
|
|
326
504
|
width: 100%;
|
|
327
505
|
}
|
|
@@ -415,4 +593,69 @@ defineExpose({
|
|
|
415
593
|
white-space: nowrap;
|
|
416
594
|
vertical-align: middle;
|
|
417
595
|
}
|
|
596
|
+
|
|
597
|
+
.tree-node-tittle {
|
|
598
|
+
position: relative;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/* 焦点提示:整行描边框 */
|
|
602
|
+
.tree-node-tittle.focus-flash::after {
|
|
603
|
+
content: "";
|
|
604
|
+
position: absolute;
|
|
605
|
+
inset: -2px -6px; /* 包裹文字 */
|
|
606
|
+
border-radius: 6px;
|
|
607
|
+
pointer-events: none;
|
|
608
|
+
/* 混合描边 + 光晕 */
|
|
609
|
+
border: 1.5px solid rgba(30, 59, 157, 0.6); /* 更明显但不硬 */
|
|
610
|
+
box-shadow: 0 0 6px rgba(30, 59, 157, 0.35);
|
|
611
|
+
animation: focusSoftGlow 1.4s ease-out 2;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
@keyframes focusSoftGlow {
|
|
615
|
+
0% {
|
|
616
|
+
opacity: 0;
|
|
617
|
+
transform: scale(0.97);
|
|
618
|
+
}
|
|
619
|
+
30% {
|
|
620
|
+
opacity: 1;
|
|
621
|
+
transform: scale(1);
|
|
622
|
+
}
|
|
623
|
+
100% {
|
|
624
|
+
opacity: 0;
|
|
625
|
+
transform: scale(1.02);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
:deep(.match-nav) {
|
|
629
|
+
display: flex;
|
|
630
|
+
align-items: center;
|
|
631
|
+
}
|
|
632
|
+
:deep(.match-nav) .match-nav-btn {
|
|
633
|
+
width: 20px;
|
|
634
|
+
height: 20px;
|
|
635
|
+
line-height: 18px;
|
|
636
|
+
text-align: center;
|
|
637
|
+
border: 1px solid rgba(0, 0, 0, 0.65);
|
|
638
|
+
border-radius: 50%;
|
|
639
|
+
color: rgba(0, 0, 0, 0.65);
|
|
640
|
+
background-color: #fff;
|
|
641
|
+
cursor: pointer;
|
|
642
|
+
font-size: 12px;
|
|
643
|
+
margin-left: 4px;
|
|
644
|
+
transition: all 0.2s;
|
|
645
|
+
}
|
|
646
|
+
:deep(.match-nav) .match-nav-btn:hover {
|
|
647
|
+
background-color: #E9EBED;
|
|
648
|
+
border-color: #1E3B9D;
|
|
649
|
+
color: #1E3B9D;
|
|
650
|
+
}
|
|
651
|
+
:deep(.match-nav) .match-nav-btn.disabled {
|
|
652
|
+
color: #ccc;
|
|
653
|
+
border-color: #ccc;
|
|
654
|
+
cursor: not-allowed;
|
|
655
|
+
background-color: #f5f5f5;
|
|
656
|
+
}
|
|
657
|
+
:deep(.match-nav) .match-nav-btn.disabled:hover {
|
|
658
|
+
background-color: #f5f5f5;
|
|
659
|
+
border-color: #ccc;
|
|
660
|
+
}
|
|
418
661
|
</style>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
HdBomTree: true
|
|
8
|
+
};
|
|
9
|
+
module.exports = exports.HdBomTree = void 0;
|
|
10
|
+
var _antDesignVue = require("ant-design-vue");
|
|
11
|
+
var _iconsVue = require("@ant-design/icons-vue");
|
|
12
|
+
var _install = require("../../utils/install");
|
|
13
|
+
var _index = _interopRequireWildcard(require("./index.vue"));
|
|
14
|
+
Object.keys(_index).forEach(function (key) {
|
|
15
|
+
if (key === "default" || key === "__esModule") return;
|
|
16
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
17
|
+
if (key in exports && exports[key] === _index[key]) return;
|
|
18
|
+
Object.defineProperty(exports, key, {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _index[key];
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
26
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
27
|
+
const antdComponents = Object.fromEntries([_antDesignVue.Input, _antDesignVue.Tree, _antDesignVue.Dropdown, _iconsVue.MoreOutlined].map(comp => [comp.name, comp]));
|
|
28
|
+
const HdBomTree = exports.HdBomTree = (0, _install.withInstall)(_index.default, antdComponents);
|
|
29
|
+
module.exports = HdBomTree;
|