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

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,7 +9,7 @@ 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
15
  import { getNamePath, difference, getDisabled } from "../../utils/tools";
@@ -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,
@@ -80,13 +76,13 @@ const RenderField = ({
80
76
  getIsNew,
81
77
  shouldUpdateDebounce
82
78
  } = 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;
79
+ let lastFieldProps = fieldProps || {};
80
+ let lastRules = rules || [];
81
+ let lastRequired = required;
82
+ let lastValueType = valueType;
83
+ let lastDisabled = false;
84
+ let lastDesensitization = desensitization || [];
85
+ let lastComponent = component || editRender;
90
86
  const isSingleMode = mode === 'single';
91
87
 
92
88
  // type类型 首字母转大写
@@ -130,16 +126,16 @@ const RenderField = ({
130
126
  // required & rules & fieldProps & disabled & valueType 函数化处理
131
127
  // 优先使用 hook 返回的值,fallback 到原始值
132
128
  if (_isFunction(required)) {
133
- _required = dynamicProps.required ?? required(rowData, reactiveParams);
129
+ lastRequired = dynamicProps.required ?? required(rowData, reactiveParams);
134
130
  }
135
131
  if (_isFunction(fieldProps)) {
136
- _fieldProps = dynamicProps.fieldProps ?? fieldProps(rowData, reactiveParams);
132
+ lastFieldProps = dynamicProps.fieldProps ?? fieldProps(rowData, reactiveParams);
137
133
  }
138
134
  if (_isFunction(rules)) {
139
- _rules = dynamicProps.rules ?? rules(rowData, reactiveParams);
135
+ lastRules = dynamicProps.rules ?? rules(rowData, reactiveParams);
140
136
  }
141
137
  if (_isFunction(valueType)) {
142
- _valueType = dynamicProps.valueType ?? valueType(currentValue, rowData, {
138
+ lastValueType = dynamicProps.valueType ?? valueType(currentValue, rowData, {
143
139
  index,
144
140
  form,
145
141
  namePath: [...namePath, index],
@@ -147,16 +143,16 @@ const RenderField = ({
147
143
  });
148
144
  }
149
145
  if (_isFunction(desensitization)) {
150
- _desensitization = dynamicProps.desensitization ?? desensitization(rowData, reactiveParams);
146
+ lastDesensitization = dynamicProps.desensitization ?? desensitization(rowData, reactiveParams);
151
147
  }
152
148
 
153
149
  // 获取最终的disabled
154
- _disabled = getDisabled({
150
+ lastDisabled = getDisabled({
155
151
  globalControl: otherProps?.globalControl,
156
152
  formDisabled: otherProps?.formDisabled,
157
153
  column,
158
154
  tabledDisabled: config?.disabled,
159
- columnFieldProps: _fieldProps,
155
+ columnFieldProps: lastFieldProps,
160
156
  params: rowParams
161
157
  });
162
158
 
@@ -166,26 +162,28 @@ const RenderField = ({
166
162
  }
167
163
 
168
164
  // component 处理 - 优先使用 hook 返回的值
169
- if (_isFunction(_component)) {
170
- _component = dynamicProps.component ?? _component(rowData, reactiveParams);
165
+ if (_isFunction(lastComponent)) {
166
+ lastComponent = dynamicProps.component ?? lastComponent(rowData, reactiveParams);
171
167
  }
172
168
 
173
- // 更新 _editRender 为处理后的 _component
174
- const _editRender = _component;
169
+ // 更新 lastEditRender 为处理后的 lastComponent
170
+ const lastEditRender = lastComponent;
175
171
 
176
172
  // 是否只读文本
177
- const isView = !isEditable || record?.['is-view'] || config.isView || virtualKey && !_isEditing || getDisabled({
173
+ const isView = !isEditable || record?.['is-view'] || config.isView || virtualKey && !isEditing || getDisabled({
178
174
  globalControl: otherProps?.globalControl,
179
175
  formDisabled: otherProps?.formDisabled,
180
176
  column,
181
177
  tabledDisabled: config?.disabled,
182
- columnFieldProps: _fieldProps,
178
+ columnFieldProps: lastFieldProps,
183
179
  params: rowParams,
184
180
  rowDisabled: rowDisabled || 'empty'
185
181
  });
186
182
 
187
183
  // 只读文本时,采用当前formItem的name,单行编辑时,使用生成的虚拟的name
188
184
  const baseName = isView ? name : namePath;
185
+
186
+ // 多态:可能是内置组件类型、自定义 component,或已渲染的 ReactElement(lastEditRender),保留显式 any
189
187
  let TargetComponent;
190
188
 
191
189
  // 将Hooks调用移到组件顶层
@@ -196,18 +194,18 @@ const RenderField = ({
196
194
  names,
197
195
  label: label,
198
196
  labelRequired,
199
- required: _required,
200
- rules: _rules,
197
+ required: lastRequired,
198
+ rules: lastRules,
201
199
  isSelect: isSelect({
202
- dataSource: _fieldProps?.dataSource,
200
+ dataSource: lastFieldProps?.dataSource,
203
201
  type
204
202
  }),
205
203
  type
206
204
  });
207
205
 
208
- // 分离form item参数,防止对于参数透传(如onChange,防止重复触发)并优先级高于 _fieldProps 内部参数
206
+ // 分离form item参数,防止对于参数透传(如onChange,防止重复触发)并优先级高于 lastFieldProps 内部参数
209
207
  const formItemChildProps = {
210
- ..._fieldProps
208
+ ...lastFieldProps
211
209
  };
212
210
 
213
211
  // 使用useMemo优化defaultProps计算
@@ -219,7 +217,7 @@ const RenderField = ({
219
217
  }), [name, formNamePath, cellName, column?.type, column?.fieldProps]);
220
218
 
221
219
  // 允许formItem的属性放在column最外层 - 使用useMemo优化(剔除会透传到 DOM 的字段)
222
- const _formItemProps = useMemo(() => ({
220
+ const lastFormItemProps = useMemo(() => ({
223
221
  ...defaultProps,
224
222
  ..._omit(resetProps, OMIT_FORM_ITEM_AND_DOM_KEYS),
225
223
  ...internalRule,
@@ -230,7 +228,7 @@ const RenderField = ({
230
228
  // 当这些函数类型存在时,自动添加 shouldUpdate
231
229
  // 因为这些函数依赖行数据,当行数据变化时需要重新计算
232
230
  // 扩展到所有模式(single/multiple/cell),统一行为
233
- // 注意:需要检查原始的 component/editRender,而不是处理后的 _component
231
+ // 注意:需要检查原始的 component/editRender,而不是处理后的 lastComponent
234
232
  const hasFunctionDependency = _isFunction(column?.disabled) ||
235
233
  // disabled 是函数
236
234
  _isFunction(fieldProps) ||
@@ -251,7 +249,7 @@ const RenderField = ({
251
249
  // 性能优化已通过 useShouldUpdateForTable hook 的缓存和防抖机制实现
252
250
  if (hasFunctionDependency) {
253
251
  // 使用 shouldUpdate 监听同一行的数据变化;shouldUpdate 与 dependencies 互斥,始终优先 shouldUpdate
254
- _formItemProps.shouldUpdate = (prevValues, currentValues) => {
252
+ lastFormItemProps.shouldUpdate = (prevValues, currentValues) => {
255
253
  const prevRow = _get(prevValues, [...namePath, index]);
256
254
  const currentRow = _get(currentValues, [...namePath, index]);
257
255
  // 如果行数据发生变化,则重新渲染
@@ -259,8 +257,8 @@ const RenderField = ({
259
257
  };
260
258
  }
261
259
  if (['Switch', 'SwitchCheckbox'].includes(type)) {
262
- _formItemProps.valuePropName = 'checked';
263
- _valueType = 'switch';
260
+ lastFormItemProps.valuePropName = 'checked';
261
+ lastValueType = 'switch';
264
262
  }
265
263
 
266
264
  /**
@@ -269,11 +267,11 @@ const RenderField = ({
269
267
  */
270
268
  const defaultTransform = useCallback(() => {
271
269
  const types = ['DatePicker', 'RangePicker'];
272
- if (!_valueType && types.includes(type)) {
273
- return transformMap?.[type]?.(_fieldProps || {});
270
+ if (!lastValueType && types.includes(type)) {
271
+ return transformMap?.[type]?.(lastFieldProps || {});
274
272
  }
275
273
  return {};
276
- }, [_valueType, type, _fieldProps]);
274
+ }, [lastValueType, type, lastFieldProps]);
277
275
 
278
276
  /**
279
277
  * 配置valueType时,基于formItem的normalize与getValueProps进行值类型转换
@@ -282,14 +280,15 @@ const RenderField = ({
282
280
  const valueTypeTransform = useCallback(() => {
283
281
  // SwitchCheckbox默认YN, 兼容已有组件
284
282
  if (type === 'SwitchCheckbox') {
285
- _valueType = 'switch';
283
+ lastValueType = 'switch';
286
284
  }
287
285
  const params = {
288
286
  ...column,
289
- mode: _fieldProps?.mode
287
+ mode: lastFieldProps?.mode
290
288
  };
291
- return _isFunction(valueTypeMap[_valueType]) ? valueTypeMap[_valueType](params) : {};
292
- }, [type, _valueType, column, _fieldProps?.mode]);
289
+ const valueTypeKey = lastValueType;
290
+ return _isFunction(valueTypeMap[valueTypeKey]) ? valueTypeMap[valueTypeKey](params) : {};
291
+ }, [type, lastValueType, column, lastFieldProps?.mode]);
293
292
  if (names?.length) {
294
293
  // 支持names配置,临时生成对应的formItem,用来存储单个对应的值
295
294
  names = names.map(key => {
@@ -318,22 +317,23 @@ const RenderField = ({
318
317
  }
319
318
  const namesStr = [...baseName, index, dataIndex];
320
319
  return transformNames({
321
- ..._formItemProps,
320
+ ...lastFormItemProps,
322
321
  ...valueTypeTransform()
323
322
  }, form, names, namesStr, type);
324
- }, [names, baseName, index, dataIndex, _formItemProps, type]);
325
- if (!_editRender && typeof type === 'string') {
323
+ }, [names, baseName, index, dataIndex, lastFormItemProps, type]);
324
+ if (!lastEditRender && typeof type === 'string') {
325
+ // componentMap 为内置组件命名空间,按字符串 type 动态取用,保留显式 any 索引
326
326
  TargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
327
327
  }
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) {
328
+ if (isEditable && isEditing) {
329
+ // lastEditRender 已经是处理后的值(通过 dynamicProps.component 或直接计算)
330
+ // 如果原本是函数,此时 lastEditRender 已经是执行后的 ReactNode
331
+ // 如果原本是 ReactElement,lastEditRender 就是 ReactElement
332
+ if ( /*#__PURE__*/React.isValidElement(lastEditRender)) {
333
+ TargetComponent = lastEditRender;
334
+ } else if (lastEditRender) {
335
335
  // 其他情况(可能是字符串或其他类型的 ReactNode)
336
- TargetComponent = _editRender;
336
+ TargetComponent = lastEditRender;
337
337
  }
338
338
  }
339
339
 
@@ -398,9 +398,9 @@ const RenderField = ({
398
398
  const debounceRef = useRef(null);
399
399
 
400
400
  // 使用 useCallback 创建稳定的 onChange 函数
401
- const _onChange = useCallback(async (...args) => {
401
+ const handleChange = useCallback(async (...args) => {
402
402
  const executeChange = async (...innerArgs) => {
403
- let _args = [...innerArgs];
403
+ let callArgs = [...innerArgs];
404
404
  const rowPath = [...namePath, index];
405
405
  if (!onFieldChange && !onChange) {
406
406
  if (dependencies?.length) {
@@ -409,15 +409,15 @@ const RenderField = ({
409
409
  form.validateFields(validateFieldKeys);
410
410
  }, 100);
411
411
  }
412
- return null;
412
+ return;
413
413
  }
414
414
  const row = form.getFieldValue(rowPath, true);
415
415
  const orgRow = _cloneDeep(row);
416
416
  if (onFieldChange) {
417
- _args = formatArgs(innerArgs);
418
- _args[1] = row;
419
- TargetComponent?.props?.onFieldChange && (await TargetComponent.props.onFieldChange(..._args));
420
- onFieldChange && (await onFieldChange(..._args));
417
+ callArgs = formatArgs(innerArgs);
418
+ callArgs[1] = row;
419
+ TargetComponent?.props?.onFieldChange && (await TargetComponent.props.onFieldChange(...callArgs));
420
+ onFieldChange && (await onFieldChange(...callArgs));
421
421
 
422
422
  // onFieldChange 内已通过 form.setFieldValue(子路径) 或原地改 record 更新 store;此处再整行 setFieldValue(rowPath, rowAfter) 易用滞后快照覆盖 Field 刚写入的新值(如 formType)。仅延后读表做校验与 forceUpdate,不再整行回写。
423
423
  setTimeout(() => {
@@ -442,9 +442,9 @@ const RenderField = ({
442
442
  }
443
443
  }, 0);
444
444
  } else {
445
- _args = _args.concat([row, index, form]);
446
- TargetComponent?.props?.onChange && (await TargetComponent.props.onChange(..._args));
447
- onChange && (await onChange(..._args));
445
+ callArgs = callArgs.concat([row, index, form]);
446
+ TargetComponent?.props?.onChange && (await TargetComponent.props.onChange(...callArgs));
447
+ onChange && (await onChange(...callArgs));
448
448
  const rowAfter = row;
449
449
  form.setFieldValue(rowPath, rowAfter);
450
450
  if (validateTrigger && validateTrigger.includes('onChange')) {
@@ -483,18 +483,18 @@ const RenderField = ({
483
483
  };
484
484
  }, []);
485
485
 
486
- // 使用useCallback优化_onblur函数
487
- const _onblur = useCallback(async (...args) => {
486
+ // 使用useCallback优化handleBlur函数
487
+ const handleBlur = useCallback(async (...args) => {
488
488
  if (!onBlur) {
489
- return null;
489
+ return;
490
490
  }
491
- let _args = formatArgs(...args);
491
+ let callArgs = formatArgs(...args);
492
492
  const rowPath = [...namePath, index];
493
493
  const row = form.getFieldValue(rowPath, true);
494
494
  const orgRow = _cloneDeep(row);
495
- _args[1] = row;
496
- TargetComponent?.props?.onBlur && (await TargetComponent.props.onBlur(..._args));
497
- onBlur && (await onBlur(..._args));
495
+ callArgs[1] = row;
496
+ TargetComponent?.props?.onBlur && (await TargetComponent.props.onBlur(...callArgs));
497
+ onBlur && (await onBlur(...callArgs));
498
498
  // 判断属性是否变动
499
499
  form.setFieldValue(rowPath, row);
500
500
  if (validateTrigger && validateTrigger.includes('onBlur')) {
@@ -520,15 +520,15 @@ const RenderField = ({
520
520
  let componentProps = useMemo(() => ({
521
521
  form,
522
522
  name: cellName,
523
- ..._fieldProps,
523
+ ...lastFieldProps,
524
524
  ...TargetComponent?.props,
525
525
  namePath: [...namePath, index],
526
- disabled: _disabled,
527
- onChange: _onChange,
528
- onBlur: _onblur,
526
+ disabled: lastDisabled,
527
+ onChange: handleChange,
528
+ onBlur: handleBlur,
529
529
  index,
530
530
  confirm,
531
- desensitization: _desensitization,
531
+ desensitization: lastDesensitization,
532
532
  otherProps: {
533
533
  form,
534
534
  names,
@@ -537,15 +537,15 @@ const RenderField = ({
537
537
  listName: cellName,
538
538
  // 用于下拉框去重消费,保持和formlist一致
539
539
  viewEmpty,
540
- valueType: _valueType,
540
+ valueType: lastValueType,
541
541
  isView,
542
542
  desensitizationKey: otherProps?.desensitizationKey,
543
543
  source: 'ProEditTable'
544
544
  }
545
- }), [cellName, _fieldProps, TargetComponent?.props, namePath, index, _disabled, _onChange, _onblur, confirm, _desensitization, names, originalName, viewEmpty, _valueType, isView, otherProps?.desensitizationKey]);
545
+ }), [cellName, lastFieldProps, TargetComponent?.props, namePath, index, lastDisabled, handleChange, handleBlur, confirm, lastDesensitization, names, originalName, viewEmpty, lastValueType, isView, otherProps?.desensitizationKey]);
546
546
  componentProps = _omit(componentProps, ['onFieldChange', 'namePath', 'index', ...OMIT_FORM_ITEM_AND_DOM_KEYS]);
547
547
  if (['Switch', 'SwitchCheckbox'].includes(type)) {
548
- _formItemProps.valuePropName = 'checked';
548
+ lastFormItemProps.valuePropName = 'checked';
549
549
  }
550
550
 
551
551
  // 可编辑表格默认关闭scrollFollowParent
@@ -560,9 +560,9 @@ const RenderField = ({
560
560
  const trimProps = isTrim(type, trim, proConfig); // 使用顶层调用的proConfig
561
561
 
562
562
  const transformNormalize = namesTransformProps?.normalize ?? defaultTransformProps?.normalize;
563
- const userNormalize = _formItemProps?.normalize;
563
+ const userNormalize = lastFormItemProps?.normalize;
564
564
  const transformGetValueProps = namesTransformProps?.getValueProps ?? defaultTransformProps?.getValueProps;
565
- const userGetValueProps = _formItemProps?.getValueProps;
565
+ const userGetValueProps = lastFormItemProps?.getValueProps;
566
566
  const finalNormalize = transformNormalize && userNormalize ? (value, prevValue, allValues, isDiffMode) => {
567
567
  // 用户 normalize 需要拿到组件原始值(如 DatePicker 的 dayjs)
568
568
  const userValue = userNormalize(value, prevValue, allValues, isDiffMode);
@@ -583,203 +583,205 @@ const RenderField = ({
583
583
  };
584
584
  } : userGetValueProps || transformGetValueProps;
585
585
  return {
586
- ..._formItemProps,
586
+ ...lastFormItemProps,
587
587
  ...defaultTransformProps,
588
588
  ...namesTransformProps,
589
589
  ...trimProps,
590
590
  normalize: finalNormalize,
591
591
  getValueProps: finalGetValueProps
592
592
  };
593
- }, [_formItemProps, defaultTransform, namesTransform, type, trim, proConfig]);
593
+ }, [lastFormItemProps, defaultTransform, namesTransform, type, trim, proConfig]);
594
594
 
595
595
  // rules 的 isView 过滤已移至 getFieldItem 内处理(支持 shouldUpdate 模式下的动态 isEditable)
596
596
 
597
- const _className = useMemo(() => classNames({
597
+ const cellClassName = useMemo(() => classNames({
598
598
  [className]: className
599
599
  }), [className]);
600
600
 
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];
601
+ // shouldUpdate 模式下重新获取最新行数据并重算所有响应式属性,返回最新渲染状态(不修改外层闭包)
602
+ const recalcShouldUpdateState = () => {
603
+ // 重新获取最新的行数据(shouldUpdate 触发时,通过 getFieldValue 拿到最新值)
604
+ const latestRowData = form.getFieldValue([...namePath, index]) || record || {};
605
+ const latestReactiveParams = {
606
+ form,
607
+ index,
608
+ namePath: [...namePath, index]
609
+ };
610
+ const latestRowParams = [latestRowData, latestReactiveParams];
620
611
 
621
- // ⭐ 关键修改:shouldUpdate 模式下,跳过缓存,直接重新计算所有响应式属性
622
- let latestFieldProps = fieldProps || {};
623
- if (_isFunction(fieldProps)) {
624
- latestFieldProps = fieldProps(latestRowData, latestReactiveParams);
625
- }
612
+ // ⭐ 关键修改:shouldUpdate 模式下,跳过缓存,直接重新计算所有响应式属性
613
+ let latestFieldProps = fieldProps || {};
614
+ if (_isFunction(fieldProps)) {
615
+ latestFieldProps = fieldProps(latestRowData, latestReactiveParams);
616
+ }
626
617
 
627
- // 重新计算 required(用于可能的后续逻辑)
628
- let latestRequired = required;
629
- if (_isFunction(required)) {
630
- latestRequired = required(latestRowData, latestReactiveParams);
631
- }
618
+ // 重新计算 required(用于可能的后续逻辑)
619
+ let latestRequired = required;
620
+ if (_isFunction(required)) {
621
+ latestRequired = required(latestRowData, latestReactiveParams);
622
+ }
632
623
 
633
- // 重新计算 rules(用于可能的后续逻辑)
634
- let latestRules = rules;
635
- if (_isFunction(rules)) {
636
- latestRules = rules(latestRowData, latestReactiveParams);
637
- }
624
+ // 重新计算 rules(用于可能的后续逻辑)
625
+ let latestRules = rules;
626
+ if (_isFunction(rules)) {
627
+ latestRules = rules(latestRowData, latestReactiveParams);
628
+ }
638
629
 
639
- // 同步到外层变量,用于后续构建 activeFinalFormItemProps
640
- effectiveRequired = latestRequired;
641
- effectiveRules = latestRules;
642
- effectiveFieldProps = latestFieldProps;
630
+ // 重新计算 desensitization
631
+ let latestDesensitization = desensitization || [];
632
+ if (_isFunction(desensitization)) {
633
+ latestDesensitization = desensitization(latestRowData, latestReactiveParams);
634
+ }
643
635
 
644
- // 重新计算 desensitization
645
- let latestDesensitization = desensitization || [];
646
- if (_isFunction(desensitization)) {
647
- latestDesensitization = desensitization(latestRowData, latestReactiveParams);
648
- }
636
+ // 重新计算 component
637
+ let latestComponent = component || editRender;
638
+ if (_isFunction(latestComponent)) {
639
+ latestComponent = latestComponent(latestRowData, latestReactiveParams);
640
+ }
649
641
 
650
- // 重新计算 component
651
- let latestComponent = component || editRender;
652
- if (_isFunction(latestComponent)) {
653
- latestComponent = latestComponent(latestRowData, latestReactiveParams);
654
- }
642
+ // 重新计算 isEditable(使用原始的 column.isEditable,而不是处理后的 isEditable)
643
+ let latestIsEditable = column.isEditable ?? true;
644
+ if (_isFunction(column.isEditable)) {
645
+ latestIsEditable = column.isEditable(latestRowData, latestReactiveParams);
646
+ }
655
647
 
656
- // 重新计算 isEditable(使用原始的 column.isEditable,而不是处理后的 isEditable)
657
- let latestIsEditable = column.isEditable ?? true;
658
- if (_isFunction(column.isEditable)) {
659
- latestIsEditable = column.isEditable(latestRowData, latestReactiveParams);
660
- }
648
+ // 重新计算 disabled
649
+ const latestDisabled = getDisabled({
650
+ globalControl: otherProps?.globalControl,
651
+ formDisabled: otherProps?.formDisabled,
652
+ column,
653
+ tabledDisabled: config?.disabled,
654
+ columnFieldProps: latestFieldProps,
655
+ params: latestRowParams
656
+ });
661
657
 
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
- });
658
+ // 更新 componentProps 中的所有响应式属性
659
+ // latestTargetComponent 稍后计算,此处先占位;最终会在下方合并 latestTargetComponent?.props
660
+ let latestComponentProps = {
661
+ ...componentProps,
662
+ ...latestFieldProps,
663
+ disabled: latestDisabled,
664
+ desensitization: latestDesensitization,
665
+ // shouldUpdate 模式下,确保事件包装函数不被 fieldProps 覆盖
666
+ onChange: handleChange,
667
+ onBlur: handleBlur
668
+ };
671
669
 
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
- };
670
+ // 关键修改:在 shouldUpdate 模式下,需要重新设置 TargetComponent
671
+ // 因为 component 函数可能返回不同的结果
672
+ let latestTargetComponent = TargetComponent;
683
673
 
684
- // ⭐ 关键修改:在 shouldUpdate 模式下,需要重新设置 TargetComponent
685
- // 因为 component 函数可能返回不同的结果
686
- let latestTargetComponent = TargetComponent;
674
+ // 首先检查是否有内置type
675
+ if (!latestComponent && typeof type === 'string') {
676
+ latestTargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
677
+ }
687
678
 
688
- // 首先检查是否有内置type
689
- if (!latestComponent && typeof type === 'string') {
690
- latestTargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
679
+ // 然后处理自定义 component
680
+ const latestIsView = !latestIsEditable || record?.['is-view'] || config.isView || virtualKey && !isEditing || getDisabled({
681
+ globalControl: otherProps?.globalControl,
682
+ formDisabled: otherProps?.formDisabled,
683
+ column,
684
+ tabledDisabled: config?.disabled,
685
+ columnFieldProps: latestFieldProps,
686
+ params: latestRowParams,
687
+ rowDisabled: rowDisabled || 'empty'
688
+ });
689
+ if (latestIsEditable && isEditing) {
690
+ if ( /*#__PURE__*/React.isValidElement(latestComponent)) {
691
+ latestTargetComponent = latestComponent;
692
+ } else if (latestComponent) {
693
+ latestTargetComponent = latestComponent;
691
694
  }
695
+ }
692
696
 
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
- }
697
+ // 查看模式
698
+ if (latestIsView) {
699
+ if (typeof viewRender === 'function') {
700
+ const latestCurrentValue = dataIndex ? latestRowData?.[dataIndex] : null;
701
+ const View = viewRender(latestCurrentValue, latestRowData || {}, options);
702
+ latestTargetComponent = /*#__PURE__*/_jsx(Container, {
703
+ viewEmpty: viewEmpty,
704
+ children: View
705
+ });
709
706
  }
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
- }
707
+ if ( /*#__PURE__*/React.isValidElement(viewRender)) {
708
+ latestTargetComponent = viewRender;
724
709
  }
710
+ }
725
711
 
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
- };
712
+ // shouldUpdate 触发时外层 componentProps.otherProps.isView 是旧快照,需用最新值覆盖
713
+ latestComponentProps = {
714
+ ...latestComponentProps,
715
+ otherProps: {
716
+ ...latestComponentProps.otherProps,
717
+ isView: latestIsView
718
+ }
719
+ };
737
720
 
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
- }
721
+ // componentProps 里展开了外层旧 TargetComponent?.props(如 { formType: "Input" }),
722
+ // 用 latestTargetComponent?.props 覆盖,确保不会被旧 cloneElement props 污染
723
+ if ( /*#__PURE__*/React.isValidElement(latestTargetComponent)) {
724
+ const elementProps = latestTargetComponent.props;
725
+ // 确保 props 是对象类型才进行展开
726
+ if (elementProps && typeof elementProps === 'object') {
727
+ latestComponentProps = {
728
+ ...latestComponentProps,
729
+ ...elementProps,
730
+ // 始终保证事件处理函数不被覆盖
731
+ onChange: handleChange,
732
+ onBlur: handleBlur
733
+ };
752
734
  }
753
735
  }
736
+ return {
737
+ finalComponentProps: latestComponentProps,
738
+ targetComponent: latestTargetComponent,
739
+ latestIsView,
740
+ effectiveRequired: latestRequired,
741
+ effectiveRules: latestRules,
742
+ effectiveFieldProps: latestFieldProps
743
+ };
744
+ };
754
745
 
755
- // 根据 latestIsView 和最新的 required/rules 构建正确的 Form.Item props
756
- // 解决 shouldUpdate 触发时外层 finalFormItemProps 是旧闭包(rules 基于旧 isView 计算)的问题
757
- let activeFinalFormItemProps = finalFormItemProps;
746
+ // 根据 latestIsView 和最新 required/rules 构建正确的 Form.Item props
747
+ // 解决 shouldUpdate 触发时外层 finalFormItemProps 是旧闭包(rules 基于旧 isView 计算)的问题
748
+ const buildActiveFormItemProps = ({
749
+ latestIsView,
750
+ shouldUpdateMode,
751
+ effectiveRequired,
752
+ effectiveRules,
753
+ effectiveFieldProps
754
+ }) => {
758
755
  if (latestIsView) {
759
756
  // 查看模式:移除 rules 不做校验
760
- activeFinalFormItemProps = _omit(finalFormItemProps, ['rules']);
761
- } else if (shouldUpdateMode) {
757
+ return _omit(finalFormItemProps, ['rules']);
758
+ }
759
+ if (shouldUpdateMode) {
762
760
  // shouldUpdate 模式下 finalFormItemProps 是旧闭包,需用最新 effectiveRequired/effectiveRules 重建 rules
763
761
  const activeRules = Array.isArray(effectiveRules) ? [...effectiveRules] : [];
764
762
  const hasRequiredRule = activeRules.some(r => r?.required === true);
765
763
  if (effectiveRequired && !hasRequiredRule) {
766
- const _isSelectVal = isSelect({
764
+ const isSelectVal = isSelect({
767
765
  dataSource: effectiveFieldProps?.dataSource,
768
766
  type
769
767
  });
770
768
  activeRules.push({
771
769
  required: true,
772
- message: `${_isSelectVal ? locale.ProForm.selectPlaceHolder : locale.ProForm.inputPlaceholder}${label || ''}`
770
+ message: `${isSelectVal ? locale.ProForm.selectPlaceHolder : locale.ProForm.inputPlaceholder}${label || ''}`
773
771
  });
774
772
  }
775
- activeFinalFormItemProps = {
773
+ return {
776
774
  ...finalFormItemProps,
777
775
  rules: activeRules.length > 0 ? activeRules : [{
778
776
  required: false
779
777
  }]
780
778
  };
781
779
  }
782
- let FormItem = null;
780
+ return finalFormItemProps;
781
+ };
782
+
783
+ // 组装字段组件:DOM 透传字段过滤、克隆/创建目标元素、原始值对比包裹(ListChangedWrapper)、确认弹窗包裹(ConfirmWrapper)
784
+ const assembleFieldComponent = finalComponentProps => {
783
785
  // 当 viewRender 存在时,需要排除 finalComponentProps 中的 children,避免覆盖 Container 的 children
784
786
  let propsForTarget = isView && typeof viewRender === 'function' ? _omit(finalComponentProps, ['children']) : finalComponentProps;
785
787
  // 当目标为原生 DOM 元素(如 viewRender 返回 <div>)时,剔除 disabled、toCSTString 等,避免 React 警告
@@ -810,8 +812,8 @@ const RenderField = ({
810
812
  form: form,
811
813
  onDiff: onDiff,
812
814
  type: type,
813
- onChange: _onChange,
814
- onBlur: _onblur,
815
+ onChange: handleChange,
816
+ onBlur: handleBlur,
815
817
  valuePropName: finalFormItemProps.valuePropName,
816
818
  normalize: finalFormItemProps.normalize,
817
819
  getValueProps: finalFormItemProps.getValueProps,
@@ -827,11 +829,42 @@ const RenderField = ({
827
829
  children: FieldComponent
828
830
  });
829
831
  }
830
- FormItem = TargetComponent ? /*#__PURE__*/_jsx(Form.Item, {
832
+ return FieldComponent;
833
+ };
834
+
835
+ // 使用useCallback优化getFieldItem函数
836
+ const getFieldItem = (shouldUpdateMode = false) => {
837
+ // 如果处于 shouldUpdate 模式,需要重新获取最新的行数据并重新计算依赖值
838
+ let finalComponentProps = componentProps;
839
+ // shouldUpdate 模式下会被更新为最新值,供外层 FieldProvider 消费
840
+ let latestIsView = isView;
841
+ // 用于在 shouldUpdate 模式下重建正确的 Form.Item rules(外层 finalFormItemProps 是旧闭包)
842
+ let effectiveRequired = lastRequired;
843
+ let effectiveRules = lastRules;
844
+ let effectiveFieldProps = lastFieldProps;
845
+ if (shouldUpdateMode) {
846
+ const recomputed = recalcShouldUpdateState();
847
+ finalComponentProps = recomputed.finalComponentProps;
848
+ // shouldUpdate 模式下用重算结果覆盖外层 TargetComponent,供下方组装逻辑消费
849
+ TargetComponent = recomputed.targetComponent;
850
+ latestIsView = recomputed.latestIsView;
851
+ effectiveRequired = recomputed.effectiveRequired;
852
+ effectiveRules = recomputed.effectiveRules;
853
+ effectiveFieldProps = recomputed.effectiveFieldProps;
854
+ }
855
+ const activeFinalFormItemProps = buildActiveFormItemProps({
856
+ latestIsView,
857
+ shouldUpdateMode,
858
+ effectiveRequired,
859
+ effectiveRules,
860
+ effectiveFieldProps
861
+ });
862
+ const FieldComponent = assembleFieldComponent(finalComponentProps);
863
+ let FormItem = TargetComponent ? /*#__PURE__*/_jsx(Form.Item, {
831
864
  validateFirst: true,
832
- ..._omit(activeFinalFormItemProps, ['render', 'key', 'width', 'hiddenNames', 'name', 'onCell', 'disabled', _formItemProps.shouldUpdate ? 'shouldUpdate' : null]),
865
+ ..._omit(activeFinalFormItemProps, ['render', 'key', 'width', 'hiddenNames', 'name', 'onCell', 'disabled', lastFormItemProps.shouldUpdate ? 'shouldUpdate' : null]),
833
866
  // 移除非必要字段,但保留 dependencies
834
- className: _className,
867
+ className: cellClassName,
835
868
  name: formNamePath ? cellName.slice(formNamePath?.length - 1) : cellName,
836
869
  children: FieldComponent
837
870
  }) : /*#__PURE__*/_jsx(Container, {
@@ -875,132 +908,4 @@ const RenderField = ({
875
908
  })
876
909
  });
877
910
  };
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
- });
911
+ export default /*#__PURE__*/memo(RenderField, arePropsEqual);