diff --git a/packages/cdk/utils/src/tree.ts b/packages/cdk/utils/src/tree.ts index 0a0c3185d..1eb4331ca 100644 --- a/packages/cdk/utils/src/tree.ts +++ b/packages/cdk/utils/src/tree.ts @@ -63,7 +63,7 @@ export function mapTree, R extends object, C extend export function filterTree, C extends keyof V>( data: V[], childrenKey: C, - filterFn: (item: V, parents: V[]) => boolean, + filterFn: (item: V, parents: V[], filteredChildren: V[] | undefined) => boolean, filterStrategy: 'and' | 'or' = 'or', ): V[] { const filter = (_data: V[], parents: V[]): V[] => { @@ -76,7 +76,7 @@ export function filterTree, C extends keyof V>( children = filter(item[childrenKey]!, [item, ...parents]) } - let itemValid = filterFn(item, parents) + let itemValid = filterFn(item, parents, children) const childrenValid = (children && children.length > 0) || (!item[childrenKey]?.length && itemValid) itemValid = filterStrategy === 'and' ? childrenValid && itemValid : childrenValid || itemValid diff --git a/packages/pro/transfer/src/composables/useTreeDataStrategy.ts b/packages/pro/transfer/src/composables/useTreeDataStrategy.ts index 7141194dd..43e8903a0 100644 --- a/packages/pro/transfer/src/composables/useTreeDataStrategy.ts +++ b/packages/pro/transfer/src/composables/useTreeDataStrategy.ts @@ -94,9 +94,10 @@ function createSeparateDataSourceFn, C extends cachedTargetData: Ref, cascaderStrategy: CascaderStrategy, targetDataCount: Ref, + dataMap: Map, flatTargetData: boolean | 'all' = false, ): Exclude['separateDataSource'], undefined> { - const targetDataKeySet = new Set() + const sourceDataKeySet = new Set() const getFilterFn = (selectedKeySet: Set, getKey: GetKeyFn): ((data: V[], isSource: boolean) => V[]) => { // under cascaderStrategy `parent`, selected child nodes are not in selectedKeys @@ -120,13 +121,13 @@ function createSeparateDataSourceFn, C extends return filterTree( data, childrenKey.value, - (item, parent) => { + (item, parent, filteredChildren) => { const filterRes = filterFn(item, parent, isSource) // set targetDataKeySet to collect targetData count later // we collect this during filter process to avoid unecessary traveral - if (!isSource && filterRes) { - targetDataKeySet.add(getKey(item)) + if (isSource && (filterRes || filteredChildren?.length)) { + sourceDataKeySet.add(getKey(item)) } return filterRes @@ -137,9 +138,7 @@ function createSeparateDataSourceFn, C extends const res: V[] = [] traverseTree(data, childrenKey.value, (item, parent) => { - const key = getKey(item) - if (filterFn(item, parent, isSource) && !targetDataKeySet.has(key)) { - targetDataKeySet.add(key) + if (filterFn(item, parent, isSource)) { res.push({ ...item, [childrenKey.value]: undefined }) } }) @@ -150,19 +149,21 @@ function createSeparateDataSourceFn, C extends return (data, _, selectedKeySet, getKey) => { const filterData = getFilterFn(selectedKeySet, getKey) + sourceDataKeySet.clear() + + const sourceData = filterData(data, true) const newTargetData = filterData(data, false) const previousTargetData = filterData(cachedTargetData.value, false) - targetDataCount.value = targetDataKeySet.size - targetDataKeySet.clear() - // merge new data with previous data // beacause we intend to cache selected data after dataSource changes const targetData = mergeTree(previousTargetData, newTargetData, childrenKey.value, getKey) cachedTargetData.value = targetData + targetDataCount.value = cascaderStrategy === 'off' ? targetData.length : dataMap.size - sourceDataKeySet.size + return { - sourceData: filterData(data, true), + sourceData, targetData: cascaderStrategy === 'off' ? targetData : flattenTargetTree(targetData, childrenKey.value, flatTargetData), } @@ -197,6 +198,7 @@ function createStrategy, C extends string>( cachedTargetData, cascaderStrategy, targetDataCount, + dataMap, flatTargetData, ), append: (keys, selectedKey) => checkStateResolver.appendKeys(selectedKey, keys),