11// 行选中相关功能:单选 + 多选
22
3- import React , { useEffect , useState , MouseEvent , useMemo } from 'react' ;
4- import { intersection , get , isFunction } from 'lodash-es' ;
5- import { isRowSelectedDisabled } from '@tdesign/common-js/table/utils' ;
3+ import React , { MouseEvent , useEffect , useMemo , useState } from 'react' ;
4+ import { get , isFunction } from 'lodash-es' ;
5+
66import log from '@tdesign/common-js/log/index' ;
7+ import { isRowSelectedDisabled } from '@tdesign/common-js/table/utils' ;
8+ import Checkbox from '../../checkbox' ;
79import useControlled from '../../hooks/useControlled' ;
8- import {
10+ import Radio from '../../radio' ;
11+
12+ import type { ClassName } from '../../common' ;
13+ import type {
914 PrimaryTableCellParams ,
1015 PrimaryTableCol ,
1116 RowClassNameParams ,
1217 TableRowData ,
1318 TdBaseTableProps ,
1419 TdPrimaryTableProps ,
1520} from '../type' ;
16- import { TableClassName } from './useClassName' ;
17- import Checkbox from '../../checkbox' ;
18- import Radio from '../../radio' ;
19- import { ClassName } from '../../common' ;
21+ import type { TableClassName } from './useClassName' ;
22+ import { DEFAULT_CURRENT , DEFAULT_PAGE_SIZE } from './usePagination' ;
2023
2124const selectedRowDataMap = new Map < string | number , TableRowData > ( ) ;
2225
2326export default function useRowSelect (
2427 props : TdPrimaryTableProps ,
2528 tableSelectedClasses : TableClassName [ 'tableSelectedClasses' ] ,
2629) {
27- const { selectedRowKeys, columns, data, rowKey, indeterminateSelectedRowKeys } = props ;
28- const { pagination, reserveSelectedRowOnPaginate } = props ;
30+ const {
31+ selectedRowKeys,
32+ columns,
33+ data,
34+ rowKey,
35+ indeterminateSelectedRowKeys,
36+ pagination,
37+ reserveSelectedRowOnPaginate,
38+ } = props ;
2939 const [ currentPaginateData , setCurrentPaginateData ] = useState < TableRowData [ ] > ( data ) ;
3040 const [ selectedRowClassNames , setSelectedRowClassNames ] = useState < TdBaseTableProps [ 'rowClassName' ] > ( ) ;
3141 const [ tSelectedRowKeys , setTSelectedRowKeys ] = useControlled ( props , 'selectedRowKeys' , props . onSelectChange , {
@@ -39,24 +49,22 @@ export default function useRowSelect(
3949 // eslint-disable-next-line
4050 } , [ reserveSelectedRowOnPaginate , data , currentPaginateData ] ) ;
4151
42- // 选中的行,和所有可以选择的行,交集,用于计算 isSelectedAll 和 isIndeterminate
43- const intersectionKeys = intersection (
44- tSelectedRowKeys ,
45- canSelectedRows . map ( ( t ) => get ( t , rowKey || 'id' ) ) ,
46- ) ;
47-
4852 useEffect (
4953 ( ) => {
5054 if ( reserveSelectedRowOnPaginate ) return ;
5155 // 分页变化时,在 onPageChange 中设置 setCurrentPaginateData,PrimaryTable 中
56+ if ( ! pagination ) {
57+ setCurrentPaginateData ( data ) ;
58+ return ;
59+ }
5260 const { pageSize, current, defaultPageSize, defaultCurrent } = pagination ;
53- const tPageSize = pageSize || defaultPageSize ;
54- const tCurrent = current || defaultCurrent ;
61+ const tPageSize = pageSize || defaultPageSize || DEFAULT_PAGE_SIZE ;
62+ const tCurrent = current || defaultCurrent || DEFAULT_CURRENT ;
5563 const newData = data . slice ( tPageSize * ( tCurrent - 1 ) , tPageSize * tCurrent ) ;
5664 setCurrentPaginateData ( newData ) ;
5765 } ,
5866 // eslint-disable-next-line
59- [ data , reserveSelectedRowOnPaginate ] ,
67+ [ data , reserveSelectedRowOnPaginate , pagination ] ,
6068 ) ;
6169
6270 useEffect (
@@ -81,22 +89,48 @@ export default function useRowSelect(
8189 return isRowSelectedDisabled ( selectColumn , row , rowIndex ) ;
8290 }
8391
84- function getSelectedHeader ( ) {
85- return ( ) => {
86- const isIndeterminate = intersectionKeys . length > 0 && intersectionKeys . length < canSelectedRows . length ;
87- const isChecked =
88- intersectionKeys . length !== 0 &&
89- canSelectedRows . length !== 0 &&
90- intersectionKeys . length === canSelectedRows . length ;
91- return (
92- < Checkbox
93- checked = { isChecked }
94- indeterminate = { isIndeterminate }
95- disabled = { ! canSelectedRows . length }
96- onChange = { handleSelectAll }
97- />
98- ) ;
92+ function renderCheckAll ( ) {
93+ const currentData = reserveSelectedRowOnPaginate ? data : currentPaginateData ;
94+ const totalRowCount = currentData ?. length || 0 ;
95+
96+ const currentPageRowKeys = currentData ?. map ( ( row ) => get ( row , rowKey ) ) || [ ] ;
97+ const selectedInCurrentPage = tSelectedRowKeys . filter ( ( key ) => currentPageRowKeys . includes ( key ) ) ;
98+
99+ const isChecked = totalRowCount > 0 && selectedInCurrentPage . length === totalRowCount ;
100+ const isIndeterminate = selectedInCurrentPage . length > 0 && selectedInCurrentPage . length < totalRowCount ;
101+
102+ const handleSelectAll = ( ) => {
103+ const canSelectedRowKeys = canSelectedRows . map ( ( record ) => get ( record , rowKey ) ) ;
104+
105+ const currentData = reserveSelectedRowOnPaginate ? data : currentPaginateData ;
106+ const disabledRowKeys =
107+ currentData ?. filter ( ( row , rowIndex ) => isDisabled ( row , rowIndex ) ) . map ( ( row ) => get ( row , rowKey ) ) || [ ] ;
108+
109+ const disabledSelectedRowKeys = selectedRowKeys ?. filter ( ( id ) => disabledRowKeys . includes ( id ) ) || [ ] ;
110+ const allSelectableRowsSelected = canSelectedRowKeys . every ( ( key ) => tSelectedRowKeys . includes ( key ) ) ;
111+ const shouldSelectAll = ! allSelectableRowsSelected ;
112+
113+ const allIds = shouldSelectAll
114+ ? [ ...disabledSelectedRowKeys , ...canSelectedRowKeys ]
115+ : [ ...disabledSelectedRowKeys ] ;
116+
117+ setTSelectedRowKeys ( allIds , {
118+ selectedRowData : shouldSelectAll
119+ ? allIds . map ( ( t ) => selectedRowDataMap . get ( t ) )
120+ : disabledSelectedRowKeys . map ( ( t ) => selectedRowDataMap . get ( t ) ) ,
121+ type : shouldSelectAll ? 'check' : 'uncheck' ,
122+ currentRowKey : 'CHECK_ALL_BOX' ,
123+ } ) ;
99124 } ;
125+
126+ return (
127+ < Checkbox
128+ checked = { isChecked }
129+ indeterminate = { isIndeterminate }
130+ disabled = { ! canSelectedRows . length }
131+ onChange = { handleSelectAll }
132+ />
133+ ) ;
100134 }
101135
102136 function getRowSelectDisabledData ( p : PrimaryTableCellParams < TableRowData > ) {
@@ -165,18 +199,6 @@ export default function useRowSelect(
165199 } ) ;
166200 }
167201
168- function handleSelectAll ( checked : boolean ) {
169- const reRowKey = rowKey || 'id' ;
170- const canSelectedRowKeys = canSelectedRows . map ( ( record ) => get ( record , reRowKey ) ) ;
171- const disabledSelectedRowKeys = selectedRowKeys ?. filter ( ( id ) => ! canSelectedRowKeys . includes ( id ) ) || [ ] ;
172- const allIds = checked ? [ ...disabledSelectedRowKeys , ...canSelectedRowKeys ] : [ ...disabledSelectedRowKeys ] ;
173- setTSelectedRowKeys ( allIds , {
174- selectedRowData : checked ? allIds . map ( ( t ) => selectedRowDataMap . get ( t ) ) : [ ] ,
175- type : checked ? 'check' : 'uncheck' ,
176- currentRowKey : 'CHECK_ALL_BOX' ,
177- } ) ;
178- }
179-
180202 function formatToRowSelectColumn ( col : PrimaryTableCol ) {
181203 const isSelection = [ 'multiple' , 'single' ] . includes ( col . type ) ;
182204 if ( ! isSelection ) return col ;
@@ -185,7 +207,7 @@ export default function useRowSelect(
185207 width : col . width || 64 ,
186208 className : tableSelectedClasses . checkCell ,
187209 cell : ( p : PrimaryTableCellParams < TableRowData > ) => renderSelectCell ( p ) ,
188- title : col . type === 'multiple' ? getSelectedHeader ( ) : col . title ,
210+ title : col . type === 'multiple' ? renderCheckAll ( ) : col . title ,
189211 } ;
190212 }
191213
0 commit comments