From a3722441043827eab93b13ab82c560e0353fc01f Mon Sep 17 00:00:00 2001 From: Lyca Date: Thu, 3 Mar 2022 11:19:59 +0800 Subject: [PATCH] feat(next/antd): support dataSource disabled props in SelectTable (#2902) --- packages/antd/src/select-table/index.tsx | 20 +++++- .../antd/src/select-table/useCheckSlackly.tsx | 68 +++++++++++++++++++ packages/antd/src/select-table/utils.ts | 25 ++++--- packages/next/src/select-table/index.tsx | 5 +- .../next/src/select-table/useTitleAddon.tsx | 5 +- packages/next/src/select-table/utils.ts | 25 ++++--- 6 files changed, 121 insertions(+), 27 deletions(-) create mode 100644 packages/antd/src/select-table/useCheckSlackly.tsx diff --git a/packages/antd/src/select-table/index.tsx b/packages/antd/src/select-table/index.tsx index c342f6b4bc9..b4fb0c6dca1 100644 --- a/packages/antd/src/select-table/index.tsx +++ b/packages/antd/src/select-table/index.tsx @@ -8,6 +8,7 @@ import { SearchProps } from 'antd/lib/input' import { useFilterOptions } from './useFilterOptions' import { useFlatOptions } from './useFlatOptions' import { useSize } from './useSize' +import { useCheckSlackly } from './useCheckSlackly' import { getUISelected, getOutputData } from './utils' import { usePrefixCls } from '../__builtins__' @@ -176,7 +177,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } const onRowClick = (record) => { - if (disabled || readOnly) { + if (disabled || readOnly || record?.disabled) { return } const selectedRowKey = record?.[primaryKey] @@ -196,6 +197,21 @@ export const SelectTable: ComposedSelectTable = observer((props) => { selectedRowKeys.includes(item?.[primaryKey]) ) } + if (rowSelection?.checkStrictly !== false) { + onInnerChange(selectedRowKeys, records) + } else { + onSlacklyChange(selectedRowKeys) + } + } + + // Antd TreeData SlacklyChange for onRowClick + const onSlacklyChange = (currentSelected: any[]) => { + let { selectedRowKeys, records } = useCheckSlackly( + currentSelected, + selected, + primaryKey, + flatDataSource + ) onInnerChange(selectedRowKeys, records) } @@ -230,7 +246,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { ...rowSelection, getCheckboxProps: (record) => ({ ...(rowSelection?.getCheckboxProps?.(record) as any), - disabled, + disabled: disabled || record?.disabled, }), // antd selectedRowKeys: selected, onChange: onInnerChange, diff --git a/packages/antd/src/select-table/useCheckSlackly.tsx b/packages/antd/src/select-table/useCheckSlackly.tsx new file mode 100644 index 00000000000..195387826a5 --- /dev/null +++ b/packages/antd/src/select-table/useCheckSlackly.tsx @@ -0,0 +1,68 @@ +import { getTreeKeys, hasSelectedKey, completedKeys } from './utils' + +/** + * 判断该字段的 indeterminate 属性 + * @param record 当前字段 + * @param selected 已选中的字段值集合 + * @param primaryKey 键名称 + * @returns indeterminate 属性值 + */ +const getIndeterminate = (record: any, selected: any[], primaryKey: string) => { + if (selected?.includes(record[primaryKey])) { + return undefined + } + return hasSelectedKey(record.children, selected, primaryKey) || undefined +} + +interface ICheckSlackly { + ( + currentSelected: any[], + allSelected: any[], + primaryKey: string, + flatDataSource: any[] + ): { + selectedRowKeys: any[] + records: any[] + } +} + +const useCheckSlackly: ICheckSlackly = ( + currentSelected, // onChange 返回的 keys + allSelected, // Table UI 展示的 keys + primaryKey, + flatDataSource +) => { + const isSelected = currentSelected.length > allSelected.length // 判断是选中还是取消 + const currentKey = [...currentSelected, ...allSelected].find( + (key) => !(currentSelected.includes(key) && allSelected.includes(key)) // 当前变化key不同时存在于两个selected + ) + const currentRecords = flatDataSource.find( + (item) => item[primaryKey] === currentKey + ) + const currentTreeKeys = getTreeKeys([currentRecords], primaryKey) + let newSelectedRowKeys = [] + if (isSelected) { + // 选中当前key及其子keys + newSelectedRowKeys = [...new Set([...allSelected, ...currentTreeKeys])] + } else { + // 移除当前key及其子keys + newSelectedRowKeys = allSelected.filter( + (key) => !currentTreeKeys.includes(key) + ) + } + + newSelectedRowKeys = completedKeys( + flatDataSource, + newSelectedRowKeys, + primaryKey + ) + + return { + selectedRowKeys: newSelectedRowKeys, + records: flatDataSource.filter((item) => + newSelectedRowKeys.includes(item[primaryKey]) + ), + } +} + +export { useCheckSlackly, getIndeterminate } diff --git a/packages/antd/src/select-table/utils.ts b/packages/antd/src/select-table/utils.ts index de0f11cfcaa..6f8bb9cf2b5 100644 --- a/packages/antd/src/select-table/utils.ts +++ b/packages/antd/src/select-table/utils.ts @@ -9,14 +9,16 @@ import { useFlatOptions } from './useFlatOptions' */ const getTreeKeys = (tree: any[], primaryKey: string) => isArr(tree) - ? tree.reduce( - (prev, current) => [ + ? tree.reduce((prev, current) => { + if (current?.disabled) { + return prev + } + return [ ...prev, current[primaryKey], ...getTreeKeys(current?.children, primaryKey), - ], - [] - ) + ] + }, []) : [] /** @@ -41,10 +43,11 @@ const hasSelectedKey = (tree: any[], selected: any[], primaryKey: string) => { * @returns 是否全部被选中 */ const isAllSelected = (list: any[], selected: any[], primaryKey: string) => { - const selectedList = list.filter((item) => + const validList = list.filter((item) => !item?.disabled) + const selectedList = validList.filter((item) => selected?.includes(item[primaryKey]) ) - return selectedList.length === list.length + return selectedList.length === validList.length } /** @@ -69,8 +72,10 @@ const completedKeys = ( primaryKey ) if (isAllSelected(item.children, allSelectedKeys, primaryKey)) { - // 如果该元素的子元素全部选中,则也选中该项(即包含全选子元素的父元素) - allSelectedKeys = [...new Set([...allSelectedKeys, item[primaryKey]])] + // 如果该元素的子元素全部选中,且该元素未禁用,则也选中该项(即包含全选子元素的父元素) + if (!item?.disabled) { + allSelectedKeys = [...new Set([...allSelectedKeys, item[primaryKey]])] + } } else { // 如果该元素的子元素未全部选中,则移除该项 allSelectedKeys = allSelectedKeys.filter( @@ -175,7 +180,7 @@ const getOutputData = ( }) } else if (valueType === 'path') { outputValue = getSelectedPath(dataSource, keys, primaryKey) - outputOptions = options + outputOptions = [...options] } else { // valueType === 'all' outputValue = [...keys] diff --git a/packages/next/src/select-table/index.tsx b/packages/next/src/select-table/index.tsx index 565dab4858c..8e24b9c9614 100644 --- a/packages/next/src/select-table/index.tsx +++ b/packages/next/src/select-table/index.tsx @@ -180,7 +180,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } const onRowClick = (record) => { - if (disabled || readOnly) { + if (disabled || readOnly || record?.disabled) { return } const selectedRowKey = record?.[primaryKey] @@ -203,7 +203,6 @@ export const SelectTable: ComposedSelectTable = observer((props) => { if (rowSelection?.checkStrictly !== false) { onInnerChange(selectedRowKeys, records) } else { - // fusion onSlacklyChange(selectedRowKeys) } } @@ -259,7 +258,7 @@ export const SelectTable: ComposedSelectTable = observer((props) => { getProps: (record, index) => ({ ...(rowSelection?.getProps?.(record, index) as any), indeterminate: getIndeterminate(record, selected, primaryKey), // 父子关联模式indeterminate值 - disabled, + disabled: disabled || record?.disabled, }), // fusion selectedRowKeys: selected, onChange: diff --git a/packages/next/src/select-table/useTitleAddon.tsx b/packages/next/src/select-table/useTitleAddon.tsx index e2d4e8d3421..a7cbf41b65f 100644 --- a/packages/next/src/select-table/useTitleAddon.tsx +++ b/packages/next/src/select-table/useTitleAddon.tsx @@ -5,7 +5,8 @@ import { Checkbox } from '@alifd/next' const newCheckbox = (selected, flatDataSource, primaryKey, disabled, readOnly, onChange) => () => { - const allDataSourceKeys = flatDataSource.map((item) => item?.[primaryKey]) + const allDataSource = flatDataSource.filter((item) => !item.disabled) + const allDataSourceKeys = allDataSource.map((item) => item?.[primaryKey]) const indeterminate = !!( selected?.length && selected.length !== allDataSourceKeys.length ) @@ -18,7 +19,7 @@ const newCheckbox = onChange={(checked) => { if (!readOnly) { if (checked || indeterminate) { - onChange?.(allDataSourceKeys, flatDataSource) + onChange?.(allDataSourceKeys, allDataSource) } else { onChange?.([], []) } diff --git a/packages/next/src/select-table/utils.ts b/packages/next/src/select-table/utils.ts index de0f11cfcaa..6f8bb9cf2b5 100644 --- a/packages/next/src/select-table/utils.ts +++ b/packages/next/src/select-table/utils.ts @@ -9,14 +9,16 @@ import { useFlatOptions } from './useFlatOptions' */ const getTreeKeys = (tree: any[], primaryKey: string) => isArr(tree) - ? tree.reduce( - (prev, current) => [ + ? tree.reduce((prev, current) => { + if (current?.disabled) { + return prev + } + return [ ...prev, current[primaryKey], ...getTreeKeys(current?.children, primaryKey), - ], - [] - ) + ] + }, []) : [] /** @@ -41,10 +43,11 @@ const hasSelectedKey = (tree: any[], selected: any[], primaryKey: string) => { * @returns 是否全部被选中 */ const isAllSelected = (list: any[], selected: any[], primaryKey: string) => { - const selectedList = list.filter((item) => + const validList = list.filter((item) => !item?.disabled) + const selectedList = validList.filter((item) => selected?.includes(item[primaryKey]) ) - return selectedList.length === list.length + return selectedList.length === validList.length } /** @@ -69,8 +72,10 @@ const completedKeys = ( primaryKey ) if (isAllSelected(item.children, allSelectedKeys, primaryKey)) { - // 如果该元素的子元素全部选中,则也选中该项(即包含全选子元素的父元素) - allSelectedKeys = [...new Set([...allSelectedKeys, item[primaryKey]])] + // 如果该元素的子元素全部选中,且该元素未禁用,则也选中该项(即包含全选子元素的父元素) + if (!item?.disabled) { + allSelectedKeys = [...new Set([...allSelectedKeys, item[primaryKey]])] + } } else { // 如果该元素的子元素未全部选中,则移除该项 allSelectedKeys = allSelectedKeys.filter( @@ -175,7 +180,7 @@ const getOutputData = ( }) } else if (valueType === 'path') { outputValue = getSelectedPath(dataSource, keys, primaryKey) - outputOptions = options + outputOptions = [...options] } else { // valueType === 'all' outputValue = [...keys]