lu-lowcode-package-form 0.11.50 → 0.11.53
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/dist/index.cjs.js +184 -184
- package/dist/index.es.js +13142 -13130
- package/package.json +1 -1
- package/src/App.jsx +1 -1
- package/src/components/field/select/search-select.jsx +2 -7
- package/src/components/form-container/index.jsx +94 -80
package/package.json
CHANGED
package/src/App.jsx
CHANGED
@@ -575,7 +575,7 @@ function App() {
|
|
575
575
|
code: 0, data: {
|
576
576
|
list:
|
577
577
|
[
|
578
|
-
{ label: '选项1', value: '1', table_fill: [{ fill_shuilv:0.13, fill_tianchong1: { label: '选项1', value: '1' }, fill_tianchong2: { label: '选项2', value: '2' } }] },
|
578
|
+
{ label: '选项1', value: '1', table_fill: [{ fill_shuilv:0.13, fill_tianchong1: { label: '选项1', value: '1' }, fill_tianchong2: { label: '选项2', value: '2' } },{ fill_shuilv:0.13, fill_tianchong1: { label: '选项1', value: '1' }, fill_tianchong2: { label: '选项2', value: '2' } }] },
|
579
579
|
{ label: '选项2', value: '2' },
|
580
580
|
{ label: '选项3', value: '3' }
|
581
581
|
]
|
@@ -79,18 +79,16 @@ const SearchSelect = forwardRef(({ addWrapper = true, form, fieldName, fieldsVal
|
|
79
79
|
// console.log("callback loadValue", loadValue)
|
80
80
|
// let item = selectOptions.find(item => item.value == loadValue?.value || item.value == loadValue);
|
81
81
|
// if (item && !isEqual(item, loadValue)) {
|
82
|
-
// console.log(`[${props?.label}]debounceFetchOptions new value /////`, item);
|
83
82
|
// typeof onChange === 'function' && onChange(item);
|
84
83
|
// }
|
85
84
|
// }
|
86
85
|
// });
|
87
86
|
debounceFetchOptions({ ...requestParams, [option_value]: loadValue?.value }, null, (selectOptions) => {
|
88
87
|
if (selectOptions && selectOptions.length > 0) {
|
89
|
-
console.log(`[${props?.label}]callback selectOptions`, selectOptions)
|
90
|
-
console.log(`[${props?.label}]callback loadValue`, loadValue)
|
88
|
+
// console.log(`[${props?.label}]callback selectOptions`, selectOptions)
|
89
|
+
// console.log(`[${props?.label}]callback loadValue`, loadValue)
|
91
90
|
let item = selectOptions.find(item => item.value == loadValue?.value || item.value == loadValue);
|
92
91
|
if (item && !isEqual(item, loadValue)) {
|
93
|
-
console.log(`[${props?.label}]debounceFetchOptions new value /////`, item);
|
94
92
|
typeof onChange === 'function' && onChange(item);
|
95
93
|
}
|
96
94
|
}
|
@@ -124,11 +122,8 @@ const SearchSelect = forwardRef(({ addWrapper = true, form, fieldName, fieldsVal
|
|
124
122
|
if (debounceFetchOptionsRef.current) clearTimeout(debounceFetchOptionsRef.current);
|
125
123
|
debounceFetchOptionsRef.current = setTimeout(() => {
|
126
124
|
const callbacks = callbackQueue.current;
|
127
|
-
console.log(`[${props?.label}]debounceFetchOptions callbackQueue`, JSON.parse(JSON.stringify(callbacks)));
|
128
125
|
callbackQueue.current = [];
|
129
126
|
fetchOptions(params, ruleParams, fieldName).then(result => {
|
130
|
-
console.log(`[${props?.label}]debounceFetchOptions result`, result);
|
131
|
-
console.log(`[${props?.label}]debounceFetchOptions callbacks`, callbacks);
|
132
127
|
while (callbacks.length > 0) {
|
133
128
|
const callback = callbacks.shift();
|
134
129
|
if (typeof callback === 'function') {
|
@@ -8,7 +8,7 @@ import { nanoid } from 'nanoid';
|
|
8
8
|
import { eventEmitter } from '../../utils/events'
|
9
9
|
|
10
10
|
|
11
|
-
function batchElements(elements, groupSize,dmap) {
|
11
|
+
function batchElements(elements, groupSize, dmap) {
|
12
12
|
const groupedElements = [];
|
13
13
|
let tempArray = [];
|
14
14
|
|
@@ -61,7 +61,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
61
61
|
if (!isEqual(formContentRef.current, newFormContent)) {
|
62
62
|
formContentRef.current = newFormContent;
|
63
63
|
setFormContent(newFormContent);
|
64
|
-
|
64
|
+
}
|
65
65
|
}
|
66
66
|
// 调用setFieldsValue时,进入锁定状态,阻止因字段值变化而触发级联处理
|
67
67
|
const lockStatus = React.useRef(0);
|
@@ -73,32 +73,42 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
73
73
|
currentCycleId: 0,
|
74
74
|
// 当前更新周期的依赖路径
|
75
75
|
updatePath: [],
|
76
|
+
// 最大更新深度限制,避免过深的嵌套引起栈溢出
|
77
|
+
MAX_DEPTH: 30,
|
76
78
|
// 开始新的更新周期
|
77
|
-
startNewCycle: function() {
|
79
|
+
startNewCycle: function () {
|
78
80
|
this.currentCycleId++;
|
79
81
|
this.updatePath = [];
|
80
82
|
return this.currentCycleId;
|
81
83
|
},
|
82
84
|
// 添加依赖路径
|
83
|
-
addToPath: function(fieldId) {
|
84
|
-
|
85
|
+
addToPath: function (fieldId) {
|
86
|
+
// 限制依赖路径深度,防止栈溢出
|
87
|
+
if (this.updatePath.length >= this.MAX_DEPTH) {
|
88
|
+
console.warn(`依赖路径深度超过限制(${this.MAX_DEPTH}),可能存在过深嵌套`);
|
89
|
+
return;
|
90
|
+
}
|
91
|
+
if (fieldId) {
|
92
|
+
this.updatePath.push(fieldId);
|
93
|
+
}
|
85
94
|
},
|
86
95
|
// 检查是否形成循环
|
87
|
-
hasCircularDependency: function(targetFieldId) {
|
96
|
+
hasCircularDependency: function (targetFieldId) {
|
97
|
+
if (!targetFieldId) return false;
|
88
98
|
return this.updatePath.includes(targetFieldId);
|
89
99
|
},
|
90
100
|
// 获取当前依赖路径
|
91
|
-
getCurrentPath: function() {
|
101
|
+
getCurrentPath: function () {
|
92
102
|
return [...this.updatePath];
|
93
103
|
},
|
94
104
|
// 结束当前字段的处理
|
95
|
-
finishField: function() {
|
105
|
+
finishField: function () {
|
96
106
|
if (this.updatePath.length > 0) {
|
97
107
|
this.updatePath.pop();
|
98
108
|
}
|
99
109
|
}
|
100
110
|
});
|
101
|
-
|
111
|
+
|
102
112
|
React.useImperativeHandle(ref, () => ({
|
103
113
|
formRef: form,
|
104
114
|
setFieldsValue: (values) => {
|
@@ -164,7 +174,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
164
174
|
// return current;
|
165
175
|
}
|
166
176
|
const initializeDependencyMap = async () => {
|
167
|
-
|
177
|
+
|
168
178
|
const fields = [];
|
169
179
|
function traverse(currentNode, parentNode = null) {
|
170
180
|
var componentName = currentNode.type?.displayName || currentNode.props?._componentName;
|
@@ -212,10 +222,10 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
212
222
|
};
|
213
223
|
const initializeFieldVisibilityImmediate = async (reloadFields = false) => {
|
214
224
|
console.log("initializeFieldVisibility *************************************")
|
215
|
-
|
216
|
-
|
225
|
+
|
226
|
+
|
217
227
|
const fieldValues = form.getFieldsValue();
|
218
|
-
|
228
|
+
|
219
229
|
await Promise.all(Array.from(dependencyMap.current.keys()).map(async (key) => {
|
220
230
|
await handleFieldsWith(key, fieldValues, true);
|
221
231
|
}))
|
@@ -226,34 +236,37 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
226
236
|
};
|
227
237
|
// 初始化字段的级联关系
|
228
238
|
const initializeFieldVisibility = debounce(async (reloadFields = false) => {
|
229
|
-
console.log("initializeFieldVisibility begin",reloadFields)
|
230
239
|
await initializeFieldVisibilityImmediate(reloadFields);
|
231
240
|
}, 100);
|
232
241
|
|
233
242
|
|
234
243
|
// 计算字段级联关系
|
235
244
|
const handleFieldsWith = async (identifier, fieldValues, init = false, fieldId = null) => {
|
245
|
+
if (mode == "desgin") {
|
246
|
+
console.log("设计模式下不进行字段级联计算")
|
247
|
+
return false
|
248
|
+
}
|
236
249
|
// console.log("handleFieldsWith identifier", identifier)
|
237
250
|
let needRefresh = false;
|
238
251
|
let parentIdentifier = [];
|
239
252
|
if (Array.isArray(identifier)) {
|
240
253
|
parentIdentifier = [...(identifier.slice(0, -1))]
|
241
254
|
identifier = identifier.filter(item => typeof item == "string").join(".")
|
255
|
+
|
242
256
|
}
|
243
|
-
|
257
|
+
|
244
258
|
// 将标识符标准化为字符串,用于依赖图谱
|
245
259
|
const currentFieldId = fieldId || identifier;
|
246
|
-
|
247
260
|
// 检查是否在当前更新链路中已存在,避免循环依赖
|
248
261
|
if (dependencyGraphRef.current.hasCircularDependency(currentFieldId)) {
|
249
262
|
const currentPath = dependencyGraphRef.current.getCurrentPath();
|
250
263
|
console.log(`检测到循环依赖链路: ${[...currentPath, currentFieldId].join(' -> ')}`);
|
251
264
|
return false;
|
252
265
|
}
|
253
|
-
|
266
|
+
|
254
267
|
// 将当前字段添加到依赖路径
|
255
268
|
dependencyGraphRef.current.addToPath(currentFieldId);
|
256
|
-
|
269
|
+
|
257
270
|
try {
|
258
271
|
if (dependencyMap.current.has(identifier)) {
|
259
272
|
const dependent = dependencyMap.current.get(identifier)
|
@@ -285,7 +298,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
285
298
|
// 在处理完毕后,从依赖路径中移除当前字段
|
286
299
|
dependencyGraphRef.current.finishField();
|
287
300
|
}
|
288
|
-
|
301
|
+
|
289
302
|
return needRefresh;
|
290
303
|
};
|
291
304
|
const removeLastFieldsValues = (name, isTable = false) => {
|
@@ -309,12 +322,12 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
309
322
|
changedFieldsState.current[fieldName] = fieldValue;
|
310
323
|
}
|
311
324
|
const recordFieldsChange = (changedFields, handleChange = false) => {
|
312
|
-
console.log("recordFieldsChange", changedFields,handleChange)
|
325
|
+
console.log("recordFieldsChange", changedFields, handleChange)
|
313
326
|
var changedKeys = Object.keys(changedFields)
|
314
327
|
if (changedKeys.length > 0) {
|
315
328
|
changedKeys.forEach(key => {
|
316
329
|
recordFieldChange(key, changedFields[key])
|
317
|
-
|
330
|
+
|
318
331
|
})
|
319
332
|
if (handleChange) debounceHandleFieldsChange();
|
320
333
|
}
|
@@ -327,7 +340,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
327
340
|
let changedFields = {}
|
328
341
|
|
329
342
|
// 将标识符标准化为字符串
|
330
|
-
const sourceFieldId = Array.isArray(current_identifier)
|
343
|
+
const sourceFieldId = Array.isArray(current_identifier)
|
331
344
|
? current_identifier.filter(item => typeof item == "string").join(".")
|
332
345
|
: current_identifier;
|
333
346
|
|
@@ -337,29 +350,29 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
337
350
|
let { source, target } = rule
|
338
351
|
let source_value = current_value?.[source]
|
339
352
|
let setValue = source_value
|
340
|
-
|
353
|
+
|
341
354
|
// 将sourceField格式化为字符串形式,用于依赖跟踪
|
342
|
-
const sourceField = Array.isArray(current_identifier)
|
355
|
+
const sourceField = Array.isArray(current_identifier)
|
343
356
|
? current_identifier.filter(item => typeof item == "string").join(".")
|
344
357
|
: current_identifier;
|
345
|
-
|
358
|
+
|
346
359
|
// 格式化目标字段
|
347
|
-
const targetField = Array.isArray(target)
|
360
|
+
const targetField = Array.isArray(target)
|
348
361
|
? target.filter(item => typeof item == "string").join(".")
|
349
362
|
: target;
|
350
|
-
|
363
|
+
|
351
364
|
// // 检查循环依赖 - 使用更高级的依赖图检测
|
352
365
|
// if (dependencyGraphRef.current.hasCircularDependency(targetField)) {
|
353
366
|
// const currentPath = dependencyGraphRef.current.getCurrentPath();
|
354
367
|
// console.log(`检测到填充规则中的循环依赖链路: ${[...currentPath, targetField].join(' -> ')}`);
|
355
368
|
// continue; // 跳过这条规则
|
356
369
|
// }
|
357
|
-
|
358
|
-
|
370
|
+
|
371
|
+
|
359
372
|
//// 添加到依赖路径
|
360
373
|
// dependencyGraphRef.current.addToPath(targetField);
|
361
|
-
|
362
|
-
|
374
|
+
|
375
|
+
|
363
376
|
// 子表
|
364
377
|
if (rule?.type == 1) {
|
365
378
|
if (dependencyMap.current.has(target)) {
|
@@ -409,7 +422,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
409
422
|
form.setFieldValue(target, undefined);
|
410
423
|
}
|
411
424
|
form.setFieldValue(target, setValue)
|
412
|
-
|
425
|
+
|
413
426
|
// 处理完当前字段后从依赖路径中移除
|
414
427
|
// dependencyGraphRef.current.finishField();
|
415
428
|
}
|
@@ -560,25 +573,25 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
560
573
|
for (let index = 0; index < table_values.length; index++) {
|
561
574
|
await handleFieldsWithFill(fieldValues, child, [childIdentifier[0], index], componentName, sourceFieldId)
|
562
575
|
}
|
563
|
-
|
576
|
+
|
564
577
|
return
|
565
578
|
}
|
566
|
-
|
579
|
+
|
567
580
|
// 将目标字段ID标准化为字符串
|
568
|
-
const targetFieldId = Array.isArray(childIdentifier)
|
569
|
-
? childIdentifier.
|
581
|
+
const targetFieldId = Array.isArray(childIdentifier)
|
582
|
+
? childIdentifier.join(".")
|
570
583
|
: childIdentifier;
|
571
|
-
|
584
|
+
|
572
585
|
// 检查是否在当前依赖链中已存在,避免循环依赖
|
573
586
|
if (dependencyGraphRef.current.hasCircularDependency(targetFieldId)) {
|
574
587
|
const currentPath = dependencyGraphRef.current.getCurrentPath();
|
575
588
|
console.log(`检测到公式计算中的循环依赖链路: ${[...currentPath, targetFieldId].join(' -> ')}`);
|
576
589
|
return;
|
577
590
|
}
|
578
|
-
|
591
|
+
|
579
592
|
// // 将当前字段添加到依赖路径
|
580
593
|
// dependencyGraphRef.current.addToPath(targetFieldId);
|
581
|
-
|
594
|
+
|
582
595
|
try {
|
583
596
|
let withDatas = [];
|
584
597
|
// 先处理依赖数据
|
@@ -654,8 +667,8 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
654
667
|
const formulaResult = evalFormula(formula);
|
655
668
|
console.log(`${childIdentifier} 计算公式:`, formula)
|
656
669
|
console.log(`${childIdentifier} 计算结果:`, formulaResult)
|
657
|
-
|
658
|
-
|
670
|
+
|
671
|
+
|
659
672
|
form.setFieldValue(childIdentifier, formulaResult)
|
660
673
|
await handleFieldsWith(childIdentifier, form.getFieldsValue(), false, targetFieldId)
|
661
674
|
}
|
@@ -716,20 +729,19 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
716
729
|
|
717
730
|
// 创建已处理字段集合,用于避免多次处理同一字段
|
718
731
|
const processedFields = new Set();
|
719
|
-
|
720
732
|
for (let key in changedFieldsState.current) {
|
721
733
|
let field = changedFieldsState.current[key];
|
722
734
|
if (!isEqual(field.value || "", getLastFieldValue(field.name) || "")) {
|
723
735
|
if (lockStatus_ != 1) {
|
724
736
|
// 获取字段标识符(字符串形式)
|
725
|
-
const fieldId = Array.isArray(field.name)
|
726
|
-
? field.name.
|
737
|
+
const fieldId = Array.isArray(field.name)
|
738
|
+
? field.name.map(item => typeof item == "string" ? item : item.toString()).join(".")
|
727
739
|
: field.name;
|
728
|
-
|
740
|
+
|
729
741
|
// 跳过已处理的字段
|
730
742
|
if (processedFields.has(fieldId)) continue;
|
731
743
|
processedFields.add(fieldId);
|
732
|
-
|
744
|
+
|
733
745
|
// 处理字段依赖关系,传递字段ID和依赖图谱
|
734
746
|
let needRefresh_ = await handleFieldsWith(field.name, fieldValues, false, fieldId);
|
735
747
|
needRefresh = needRefresh || needRefresh_;
|
@@ -746,16 +758,18 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
746
758
|
}, []);
|
747
759
|
|
748
760
|
const handleFieldsChange = React.useCallback((changedFields) => {
|
749
|
-
|
750
|
-
|
751
|
-
|
752
|
-
|
753
|
-
|
754
|
-
|
755
|
-
}
|
756
|
-
})
|
761
|
+
setTimeout(() => {
|
762
|
+
changedFields.filter(field => {
|
763
|
+
if (field.name && field.name.length > 0) {
|
764
|
+
// const fieldKey = field.name.filter(item => typeof item == "string").join(".")
|
765
|
+
changedFieldsState.current[field.name] = field;
|
757
766
|
|
758
|
-
|
767
|
+
|
768
|
+
}
|
769
|
+
})
|
770
|
+
console.log("handleFieldsChange", changedFieldsState.current)
|
771
|
+
debounceHandleFieldsChange();
|
772
|
+
}, 0);
|
759
773
|
}, []);
|
760
774
|
|
761
775
|
const getTableWithIds = (ids) => {
|
@@ -773,7 +787,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
773
787
|
})
|
774
788
|
return withAllIds
|
775
789
|
}
|
776
|
-
const handleTableAddRow =
|
790
|
+
const handleTableAddRow = (ids) => {
|
777
791
|
let withAllIds = getTableWithIds(ids)
|
778
792
|
const fieldValues = form.getFieldsValue();
|
779
793
|
setTimeout(async () => {
|
@@ -807,7 +821,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
807
821
|
return renderChildren();
|
808
822
|
}
|
809
823
|
return null;
|
810
|
-
|
824
|
+
}
|
811
825
|
const renderChildren = () => {
|
812
826
|
console.log("renderChildren")
|
813
827
|
const renderKey = nanoid()
|
@@ -824,7 +838,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
824
838
|
);
|
825
839
|
|
826
840
|
|
827
|
-
|
841
|
+
|
828
842
|
|
829
843
|
|
830
844
|
|
@@ -860,7 +874,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
860
874
|
|
861
875
|
let childComponent
|
862
876
|
if (isTable || isLayoutComponent) {
|
863
|
-
childComponent = React.cloneElement(child, { onTableAddRow: handleTableAddRow, getTableWithIds, onTableRemoveRow: handleTableRemoveRow, removeLastFieldsValues, form: form, fieldName: identifier, onCustomChange, initializeFormRender, mode, recordFieldsChange
|
877
|
+
childComponent = React.cloneElement(child, { onTableAddRow: handleTableAddRow, getTableWithIds, onTableRemoveRow: handleTableRemoveRow, removeLastFieldsValues, form: form, fieldName: identifier, onCustomChange, initializeFormRender, mode, recordFieldsChange, getDependencyMapItem, renderKey })
|
864
878
|
}
|
865
879
|
else if (componentName === "Field.WithSingleSelect" || componentName === "Field.WithMultipleSelect" || componentName === "Show.WithTable") {
|
866
880
|
childComponent = <Form.Item
|
@@ -925,7 +939,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
925
939
|
style={{ marginBottom: 0 }}
|
926
940
|
>
|
927
941
|
{childComponent}
|
928
|
-
</Col>
|
942
|
+
</Col>
|
929
943
|
);
|
930
944
|
})}
|
931
945
|
</Row>
|
@@ -934,26 +948,26 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
934
948
|
|
935
949
|
return (
|
936
950
|
<ConfigProvider
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
951
|
+
theme={{
|
952
|
+
components: {
|
953
|
+
Table: {
|
954
|
+
rowHoverBg: '#ebebeb',
|
955
|
+
// "fontSize": 14,
|
956
|
+
// "cellPaddingBlock": 6
|
957
|
+
},
|
958
|
+
},
|
959
|
+
token: {
|
960
|
+
colorBgContainerDisabled: 'rgba(0, 0, 0, 0.02)', // 设置更浅的灰色背景
|
961
|
+
colorTextDisabled: '#333',
|
962
|
+
}
|
963
|
+
}}
|
964
|
+
>
|
965
|
+
<Form form={form} className={"form-container fp-0 fw-full fh-full box-border fflex fflex-col " + (mode == "desgin" ? " fp-6" : "")} onFieldsChange={handleFieldsChange}>
|
966
|
+
<Form.Item name="__id" hidden={true}>
|
967
|
+
<input type="hidden" />
|
968
|
+
</Form.Item>
|
969
|
+
{formContent}
|
970
|
+
</Form>
|
957
971
|
</ConfigProvider>
|
958
972
|
);
|
959
973
|
});
|