Skip to content

Commit 11d52a0

Browse files
authored
fix: page tree search results do not automatically expanded (opentiny#1476)
1 parent aaf416b commit 11d52a0

File tree

1 file changed

+66
-24
lines changed

1 file changed

+66
-24
lines changed

packages/plugins/page/src/Tree.vue

Lines changed: 66 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
</template>
4040

4141
<script lang="ts" setup>
42-
import { computed, defineEmits, defineProps, ref } from 'vue'
42+
import { computed, defineEmits, defineProps, ref, watch } from 'vue'
4343
import LayerLines from './LayerLines.vue'
4444
4545
const props = defineProps({
@@ -81,27 +81,36 @@ const emit = defineEmits(['clickRow', 'moveNode'])
8181
const useCollapseMap = () => {
8282
const collapseMap = ref<Record<string, boolean>>({})
8383
84-
const setCollapse = (id: string, value: boolean) => {
84+
const setCollapse = (id: string | number, value: boolean) => {
8585
collapseMap.value[id] = value
8686
}
8787
88-
const switchCollapse = (id: string) => {
88+
const switchCollapse = (id: string | number) => {
8989
collapseMap.value[id] = !collapseMap.value[id]
9090
}
9191
9292
return { collapseMap, setCollapse, switchCollapse }
9393
}
9494
95-
const { collapseMap, switchCollapse } = useCollapseMap()
95+
const { collapseMap, setCollapse, switchCollapse } = useCollapseMap()
9696
97-
const handleSwitchCollapse = (node) => {
97+
interface TreeNode {
98+
id: string | number
99+
label: string
100+
parentId?: string | number
101+
level: number
102+
collapsed?: boolean
103+
rawData?: any
104+
}
105+
106+
const handleSwitchCollapse = (node: TreeNode) => {
98107
const children = node.rawData[props.childrenKey]
99108
if (Array.isArray(children) && children.length > 0) {
100109
switchCollapse(node.id)
101110
}
102111
}
103112
104-
const flattenTreeData = (node, parentId, level = 0, collapsed = false) => {
113+
const flattenTreeData = (node: any, parentId?: string | number, level = 0, collapsed = false): TreeNode[] => {
105114
const { idKey, labelKey, childrenKey } = props
106115
107116
const currentNode = {
@@ -112,7 +121,7 @@ const flattenTreeData = (node, parentId, level = 0, collapsed = false) => {
112121
collapsed,
113122
rawData: node
114123
}
115-
const result = [currentNode]
124+
const result: TreeNode[] = [currentNode]
116125
117126
const children = node[childrenKey]
118127
@@ -129,18 +138,14 @@ const nodes = computed(() => {
129138
return flattenTreeData({ [props.idKey]: props.rootId, [props.childrenKey]: props.data }).slice(1)
130139
})
131140
132-
const nodesMap = computed(() => {
141+
const nodesMap = computed<Record<string | number, TreeNode>>(() => {
133142
return nodes.value.reduce((result, node) => {
134143
result[node.id] = node
135144
return result
136-
}, {})
137-
})
138-
139-
const filteredNodes = computed(() => {
140-
return nodes.value.filter((node) => node.label.toLowerCase().includes(props.filterValue.toLowerCase()))
145+
}, {} as Record<string | number, TreeNode>)
141146
})
142147
143-
const getAncestorIds = (nodeId) => {
148+
const getAncestorIds = (nodeId: string | number): (string | number)[] => {
144149
const currentNode = nodesMap.value[nodeId]
145150
146151
if (!currentNode || !currentNode.parentId) {
@@ -154,6 +159,43 @@ const getAncestorIds = (nodeId) => {
154159
return ancestors
155160
}
156161
162+
const filteredNodes = ref<TreeNode[]>([])
163+
164+
// 下面两个 watch 对应的两个重新计算 filteredNodes 的场景。场景2比场景1多了展开匹配到的节点的操作
165+
166+
// 场景1. 页面树的结构发生变化,或者有节点收起或者展开,重新计算 filteredNodes
167+
watch(nodes, (nodes) => {
168+
filteredNodes.value = nodes.filter((node) => node.label.toLowerCase().includes(props.filterValue.toLowerCase()))
169+
})
170+
171+
// 场景2. 过滤条件发生变化,重新计算 filteredNodes,并且展开匹配到的节点
172+
watch(
173+
() => props.filterValue,
174+
(filterValue) => {
175+
const filtered = nodes.value.filter((node) => node.label.toLowerCase().includes(filterValue.toLowerCase()))
176+
177+
let collapseMapChanged = false
178+
179+
filtered.forEach((node) => {
180+
// 每个节点的祖先节点中,如果存在折叠的节点,则展开
181+
for (const id of getAncestorIds(node.id)) {
182+
if (collapseMap.value[id]) {
183+
setCollapse(id, false)
184+
collapseMapChanged = true
185+
}
186+
}
187+
})
188+
189+
// - 如果 collapseMap 有变化,会自动重新计算 nodes,更新路径:
190+
// props.filterValue -> collapseMap -> nodes -> filteredNodes -> filteredNodesWithAncestors
191+
// - 如果 collapseMap 没有变化,则重新设置 filteredNodes,更新路径:
192+
// props.filterValue -> filteredNodes -> filteredNodesWithAncestors
193+
if (!collapseMapChanged) {
194+
filteredNodes.value = filtered
195+
}
196+
}
197+
)
198+
157199
const filteredNodesWithAncestors = computed(() => {
158200
const idSet = new Set()
159201
@@ -174,7 +216,7 @@ const lines = {
174216
}
175217
176218
const layerLine = computed(() => {
177-
const result = {}
219+
const result: Record<number, Record<number, number>> = {}
178220
179221
const nodes = filteredNodesWithAncestors.value
180222
@@ -193,14 +235,14 @@ const layerLine = computed(() => {
193235
return result
194236
})
195237
196-
const handleClickRow = (node) => {
238+
const handleClickRow = (node: TreeNode) => {
197239
emit('clickRow', node)
198240
}
199241
200-
const draggedNode = ref(null)
201-
const hoveringNodeId = ref(null)
242+
const draggedNode = ref<TreeNode | null>(null)
243+
const hoveringNodeId = ref<string | number | null>(null)
202244
203-
const handleDragStart = (event, node) => {
245+
const handleDragStart = (_event: DragEvent, node: TreeNode) => {
204246
if (!props.draggable) {
205247
return
206248
}
@@ -209,12 +251,12 @@ const handleDragStart = (event, node) => {
209251
}
210252
211253
// dragover和dragenter事件回调函数都为handleDragOver。跨行拖动时,禁止拖拽图标可能会闪一下,所以将dragenter事件也加上回调函数
212-
const handleDragOver = (event, node) => {
254+
const handleDragOver = (event: DragEvent, node: TreeNode) => {
213255
if (!props.draggable) {
214256
return
215257
}
216258
217-
const isDescendant = getAncestorIds(node.id).includes(draggedNode.value.id)
259+
const isDescendant = getAncestorIds(node.id).includes(draggedNode.value!.id)
218260
219261
if (!isDescendant) {
220262
// 阻止默认行为以允许放置
@@ -225,7 +267,7 @@ const handleDragOver = (event, node) => {
225267
}
226268
}
227269
228-
const handleDrop = (event, node) => {
270+
const handleDrop = (event: DragEvent, node: Pick<TreeNode, 'id'>) => {
229271
event.preventDefault()
230272
231273
const dragged = draggedNode.value
@@ -246,7 +288,7 @@ const handleDragEnd = () => {
246288
hoveringNodeId.value = null
247289
}
248290
249-
const handleContainerDragOver = (event) => {
291+
const handleContainerDragOver = (event: DragEvent) => {
250292
if (!props.draggable) {
251293
return
252294
}
@@ -259,7 +301,7 @@ const handleContainerDragOver = (event) => {
259301
hoveringNodeId.value = props.rootId
260302
}
261303
262-
const handleContainerDragLeave = (event) => {
304+
const handleContainerDragLeave = (event: DragEvent) => {
263305
if (!props.draggable) {
264306
return
265307
}

0 commit comments

Comments
 (0)