@zat-design/sisyphus-react 4.4.3-beta.2 → 4.5.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,4 @@
1
1
  import _get from "lodash/get";
2
- import _isEqualWith from "lodash/isEqualWith";
3
2
  import _isFunction from "lodash/isFunction";
4
3
  import _omit from "lodash/omit";
5
4
  import _debounce from "lodash/debounce";
@@ -10,10 +9,10 @@ import _cloneDeep from "lodash/cloneDeep";
10
9
  import React, { useEffect, useCallback, useMemo, memo, useRef } from 'react';
11
10
  import { Form } from 'antd';
12
11
  import classNames from 'classnames';
13
- import { compatStartTransition, customEqualForFunction } from "../../../utils";
12
+ import { compatStartTransition } from "../../../utils";
14
13
  import valueTypeMap from "../../../ProForm/utils/valueType";
15
14
  import transformMap from "../../utils/transform";
16
- import { getNamePath, difference, getDisabled } from "../../utils/tools";
15
+ import { getNamePath, difference, getDisabled, resolveChangedFields, syncGroupCombinedValues } from "../../utils/tools";
17
16
  import * as componentMap from "../../../ProForm/components";
18
17
  import { useProConfig } from "../../../ProConfigProvider";
19
18
  import Container from "../../../ProForm/components/Container";
@@ -26,11 +25,8 @@ import ConfirmWrapper from "../../../ProForm/components/render/ConfirmWrapper";
26
25
  import { getDefaultProps } from "../../utils/getDefaultProps";
27
26
  import ListChangedWrapper from "./ListChangedWrapper";
28
27
  import useShouldUpdateForTable from "../../utils/useShouldUpdateForTable";
29
-
30
- /** 列配置中不应透传到 Form.Item 或 DOM 的字段(与 ProForm Render 保持一致) */
28
+ import { OMIT_FORM_ITEM_AND_DOM_KEYS, arePropsEqual } from "./tools";
31
29
  import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
32
- const OMIT_FORM_ITEM_AND_DOM_KEYS = ['format', 'toISOString', 'toCSTString', 'switchValue', 'precision', 'clearNotShow', 'dependNames', 'shouldCellUpdate' // 表格内部性能优化属性,不应传递给 Form.Item
33
- ];
34
30
  const RenderField = ({
35
31
  text: value,
36
32
  record,
@@ -65,7 +61,7 @@ const RenderField = ({
65
61
  const {
66
62
  mode,
67
63
  cellName,
68
- _isEditing,
64
+ _isEditing: isEditing,
69
65
  form,
70
66
  setState,
71
67
  name,
@@ -78,15 +74,18 @@ const RenderField = ({
78
74
  otherProps,
79
75
  diffConfig,
80
76
  getIsNew,
81
- shouldUpdateDebounce
77
+ shouldUpdateDebounce,
78
+ virtual,
79
+ errorStore,
80
+ columns
82
81
  } = config;
83
- let _fieldProps = fieldProps || {};
84
- let _rules = rules || [];
85
- let _required = required;
86
- let _valueType = valueType;
87
- let _disabled = false;
88
- let _desensitization = desensitization || [];
89
- let _component = component || editRender;
82
+ let lastFieldProps = fieldProps || {};
83
+ let lastRules = rules || [];
84
+ let lastRequired = required;
85
+ let lastValueType = valueType;
86
+ let lastDisabled = false;
87
+ let lastDesensitization = desensitization || [];
88
+ let lastComponent = component || editRender;
90
89
  const isSingleMode = mode === 'single';
91
90
 
92
91
  // type类型 首字母转大写
@@ -130,16 +129,16 @@ const RenderField = ({
130
129
  // required & rules & fieldProps & disabled & valueType 函数化处理
131
130
  // 优先使用 hook 返回的值,fallback 到原始值
132
131
  if (_isFunction(required)) {
133
- _required = dynamicProps.required ?? required(rowData, reactiveParams);
132
+ lastRequired = dynamicProps.required ?? required(rowData, reactiveParams);
134
133
  }
135
134
  if (_isFunction(fieldProps)) {
136
- _fieldProps = dynamicProps.fieldProps ?? fieldProps(rowData, reactiveParams);
135
+ lastFieldProps = dynamicProps.fieldProps ?? fieldProps(rowData, reactiveParams);
137
136
  }
138
137
  if (_isFunction(rules)) {
139
- _rules = dynamicProps.rules ?? rules(rowData, reactiveParams);
138
+ lastRules = dynamicProps.rules ?? rules(rowData, reactiveParams);
140
139
  }
141
140
  if (_isFunction(valueType)) {
142
- _valueType = dynamicProps.valueType ?? valueType(currentValue, rowData, {
141
+ lastValueType = dynamicProps.valueType ?? valueType(currentValue, rowData, {
143
142
  index,
144
143
  form,
145
144
  namePath: [...namePath, index],
@@ -147,16 +146,16 @@ const RenderField = ({
147
146
  });
148
147
  }
149
148
  if (_isFunction(desensitization)) {
150
- _desensitization = dynamicProps.desensitization ?? desensitization(rowData, reactiveParams);
149
+ lastDesensitization = dynamicProps.desensitization ?? desensitization(rowData, reactiveParams);
151
150
  }
152
151
 
153
152
  // 获取最终的disabled
154
- _disabled = getDisabled({
153
+ lastDisabled = getDisabled({
155
154
  globalControl: otherProps?.globalControl,
156
155
  formDisabled: otherProps?.formDisabled,
157
156
  column,
158
157
  tabledDisabled: config?.disabled,
159
- columnFieldProps: _fieldProps,
158
+ columnFieldProps: lastFieldProps,
160
159
  params: rowParams
161
160
  });
162
161
 
@@ -166,26 +165,28 @@ const RenderField = ({
166
165
  }
167
166
 
168
167
  // component 处理 - 优先使用 hook 返回的值
169
- if (_isFunction(_component)) {
170
- _component = dynamicProps.component ?? _component(rowData, reactiveParams);
168
+ if (_isFunction(lastComponent)) {
169
+ lastComponent = dynamicProps.component ?? lastComponent(rowData, reactiveParams);
171
170
  }
172
171
 
173
- // 更新 _editRender 为处理后的 _component
174
- const _editRender = _component;
172
+ // 更新 lastEditRender 为处理后的 lastComponent
173
+ const lastEditRender = lastComponent;
175
174
 
176
175
  // 是否只读文本
177
- const isView = !isEditable || record?.['is-view'] || config.isView || virtualKey && !_isEditing || getDisabled({
176
+ const isView = !isEditable || record?.['is-view'] || config.isView || virtualKey && !isEditing || getDisabled({
178
177
  globalControl: otherProps?.globalControl,
179
178
  formDisabled: otherProps?.formDisabled,
180
179
  column,
181
180
  tabledDisabled: config?.disabled,
182
- columnFieldProps: _fieldProps,
181
+ columnFieldProps: lastFieldProps,
183
182
  params: rowParams,
184
183
  rowDisabled: rowDisabled || 'empty'
185
184
  });
186
185
 
187
186
  // 只读文本时,采用当前formItem的name,单行编辑时,使用生成的虚拟的name
188
187
  const baseName = isView ? name : namePath;
188
+
189
+ // 多态:可能是内置组件类型、自定义 component,或已渲染的 ReactElement(lastEditRender),保留显式 any
189
190
  let TargetComponent;
190
191
 
191
192
  // 将Hooks调用移到组件顶层
@@ -196,18 +197,18 @@ const RenderField = ({
196
197
  names,
197
198
  label: label,
198
199
  labelRequired,
199
- required: _required,
200
- rules: _rules,
200
+ required: lastRequired,
201
+ rules: lastRules,
201
202
  isSelect: isSelect({
202
- dataSource: _fieldProps?.dataSource,
203
+ dataSource: lastFieldProps?.dataSource,
203
204
  type
204
205
  }),
205
206
  type
206
207
  });
207
208
 
208
- // 分离form item参数,防止对于参数透传(如onChange,防止重复触发)并优先级高于 _fieldProps 内部参数
209
+ // 分离form item参数,防止对于参数透传(如onChange,防止重复触发)并优先级高于 lastFieldProps 内部参数
209
210
  const formItemChildProps = {
210
- ..._fieldProps
211
+ ...lastFieldProps
211
212
  };
212
213
 
213
214
  // 使用useMemo优化defaultProps计算
@@ -219,7 +220,7 @@ const RenderField = ({
219
220
  }), [name, formNamePath, cellName, column?.type, column?.fieldProps]);
220
221
 
221
222
  // 允许formItem的属性放在column最外层 - 使用useMemo优化(剔除会透传到 DOM 的字段)
222
- const _formItemProps = useMemo(() => ({
223
+ const lastFormItemProps = useMemo(() => ({
223
224
  ...defaultProps,
224
225
  ..._omit(resetProps, OMIT_FORM_ITEM_AND_DOM_KEYS),
225
226
  ...internalRule,
@@ -230,7 +231,7 @@ const RenderField = ({
230
231
  // 当这些函数类型存在时,自动添加 shouldUpdate
231
232
  // 因为这些函数依赖行数据,当行数据变化时需要重新计算
232
233
  // 扩展到所有模式(single/multiple/cell),统一行为
233
- // 注意:需要检查原始的 component/editRender,而不是处理后的 _component
234
+ // 注意:需要检查原始的 component/editRender,而不是处理后的 lastComponent
234
235
  const hasFunctionDependency = _isFunction(column?.disabled) ||
235
236
  // disabled 是函数
236
237
  _isFunction(fieldProps) ||
@@ -251,7 +252,7 @@ const RenderField = ({
251
252
  // 性能优化已通过 useShouldUpdateForTable hook 的缓存和防抖机制实现
252
253
  if (hasFunctionDependency) {
253
254
  // 使用 shouldUpdate 监听同一行的数据变化;shouldUpdate 与 dependencies 互斥,始终优先 shouldUpdate
254
- _formItemProps.shouldUpdate = (prevValues, currentValues) => {
255
+ lastFormItemProps.shouldUpdate = (prevValues, currentValues) => {
255
256
  const prevRow = _get(prevValues, [...namePath, index]);
256
257
  const currentRow = _get(currentValues, [...namePath, index]);
257
258
  // 如果行数据发生变化,则重新渲染
@@ -259,8 +260,8 @@ const RenderField = ({
259
260
  };
260
261
  }
261
262
  if (['Switch', 'SwitchCheckbox'].includes(type)) {
262
- _formItemProps.valuePropName = 'checked';
263
- _valueType = 'switch';
263
+ lastFormItemProps.valuePropName = 'checked';
264
+ lastValueType = 'switch';
264
265
  }
265
266
 
266
267
  /**
@@ -269,11 +270,11 @@ const RenderField = ({
269
270
  */
270
271
  const defaultTransform = useCallback(() => {
271
272
  const types = ['DatePicker', 'RangePicker'];
272
- if (!_valueType && types.includes(type)) {
273
- return transformMap?.[type]?.(_fieldProps || {});
273
+ if (!lastValueType && types.includes(type)) {
274
+ return transformMap?.[type]?.(lastFieldProps || {});
274
275
  }
275
276
  return {};
276
- }, [_valueType, type, _fieldProps]);
277
+ }, [lastValueType, type, lastFieldProps]);
277
278
 
278
279
  /**
279
280
  * 配置valueType时,基于formItem的normalize与getValueProps进行值类型转换
@@ -282,14 +283,15 @@ const RenderField = ({
282
283
  const valueTypeTransform = useCallback(() => {
283
284
  // SwitchCheckbox默认YN, 兼容已有组件
284
285
  if (type === 'SwitchCheckbox') {
285
- _valueType = 'switch';
286
+ lastValueType = 'switch';
286
287
  }
287
288
  const params = {
288
289
  ...column,
289
- mode: _fieldProps?.mode
290
+ mode: lastFieldProps?.mode
290
291
  };
291
- return _isFunction(valueTypeMap[_valueType]) ? valueTypeMap[_valueType](params) : {};
292
- }, [type, _valueType, column, _fieldProps?.mode]);
292
+ const valueTypeKey = lastValueType;
293
+ return _isFunction(valueTypeMap[valueTypeKey]) ? valueTypeMap[valueTypeKey](params) : {};
294
+ }, [type, lastValueType, column, lastFieldProps?.mode]);
293
295
  if (names?.length) {
294
296
  // 支持names配置,临时生成对应的formItem,用来存储单个对应的值
295
297
  names = names.map(key => {
@@ -318,22 +320,23 @@ const RenderField = ({
318
320
  }
319
321
  const namesStr = [...baseName, index, dataIndex];
320
322
  return transformNames({
321
- ..._formItemProps,
323
+ ...lastFormItemProps,
322
324
  ...valueTypeTransform()
323
325
  }, form, names, namesStr, type);
324
- }, [names, baseName, index, dataIndex, _formItemProps, type]);
325
- if (!_editRender && typeof type === 'string') {
326
+ }, [names, baseName, index, dataIndex, lastFormItemProps, type]);
327
+ if (!lastEditRender && typeof type === 'string') {
328
+ // componentMap 为内置组件命名空间,按字符串 type 动态取用,保留显式 any 索引
326
329
  TargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
327
330
  }
328
- if (isEditable && _isEditing) {
329
- // _editRender 已经是处理后的值(通过 dynamicProps.component 或直接计算)
330
- // 如果原本是函数,此时 _editRender 已经是执行后的 ReactNode
331
- // 如果原本是 ReactElement,_editRender 就是 ReactElement
332
- if ( /*#__PURE__*/React.isValidElement(_editRender)) {
333
- TargetComponent = _editRender;
334
- } else if (_editRender) {
331
+ if (isEditable && isEditing) {
332
+ // lastEditRender 已经是处理后的值(通过 dynamicProps.component 或直接计算)
333
+ // 如果原本是函数,此时 lastEditRender 已经是执行后的 ReactNode
334
+ // 如果原本是 ReactElement,lastEditRender 就是 ReactElement
335
+ if ( /*#__PURE__*/React.isValidElement(lastEditRender)) {
336
+ TargetComponent = lastEditRender;
337
+ } else if (lastEditRender) {
335
338
  // 其他情况(可能是字符串或其他类型的 ReactNode)
336
- TargetComponent = _editRender;
339
+ TargetComponent = lastEditRender;
337
340
  }
338
341
  }
339
342
 
@@ -398,9 +401,13 @@ const RenderField = ({
398
401
  const debounceRef = useRef(null);
399
402
 
400
403
  // 使用 useCallback 创建稳定的 onChange 函数
401
- const _onChange = useCallback(async (...args) => {
404
+ const handleChange = useCallback(async (...args) => {
402
405
  const executeChange = async (...innerArgs) => {
403
- let _args = [...innerArgs];
406
+ // 虚拟表格:用户编辑本单元格 清掉旧的常驻报错,提交时再以最新值统一重校
407
+ if (virtual && errorStore && record?.rowKey != null) {
408
+ errorStore.clearCell(record.rowKey, String(column?.dataIndex));
409
+ }
410
+ let callArgs = [...innerArgs];
404
411
  const rowPath = [...namePath, index];
405
412
  if (!onFieldChange && !onChange) {
406
413
  if (dependencies?.length) {
@@ -409,15 +416,15 @@ const RenderField = ({
409
416
  form.validateFields(validateFieldKeys);
410
417
  }, 100);
411
418
  }
412
- return null;
419
+ return;
413
420
  }
414
421
  const row = form.getFieldValue(rowPath, true);
415
422
  const orgRow = _cloneDeep(row);
416
423
  if (onFieldChange) {
417
- _args = formatArgs(innerArgs);
418
- _args[1] = row;
419
- TargetComponent?.props?.onFieldChange && (await TargetComponent.props.onFieldChange(..._args));
420
- onFieldChange && (await onFieldChange(..._args));
424
+ callArgs = formatArgs(innerArgs);
425
+ callArgs[1] = row;
426
+ TargetComponent?.props?.onFieldChange && (await TargetComponent.props.onFieldChange(...callArgs));
427
+ onFieldChange && (await onFieldChange(...callArgs));
421
428
 
422
429
  // onFieldChange 内已通过 form.setFieldValue(子路径) 或原地改 record 更新 store;此处再整行 setFieldValue(rowPath, rowAfter) 易用滞后快照覆盖 Field 刚写入的新值(如 formType)。仅延后读表做校验与 forceUpdate,不再整行回写。
423
430
  setTimeout(() => {
@@ -425,7 +432,16 @@ const RenderField = ({
425
432
  if (validateTrigger && validateTrigger.includes('onChange')) {
426
433
  if (!_isEqual(orgRow, rowAfter)) {
427
434
  const diff = difference(rowAfter, orgRow) || {};
428
- const validateFieldKeys = Object.keys(diff)?.map?.(key => [...rowPath, key]).concat(dependencies || []);
435
+ const changedKeys = Object.keys(diff);
436
+ // 联动回填只写了子键,names 组合列的合并字段值未同步 → 先按子键组合写回,确保校验读到最新值
437
+ syncGroupCombinedValues(form, rowPath, changedKeys, columns);
438
+ // 把变更子键映射回所属列字段名(names 组合列 → 合并名),否则 group 列重校验路径对不上、旧报错不清
439
+ const changedFields = resolveChangedFields(changedKeys, columns);
440
+ // 虚拟表格:联动改写到的列同步清掉常驻报错,避免滚动重挂载后回填旧错
441
+ if (virtual && errorStore && record?.rowKey != null) {
442
+ changedFields.forEach(id => errorStore.clearCell(record.rowKey, id));
443
+ }
444
+ const validateFieldKeys = changedFields.map(id => [...rowPath, id]).concat(dependencies || []);
429
445
  if (validateFieldKeys?.length) {
430
446
  debounceValidate(validateFieldKeys);
431
447
  }
@@ -442,15 +458,23 @@ const RenderField = ({
442
458
  }
443
459
  }, 0);
444
460
  } else {
445
- _args = _args.concat([row, index, form]);
446
- TargetComponent?.props?.onChange && (await TargetComponent.props.onChange(..._args));
447
- onChange && (await onChange(..._args));
461
+ callArgs = callArgs.concat([row, index, form]);
462
+ TargetComponent?.props?.onChange && (await TargetComponent.props.onChange(...callArgs));
463
+ onChange && (await onChange(...callArgs));
448
464
  const rowAfter = row;
449
465
  form.setFieldValue(rowPath, rowAfter);
450
466
  if (validateTrigger && validateTrigger.includes('onChange')) {
451
467
  if (!_isEqual(orgRow, rowAfter)) {
452
468
  const diff = difference(rowAfter, orgRow) || {};
453
- const validateFieldKeys = Object.keys(diff)?.map?.(key => [...rowPath, key]).concat(dependencies || []);
469
+ const changedKeys = Object.keys(diff);
470
+ // 联动回填只写了子键,names 组合列的合并字段值未同步 → 先按子键组合写回,确保校验读到最新值
471
+ syncGroupCombinedValues(form, rowPath, changedKeys, columns);
472
+ // 把变更子键映射回所属列字段名(names 组合列 → 合并名),否则 group 列重校验路径对不上、旧报错不清
473
+ const changedFields = resolveChangedFields(changedKeys, columns);
474
+ if (virtual && errorStore && record?.rowKey != null) {
475
+ changedFields.forEach(id => errorStore.clearCell(record.rowKey, id));
476
+ }
477
+ const validateFieldKeys = changedFields.map(id => [...rowPath, id]).concat(dependencies || []);
454
478
  if (validateFieldKeys?.length) {
455
479
  debounceValidate(validateFieldKeys);
456
480
  }
@@ -483,18 +507,36 @@ const RenderField = ({
483
507
  };
484
508
  }, []);
485
509
 
486
- // 使用useCallback优化_onblur函数
487
- const _onblur = useCallback(async (...args) => {
510
+ // 虚拟表格:单元格(重新)挂载时,回填 errorStore 中已存储的真实报错,实现报错常驻。
511
+ // 虚拟滚动会卸载视口外行的 Field 实体导致 antd 报错丢失,重新挂载后由此恢复红字。
512
+ useEffect(() => {
513
+ if (!virtual || !errorStore || record?.rowKey == null) {
514
+ return;
515
+ }
516
+ const cellKey = String(column?.dataIndex);
517
+ const errs = errorStore.get(record.rowKey, cellKey);
518
+ if (errs?.length) {
519
+ const fieldName = formNamePath ? cellName.slice(formNamePath?.length - 1) : cellName;
520
+ form.setFields([{
521
+ name: fieldName,
522
+ errors: errs
523
+ }]);
524
+ }
525
+ // 仅在挂载或行/列标识变化时回填
526
+ }, [virtual, record?.rowKey, column?.dataIndex]);
527
+
528
+ // 使用useCallback优化handleBlur函数
529
+ const handleBlur = useCallback(async (...args) => {
488
530
  if (!onBlur) {
489
- return null;
531
+ return;
490
532
  }
491
- let _args = formatArgs(...args);
533
+ let callArgs = formatArgs(...args);
492
534
  const rowPath = [...namePath, index];
493
535
  const row = form.getFieldValue(rowPath, true);
494
536
  const orgRow = _cloneDeep(row);
495
- _args[1] = row;
496
- TargetComponent?.props?.onBlur && (await TargetComponent.props.onBlur(..._args));
497
- onBlur && (await onBlur(..._args));
537
+ callArgs[1] = row;
538
+ TargetComponent?.props?.onBlur && (await TargetComponent.props.onBlur(...callArgs));
539
+ onBlur && (await onBlur(...callArgs));
498
540
  // 判断属性是否变动
499
541
  form.setFieldValue(rowPath, row);
500
542
  if (validateTrigger && validateTrigger.includes('onBlur')) {
@@ -520,15 +562,15 @@ const RenderField = ({
520
562
  let componentProps = useMemo(() => ({
521
563
  form,
522
564
  name: cellName,
523
- ..._fieldProps,
565
+ ...lastFieldProps,
524
566
  ...TargetComponent?.props,
525
567
  namePath: [...namePath, index],
526
- disabled: _disabled,
527
- onChange: _onChange,
528
- onBlur: _onblur,
568
+ disabled: lastDisabled,
569
+ onChange: handleChange,
570
+ onBlur: handleBlur,
529
571
  index,
530
572
  confirm,
531
- desensitization: _desensitization,
573
+ desensitization: lastDesensitization,
532
574
  otherProps: {
533
575
  form,
534
576
  names,
@@ -537,15 +579,15 @@ const RenderField = ({
537
579
  listName: cellName,
538
580
  // 用于下拉框去重消费,保持和formlist一致
539
581
  viewEmpty,
540
- valueType: _valueType,
582
+ valueType: lastValueType,
541
583
  isView,
542
584
  desensitizationKey: otherProps?.desensitizationKey,
543
585
  source: 'ProEditTable'
544
586
  }
545
- }), [cellName, _fieldProps, TargetComponent?.props, namePath, index, _disabled, _onChange, _onblur, confirm, _desensitization, names, originalName, viewEmpty, _valueType, isView, otherProps?.desensitizationKey]);
587
+ }), [cellName, lastFieldProps, TargetComponent?.props, namePath, index, lastDisabled, handleChange, handleBlur, confirm, lastDesensitization, names, originalName, viewEmpty, lastValueType, isView, otherProps?.desensitizationKey]);
546
588
  componentProps = _omit(componentProps, ['onFieldChange', 'namePath', 'index', ...OMIT_FORM_ITEM_AND_DOM_KEYS]);
547
589
  if (['Switch', 'SwitchCheckbox'].includes(type)) {
548
- _formItemProps.valuePropName = 'checked';
590
+ lastFormItemProps.valuePropName = 'checked';
549
591
  }
550
592
 
551
593
  // 可编辑表格默认关闭scrollFollowParent
@@ -560,9 +602,9 @@ const RenderField = ({
560
602
  const trimProps = isTrim(type, trim, proConfig); // 使用顶层调用的proConfig
561
603
 
562
604
  const transformNormalize = namesTransformProps?.normalize ?? defaultTransformProps?.normalize;
563
- const userNormalize = _formItemProps?.normalize;
605
+ const userNormalize = lastFormItemProps?.normalize;
564
606
  const transformGetValueProps = namesTransformProps?.getValueProps ?? defaultTransformProps?.getValueProps;
565
- const userGetValueProps = _formItemProps?.getValueProps;
607
+ const userGetValueProps = lastFormItemProps?.getValueProps;
566
608
  const finalNormalize = transformNormalize && userNormalize ? (value, prevValue, allValues, isDiffMode) => {
567
609
  // 用户 normalize 需要拿到组件原始值(如 DatePicker 的 dayjs)
568
610
  const userValue = userNormalize(value, prevValue, allValues, isDiffMode);
@@ -583,203 +625,205 @@ const RenderField = ({
583
625
  };
584
626
  } : userGetValueProps || transformGetValueProps;
585
627
  return {
586
- ..._formItemProps,
628
+ ...lastFormItemProps,
587
629
  ...defaultTransformProps,
588
630
  ...namesTransformProps,
589
631
  ...trimProps,
590
632
  normalize: finalNormalize,
591
633
  getValueProps: finalGetValueProps
592
634
  };
593
- }, [_formItemProps, defaultTransform, namesTransform, type, trim, proConfig]);
635
+ }, [lastFormItemProps, defaultTransform, namesTransform, type, trim, proConfig]);
594
636
 
595
637
  // rules 的 isView 过滤已移至 getFieldItem 内处理(支持 shouldUpdate 模式下的动态 isEditable)
596
638
 
597
- const _className = useMemo(() => classNames({
639
+ const cellClassName = useMemo(() => classNames({
598
640
  [className]: className
599
641
  }), [className]);
600
642
 
601
- // 使用useCallback优化getFieldItem函数
602
- const getFieldItem = (shouldUpdateMode = false) => {
603
- // 如果处于 shouldUpdate 模式,需要重新获取最新的行数据并重新计算依赖值
604
- let finalComponentProps = componentProps;
605
- // shouldUpdate 模式下会被更新为最新值,供外层 FieldProvider 消费
606
- let latestIsView = isView;
607
- // 用于在 shouldUpdate 模式下重建正确的 Form.Item rules(外层 finalFormItemProps 是旧闭包)
608
- let effectiveRequired = _required;
609
- let effectiveRules = _rules;
610
- let effectiveFieldProps = _fieldProps;
611
- if (shouldUpdateMode) {
612
- // 重新获取最新的行数据(shouldUpdate 触发时,通过 getFieldValue 拿到最新值)
613
- const latestRowData = form.getFieldValue([...namePath, index]) || record || {};
614
- const latestReactiveParams = {
615
- form,
616
- index,
617
- namePath: [...namePath, index]
618
- };
619
- const latestRowParams = [latestRowData, latestReactiveParams];
643
+ // shouldUpdate 模式下重新获取最新行数据并重算所有响应式属性,返回最新渲染状态(不修改外层闭包)
644
+ const recalcShouldUpdateState = () => {
645
+ // 重新获取最新的行数据(shouldUpdate 触发时,通过 getFieldValue 拿到最新值)
646
+ const latestRowData = form.getFieldValue([...namePath, index]) || record || {};
647
+ const latestReactiveParams = {
648
+ form,
649
+ index,
650
+ namePath: [...namePath, index]
651
+ };
652
+ const latestRowParams = [latestRowData, latestReactiveParams];
620
653
 
621
- // ⭐ 关键修改:shouldUpdate 模式下,跳过缓存,直接重新计算所有响应式属性
622
- let latestFieldProps = fieldProps || {};
623
- if (_isFunction(fieldProps)) {
624
- latestFieldProps = fieldProps(latestRowData, latestReactiveParams);
625
- }
654
+ // ⭐ 关键修改:shouldUpdate 模式下,跳过缓存,直接重新计算所有响应式属性
655
+ let latestFieldProps = fieldProps || {};
656
+ if (_isFunction(fieldProps)) {
657
+ latestFieldProps = fieldProps(latestRowData, latestReactiveParams);
658
+ }
626
659
 
627
- // 重新计算 required(用于可能的后续逻辑)
628
- let latestRequired = required;
629
- if (_isFunction(required)) {
630
- latestRequired = required(latestRowData, latestReactiveParams);
631
- }
660
+ // 重新计算 required(用于可能的后续逻辑)
661
+ let latestRequired = required;
662
+ if (_isFunction(required)) {
663
+ latestRequired = required(latestRowData, latestReactiveParams);
664
+ }
632
665
 
633
- // 重新计算 rules(用于可能的后续逻辑)
634
- let latestRules = rules;
635
- if (_isFunction(rules)) {
636
- latestRules = rules(latestRowData, latestReactiveParams);
637
- }
666
+ // 重新计算 rules(用于可能的后续逻辑)
667
+ let latestRules = rules;
668
+ if (_isFunction(rules)) {
669
+ latestRules = rules(latestRowData, latestReactiveParams);
670
+ }
638
671
 
639
- // 同步到外层变量,用于后续构建 activeFinalFormItemProps
640
- effectiveRequired = latestRequired;
641
- effectiveRules = latestRules;
642
- effectiveFieldProps = latestFieldProps;
672
+ // 重新计算 desensitization
673
+ let latestDesensitization = desensitization || [];
674
+ if (_isFunction(desensitization)) {
675
+ latestDesensitization = desensitization(latestRowData, latestReactiveParams);
676
+ }
643
677
 
644
- // 重新计算 desensitization
645
- let latestDesensitization = desensitization || [];
646
- if (_isFunction(desensitization)) {
647
- latestDesensitization = desensitization(latestRowData, latestReactiveParams);
648
- }
678
+ // 重新计算 component
679
+ let latestComponent = component || editRender;
680
+ if (_isFunction(latestComponent)) {
681
+ latestComponent = latestComponent(latestRowData, latestReactiveParams);
682
+ }
649
683
 
650
- // 重新计算 component
651
- let latestComponent = component || editRender;
652
- if (_isFunction(latestComponent)) {
653
- latestComponent = latestComponent(latestRowData, latestReactiveParams);
654
- }
684
+ // 重新计算 isEditable(使用原始的 column.isEditable,而不是处理后的 isEditable)
685
+ let latestIsEditable = column.isEditable ?? true;
686
+ if (_isFunction(column.isEditable)) {
687
+ latestIsEditable = column.isEditable(latestRowData, latestReactiveParams);
688
+ }
655
689
 
656
- // 重新计算 isEditable(使用原始的 column.isEditable,而不是处理后的 isEditable)
657
- let latestIsEditable = column.isEditable ?? true;
658
- if (_isFunction(column.isEditable)) {
659
- latestIsEditable = column.isEditable(latestRowData, latestReactiveParams);
660
- }
690
+ // 重新计算 disabled
691
+ const latestDisabled = getDisabled({
692
+ globalControl: otherProps?.globalControl,
693
+ formDisabled: otherProps?.formDisabled,
694
+ column,
695
+ tabledDisabled: config?.disabled,
696
+ columnFieldProps: latestFieldProps,
697
+ params: latestRowParams
698
+ });
661
699
 
662
- // 重新计算 disabled
663
- const latestDisabled = getDisabled({
664
- globalControl: otherProps?.globalControl,
665
- formDisabled: otherProps?.formDisabled,
666
- column,
667
- tabledDisabled: config?.disabled,
668
- columnFieldProps: latestFieldProps,
669
- params: latestRowParams
670
- });
700
+ // 更新 componentProps 中的所有响应式属性
701
+ // latestTargetComponent 稍后计算,此处先占位;最终会在下方合并 latestTargetComponent?.props
702
+ let latestComponentProps = {
703
+ ...componentProps,
704
+ ...latestFieldProps,
705
+ disabled: latestDisabled,
706
+ desensitization: latestDesensitization,
707
+ // shouldUpdate 模式下,确保事件包装函数不被 fieldProps 覆盖
708
+ onChange: handleChange,
709
+ onBlur: handleBlur
710
+ };
671
711
 
672
- // 更新 componentProps 中的所有响应式属性
673
- // latestTargetComponent 稍后计算,此处先占位;最终 finalComponentProps 会在下方合并 latestTargetComponent?.props
674
- finalComponentProps = {
675
- ...componentProps,
676
- ...latestFieldProps,
677
- disabled: latestDisabled,
678
- desensitization: latestDesensitization,
679
- // shouldUpdate 模式下,确保事件包装函数不被 fieldProps 覆盖
680
- onChange: _onChange,
681
- onBlur: _onblur
682
- };
712
+ // 关键修改:在 shouldUpdate 模式下,需要重新设置 TargetComponent
713
+ // 因为 component 函数可能返回不同的结果
714
+ let latestTargetComponent = TargetComponent;
683
715
 
684
- // ⭐ 关键修改:在 shouldUpdate 模式下,需要重新设置 TargetComponent
685
- // 因为 component 函数可能返回不同的结果
686
- let latestTargetComponent = TargetComponent;
716
+ // 首先检查是否有内置type
717
+ if (!latestComponent && typeof type === 'string') {
718
+ latestTargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
719
+ }
687
720
 
688
- // 首先检查是否有内置type
689
- if (!latestComponent && typeof type === 'string') {
690
- latestTargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
721
+ // 然后处理自定义 component
722
+ const latestIsView = !latestIsEditable || record?.['is-view'] || config.isView || virtualKey && !isEditing || getDisabled({
723
+ globalControl: otherProps?.globalControl,
724
+ formDisabled: otherProps?.formDisabled,
725
+ column,
726
+ tabledDisabled: config?.disabled,
727
+ columnFieldProps: latestFieldProps,
728
+ params: latestRowParams,
729
+ rowDisabled: rowDisabled || 'empty'
730
+ });
731
+ if (latestIsEditable && isEditing) {
732
+ if ( /*#__PURE__*/React.isValidElement(latestComponent)) {
733
+ latestTargetComponent = latestComponent;
734
+ } else if (latestComponent) {
735
+ latestTargetComponent = latestComponent;
691
736
  }
737
+ }
692
738
 
693
- // 然后处理自定义 component
694
- latestIsView = !latestIsEditable || record?.['is-view'] || config.isView || virtualKey && !_isEditing || getDisabled({
695
- globalControl: otherProps?.globalControl,
696
- formDisabled: otherProps?.formDisabled,
697
- column,
698
- tabledDisabled: config?.disabled,
699
- columnFieldProps: latestFieldProps,
700
- params: latestRowParams,
701
- rowDisabled: rowDisabled || 'empty'
702
- });
703
- if (latestIsEditable && _isEditing) {
704
- if ( /*#__PURE__*/React.isValidElement(latestComponent)) {
705
- latestTargetComponent = latestComponent;
706
- } else if (latestComponent) {
707
- latestTargetComponent = latestComponent;
708
- }
739
+ // 查看模式
740
+ if (latestIsView) {
741
+ if (typeof viewRender === 'function') {
742
+ const latestCurrentValue = dataIndex ? latestRowData?.[dataIndex] : null;
743
+ const View = viewRender(latestCurrentValue, latestRowData || {}, options);
744
+ latestTargetComponent = /*#__PURE__*/_jsx(Container, {
745
+ viewEmpty: viewEmpty,
746
+ children: View
747
+ });
709
748
  }
710
-
711
- // 查看模式
712
- if (latestIsView) {
713
- if (typeof viewRender === 'function') {
714
- const latestCurrentValue = dataIndex ? latestRowData?.[dataIndex] : null;
715
- const View = viewRender(latestCurrentValue, latestRowData || {}, options);
716
- latestTargetComponent = /*#__PURE__*/_jsx(Container, {
717
- viewEmpty: viewEmpty,
718
- children: View
719
- });
720
- }
721
- if ( /*#__PURE__*/React.isValidElement(viewRender)) {
722
- latestTargetComponent = viewRender;
723
- }
749
+ if ( /*#__PURE__*/React.isValidElement(viewRender)) {
750
+ latestTargetComponent = viewRender;
724
751
  }
752
+ }
725
753
 
726
- // 使用重新计算的 TargetComponent
727
- TargetComponent = latestTargetComponent;
728
-
729
- // shouldUpdate 触发时外层 componentProps.otherProps.isView 是旧快照,需用最新值覆盖
730
- finalComponentProps = {
731
- ...finalComponentProps,
732
- otherProps: {
733
- ...finalComponentProps.otherProps,
734
- isView: latestIsView
735
- }
736
- };
754
+ // shouldUpdate 触发时外层 componentProps.otherProps.isView 是旧快照,需用最新值覆盖
755
+ latestComponentProps = {
756
+ ...latestComponentProps,
757
+ otherProps: {
758
+ ...latestComponentProps.otherProps,
759
+ isView: latestIsView
760
+ }
761
+ };
737
762
 
738
- // componentProps 里展开了外层旧 TargetComponent?.props(如 { formType: "Input" }),
739
- // 用 latestTargetComponent?.props 覆盖,确保不会被旧 cloneElement props 污染
740
- if ( /*#__PURE__*/React.isValidElement(latestTargetComponent)) {
741
- const componentProps = latestTargetComponent.props;
742
- // 确保 props 是对象类型才进行展开
743
- if (componentProps && typeof componentProps === 'object') {
744
- finalComponentProps = {
745
- ...finalComponentProps,
746
- ...componentProps,
747
- // 始终保证事件处理函数不被覆盖
748
- onChange: _onChange,
749
- onBlur: _onblur
750
- };
751
- }
763
+ // componentProps 里展开了外层旧 TargetComponent?.props(如 { formType: "Input" }),
764
+ // 用 latestTargetComponent?.props 覆盖,确保不会被旧 cloneElement props 污染
765
+ if ( /*#__PURE__*/React.isValidElement(latestTargetComponent)) {
766
+ const elementProps = latestTargetComponent.props;
767
+ // 确保 props 是对象类型才进行展开
768
+ if (elementProps && typeof elementProps === 'object') {
769
+ latestComponentProps = {
770
+ ...latestComponentProps,
771
+ ...elementProps,
772
+ // 始终保证事件处理函数不被覆盖
773
+ onChange: handleChange,
774
+ onBlur: handleBlur
775
+ };
752
776
  }
753
777
  }
778
+ return {
779
+ finalComponentProps: latestComponentProps,
780
+ targetComponent: latestTargetComponent,
781
+ latestIsView,
782
+ effectiveRequired: latestRequired,
783
+ effectiveRules: latestRules,
784
+ effectiveFieldProps: latestFieldProps
785
+ };
786
+ };
754
787
 
755
- // 根据 latestIsView 和最新的 required/rules 构建正确的 Form.Item props
756
- // 解决 shouldUpdate 触发时外层 finalFormItemProps 是旧闭包(rules 基于旧 isView 计算)的问题
757
- let activeFinalFormItemProps = finalFormItemProps;
788
+ // 根据 latestIsView 和最新 required/rules 构建正确的 Form.Item props
789
+ // 解决 shouldUpdate 触发时外层 finalFormItemProps 是旧闭包(rules 基于旧 isView 计算)的问题
790
+ const buildActiveFormItemProps = ({
791
+ latestIsView,
792
+ shouldUpdateMode,
793
+ effectiveRequired,
794
+ effectiveRules,
795
+ effectiveFieldProps
796
+ }) => {
758
797
  if (latestIsView) {
759
798
  // 查看模式:移除 rules 不做校验
760
- activeFinalFormItemProps = _omit(finalFormItemProps, ['rules']);
761
- } else if (shouldUpdateMode) {
799
+ return _omit(finalFormItemProps, ['rules']);
800
+ }
801
+ if (shouldUpdateMode) {
762
802
  // shouldUpdate 模式下 finalFormItemProps 是旧闭包,需用最新 effectiveRequired/effectiveRules 重建 rules
763
803
  const activeRules = Array.isArray(effectiveRules) ? [...effectiveRules] : [];
764
804
  const hasRequiredRule = activeRules.some(r => r?.required === true);
765
805
  if (effectiveRequired && !hasRequiredRule) {
766
- const _isSelectVal = isSelect({
806
+ const isSelectVal = isSelect({
767
807
  dataSource: effectiveFieldProps?.dataSource,
768
808
  type
769
809
  });
770
810
  activeRules.push({
771
811
  required: true,
772
- message: `${_isSelectVal ? locale.ProForm.selectPlaceHolder : locale.ProForm.inputPlaceholder}${label || ''}`
812
+ message: `${isSelectVal ? locale.ProForm.selectPlaceHolder : locale.ProForm.inputPlaceholder}${label || ''}`
773
813
  });
774
814
  }
775
- activeFinalFormItemProps = {
815
+ return {
776
816
  ...finalFormItemProps,
777
817
  rules: activeRules.length > 0 ? activeRules : [{
778
818
  required: false
779
819
  }]
780
820
  };
781
821
  }
782
- let FormItem = null;
822
+ return finalFormItemProps;
823
+ };
824
+
825
+ // 组装字段组件:DOM 透传字段过滤、克隆/创建目标元素、原始值对比包裹(ListChangedWrapper)、确认弹窗包裹(ConfirmWrapper)
826
+ const assembleFieldComponent = finalComponentProps => {
783
827
  // 当 viewRender 存在时,需要排除 finalComponentProps 中的 children,避免覆盖 Container 的 children
784
828
  let propsForTarget = isView && typeof viewRender === 'function' ? _omit(finalComponentProps, ['children']) : finalComponentProps;
785
829
  // 当目标为原生 DOM 元素(如 viewRender 返回 <div>)时,剔除 disabled、toCSTString 等,避免 React 警告
@@ -810,8 +854,8 @@ const RenderField = ({
810
854
  form: form,
811
855
  onDiff: onDiff,
812
856
  type: type,
813
- onChange: _onChange,
814
- onBlur: _onblur,
857
+ onChange: handleChange,
858
+ onBlur: handleBlur,
815
859
  valuePropName: finalFormItemProps.valuePropName,
816
860
  normalize: finalFormItemProps.normalize,
817
861
  getValueProps: finalFormItemProps.getValueProps,
@@ -827,11 +871,42 @@ const RenderField = ({
827
871
  children: FieldComponent
828
872
  });
829
873
  }
830
- FormItem = TargetComponent ? /*#__PURE__*/_jsx(Form.Item, {
874
+ return FieldComponent;
875
+ };
876
+
877
+ // 使用useCallback优化getFieldItem函数
878
+ const getFieldItem = (shouldUpdateMode = false) => {
879
+ // 如果处于 shouldUpdate 模式,需要重新获取最新的行数据并重新计算依赖值
880
+ let finalComponentProps = componentProps;
881
+ // shouldUpdate 模式下会被更新为最新值,供外层 FieldProvider 消费
882
+ let latestIsView = isView;
883
+ // 用于在 shouldUpdate 模式下重建正确的 Form.Item rules(外层 finalFormItemProps 是旧闭包)
884
+ let effectiveRequired = lastRequired;
885
+ let effectiveRules = lastRules;
886
+ let effectiveFieldProps = lastFieldProps;
887
+ if (shouldUpdateMode) {
888
+ const recomputed = recalcShouldUpdateState();
889
+ finalComponentProps = recomputed.finalComponentProps;
890
+ // shouldUpdate 模式下用重算结果覆盖外层 TargetComponent,供下方组装逻辑消费
891
+ TargetComponent = recomputed.targetComponent;
892
+ latestIsView = recomputed.latestIsView;
893
+ effectiveRequired = recomputed.effectiveRequired;
894
+ effectiveRules = recomputed.effectiveRules;
895
+ effectiveFieldProps = recomputed.effectiveFieldProps;
896
+ }
897
+ const activeFinalFormItemProps = buildActiveFormItemProps({
898
+ latestIsView,
899
+ shouldUpdateMode,
900
+ effectiveRequired,
901
+ effectiveRules,
902
+ effectiveFieldProps
903
+ });
904
+ const FieldComponent = assembleFieldComponent(finalComponentProps);
905
+ let FormItem = TargetComponent ? /*#__PURE__*/_jsx(Form.Item, {
831
906
  validateFirst: true,
832
- ..._omit(activeFinalFormItemProps, ['render', 'key', 'width', 'hiddenNames', 'name', 'onCell', 'disabled', _formItemProps.shouldUpdate ? 'shouldUpdate' : null]),
907
+ ..._omit(activeFinalFormItemProps, ['render', 'key', 'width', 'hiddenNames', 'name', 'onCell', 'disabled', lastFormItemProps.shouldUpdate ? 'shouldUpdate' : null]),
833
908
  // 移除非必要字段,但保留 dependencies
834
- className: _className,
909
+ className: cellClassName,
835
910
  name: formNamePath ? cellName.slice(formNamePath?.length - 1) : cellName,
836
911
  children: FieldComponent
837
912
  }) : /*#__PURE__*/_jsx(Container, {
@@ -875,132 +950,4 @@ const RenderField = ({
875
950
  })
876
951
  });
877
952
  };
878
- export default /*#__PURE__*/memo(RenderField, (prevProps, nextProps) => {
879
- // 自定义比较函数,只有关键props变化时才重新渲染
880
- const {
881
- text: prevText,
882
- record: prevRecord,
883
- index: prevIndex,
884
- column: prevColumn,
885
- config: prevConfig
886
- } = prevProps;
887
- const {
888
- text: nextText,
889
- record: nextRecord,
890
- index: nextIndex,
891
- column: nextColumn,
892
- config: nextConfig
893
- } = nextProps;
894
-
895
- // 函数型动态属性(component/editRender/fieldProps/rules/required/disabled/isEditable/valueType)
896
- // 可能依赖行内兄弟字段;行对象为同引用(原地修改)时,浅比较无法区分,需强制重渲染
897
- const hasFunctionDependency = _isFunction(prevColumn?.component) || _isFunction(prevColumn?.editRender) || _isFunction(prevColumn?.fieldProps) || _isFunction(prevColumn?.rules) || _isFunction(prevColumn?.required) || _isFunction(prevColumn?.disabled) || _isFunction(prevColumn?.isEditable) || _isFunction(prevColumn?.valueType) || _isFunction(nextColumn?.component) || _isFunction(nextColumn?.editRender) || _isFunction(nextColumn?.fieldProps) || _isFunction(nextColumn?.rules) || _isFunction(nextColumn?.required) || _isFunction(nextColumn?.disabled) || _isFunction(nextColumn?.isEditable) || _isFunction(nextColumn?.valueType);
898
- if (hasFunctionDependency && prevRecord === nextRecord) {
899
- return false;
900
- }
901
-
902
- // 构建新的参数格式(与 ProForm 保持一致)
903
- const prevNamePath = getNamePath(prevConfig?.name, prevConfig?.virtualKey);
904
- const nextNamePath = getNamePath(nextConfig?.name, nextConfig?.virtualKey);
905
- const prevReactiveParams = {
906
- form: prevConfig?.form,
907
- index: prevIndex,
908
- namePath: [...prevNamePath, prevIndex]
909
- };
910
- const nextReactiveParams = {
911
- form: nextConfig?.form,
912
- index: nextIndex,
913
- namePath: [...nextNamePath, nextIndex]
914
- };
915
- const prevRowParams = [prevRecord, prevReactiveParams];
916
- const nextRowParams = [nextRecord, nextReactiveParams];
917
- if (_isFunction(prevColumn?.disabled) && _isFunction(nextColumn?.disabled)) {
918
- if (prevColumn?.disabled(prevRecord, prevReactiveParams) !== nextColumn?.disabled(nextRecord, nextReactiveParams)) {
919
- return false;
920
- }
921
- }
922
-
923
- // fieldProps 函数化直接更新,无法比对返回值是否一致
924
- // 优化:不直接调用函数,而是比较输入参数(record 和 reactiveParams)
925
- // 如果输入参数相同,fieldProps 的返回值应该相同(纯函数假设)
926
- if (_isFunction(prevColumn?.fieldProps) && _isFunction(nextColumn?.fieldProps)) {
927
- // 比较 record 数据是否变化
928
- if (!_isEqualWith(prevRecord, nextRecord, customEqualForFunction)) {
929
- return false;
930
- }
931
- // reactiveParams 中的 form、index、namePath 已经在外层比较过了,无需重复比较
932
- }
933
- // fieldProps 为对象时,必须比较配置变化(如 dataSource 异步更新)
934
- if (!_isFunction(prevColumn?.fieldProps) && !_isFunction(nextColumn?.fieldProps)) {
935
- const isFieldPropsEqual = _isEqualWith(prevColumn?.fieldProps, nextColumn?.fieldProps, customEqualForFunction);
936
- if (!isFieldPropsEqual) {
937
- return false;
938
- }
939
- }
940
-
941
- // 通用函数比较方法
942
- // 优化:不直接调用函数,而是比较函数引用和输入参数
943
- const compareFunctionResult = (prevColumn, nextColumn, prevValues, nextValues, prevReactiveParams, nextReactiveParams, functionName) => {
944
- const prevFunc = prevColumn?.[functionName];
945
- const nextFunc = nextColumn?.[functionName];
946
- if (_isFunction(prevFunc) && _isFunction(nextFunc)) {
947
- // 函数引用变化说明闭包可能捕获了新的外部状态(如异步加载的 list),必须重渲染
948
- if (prevFunc !== nextFunc) return false;
949
- // 同引用函数,比较输入参数(纯函数假设:输入相同则输出相同)
950
- return _isEqualWith(prevValues, nextValues, customEqualForFunction);
951
- }
952
- return true; // 如果不是函数或只有一个是函数,认为相等
953
- };
954
-
955
- // 使用简化后的比较逻辑
956
- const functionFields = ['rules', 'component', 'desensitization', 'isEditable', 'required'];
957
- if (functionFields.some(field => !compareFunctionResult(prevColumn, nextColumn, prevRecord, nextRecord, prevReactiveParams, nextReactiveParams, field))) {
958
- return false;
959
- }
960
-
961
- // 基本props比较
962
- if (!_isEqual(prevText, nextText) || prevIndex !== nextIndex) {
963
- return false;
964
- }
965
-
966
- // 记录关键字段比较(避免完整对象比较的性能开销)
967
- if (prevRecord?.rowKey !== nextRecord?.rowKey || prevRecord?._addFlag !== nextRecord?._addFlag) {
968
- return false;
969
- }
970
-
971
- // 列配置比较(只比较关键字段),required,disabled为函数时,需要重新计算
972
- if (prevColumn?.dataIndex !== nextColumn?.dataIndex || prevColumn?.type !== nextColumn?.type || prevColumn?.name !== nextColumn?.name) {
973
- return false;
974
- }
975
-
976
- // config中关键字段比较
977
- if (prevConfig?._isEditing !== nextConfig?._isEditing || prevConfig?.mode !== nextConfig?.mode) {
978
- return false;
979
- }
980
-
981
- // 当前单元格的值比较
982
- const prevDataIndex = prevColumn?.dataIndex;
983
- const nextDataIndex = nextColumn?.dataIndex;
984
- if (prevDataIndex && nextDataIndex && prevDataIndex === nextDataIndex) {
985
- if (prevRecord?.[prevDataIndex] !== nextRecord?.[nextDataIndex]) {
986
- return false;
987
- }
988
- }
989
-
990
- // 特殊处理:当使用自定义 component 函数时,比较整个 record 对象
991
- // 因为自定义组件可能依赖 record 中的其他字段(不只是当前列的 dataIndex)
992
- if (_isFunction(prevColumn?.component) || _isFunction(nextColumn?.component)) {
993
- // 浅比较 record 的所有属性
994
- const prevKeys = Object.keys(prevRecord || {});
995
- const nextKeys = Object.keys(nextRecord || {});
996
- if (prevKeys.length !== nextKeys.length) {
997
- return false;
998
- }
999
-
1000
- // 使用 some 方法代替 for 循环
1001
- if (prevKeys.some(key => prevRecord?.[key] !== nextRecord?.[key])) {
1002
- return false;
1003
- }
1004
- }
1005
- return true;
1006
- });
953
+ export default /*#__PURE__*/memo(RenderField, arePropsEqual);