From b009589585825b828bf136ad8831413fe6a8e610 Mon Sep 17 00:00:00 2001 From: Lyca Date: Tue, 4 Jan 2022 19:44:45 +0800 Subject: [PATCH] feat(next/antd): optimize SelectTable component (#2725) --- packages/antd/src/select-table/index.tsx | 66 +++++++++++++++++-- .../antd/src/select-table/useFlatOptions.tsx | 15 +++++ packages/antd/src/select-table/useSize.tsx | 36 ++++++++++ packages/next/src/select-table/index.tsx | 63 ++++++++++++++++-- .../next/src/select-table/useFlatOptions.tsx | 15 +++++ packages/next/src/select-table/useSize.tsx | 36 ++++++++++ .../next/src/select-table/useTitleAddon.tsx | 33 ++++------ 7 files changed, 235 insertions(+), 29 deletions(-) create mode 100644 packages/antd/src/select-table/useFlatOptions.tsx create mode 100644 packages/antd/src/select-table/useSize.tsx create mode 100644 packages/next/src/select-table/useFlatOptions.tsx create mode 100644 packages/next/src/select-table/useSize.tsx diff --git a/packages/antd/src/select-table/index.tsx b/packages/antd/src/select-table/index.tsx index b2223f5ffaf..b5af399c2c6 100644 --- a/packages/antd/src/select-table/index.tsx +++ b/packages/antd/src/select-table/index.tsx @@ -6,6 +6,8 @@ import { Input, Table } from 'antd' import { TableProps, ColumnProps } from 'antd/lib/table' import { SearchProps } from 'antd/lib/input' import { useFilterOptions } from './useFilterOptions' +import { useFlatOptions } from './useFlatOptions' +import { useSize } from './useSize' import { usePrefixCls } from '../__builtins__' const { Search } = Input @@ -62,10 +64,16 @@ const useColumns = () => { } const addPrimaryKey = (dataSource, rowKey, primaryKey) => - dataSource.map((item) => ({ - ...item, - [primaryKey]: rowKey(item), - })) + dataSource.map((item) => { + const children = isArr(item.children) + ? addPrimaryKey(item.children, rowKey, primaryKey) + : {} + return { + ...item, + ...children, + [primaryKey]: rowKey(item), + } + }) export const SelectTable: ComposedSelectTable = observer((props) => { const { @@ -91,12 +99,19 @@ export const SelectTable: ComposedSelectTable = observer((props) => { const field = useField() as any const loading = isBool(props.loading) ? props.loading : field.loading const disabled = field.disabled + const readOnly = field.readOnly const readPretty = field.readPretty + const { searchSize, tableSize } = useSize( + field.decoratorProps?.size, + searchProps?.size, + props?.size + ) const primaryKey = isFn(rowKey) ? '__formily_key__' : rowKey let dataSource = isArr(propsDataSource) ? propsDataSource : field.dataSource dataSource = isFn(rowKey) ? addPrimaryKey(dataSource, rowKey, primaryKey) : dataSource + const flatDataSource = useFlatOptions(dataSource) const columns = useColumns() // Filter dataSource By Search @@ -131,6 +146,9 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } const onInnerChange = (selectedRowKeys: any[], records: any[]) => { + if (readOnly) { + return + } let outputValue = optionAsValue ? records.map((item) => { const validItem = { ...item } @@ -142,6 +160,30 @@ export const SelectTable: ComposedSelectTable = observer((props) => { onChange?.(outputValue) } + const onRowClick = (record) => { + if (disabled || readOnly) { + return + } + const selectedRowKey = record?.[primaryKey] + const isSelected = selected?.includes(selectedRowKey) + let selectedRowKeys = [] + let records = [] + if (mode === 'single') { + selectedRowKeys = [selectedRowKey] + records = [record] + } else { + if (isSelected) { + selectedRowKeys = selected.filter((item) => item !== selectedRowKey) + } else { + selectedRowKeys = [...selected, selectedRowKey] + } + records = flatDataSource.filter((item) => + selectedRowKeys.includes(item?.[primaryKey]) + ) + } + onInnerChange(selectedRowKeys, records) + } + // Antd rowSelection type const modeAsType: any = { multiple: 'checkbox', single: 'radio' }?.[mode] @@ -161,8 +203,12 @@ export const SelectTable: ComposedSelectTable = observer((props) => { onInnerSearch(e.target.value)} disabled={disabled} + readOnly={readOnly} + size={searchSize} loading={loading} // antd /> ) : null} @@ -189,6 +235,18 @@ export const SelectTable: ComposedSelectTable = observer((props) => { columns={props.columns || columns} rowKey={primaryKey} loading={loading} + size={tableSize} + onRow={(record) => { + // antd + const onRowResult = otherTableProps.onRow?.(record) + return { + ...onRowResult, + onClick: (e) => { + onRowResult?.onClick?.(e) + onRowClick(record) + }, + } + }} > {''} diff --git a/packages/antd/src/select-table/useFlatOptions.tsx b/packages/antd/src/select-table/useFlatOptions.tsx new file mode 100644 index 00000000000..67ac2587bec --- /dev/null +++ b/packages/antd/src/select-table/useFlatOptions.tsx @@ -0,0 +1,15 @@ +const useFlatOptions = (tree: any[]) => { + const flatData = (data) => { + let list = [] + data.forEach((item) => { + list = [...list, item] + if (item?.children?.length) { + list = [...list, ...flatData(item.children)] + } + }) + return list + } + return flatData(tree) +} + +export { useFlatOptions } diff --git a/packages/antd/src/select-table/useSize.tsx b/packages/antd/src/select-table/useSize.tsx new file mode 100644 index 00000000000..fd2dd1cc310 --- /dev/null +++ b/packages/antd/src/select-table/useSize.tsx @@ -0,0 +1,36 @@ +interface ISize { + ( + fieldSize: 'large' | 'default' | 'small', + searchSize: 'large' | 'middle' | 'small', + tableSize: 'large' | 'middle' | 'small' + ): { + searchSize: 'large' | 'middle' | 'small' + tableSize: 'large' | 'middle' | 'small' + } +} + +const useSize: ISize = (fieldSize = 'default', searchSize, tableSize) => { + const fieldSizeMap: any = { + small: { + searchSize: 'small', + tableSize: 'small', + }, + default: { + searchSize: 'middle', + tableSize: 'middle', + }, + large: { + searchSize: 'large', + tableSize: 'default', + }, + } + const { searchSize: fieldSearchSize, tableSize: fieldTableSize } = + fieldSizeMap[fieldSize] + + return { + searchSize: searchSize || fieldSearchSize, + tableSize: tableSize || fieldTableSize, + } +} + +export { useSize } diff --git a/packages/next/src/select-table/index.tsx b/packages/next/src/select-table/index.tsx index a733bf2a548..75d4a946f02 100644 --- a/packages/next/src/select-table/index.tsx +++ b/packages/next/src/select-table/index.tsx @@ -6,7 +6,9 @@ import { Search, Table } from '@alifd/next' import { TableProps, ColumnProps } from '@alifd/next/types/table' import { SearchProps } from '@alifd/next/types/search' import { useFilterOptions } from './useFilterOptions' +import { useFlatOptions } from './useFlatOptions' import { useTitleAddon } from './useTitleAddon' +import { useSize } from './useSize' import { usePrefixCls } from '../__builtins__' type IFilterOption = boolean | ((option: any, keyword: string) => boolean) @@ -61,10 +63,16 @@ const useColumns = () => { } const addPrimaryKey = (dataSource, rowKey, primaryKey) => - dataSource.map((item) => ({ - ...item, - [primaryKey]: rowKey(item), - })) + dataSource.map((item) => { + const children = isArr(item.children) + ? addPrimaryKey(item.children, rowKey, primaryKey) + : {} + return { + ...item, + ...children, + [primaryKey]: rowKey(item), + } + }) export const SelectTable: ComposedSelectTable = observer((props) => { const { @@ -90,12 +98,19 @@ export const SelectTable: ComposedSelectTable = observer((props) => { const field = useField() as any const loading = isBool(props.loading) ? props.loading : field.loading const disabled = field.disabled + const readOnly = field.readOnly const readPretty = field.readPretty + const { searchSize, tableSize } = useSize( + field.decoratorProps?.size, + searchProps?.size, + props?.size + ) const primaryKey = isFn(rowKey) ? '__formily_key__' : rowKey let dataSource = isArr(propsDataSource) ? propsDataSource : field.dataSource dataSource = isFn(rowKey) ? addPrimaryKey(dataSource, rowKey, primaryKey) : dataSource + const flatDataSource = useFlatOptions(dataSource) const columns = useColumns() // Filter dataSource By Search @@ -130,6 +145,9 @@ export const SelectTable: ComposedSelectTable = observer((props) => { } const onInnerChange = (selectedRowKeys: any[], records: any[]) => { + if (readOnly) { + return + } let outputValue = optionAsValue ? records.map((item) => { const validItem = { ...item } @@ -141,13 +159,38 @@ export const SelectTable: ComposedSelectTable = observer((props) => { onChange?.(outputValue) } + const onRowClick = (record) => { + if (disabled || readOnly) { + return + } + const selectedRowKey = record?.[primaryKey] + const isSelected = selected?.includes(selectedRowKey) + let selectedRowKeys = [] + let records = [] + if (mode === 'single') { + selectedRowKeys = [selectedRowKey] + records = [record] + } else { + if (isSelected) { + selectedRowKeys = selected.filter((item) => item !== selectedRowKey) + } else { + selectedRowKeys = [...selected, selectedRowKey] + } + records = flatDataSource.filter((item) => + selectedRowKeys.includes(item?.[primaryKey]) + ) + } + onInnerChange(selectedRowKeys, records) + } + // Fusion Table Checkbox const titleAddon = useTitleAddon( selected, - dataSource, + flatDataSource, primaryKey, mode, disabled, + readOnly, onInnerChange ) @@ -167,8 +210,12 @@ export const SelectTable: ComposedSelectTable = observer((props) => { ) : null} @@ -196,6 +243,12 @@ export const SelectTable: ComposedSelectTable = observer((props) => { columns={props.columns || columns} primaryKey={primaryKey} loading={loading} + size={tableSize} + onRowClick={(record, index, e) => { + // fusion + onRowClick(record) + props.onRowClick?.(record, index, e) + }} > {''} diff --git a/packages/next/src/select-table/useFlatOptions.tsx b/packages/next/src/select-table/useFlatOptions.tsx new file mode 100644 index 00000000000..67ac2587bec --- /dev/null +++ b/packages/next/src/select-table/useFlatOptions.tsx @@ -0,0 +1,15 @@ +const useFlatOptions = (tree: any[]) => { + const flatData = (data) => { + let list = [] + data.forEach((item) => { + list = [...list, item] + if (item?.children?.length) { + list = [...list, ...flatData(item.children)] + } + }) + return list + } + return flatData(tree) +} + +export { useFlatOptions } diff --git a/packages/next/src/select-table/useSize.tsx b/packages/next/src/select-table/useSize.tsx new file mode 100644 index 00000000000..0c30413cd58 --- /dev/null +++ b/packages/next/src/select-table/useSize.tsx @@ -0,0 +1,36 @@ +interface ISize { + ( + fieldSize: 'large' | 'default' | 'small', + searchSize: 'large' | 'medium', + tableSize: 'small' | 'medium' + ): { + searchSize: 'large' | 'medium' + tableSize: 'small' | 'medium' + } +} + +const useSize: ISize = (fieldSize = 'default', searchSize, tableSize) => { + const fieldSizeMap: any = { + small: { + searchSize: 'medium', + tableSize: 'small', + }, + default: { + searchSize: 'medium', + tableSize: 'medium', + }, + large: { + searchSize: 'large', + tableSize: 'medium', + }, + } + const { searchSize: fieldSearchSize, tableSize: fieldTableSize } = + fieldSizeMap[fieldSize] + + return { + searchSize: searchSize || fieldSearchSize, + tableSize: tableSize || fieldTableSize, + } +} + +export { useSize } diff --git a/packages/next/src/select-table/useTitleAddon.tsx b/packages/next/src/select-table/useTitleAddon.tsx index cc745d6b535..f810f9981d9 100644 --- a/packages/next/src/select-table/useTitleAddon.tsx +++ b/packages/next/src/select-table/useTitleAddon.tsx @@ -3,20 +3,9 @@ import { Checkbox } from '@alifd/next' // 重写表格表头Checkbox const newCheckbox = - (selected, dataSource, primaryKey, disabled, onChange) => () => { - const getDataSourceKey = (data: any[], primaryKey: string) => { - let keys = [] - data?.forEach((item: any) => { - if (item?.[primaryKey]) { - keys = [...keys, item[primaryKey]] - } - if (item?.children?.length) { - keys = [...keys, ...getDataSourceKey(item.children, primaryKey)] - } - }) - return keys - } - const allDataSourceKeys = getDataSourceKey(dataSource, primaryKey) + (selected, flatDataSource, primaryKey, disabled, readOnly, onChange) => + () => { + const allDataSourceKeys = flatDataSource.map((item) => item?.[primaryKey]) return ( { - if (checked) { - onChange?.(allDataSourceKeys, dataSource) - } else { - onChange?.([], []) + if (!readOnly) { + if (checked) { + onChange?.(allDataSourceKeys, flatDataSource) + } else { + onChange?.([], []) + } } }} /> @@ -38,10 +29,11 @@ const newCheckbox = const useTitleAddon = ( selected: any[], - dataSource: any[], + flatDataSource: any[], primaryKey: string, mode: string, disabled: boolean, + readOnly: boolean, onChange: (selectedRowKeys: any[], record: any[]) => any ) => { if (mode === 'single') { @@ -53,9 +45,10 @@ const useTitleAddon = ( }), titleAddons: newCheckbox( selected, - dataSource, + flatDataSource, primaryKey, disabled, + readOnly, onChange ), }