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'
4343import LayerLines from ' ./LayerLines.vue'
4444
4545const props = defineProps ({
@@ -81,27 +81,36 @@ const emit = defineEmits(['clickRow', 'moveNode'])
8181const 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,39 @@ const getAncestorIds = (nodeId) => {
154159 return ancestors
155160}
156161
162+ const filteredNodes = ref <TreeNode []>([])
163+
164+ watch (nodes , (nodes ) => {
165+ filteredNodes .value = nodes .filter ((node ) => node .label .toLowerCase ().includes (props .filterValue .toLowerCase ()))
166+ })
167+
168+ watch (
169+ () => props .filterValue ,
170+ (filterValue ) => {
171+ const filtered = nodes .value .filter ((node ) => node .label .toLowerCase ().includes (filterValue .toLowerCase ()))
172+
173+ let collapseMapChanged = false
174+
175+ filtered .forEach ((node ) => {
176+ // 每个节点的祖先节点中,如果存在折叠的节点,则展开
177+ for (const id of getAncestorIds (node .id )) {
178+ if (collapseMap .value [id ]) {
179+ setCollapse (id , false )
180+ collapseMapChanged = true
181+ }
182+ }
183+ })
184+
185+ // - 如果 collapseMap 有变化,会自动重新计算 nodes,更新路径:
186+ // props.filterValue -> collapseMap -> nodes -> filteredNodes -> filteredNodesWithAncestors
187+ // - 如果 collapseMap 没有变化,则重新设置 filteredNodes,更新路径:
188+ // props.filterValue -> filteredNodes -> filteredNodesWithAncestors
189+ if (! collapseMapChanged ) {
190+ filteredNodes .value = filtered
191+ }
192+ }
193+ )
194+
157195const filteredNodesWithAncestors = computed (() => {
158196 const idSet = new Set ()
159197
@@ -174,7 +212,7 @@ const lines = {
174212}
175213
176214const layerLine = computed (() => {
177- const result = {}
215+ const result: Record < number , Record < number , number >> = {}
178216
179217 const nodes = filteredNodesWithAncestors .value
180218
@@ -193,14 +231,14 @@ const layerLine = computed(() => {
193231 return result
194232})
195233
196- const handleClickRow = (node ) => {
234+ const handleClickRow = (node : TreeNode ) => {
197235 emit (' clickRow' , node )
198236}
199237
200- const draggedNode = ref (null )
201- const hoveringNodeId = ref (null )
238+ const draggedNode = ref < TreeNode | null > (null )
239+ const hoveringNodeId = ref < string | number | null > (null )
202240
203- const handleDragStart = (event , node ) => {
241+ const handleDragStart = (_event : DragEvent , node : TreeNode ) => {
204242 if (! props .draggable ) {
205243 return
206244 }
@@ -209,12 +247,12 @@ const handleDragStart = (event, node) => {
209247}
210248
211249// dragover和dragenter事件回调函数都为handleDragOver。跨行拖动时,禁止拖拽图标可能会闪一下,所以将dragenter事件也加上回调函数
212- const handleDragOver = (event , node ) => {
250+ const handleDragOver = (event : DragEvent , node : TreeNode ) => {
213251 if (! props .draggable ) {
214252 return
215253 }
216254
217- const isDescendant = getAncestorIds (node .id ).includes (draggedNode .value .id )
255+ const isDescendant = getAncestorIds (node .id ).includes (draggedNode .value ! .id )
218256
219257 if (! isDescendant ) {
220258 // 阻止默认行为以允许放置
@@ -225,7 +263,7 @@ const handleDragOver = (event, node) => {
225263 }
226264}
227265
228- const handleDrop = (event , node ) => {
266+ const handleDrop = (event : DragEvent , node : Pick < TreeNode , ' id ' > ) => {
229267 event .preventDefault ()
230268
231269 const dragged = draggedNode .value
@@ -246,7 +284,7 @@ const handleDragEnd = () => {
246284 hoveringNodeId .value = null
247285}
248286
249- const handleContainerDragOver = (event ) => {
287+ const handleContainerDragOver = (event : DragEvent ) => {
250288 if (! props .draggable ) {
251289 return
252290 }
@@ -259,7 +297,7 @@ const handleContainerDragOver = (event) => {
259297 hoveringNodeId .value = props .rootId
260298}
261299
262- const handleContainerDragLeave = (event ) => {
300+ const handleContainerDragLeave = (event : DragEvent ) => {
263301 if (! props .draggable ) {
264302 return
265303 }
0 commit comments