11import React , {
22 Children ,
3- KeyboardEvent ,
4- WheelEvent ,
53 cloneElement ,
64 isValidElement ,
75 useCallback ,
@@ -27,7 +25,7 @@ import SelectInput, { type SelectInputValue, type SelectInputValueChangeContext
2725import Tag from '../../tag' ;
2826import { selectDefaultProps } from '../defaultProps' ;
2927import useOptions , { isSelectOptionGroup } from '../hooks/useOptions' ;
30- import { getSelectValueArr , getSelectedOptions } from '../util/helper' ;
28+ import { getKeyMapping , getSelectValueArr , getSelectedOptions } from '../util/helper' ;
3129import Option from './Option' ;
3230import OptionGroup from './OptionGroup' ;
3331import PopupContent from './PopupContent' ;
@@ -121,10 +119,11 @@ const Select = forwardRefWithStatics(
121119 ) ;
122120
123121 const selectedLabel = useMemo ( ( ) => {
122+ const { labelKey } = getKeyMapping ( keys ) ;
124123 if ( multiple ) {
125- return selectedOptions . map ( ( selectedOption ) => get ( selectedOption || { } , keys ?. label || 'label' ) || '' ) ;
124+ return selectedOptions . map ( ( selectedOption ) => get ( selectedOption || { } , labelKey ) || '' ) ;
126125 }
127- return get ( selectedOptions [ 0 ] || { } , keys ?. label || 'label' ) || undefined ;
126+ return get ( selectedOptions [ 0 ] || { } , labelKey ) || undefined ;
128127 } , [ selectedOptions , keys , multiple ] ) ;
129128
130129 const handleShowPopup = ( visible : boolean , ctx : PopupVisibleChangeContext ) => {
@@ -188,37 +187,40 @@ const Select = forwardRefWithStatics(
188187 return ;
189188 }
190189
191- const isSelectableOption = ( opt : TdOptionProps ) => ! opt . checkAll && ! opt . disabled ;
192- const getOptionValue = ( option : SelectOption ) =>
193- valueType === 'object' ? option : option [ keys ?. value || 'value' ] ;
190+ const { valueKey } = getKeyMapping ( keys ) ;
191+ const isObjectType = valueType === 'object' ;
194192
195- const values = [ ] ;
196- currentOptions . forEach ( ( option ) => {
197- if ( isSelectOptionGroup ( option ) ) {
198- option . children . forEach ( ( item ) => {
199- if ( isSelectableOption ( item ) ) {
200- values . push ( getOptionValue ( item ) ) ;
201- }
202- } ) ;
203- } else if ( isSelectableOption ( option ) ) {
204- values . push ( getOptionValue ( option ) ) ;
193+ const enabledOptions = currentOptions . filter (
194+ ( opt ) => ! isSelectOptionGroup ( opt ) && ! opt . checkAll && ! opt . disabled ,
195+ ) ;
196+
197+ const currentValues = Array . isArray ( value ) ? value : [ ] ;
198+ const disabledSelectedOptions = currentOptions . filter ( ( opt ) => {
199+ if ( isSelectOptionGroup ( opt ) || opt . checkAll ) return false ;
200+ if ( ! opt . disabled ) return false ;
201+ if ( isObjectType ) {
202+ return currentValues . some ( ( v ) => get ( v , valueKey ) === opt [ valueKey ] ) ;
205203 }
204+ return currentValues . includes ( opt [ valueKey ] ) ;
206205 } ) ;
207206
208- const { currentSelectedOptions, allSelectedValue } = getSelectedOptions (
209- values ,
210- multiple ,
211- valueType ,
212- keys ,
213- valueToOption ,
214- ) ;
207+ let checkAllValue : SelectValue [ ] ;
208+
209+ if ( checkAll ) {
210+ // 全选:选中所有未禁用的选项 + 保留已选中的禁用选项
211+ const enabledValues = enabledOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
212+ const disabledValues = disabledSelectedOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
213+ checkAllValue = [ ...disabledValues , ...enabledValues ] ;
214+ } else {
215+ // 取消全选:只保留已选中的禁用选项
216+ checkAllValue = disabledSelectedOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
217+ }
215218
216- const checkAllValue =
217- ! checkAll && allSelectedValue . length !== ( props . value as Array < SelectOption > ) ?. length ? allSelectedValue : [ ] ;
219+ const { currentSelectedOptions } = getSelectedOptions ( checkAllValue , multiple , valueType , keys , valueToOption ) ;
218220
219221 onChange ?.( checkAllValue , {
220222 e,
221- trigger : ! checkAll ? 'check' : 'uncheck' ,
223+ trigger : checkAll ? 'check' : 'uncheck' ,
222224 selectedOptions : currentSelectedOptions ,
223225 } ) ;
224226 } ;
@@ -323,7 +325,7 @@ const Select = forwardRefWithStatics(
323325 return ;
324326 }
325327 if ( isFunction ( onSearch ) ) {
326- onSearch ( value , { e : context . e as KeyboardEvent < HTMLDivElement > } ) ;
328+ onSearch ( value , { e : context . e as React . KeyboardEvent < HTMLDivElement > } ) ;
327329 return ;
328330 }
329331 } ;
@@ -403,18 +405,22 @@ const Select = forwardRefWithStatics(
403405 return '' ;
404406 }
405407 return ( { value : val } ) =>
406- val . slice ( 0 , minCollapsedNum ? minCollapsedNum : val . length ) . map ( ( v : string , key : number ) => {
407- const filterOption : SelectOption & { disabled ?: boolean } = options ?. find ( ( option ) => option . label === v ) ;
408+ val . slice ( 0 , minCollapsedNum ? minCollapsedNum : val . length ) . map ( ( _ , index : number ) => {
409+ const { valueKey, labelKey, disabledKey } = getKeyMapping ( keys ) ;
410+ const targetVal = get ( selectedOptions [ index ] , valueKey ) ;
411+ const targetLabel = get ( selectedOptions [ index ] , labelKey ) ;
412+ const targetOption = valueToOption [ targetVal ] ;
413+ if ( ! targetOption ) return null ;
408414 return (
409415 < Tag
410- key = { key }
411- closable = { ! filterOption ?. disabled && ! disabled && ! readonly }
416+ key = { index }
417+ closable = { ! get ( targetOption , disabledKey ) && ! disabled && ! readonly }
412418 size = { size }
413419 { ...tagProps }
414420 onClose = { ( { e } ) => {
415421 e . stopPropagation ( ) ;
416422 e ?. nativeEvent ?. stopImmediatePropagation ?.( ) ;
417- const values = getSelectValueArr ( value , value [ key ] , true , valueType , keys ) ;
423+ const values = getSelectValueArr ( value , value [ index ] , true , valueType , keys ) ;
418424
419425 const { currentSelectedOptions } = getSelectedOptions (
420426 values ,
@@ -432,13 +438,13 @@ const Select = forwardRefWithStatics(
432438 tagProps ?. onClose ?.( { e } ) ;
433439
434440 onRemove ?.( {
435- value : value [ key ] ,
436- data : { label : v , value : value [ key ] } ,
441+ value : targetVal ,
442+ data : { label : targetLabel , value : targetVal } ,
437443 e : e as unknown as React . MouseEvent < HTMLDivElement , MouseEvent > ,
438444 } ) ;
439445 } }
440446 >
441- { v }
447+ { targetLabel }
442448 </ Tag >
443449 ) ;
444450 } ) ;
@@ -496,11 +502,11 @@ const Select = forwardRefWithStatics(
496502
497503 const { onMouseEnter, onMouseLeave } = props ;
498504
499- const handleEnter = ( _ , context : { inputValue : string ; e : KeyboardEvent < HTMLDivElement > } ) => {
505+ const handleEnter = ( _ , context : { inputValue : string ; e : React . KeyboardEvent < HTMLDivElement > } ) => {
500506 onEnter ?.( { ...context , value } ) ;
501507 } ;
502508
503- const handleScroll = ( { e } : { e : WheelEvent < HTMLDivElement > } ) => {
509+ const handleScroll = ( { e } : { e : React . WheelEvent < HTMLDivElement > } ) => {
504510 toggleIsScrolling ( true ) ;
505511
506512 onScroll ?.( { e } ) ;
0 commit comments