@@ -119,6 +119,76 @@ const Select = forwardRefWithStatics(
119119 reserveKeyword ,
120120 ) ;
121121
122+ const onCheckAllChange = useCallback (
123+ ( checkAll : boolean , e : React . MouseEvent < HTMLLIElement > ) => {
124+ const isDisabledCheckAll = ( opt : TdOptionProps ) => opt . checkAll && opt . disabled ;
125+ if ( ! multiple || currentOptions . some ( ( opt ) => ! isSelectOptionGroup ( opt ) && isDisabledCheckAll ( opt ) ) ) {
126+ return ;
127+ }
128+
129+ const { valueKey } = getKeyMapping ( keys ) ;
130+ const isObjectType = valueType === 'object' ;
131+
132+ const enabledOptions : SelectOption [ ] = [ ] ;
133+
134+ currentOptions . forEach ( ( option ) => {
135+ // 如果涉及分组,需要将分组内的选项进行计算,否则会影响全选的功能
136+ if ( isSelectOptionGroup ( option ) ) {
137+ option . children ?. forEach ( ( item ) => {
138+ if ( ! item . checkAll && ! item . disabled ) {
139+ enabledOptions . push ( item ) ;
140+ }
141+ } ) ;
142+ } else {
143+ ! option . checkAll && ! option . disabled && enabledOptions . push ( option ) ;
144+ }
145+ } ) ;
146+
147+ const currentValues = Array . isArray ( value ) ? value : [ ] ;
148+ const disabledSelectedOptions : SelectOption [ ] = [ ] ;
149+
150+ const isDisabledAndSelected = ( opt : TdOptionProps ) => {
151+ if ( opt . checkAll || ! opt . disabled ) return false ;
152+ if ( isObjectType ) return currentValues . some ( ( v ) => get ( v , valueKey ) === opt [ valueKey ] ) ;
153+ return currentValues . includes ( opt [ valueKey ] ) ;
154+ } ;
155+
156+ currentOptions . forEach ( ( opt ) => {
157+ if ( isSelectOptionGroup ( opt ) ) {
158+ // 处理分组内的禁用选项
159+ opt . children ?. forEach ( ( item ) => {
160+ if ( isDisabledAndSelected ( item ) ) {
161+ disabledSelectedOptions . push ( item ) ;
162+ }
163+ } ) ;
164+ } else if ( isDisabledAndSelected ( opt ) ) {
165+ disabledSelectedOptions . push ( opt ) ;
166+ }
167+ } ) ;
168+
169+ let checkAllValue : SelectValue [ ] ;
170+
171+ if ( checkAll ) {
172+ // 全选:选中所有未禁用的选项 + 保留已选中的禁用选项
173+ const enabledValues = enabledOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
174+ const disabledValues = disabledSelectedOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
175+ checkAllValue = [ ...disabledValues , ...enabledValues ] ;
176+ } else {
177+ // 取消全选:只保留已选中的禁用选项
178+ checkAllValue = disabledSelectedOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
179+ }
180+
181+ const { currentSelectedOptions } = getSelectedOptions ( checkAllValue , multiple , valueType , keys , valueToOption ) ;
182+
183+ onChange ?.( checkAllValue , {
184+ e,
185+ trigger : checkAll ? 'check' : 'uncheck' ,
186+ selectedOptions : currentSelectedOptions ,
187+ } ) ;
188+ } ,
189+ [ currentOptions , keys , multiple , onChange , value , valueToOption , valueType ] ,
190+ ) ;
191+
122192 const { handleKeyDown, hoverIndex } = useKeyboardControl ( {
123193 displayOptions : currentOptions as TdOptionProps [ ] ,
124194 max,
@@ -127,6 +197,8 @@ const Select = forwardRefWithStatics(
127197 innerPopupVisible : showPopup ,
128198 setInnerValue : onChange ,
129199 innerValue : value ,
200+ onCheckAllChange,
201+ selectInputRef,
130202 } ) ;
131203
132204 const selectedLabel = useMemo ( ( ) => {
@@ -191,73 +263,6 @@ const Select = forwardRefWithStatics(
191263 }
192264 } ;
193265
194- const onCheckAllChange = ( checkAll : boolean , e : React . MouseEvent < HTMLLIElement > ) => {
195- const isDisabledCheckAll = ( opt : TdOptionProps ) => opt . checkAll && opt . disabled ;
196- if ( ! multiple || currentOptions . some ( ( opt ) => ! isSelectOptionGroup ( opt ) && isDisabledCheckAll ( opt ) ) ) {
197- return ;
198- }
199-
200- const { valueKey } = getKeyMapping ( keys ) ;
201- const isObjectType = valueType === 'object' ;
202-
203- const enabledOptions : SelectOption [ ] = [ ] ;
204-
205- currentOptions . forEach ( ( option ) => {
206- // 如果涉及分组,需要将分组内的选项进行计算,否则会影响全选的功能
207- if ( isSelectOptionGroup ( option ) ) {
208- option . children ?. forEach ( ( item ) => {
209- if ( ! item . checkAll && ! item . disabled ) {
210- enabledOptions . push ( item ) ;
211- }
212- } ) ;
213- } else {
214- ! option . checkAll && ! option . disabled && enabledOptions . push ( option ) ;
215- }
216- } ) ;
217-
218- const currentValues = Array . isArray ( value ) ? value : [ ] ;
219- const disabledSelectedOptions : SelectOption [ ] = [ ] ;
220-
221- const isDisabledAndSelected = ( opt : TdOptionProps ) => {
222- if ( opt . checkAll || ! opt . disabled ) return false ;
223- if ( isObjectType ) return currentValues . some ( ( v ) => get ( v , valueKey ) === opt [ valueKey ] ) ;
224- return currentValues . includes ( opt [ valueKey ] ) ;
225- } ;
226-
227- currentOptions . forEach ( ( opt ) => {
228- if ( isSelectOptionGroup ( opt ) ) {
229- // 处理分组内的禁用选项
230- opt . children ?. forEach ( ( item ) => {
231- if ( isDisabledAndSelected ( item ) ) {
232- disabledSelectedOptions . push ( item ) ;
233- }
234- } ) ;
235- } else if ( isDisabledAndSelected ( opt ) ) {
236- disabledSelectedOptions . push ( opt ) ;
237- }
238- } ) ;
239-
240- let checkAllValue : SelectValue [ ] ;
241-
242- if ( checkAll ) {
243- // 全选:选中所有未禁用的选项 + 保留已选中的禁用选项
244- const enabledValues = enabledOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
245- const disabledValues = disabledSelectedOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
246- checkAllValue = [ ...disabledValues , ...enabledValues ] ;
247- } else {
248- // 取消全选:只保留已选中的禁用选项
249- checkAllValue = disabledSelectedOptions . map ( ( opt ) => ( isObjectType ? opt : opt [ valueKey ] ) ) ;
250- }
251-
252- const { currentSelectedOptions } = getSelectedOptions ( checkAllValue , multiple , valueType , keys , valueToOption ) ;
253-
254- onChange ?.( checkAllValue , {
255- e,
256- trigger : checkAll ? 'check' : 'uncheck' ,
257- selectedOptions : currentSelectedOptions ,
258- } ) ;
259- } ;
260-
261266 // 选中 Popup 某项
262267 const handleChange = (
263268 value : string | number | Array < string | number | Record < string , string | number > > ,
0 commit comments