Skip to content

Commit feba637

Browse files
authored
feat(next): support checkStrictly props in SelectTable (#2824)
1 parent 16a376d commit feba637

File tree

7 files changed

+229
-7
lines changed

7 files changed

+229
-7
lines changed

packages/antd/docs/components/SelectTable.md

+16
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ const schema = {
448448
.toLowerCase()
449449
.localeCompare(optionB.description.toLowerCase()),
450450
optionAsValue: true,
451+
rowSelection: {
452+
checkStrictly: false,
453+
},
451454
},
452455
enum: [
453456
{ key: '1', name: 'title-1', description: 'A-description' },
@@ -468,6 +471,11 @@ const schema = {
468471
},
469472
],
470473
},
474+
{
475+
key: '2-2',
476+
name: 'title2-2',
477+
description: 'YY-description',
478+
},
471479
],
472480
},
473481
{ key: '3', name: 'title-3', description: 'C-description' },
@@ -608,6 +616,14 @@ export default () => (
608616

609617
`TableProps` type definition reference antd https://ant.design/components/table/
610618

619+
### rowSelection
620+
621+
| Property name | Type | Description | Default value |
622+
| ------------- | ------- | -------------------------------------------------------------------------- | ------------- |
623+
| checkStrictly | boolean | Check table row precisely; parent row and children rows are not associated | true |
624+
625+
`rowSelectionProps` type definition reference antd https://ant.design/components/table/#rowSelection
626+
611627
### SelectTable.Column
612628

613629
`ColumnProps` type definition reference antd https://ant.design/components/table/ Table.Column

packages/antd/docs/components/SelectTable.zh-CN.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ const schema = {
448448
.toLowerCase()
449449
.localeCompare(optionB.description.toLowerCase()),
450450
optionAsValue: true,
451+
rowSelection: {
452+
checkStrictly: false,
453+
},
451454
},
452455
enum: [
453456
{ key: '1', name: '标题1', description: 'A-描述' },
@@ -464,6 +467,11 @@ const schema = {
464467
{ key: '2-1-1', name: '标题2-1-1', description: 'Z-描述' },
465468
],
466469
},
470+
{
471+
key: '2-2',
472+
name: '标题2-2',
473+
description: 'YY-描述',
474+
},
467475
],
468476
},
469477
{ key: '3', name: '标题3', description: 'C-描述' },
@@ -602,7 +610,15 @@ export default () => (
602610
| filterSort | (optionA, optionB) => number | 搜索时对筛选结果项的排序函数, 类似 Array.sort 里的 compareFunction | - |
603611
| onSearch | 文本框值变化时回调 | (inputValue) => void | - |
604612

605-
其余参考 https://ant.design/components/table-cn/
613+
参考 https://ant.design/components/table-cn/
614+
615+
### rowSelection
616+
617+
| 属性名 | 类型 | 描述 | 默认值 |
618+
| ------------- | ------- | ------------------------------------------------------------ | ------ |
619+
| checkStrictly | boolean | checkable 状态下节点选择完全受控(父子数据选中状态不再关联) | true |
620+
621+
参考 https://ant.design/components/table/#rowSelection
606622

607623
### SelectTable.Column
608624

packages/next/docs/components/SelectTable.md

+16
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ const schema = {
452452
.toLowerCase()
453453
.localeCompare(optionB.description.toLowerCase()),
454454
optionAsValue: true,
455+
rowSelection: {
456+
checkStrictly: false,
457+
},
455458
},
456459
enum: [
457460
{ key: '1', name: 'title-1', description: 'A-description' },
@@ -472,6 +475,11 @@ const schema = {
472475
},
473476
],
474477
},
478+
{
479+
key: '2-2',
480+
name: 'title2-2',
481+
description: 'YY-description',
482+
},
475483
],
476484
},
477485
{ key: '3', name: 'title-3', description: 'C-description' },
@@ -613,6 +621,14 @@ export default () => (
613621

614622
`TableProps` type definition reference fusion https://fusion.design/pc/component/basic/table
615623

624+
### rowSelection
625+
626+
| Property name | Type | Description | Default value |
627+
| ------------- | ------- | -------------------------------------------------------------------------- | ------------- |
628+
| checkStrictly | boolean | Check table row precisely; parent row and children rows are not associated | true |
629+
630+
`rowSelectionProps` type definition reference fusion https://fusion.design/pc/component/basic/table rowSelection
631+
616632
### SelectTable.Column
617633

618634
`ColumnProps` type definition reference fusion https://fusion.design/pc/component/basic/table Table.Column

packages/next/docs/components/SelectTable.zh-CN.md

+17-1
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ const schema = {
452452
.toLowerCase()
453453
.localeCompare(optionB.description.toLowerCase()),
454454
optionAsValue: true,
455+
rowSelection: {
456+
checkStrictly: false,
457+
},
455458
},
456459
enum: [
457460
{ key: '1', name: '标题1', description: 'A-描述' },
@@ -468,6 +471,11 @@ const schema = {
468471
{ key: '2-1-1', name: '标题2-1-1', description: 'Z-描述' },
469472
],
470473
},
474+
{
475+
key: '2-2',
476+
name: '标题2-2',
477+
description: 'YY-描述',
478+
},
471479
],
472480
},
473481
{ key: '3', name: '标题3', description: 'C-描述' },
@@ -607,7 +615,15 @@ export default () => (
607615
| filterSort | (optionA, optionB) => number | 搜索时对筛选结果项的排序函数, 类似 Array.sort 里的 compareFunction | - |
608616
| onSearch | 文本框值变化时回调 | (inputValue) => void | - |
609617

610-
其余参考 https://fusion.design/pc/component/basic/table
618+
参考 https://fusion.design/pc/component/basic/table
619+
620+
### rowSelection
621+
622+
| 属性名 | 类型 | 描述 | 默认值 |
623+
| ------------- | ------- | ------------------------------------------------------------ | ------ |
624+
| checkStrictly | boolean | checkable 状态下节点选择完全受控(父子数据选中状态不再关联) | true |
625+
626+
参考 https://fusion.design/pc/component/basic/table rowSelection
611627

612628
### SelectTable.Column
613629

packages/next/src/select-table/index.tsx

+27-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useFilterOptions } from './useFilterOptions'
99
import { useFlatOptions } from './useFlatOptions'
1010
import { useTitleAddon } from './useTitleAddon'
1111
import { useSize } from './useSize'
12+
import { useCheckSlackly, getCheckedProps } from './useCheckSlackly'
1213
import { usePrefixCls } from '../__builtins__'
1314

1415
type IFilterOption = boolean | ((option: any, keyword: string) => boolean)
@@ -32,6 +33,9 @@ export interface ISelectTableProps extends Omit<TableProps, 'primaryKey'> {
3233
onSearch?: (keyword: string) => void
3334
onChange?: (value: any) => void
3435
value?: any
36+
rowSelection?: TableProps['rowSelection'] & {
37+
checkStrictly?: boolean
38+
}
3539
}
3640

3741
type ComposedSelectTable = React.FC<ISelectTableProps> & {
@@ -180,6 +184,22 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
180184
selectedRowKeys.includes(item?.[primaryKey])
181185
)
182186
}
187+
if (rowSelection?.checkStrictly !== false) {
188+
onInnerChange(selectedRowKeys, records)
189+
} else {
190+
onSlacklyChange(selectedRowKeys)
191+
}
192+
}
193+
194+
// Fusion TreeData SlacklyChange
195+
const onSlacklyChange = (prevSelectedRowKeys: any[]) => {
196+
const { selectedRowKeys, records } = useCheckSlackly(
197+
prevSelectedRowKeys,
198+
selected,
199+
primaryKey,
200+
flatDataSource
201+
)
202+
183203
onInnerChange(selectedRowKeys, records)
184204
}
185205

@@ -232,10 +252,16 @@ export const SelectTable: ComposedSelectTable = observer((props) => {
232252
...rowSelection,
233253
getProps: (record, index) => ({
234254
...(rowSelection?.getProps?.(record, index) as any),
255+
...(rowSelection?.checkStrictly !== false
256+
? {}
257+
: getCheckedProps(record, primaryKey, selected)), // 父子关联模式indeterminate值
235258
disabled,
236259
}), // fusion
237260
selectedRowKeys: selected,
238-
onChange: onInnerChange,
261+
onChange:
262+
rowSelection?.checkStrictly !== false
263+
? onInnerChange
264+
: onSlacklyChange,
239265
mode,
240266
...titleAddon,
241267
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* 获取该字段Checkbox的indeterminate属性
3+
* @param record 字段项
4+
* @param primaryKey 键名称
5+
* @param selected 当前选中的字段值集合
6+
* @returns indeterminate属性值
7+
*/
8+
const getCheckedProps = (record: any, primaryKey: string, selected: any[]) => {
9+
if (record.children?.length) {
10+
const childrenDataSource = record.children
11+
const selectedChildren = childrenDataSource.filter((item) =>
12+
selected?.includes(item[primaryKey])
13+
)
14+
return {
15+
// checked受控,此处配置在rowSelection并不会生效,供getFinalTreeKeys使用
16+
checked: selectedChildren.length === childrenDataSource.length,
17+
indeterminate: !!(
18+
selectedChildren.length &&
19+
selectedChildren.length !== childrenDataSource.length
20+
),
21+
}
22+
}
23+
return {}
24+
}
25+
26+
/**
27+
* 获取树列表某个键值的集合
28+
* @param tree 树列表
29+
* @param primaryKey 键名称
30+
* @returns 键值数组集合
31+
*/
32+
const getTreeKeys = (tree: any[] = [], primaryKey: string) =>
33+
tree.reduce(
34+
(prev, current) => [
35+
...prev,
36+
current[primaryKey],
37+
...getTreeKeys(current?.children, primaryKey),
38+
],
39+
[]
40+
)
41+
42+
/**
43+
* 获取最终选中值(添加选中所有子元素的父元素,或移除未选中所有子元素的父元素)
44+
* @param tree 树列表
45+
* @param primaryKey 键名称
46+
* @param selectedRowKeys 当前选中的字段值集合
47+
* @returns 最终选中的字段值集合
48+
*/
49+
const getFinalTreeKeys = (
50+
tree: any[] = [],
51+
primaryKey: string,
52+
selectedRowKeys: any[]
53+
) => {
54+
let finalSelectedRowKeys = [...selectedRowKeys]
55+
56+
tree.forEach((item) => {
57+
if (item.children?.length) {
58+
// 优先递归子元素
59+
finalSelectedRowKeys = getFinalTreeKeys(
60+
item.children,
61+
primaryKey,
62+
finalSelectedRowKeys
63+
)
64+
if (getCheckedProps(item, primaryKey, finalSelectedRowKeys)?.checked) {
65+
// 如果该元素的子元素全部选中,则也选中该项(即包含全选子元素的父元素)
66+
finalSelectedRowKeys = [
67+
...new Set([...finalSelectedRowKeys, item[primaryKey]]),
68+
]
69+
} else {
70+
// 如果该元素的子元素未全部选中,则移除该项
71+
finalSelectedRowKeys = finalSelectedRowKeys.filter(
72+
(key) => key !== item[primaryKey]
73+
)
74+
}
75+
}
76+
})
77+
78+
return finalSelectedRowKeys
79+
}
80+
81+
interface ICheckSlackly {
82+
(
83+
selectedRowKeys: any[],
84+
selected: any[],
85+
primaryKey: string,
86+
flatDataSource: any[]
87+
): {
88+
selectedRowKeys: any[]
89+
records: any[]
90+
}
91+
}
92+
93+
const useCheckSlackly: ICheckSlackly = (
94+
selectedRowKeys,
95+
selected,
96+
primaryKey,
97+
flatDataSource
98+
) => {
99+
const isSelected = selectedRowKeys.length > selected.length
100+
const currentKey = [...selectedRowKeys, ...selected].find(
101+
(key) => !(selectedRowKeys.includes(key) && selected.includes(key))
102+
)
103+
const currentRecords = flatDataSource.find(
104+
(item) => item[primaryKey] === currentKey
105+
)
106+
const currentTreeKeys = getTreeKeys([currentRecords], primaryKey)
107+
let newSelectedRowKeys = []
108+
109+
if (isSelected) {
110+
newSelectedRowKeys = [...new Set([...selected, ...currentTreeKeys])]
111+
} else {
112+
newSelectedRowKeys = selected.filter(
113+
(key) => !currentTreeKeys.includes(key)
114+
)
115+
}
116+
// 添加选中所有子元素的父元素,或移除未选中所有子元素的父元素
117+
newSelectedRowKeys = getFinalTreeKeys(
118+
flatDataSource,
119+
primaryKey,
120+
newSelectedRowKeys
121+
)
122+
123+
return {
124+
selectedRowKeys: newSelectedRowKeys,
125+
records: flatDataSource.filter((item) =>
126+
newSelectedRowKeys.includes(item[primaryKey])
127+
),
128+
}
129+
}
130+
131+
export { useCheckSlackly, getCheckedProps }

packages/next/src/select-table/useTitleAddon.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@ const newCheckbox =
66
(selected, flatDataSource, primaryKey, disabled, readOnly, onChange) =>
77
() => {
88
const allDataSourceKeys = flatDataSource.map((item) => item?.[primaryKey])
9+
const indeterminate = !!(
10+
selected?.length && selected.length !== allDataSourceKeys.length
11+
)
912
return (
1013
<Checkbox
1114
key="titleAddons"
1215
checked={!!selected?.length}
1316
disabled={disabled}
14-
indeterminate={
15-
!!(selected?.length && selected.length !== allDataSourceKeys.length)
16-
}
17+
indeterminate={indeterminate}
1718
onChange={(checked) => {
1819
if (!readOnly) {
19-
if (checked) {
20+
if (checked || indeterminate) {
2021
onChange?.(allDataSourceKeys, flatDataSource)
2122
} else {
2223
onChange?.([], [])

0 commit comments

Comments
 (0)