@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.
- package/README.md +1 -42
- package/es/ProEditTable/components/RenderField/ListChangedWrapper.d.ts +1 -14
- package/es/ProEditTable/components/RenderField/ListChangedWrapper.js +27 -102
- package/es/ProEditTable/components/RenderField/index.js +313 -366
- package/es/ProEditTable/components/RenderField/propsType.d.ts +30 -0
- package/es/ProEditTable/components/RenderField/propsType.js +1 -0
- package/es/ProEditTable/components/RenderField/tools.d.ts +22 -0
- package/es/ProEditTable/components/RenderField/tools.js +203 -0
- package/es/ProEditTable/components/Validator/index.d.ts +9 -0
- package/es/ProEditTable/components/Validator/index.js +56 -6
- package/es/ProEditTable/index.js +16 -2
- package/es/ProEditTable/utils/config.d.ts +1 -1
- package/es/ProEditTable/utils/config.js +18 -7
- package/es/ProEditTable/utils/tools.d.ts +30 -1
- package/es/ProEditTable/utils/tools.js +95 -12
- package/es/ProEditTable/utils/validateAll.d.ts +86 -0
- package/es/ProEditTable/utils/validateAll.js +319 -0
- package/es/ProForm/components/combination/Group/utils/index.d.ts +25 -25
- package/es/ProTree/components/ProTreeSelect/index.js +3 -2
- package/es/ProTree/utils.d.ts +9 -0
- package/es/ProTree/utils.js +31 -0
- package/package.json +1 -2
|
@@ -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
|
|
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
|
|
84
|
-
let
|
|
85
|
-
let
|
|
86
|
-
let
|
|
87
|
-
let
|
|
88
|
-
let
|
|
89
|
-
let
|
|
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
|
-
|
|
132
|
+
lastRequired = dynamicProps.required ?? required(rowData, reactiveParams);
|
|
134
133
|
}
|
|
135
134
|
if (_isFunction(fieldProps)) {
|
|
136
|
-
|
|
135
|
+
lastFieldProps = dynamicProps.fieldProps ?? fieldProps(rowData, reactiveParams);
|
|
137
136
|
}
|
|
138
137
|
if (_isFunction(rules)) {
|
|
139
|
-
|
|
138
|
+
lastRules = dynamicProps.rules ?? rules(rowData, reactiveParams);
|
|
140
139
|
}
|
|
141
140
|
if (_isFunction(valueType)) {
|
|
142
|
-
|
|
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
|
-
|
|
149
|
+
lastDesensitization = dynamicProps.desensitization ?? desensitization(rowData, reactiveParams);
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
// 获取最终的disabled
|
|
154
|
-
|
|
153
|
+
lastDisabled = getDisabled({
|
|
155
154
|
globalControl: otherProps?.globalControl,
|
|
156
155
|
formDisabled: otherProps?.formDisabled,
|
|
157
156
|
column,
|
|
158
157
|
tabledDisabled: config?.disabled,
|
|
159
|
-
columnFieldProps:
|
|
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(
|
|
170
|
-
|
|
168
|
+
if (_isFunction(lastComponent)) {
|
|
169
|
+
lastComponent = dynamicProps.component ?? lastComponent(rowData, reactiveParams);
|
|
171
170
|
}
|
|
172
171
|
|
|
173
|
-
// 更新
|
|
174
|
-
const
|
|
172
|
+
// 更新 lastEditRender 为处理后的 lastComponent
|
|
173
|
+
const lastEditRender = lastComponent;
|
|
175
174
|
|
|
176
175
|
// 是否只读文本
|
|
177
|
-
const isView = !isEditable || record?.['is-view'] || config.isView || virtualKey && !
|
|
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:
|
|
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:
|
|
200
|
-
rules:
|
|
200
|
+
required: lastRequired,
|
|
201
|
+
rules: lastRules,
|
|
201
202
|
isSelect: isSelect({
|
|
202
|
-
dataSource:
|
|
203
|
+
dataSource: lastFieldProps?.dataSource,
|
|
203
204
|
type
|
|
204
205
|
}),
|
|
205
206
|
type
|
|
206
207
|
});
|
|
207
208
|
|
|
208
|
-
// 分离form item参数,防止对于参数透传(如onChange,防止重复触发)并优先级高于
|
|
209
|
+
// 分离form item参数,防止对于参数透传(如onChange,防止重复触发)并优先级高于 lastFieldProps 内部参数
|
|
209
210
|
const formItemChildProps = {
|
|
210
|
-
...
|
|
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
|
|
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,而不是处理后的
|
|
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
|
-
|
|
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
|
-
|
|
263
|
-
|
|
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 (!
|
|
273
|
-
return transformMap?.[type]?.(
|
|
273
|
+
if (!lastValueType && types.includes(type)) {
|
|
274
|
+
return transformMap?.[type]?.(lastFieldProps || {});
|
|
274
275
|
}
|
|
275
276
|
return {};
|
|
276
|
-
}, [
|
|
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
|
-
|
|
286
|
+
lastValueType = 'switch';
|
|
286
287
|
}
|
|
287
288
|
const params = {
|
|
288
289
|
...column,
|
|
289
|
-
mode:
|
|
290
|
+
mode: lastFieldProps?.mode
|
|
290
291
|
};
|
|
291
|
-
|
|
292
|
-
|
|
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
|
-
...
|
|
323
|
+
...lastFormItemProps,
|
|
322
324
|
...valueTypeTransform()
|
|
323
325
|
}, form, names, namesStr, type);
|
|
324
|
-
}, [names, baseName, index, dataIndex,
|
|
325
|
-
if (!
|
|
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 &&
|
|
329
|
-
//
|
|
330
|
-
// 如果原本是函数,此时
|
|
331
|
-
// 如果原本是 ReactElement,
|
|
332
|
-
if ( /*#__PURE__*/React.isValidElement(
|
|
333
|
-
TargetComponent =
|
|
334
|
-
} else if (
|
|
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 =
|
|
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
|
|
404
|
+
const handleChange = useCallback(async (...args) => {
|
|
402
405
|
const executeChange = async (...innerArgs) => {
|
|
403
|
-
|
|
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
|
|
419
|
+
return;
|
|
413
420
|
}
|
|
414
421
|
const row = form.getFieldValue(rowPath, true);
|
|
415
422
|
const orgRow = _cloneDeep(row);
|
|
416
423
|
if (onFieldChange) {
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
TargetComponent?.props?.onFieldChange && (await TargetComponent.props.onFieldChange(...
|
|
420
|
-
onFieldChange && (await onFieldChange(...
|
|
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
|
|
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
|
-
|
|
446
|
-
TargetComponent?.props?.onChange && (await TargetComponent.props.onChange(...
|
|
447
|
-
onChange && (await onChange(...
|
|
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
|
|
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
|
-
//
|
|
487
|
-
|
|
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
|
|
531
|
+
return;
|
|
490
532
|
}
|
|
491
|
-
let
|
|
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
|
-
|
|
496
|
-
TargetComponent?.props?.onBlur && (await TargetComponent.props.onBlur(...
|
|
497
|
-
onBlur && (await onBlur(...
|
|
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
|
-
...
|
|
565
|
+
...lastFieldProps,
|
|
524
566
|
...TargetComponent?.props,
|
|
525
567
|
namePath: [...namePath, index],
|
|
526
|
-
disabled:
|
|
527
|
-
onChange:
|
|
528
|
-
onBlur:
|
|
568
|
+
disabled: lastDisabled,
|
|
569
|
+
onChange: handleChange,
|
|
570
|
+
onBlur: handleBlur,
|
|
529
571
|
index,
|
|
530
572
|
confirm,
|
|
531
|
-
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:
|
|
582
|
+
valueType: lastValueType,
|
|
541
583
|
isView,
|
|
542
584
|
desensitizationKey: otherProps?.desensitizationKey,
|
|
543
585
|
source: 'ProEditTable'
|
|
544
586
|
}
|
|
545
|
-
}), [cellName,
|
|
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
|
-
|
|
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 =
|
|
605
|
+
const userNormalize = lastFormItemProps?.normalize;
|
|
564
606
|
const transformGetValueProps = namesTransformProps?.getValueProps ?? defaultTransformProps?.getValueProps;
|
|
565
|
-
const userGetValueProps =
|
|
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
|
-
...
|
|
628
|
+
...lastFormItemProps,
|
|
587
629
|
...defaultTransformProps,
|
|
588
630
|
...namesTransformProps,
|
|
589
631
|
...trimProps,
|
|
590
632
|
normalize: finalNormalize,
|
|
591
633
|
getValueProps: finalGetValueProps
|
|
592
634
|
};
|
|
593
|
-
}, [
|
|
635
|
+
}, [lastFormItemProps, defaultTransform, namesTransform, type, trim, proConfig]);
|
|
594
636
|
|
|
595
637
|
// rules 的 isView 过滤已移至 getFieldItem 内处理(支持 shouldUpdate 模式下的动态 isEditable)
|
|
596
638
|
|
|
597
|
-
const
|
|
639
|
+
const cellClassName = useMemo(() => classNames({
|
|
598
640
|
[className]: className
|
|
599
641
|
}), [className]);
|
|
600
642
|
|
|
601
|
-
//
|
|
602
|
-
const
|
|
603
|
-
//
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
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
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
654
|
+
// ⭐ 关键修改:shouldUpdate 模式下,跳过缓存,直接重新计算所有响应式属性
|
|
655
|
+
let latestFieldProps = fieldProps || {};
|
|
656
|
+
if (_isFunction(fieldProps)) {
|
|
657
|
+
latestFieldProps = fieldProps(latestRowData, latestReactiveParams);
|
|
658
|
+
}
|
|
626
659
|
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
660
|
+
// 重新计算 required(用于可能的后续逻辑)
|
|
661
|
+
let latestRequired = required;
|
|
662
|
+
if (_isFunction(required)) {
|
|
663
|
+
latestRequired = required(latestRowData, latestReactiveParams);
|
|
664
|
+
}
|
|
632
665
|
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
666
|
+
// 重新计算 rules(用于可能的后续逻辑)
|
|
667
|
+
let latestRules = rules;
|
|
668
|
+
if (_isFunction(rules)) {
|
|
669
|
+
latestRules = rules(latestRowData, latestReactiveParams);
|
|
670
|
+
}
|
|
638
671
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
672
|
+
// 重新计算 desensitization
|
|
673
|
+
let latestDesensitization = desensitization || [];
|
|
674
|
+
if (_isFunction(desensitization)) {
|
|
675
|
+
latestDesensitization = desensitization(latestRowData, latestReactiveParams);
|
|
676
|
+
}
|
|
643
677
|
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
678
|
+
// 重新计算 component
|
|
679
|
+
let latestComponent = component || editRender;
|
|
680
|
+
if (_isFunction(latestComponent)) {
|
|
681
|
+
latestComponent = latestComponent(latestRowData, latestReactiveParams);
|
|
682
|
+
}
|
|
649
683
|
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
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
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
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
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
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
|
-
|
|
673
|
-
|
|
674
|
-
|
|
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
|
-
|
|
685
|
-
|
|
686
|
-
|
|
716
|
+
// 首先检查是否有内置type
|
|
717
|
+
if (!latestComponent && typeof type === 'string') {
|
|
718
|
+
latestTargetComponent = componentMap[type] ?? /*#__PURE__*/_jsx(_Fragment, {});
|
|
719
|
+
}
|
|
687
720
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
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
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
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
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
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
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
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
|
-
|
|
756
|
-
|
|
757
|
-
|
|
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
|
-
|
|
761
|
-
}
|
|
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
|
|
806
|
+
const isSelectVal = isSelect({
|
|
767
807
|
dataSource: effectiveFieldProps?.dataSource,
|
|
768
808
|
type
|
|
769
809
|
});
|
|
770
810
|
activeRules.push({
|
|
771
811
|
required: true,
|
|
772
|
-
message: `${
|
|
812
|
+
message: `${isSelectVal ? locale.ProForm.selectPlaceHolder : locale.ProForm.inputPlaceholder}${label || ''}`
|
|
773
813
|
});
|
|
774
814
|
}
|
|
775
|
-
|
|
815
|
+
return {
|
|
776
816
|
...finalFormItemProps,
|
|
777
817
|
rules: activeRules.length > 0 ? activeRules : [{
|
|
778
818
|
required: false
|
|
779
819
|
}]
|
|
780
820
|
};
|
|
781
821
|
}
|
|
782
|
-
|
|
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:
|
|
814
|
-
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
|
-
|
|
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',
|
|
907
|
+
..._omit(activeFinalFormItemProps, ['render', 'key', 'width', 'hiddenNames', 'name', 'onCell', 'disabled', lastFormItemProps.shouldUpdate ? 'shouldUpdate' : null]),
|
|
833
908
|
// 移除非必要字段,但保留 dependencies
|
|
834
|
-
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,
|
|
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);
|