From 0d9438601d09ce73fabf6f5e3a7c2fc4acea302c Mon Sep 17 00:00:00 2001 From: xiamiao Date: Thu, 1 Aug 2024 17:01:31 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat(check-tree-select):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=94=AF=E6=8C=81=E8=BF=87=E6=BB=A4=E5=B7=B2=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E9=A1=B9(#2951)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../check-tree-select/src/CheckTreeSelect.tsx | 75 ++++++++++++- .../stories/index.stories.tsx | 1 + .../stories/only-checked.stories.tsx | 102 ++++++++++++++++++ 3 files changed, 174 insertions(+), 4 deletions(-) create mode 100644 packages/ui/check-tree-select/stories/only-checked.stories.tsx diff --git a/packages/ui/check-tree-select/src/CheckTreeSelect.tsx b/packages/ui/check-tree-select/src/CheckTreeSelect.tsx index 7c6d2f44d..1a803c313 100644 --- a/packages/ui/check-tree-select/src/CheckTreeSelect.tsx +++ b/packages/ui/check-tree-select/src/CheckTreeSelect.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef, useCallback, useMemo } from 'react' +import React, { forwardRef, useCallback, useMemo, useState, useRef } from 'react' import { cx, getPrefixCls } from '@hi-ui/classname' import { __DEV__ } from '@hi-ui/env' import { @@ -11,7 +11,7 @@ import { useUncontrolledToggle } from '@hi-ui/use-toggle' import { FlattedTreeNodeData, Tree } from '@hi-ui/tree' import { useUncontrolledState } from '@hi-ui/use-uncontrolled-state' import { Picker, PickerProps } from '@hi-ui/picker' -import { baseFlattenTree } from '@hi-ui/tree-utils' +import { baseFlattenTree, filterTree } from '@hi-ui/tree-utils' import { isArrayNonEmpty, isUndef } from '@hi-ui/type-assertion' import { uniqBy } from '@hi-ui/array-utils' import { Highlighter } from '@hi-ui/highlighter' @@ -30,6 +30,7 @@ import { } from '@hi-ui/use-search-mode' import { useCheck } from './hooks/use-check' import { getAllCheckedStatus } from './utils' +import { BaseTreeNodeData } from 'packages/utils/tree-utils/lib/types/types' const TREE_SELECT_PREFIX = getPrefixCls('check-tree-select') const DEFAULT_DATA = [] as [] @@ -88,6 +89,7 @@ export const CheckTreeSelect = forwardRef(null) + const expandedViewRef = useRef<'normal' | 'onlyChecked'>('normal') + const activeExpandable = showOnlyShowChecked && !!filterItems && menuVisible + /** * 转换对象 */ @@ -244,9 +250,9 @@ export const CheckTreeSelect = forwardRef setStateInSearch((prev: any) => ({ ...prev, expandedIds: ids })) @@ -377,6 +383,63 @@ export const CheckTreeSelect = forwardRef { + if (!showOnlyShowChecked) return + + evt.preventDefault() + if (filterItems) { + setFilterItems(null) + } + + if (menuVisible) { + if (expandedViewRef.current === 'normal') { + menuVisibleAction.off() + } + } else { + menuVisibleAction.on() + } + + expandedViewRef.current = 'normal' + }} + expandable={showOnlyShowChecked} + activeExpandable={activeExpandable} + onExpand={(evt) => { + if (!showOnlyShowChecked) return + + // 阻止冒泡触发外层 onClick + evt.preventDefault() + evt.stopPropagation() + + // 选中数据 + setFilterItems(() => { + const filterFunc = (node: BaseTreeNodeData): boolean => { + if (parsedCheckedIds.includes(node.id)) { + return true + } + + if (node.children && node.children?.length > 0) { + return node.children.some((child) => filterFunc(child)) + } + + return false + } + // filterTree 过滤树结构,将不包含value中的节点分支过滤掉 + // 返回过滤后的树结构 + const treeData = filterTree(data as BaseTreeNodeData[], filterFunc) + + return treeData + }) + // 展开/关闭操作 + if (menuVisible) { + if (expandedViewRef.current !== 'normal') { + menuVisibleAction.off() + } + } else { + menuVisibleAction.on() + } + + expandedViewRef.current = 'onlyChecked' + }} /> ) } @@ -542,6 +605,10 @@ export interface CheckTreeSelectProps * 是否开启全选功能,需要对数据全量操作。异步数据场景暂不支持,可自行渲染弹层底部实现 */ showCheckAll?: boolean + /** + * 是否开启查看仅已选功能 + */ + showOnlyShowChecked?: boolean /** * TagInput 参数设置 */ diff --git a/packages/ui/check-tree-select/stories/index.stories.tsx b/packages/ui/check-tree-select/stories/index.stories.tsx index 7f920ac47..d3756e4e1 100644 --- a/packages/ui/check-tree-select/stories/index.stories.tsx +++ b/packages/ui/check-tree-select/stories/index.stories.tsx @@ -16,6 +16,7 @@ export * from './check-all.stories' export * from './virtual-list.stories' export * from './custom-render.stories' export * from './addon.stories' +export * from './only-checked.stories' export default { title: 'Data Input/CheckTreeSelect', diff --git a/packages/ui/check-tree-select/stories/only-checked.stories.tsx b/packages/ui/check-tree-select/stories/only-checked.stories.tsx new file mode 100644 index 000000000..7f8cb6431 --- /dev/null +++ b/packages/ui/check-tree-select/stories/only-checked.stories.tsx @@ -0,0 +1,102 @@ +import React from 'react' +import CheckTreeSelect from '../src' + +/** + * @title 仅过滤已选用法 + */ +export const OnlyChecked = () => { + const [data] = React.useState([ + { + title: '手机类', + id: '0', + children: [ + { + title: 'Redmi系列', + id: '0-0', + disabled: true, + children: [ + { + id: '0-0-1', + title: 'Redmi K30', + }, + { + id: '0-0-2', + title: 'Redmi K30 Pro', + }, + { + id: '0-0-3', + title: 'Redmi 10X 5G', + }, + { + id: '0-0-4', + title: 'Redmi Note 8', + }, + { + id: '0-0-5', + title: 'Redmi 9', + }, + { + id: '0-0-6', + title: 'Redmi 9A', + }, + ], + }, + { + title: '小米手机', + id: '0-1', + children: [ + { + id: '0-1-1', + title: '小米10 Pro', + }, + { + id: '0-1-2', + title: '小米10', + }, + { + id: '0-1-3', + title: '小米10 青春版 5G', + }, + { + id: '0-1-4', + title: '小米MIX Alpha', + }, + ], + }, + ], + }, + { + title: '电视', + id: '1', + children: [ + { + title: '小米电视 大师 65英寸OLED', + id: '1-0', + }, + { + title: 'Redmi 智能电视 MAX 98', + id: '1-1', + }, + { + title: '小米电视4A 60英寸', + id: '1-2', + }, + ], + }, + ]) + + return ( + <> +

Only Checked

+
+ +
+ + ) +} From 204df17707c05e435e6eb6cab9c524d33450e4cb Mon Sep 17 00:00:00 2001 From: xiamiao Date: Thu, 1 Aug 2024 17:04:16 +0800 Subject: [PATCH 2/3] =?UTF-8?q?chore(check-tree-select):=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E5=8F=98=E6=9B=B4=E8=AE=B0=E5=BD=95=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/four-cameras-float.md | 5 +++++ .changeset/healthy-suits-drop.md | 5 +++++ 2 files changed, 10 insertions(+) create mode 100644 .changeset/four-cameras-float.md create mode 100644 .changeset/healthy-suits-drop.md diff --git a/.changeset/four-cameras-float.md b/.changeset/four-cameras-float.md new file mode 100644 index 000000000..8a6e7b361 --- /dev/null +++ b/.changeset/four-cameras-float.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/check-tree-select": minor +--- + +feat: 新增支持过滤已选择项 diff --git a/.changeset/healthy-suits-drop.md b/.changeset/healthy-suits-drop.md new file mode 100644 index 000000000..04e7bfbac --- /dev/null +++ b/.changeset/healthy-suits-drop.md @@ -0,0 +1,5 @@ +--- +"@hi-ui/hiui": patch +--- + +feat(check-tree-select): 新增支持过滤已选择项 From eabc67d2158a2b08746879b4fea2e815427b4fe2 Mon Sep 17 00:00:00 2001 From: xiamiao Date: Wed, 7 Aug 2024 19:08:07 +0800 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20=E4=BF=AE=E6=94=B9=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=92=8C=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/ui/check-tree-select/src/CheckTreeSelect.tsx | 2 +- packages/ui/check-tree-select/stories/only-checked.stories.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/check-tree-select/src/CheckTreeSelect.tsx b/packages/ui/check-tree-select/src/CheckTreeSelect.tsx index 1a803c313..19467866e 100644 --- a/packages/ui/check-tree-select/src/CheckTreeSelect.tsx +++ b/packages/ui/check-tree-select/src/CheckTreeSelect.tsx @@ -112,7 +112,7 @@ export const CheckTreeSelect = forwardRef(null) + const [filterItems, setFilterItems] = useState(null) const expandedViewRef = useRef<'normal' | 'onlyChecked'>('normal') const activeExpandable = showOnlyShowChecked && !!filterItems && menuVisible diff --git a/packages/ui/check-tree-select/stories/only-checked.stories.tsx b/packages/ui/check-tree-select/stories/only-checked.stories.tsx index 7f8cb6431..a129c0d99 100644 --- a/packages/ui/check-tree-select/stories/only-checked.stories.tsx +++ b/packages/ui/check-tree-select/stories/only-checked.stories.tsx @@ -2,7 +2,7 @@ import React from 'react' import CheckTreeSelect from '../src' /** - * @title 仅过滤已选用法 + * @title 查看已选 */ export const OnlyChecked = () => { const [data] = React.useState([