lu-lowcode-package-form 0.11.46 → 0.11.50
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 +200 -200
- package/dist/index.es.js +8519 -8467
- package/package.json +2 -1
- package/src/App.jsx +544 -14
- package/src/components/form-container/index.jsx +215 -101
@@ -65,6 +65,40 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
65
65
|
}
|
66
66
|
// 调用setFieldsValue时,进入锁定状态,阻止因字段值变化而触发级联处理
|
67
67
|
const lockStatus = React.useRef(0);
|
68
|
+
// // 字段变更源跟踪,用于处理双向依赖问题
|
69
|
+
// const updateSourceRef = React.useRef(new Map());
|
70
|
+
// 更新周期依赖图,用于处理复杂循环依赖 (如 a→b→c→a)
|
71
|
+
const dependencyGraphRef = React.useRef({
|
72
|
+
// 当前更新周期ID
|
73
|
+
currentCycleId: 0,
|
74
|
+
// 当前更新周期的依赖路径
|
75
|
+
updatePath: [],
|
76
|
+
// 开始新的更新周期
|
77
|
+
startNewCycle: function() {
|
78
|
+
this.currentCycleId++;
|
79
|
+
this.updatePath = [];
|
80
|
+
return this.currentCycleId;
|
81
|
+
},
|
82
|
+
// 添加依赖路径
|
83
|
+
addToPath: function(fieldId) {
|
84
|
+
this.updatePath.push(fieldId);
|
85
|
+
},
|
86
|
+
// 检查是否形成循环
|
87
|
+
hasCircularDependency: function(targetFieldId) {
|
88
|
+
return this.updatePath.includes(targetFieldId);
|
89
|
+
},
|
90
|
+
// 获取当前依赖路径
|
91
|
+
getCurrentPath: function() {
|
92
|
+
return [...this.updatePath];
|
93
|
+
},
|
94
|
+
// 结束当前字段的处理
|
95
|
+
finishField: function() {
|
96
|
+
if (this.updatePath.length > 0) {
|
97
|
+
this.updatePath.pop();
|
98
|
+
}
|
99
|
+
}
|
100
|
+
});
|
101
|
+
|
68
102
|
React.useImperativeHandle(ref, () => ({
|
69
103
|
formRef: form,
|
70
104
|
setFieldsValue: (values) => {
|
@@ -130,6 +164,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
130
164
|
// return current;
|
131
165
|
}
|
132
166
|
const initializeDependencyMap = async () => {
|
167
|
+
|
133
168
|
const fields = [];
|
134
169
|
function traverse(currentNode, parentNode = null) {
|
135
170
|
var componentName = currentNode.type?.displayName || currentNode.props?._componentName;
|
@@ -177,6 +212,8 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
177
212
|
};
|
178
213
|
const initializeFieldVisibilityImmediate = async (reloadFields = false) => {
|
179
214
|
console.log("initializeFieldVisibility *************************************")
|
215
|
+
|
216
|
+
|
180
217
|
const fieldValues = form.getFieldsValue();
|
181
218
|
|
182
219
|
await Promise.all(Array.from(dependencyMap.current.keys()).map(async (key) => {
|
@@ -195,7 +232,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
195
232
|
|
196
233
|
|
197
234
|
// 计算字段级联关系
|
198
|
-
const handleFieldsWith = async (identifier, fieldValues, init = false) => {
|
235
|
+
const handleFieldsWith = async (identifier, fieldValues, init = false, fieldId = null) => {
|
199
236
|
// console.log("handleFieldsWith identifier", identifier)
|
200
237
|
let needRefresh = false;
|
201
238
|
let parentIdentifier = [];
|
@@ -203,34 +240,53 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
203
240
|
parentIdentifier = [...(identifier.slice(0, -1))]
|
204
241
|
identifier = identifier.filter(item => typeof item == "string").join(".")
|
205
242
|
}
|
206
|
-
|
207
|
-
|
208
|
-
|
243
|
+
|
244
|
+
// 将标识符标准化为字符串,用于依赖图谱
|
245
|
+
const currentFieldId = fieldId || identifier;
|
246
|
+
|
247
|
+
// 检查是否在当前更新链路中已存在,避免循环依赖
|
248
|
+
if (dependencyGraphRef.current.hasCircularDependency(currentFieldId)) {
|
249
|
+
const currentPath = dependencyGraphRef.current.getCurrentPath();
|
250
|
+
console.log(`检测到循环依赖链路: ${[...currentPath, currentFieldId].join(' -> ')}`);
|
251
|
+
return false;
|
252
|
+
}
|
253
|
+
|
254
|
+
// 将当前字段添加到依赖路径
|
255
|
+
dependencyGraphRef.current.addToPath(currentFieldId);
|
256
|
+
|
257
|
+
try {
|
258
|
+
if (dependencyMap.current.has(identifier)) {
|
259
|
+
const dependent = dependencyMap.current.get(identifier)
|
260
|
+
const dependentChildren = dependent.children;
|
209
261
|
|
210
262
|
|
211
|
-
|
212
|
-
|
213
|
-
}
|
214
|
-
for (let index = 0; index < dependentChildren.length; index++) {
|
215
|
-
const child = dependentChildren[index];
|
216
|
-
if (child.component.props.withVisibleFunc && typeof child.component.props.withVisibleFunc === 'function') {
|
217
|
-
let needRefresh_ = handleFieldsVisibleFunc(fieldValues, child, parentIdentifier)
|
218
|
-
needRefresh = needRefresh || needRefresh_
|
263
|
+
if (!init && dependent?.fillRules && Array.isArray(dependent?.fillRules) && dependent?.fillRules.length > 0) {
|
264
|
+
handleFillRules(identifier, parentIdentifier, fieldValues, dependent?.fillRules)
|
219
265
|
}
|
266
|
+
for (let index = 0; index < dependentChildren.length; index++) {
|
267
|
+
const child = dependentChildren[index];
|
268
|
+
if (child.component.props.withVisibleFunc && typeof child.component.props.withVisibleFunc === 'function') {
|
269
|
+
let needRefresh_ = handleFieldsVisibleFunc(fieldValues, child, parentIdentifier)
|
270
|
+
needRefresh = needRefresh || needRefresh_
|
271
|
+
}
|
220
272
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
273
|
+
if (child.component.props.withVisible) {
|
274
|
+
let needRefresh_ = await handleFieldsVisible(fieldValues, child, parentIdentifier, dependent?.componentName)
|
275
|
+
needRefresh = needRefresh || needRefresh_
|
276
|
+
}
|
225
277
|
|
226
278
|
|
227
|
-
|
228
|
-
|
279
|
+
if (!init && child.component.props.withFill)
|
280
|
+
await handleFieldsWithFill(fieldValues, child, parentIdentifier, dependent?.componentName, currentFieldId)
|
229
281
|
|
282
|
+
}
|
230
283
|
}
|
284
|
+
} finally {
|
285
|
+
// 在处理完毕后,从依赖路径中移除当前字段
|
286
|
+
dependencyGraphRef.current.finishField();
|
231
287
|
}
|
288
|
+
|
232
289
|
return needRefresh;
|
233
|
-
|
234
290
|
};
|
235
291
|
const removeLastFieldsValues = (name, isTable = false) => {
|
236
292
|
if (!lastFormValues.current) return
|
@@ -258,6 +314,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
258
314
|
if (changedKeys.length > 0) {
|
259
315
|
changedKeys.forEach(key => {
|
260
316
|
recordFieldChange(key, changedFields[key])
|
317
|
+
|
261
318
|
})
|
262
319
|
if (handleChange) debounceHandleFieldsChange();
|
263
320
|
}
|
@@ -269,12 +326,40 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
269
326
|
let current_value = getParamValue("fieldsValue", current_identifier, fieldValues, null)
|
270
327
|
let changedFields = {}
|
271
328
|
|
329
|
+
// 将标识符标准化为字符串
|
330
|
+
const sourceFieldId = Array.isArray(current_identifier)
|
331
|
+
? current_identifier.filter(item => typeof item == "string").join(".")
|
332
|
+
: current_identifier;
|
333
|
+
|
272
334
|
let idGroups = []
|
273
335
|
for (let index = 0; index < fillRules.length; index++) {
|
274
336
|
const rule = fillRules[index];
|
275
337
|
let { source, target } = rule
|
276
338
|
let source_value = current_value?.[source]
|
277
339
|
let setValue = source_value
|
340
|
+
|
341
|
+
// 将sourceField格式化为字符串形式,用于依赖跟踪
|
342
|
+
const sourceField = Array.isArray(current_identifier)
|
343
|
+
? current_identifier.filter(item => typeof item == "string").join(".")
|
344
|
+
: current_identifier;
|
345
|
+
|
346
|
+
// 格式化目标字段
|
347
|
+
const targetField = Array.isArray(target)
|
348
|
+
? target.filter(item => typeof item == "string").join(".")
|
349
|
+
: target;
|
350
|
+
|
351
|
+
// // 检查循环依赖 - 使用更高级的依赖图检测
|
352
|
+
// if (dependencyGraphRef.current.hasCircularDependency(targetField)) {
|
353
|
+
// const currentPath = dependencyGraphRef.current.getCurrentPath();
|
354
|
+
// console.log(`检测到填充规则中的循环依赖链路: ${[...currentPath, targetField].join(' -> ')}`);
|
355
|
+
// continue; // 跳过这条规则
|
356
|
+
// }
|
357
|
+
|
358
|
+
|
359
|
+
//// 添加到依赖路径
|
360
|
+
// dependencyGraphRef.current.addToPath(targetField);
|
361
|
+
|
362
|
+
|
278
363
|
// 子表
|
279
364
|
if (rule?.type == 1) {
|
280
365
|
if (dependencyMap.current.has(target)) {
|
@@ -324,15 +409,9 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
324
409
|
form.setFieldValue(target, undefined);
|
325
410
|
}
|
326
411
|
form.setFieldValue(target, setValue)
|
327
|
-
|
328
|
-
//
|
329
|
-
//
|
330
|
-
// handleFieldsWith(target, form.getFieldsValue())
|
331
|
-
// if (idGroups.length > 0) handleTableAddRow(idGroups)
|
332
|
-
// }, 0);
|
333
|
-
|
334
|
-
|
335
|
-
// if (idGroups.length > 0) setTimeout(() => handleTableAddRow(idGroups), 0)
|
412
|
+
|
413
|
+
// 处理完当前字段后从依赖路径中移除
|
414
|
+
// dependencyGraphRef.current.finishField();
|
336
415
|
}
|
337
416
|
|
338
417
|
setTimeout(() => {
|
@@ -340,7 +419,6 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
340
419
|
// console.log("idGroups", idGroups)
|
341
420
|
if (idGroups.length > 0) idGroups.forEach(ids => { if (Array.isArray(ids) && ids.length > 0) handleTableAddRow(ids) })
|
342
421
|
}, 0)
|
343
|
-
|
344
422
|
}
|
345
423
|
// 处理级联显示隐藏 @return {boolean} 是否需要重新渲染表单的字段
|
346
424
|
const handleFieldsVisibleFunc = (fieldValues, child, parentIdentifier) => {
|
@@ -458,7 +536,7 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
458
536
|
}
|
459
537
|
// 处理级联数据源
|
460
538
|
// 处理级联填充
|
461
|
-
const handleFieldsWithFill = async (fieldValues, child, parentIdentifier, componentName) => {
|
539
|
+
const handleFieldsWithFill = async (fieldValues, child, parentIdentifier, componentName, sourceFieldId) => {
|
462
540
|
// console.log("handleFieldsWithFill child.identifier", child.identifier)
|
463
541
|
// console.log("handleFieldsWithFill parentIdentifier", parentIdentifier)
|
464
542
|
console.log("handleFieldsWithFill componentName", componentName)
|
@@ -480,89 +558,110 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
480
558
|
let table_values = getParamValue("fieldsValue", childIdentifier[0], fieldValues, [])
|
481
559
|
if (Array.isArray(table_values) && table_values.length > 0)
|
482
560
|
for (let index = 0; index < table_values.length; index++) {
|
483
|
-
await handleFieldsWithFill(fieldValues, child, [childIdentifier[0], index], componentName)
|
561
|
+
await handleFieldsWithFill(fieldValues, child, [childIdentifier[0], index], componentName, sourceFieldId)
|
484
562
|
}
|
485
563
|
|
486
|
-
|
487
564
|
return
|
488
|
-
|
489
565
|
}
|
490
|
-
|
491
|
-
//
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
566
|
+
|
567
|
+
// 将目标字段ID标准化为字符串
|
568
|
+
const targetFieldId = Array.isArray(childIdentifier)
|
569
|
+
? childIdentifier.filter(item => typeof item == "string").join(".")
|
570
|
+
: childIdentifier;
|
571
|
+
|
572
|
+
// 检查是否在当前依赖链中已存在,避免循环依赖
|
573
|
+
if (dependencyGraphRef.current.hasCircularDependency(targetFieldId)) {
|
574
|
+
const currentPath = dependencyGraphRef.current.getCurrentPath();
|
575
|
+
console.log(`检测到公式计算中的循环依赖链路: ${[...currentPath, targetFieldId].join(' -> ')}`);
|
576
|
+
return;
|
577
|
+
}
|
578
|
+
|
579
|
+
// // 将当前字段添加到依赖路径
|
580
|
+
// dependencyGraphRef.current.addToPath(targetFieldId);
|
581
|
+
|
582
|
+
try {
|
583
|
+
let withDatas = [];
|
584
|
+
// 先处理依赖数据
|
585
|
+
if (withFill?.withData && withFill?.withData.length > 0 && withDataFetch && typeof withDataFetch === 'function') {
|
586
|
+
for (let index = 0; index < withFill?.withData.length; index++) {
|
587
|
+
const element = withFill?.withData[index];
|
588
|
+
let params = {}
|
589
|
+
params.tableName = element.withTable.table_name
|
590
|
+
params.filter = {}
|
591
|
+
for (let index = 0; index < element.withCondition.length; index++) {
|
592
|
+
const { value: condition_value, column: condition_column } = element.withCondition[index];
|
593
|
+
let filter_value = getParamValue(condition_value.group_key, condition_value.field_key, fieldValues, withDatas)
|
594
|
+
if (Array.isArray(filter_value)) {
|
595
|
+
if (Array.isArray(childIdentifier) && filter_value.length > withFillIndex) {
|
596
|
+
filter_value = filter_value[withFillIndex]
|
597
|
+
}
|
504
598
|
}
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
599
|
+
if (filter_value && typeof filter_value === "string") {
|
600
|
+
try {
|
601
|
+
filter_value = JSON.parse(filter_value)
|
602
|
+
} catch (error) {
|
603
|
+
}
|
510
604
|
}
|
605
|
+
if (filter_value?.value) filter_value = filter_value.value
|
606
|
+
// if (componentName == "Field.WithSingleSelect" && filter_value) {
|
607
|
+
// if (typeof filter_value === "string") {
|
608
|
+
// filter_value = JSON.parse(filter_value)
|
609
|
+
// }
|
610
|
+
// filter_value = filter_value?.value
|
611
|
+
// }
|
612
|
+
params.filter[condition_column.column_name] = filter_value
|
511
613
|
}
|
512
|
-
if (filter_value?.value) filter_value = filter_value.value
|
513
|
-
// if (componentName == "Field.WithSingleSelect" && filter_value) {
|
514
|
-
// if (typeof filter_value === "string") {
|
515
|
-
// filter_value = JSON.parse(filter_value)
|
516
|
-
// }
|
517
|
-
// filter_value = filter_value?.value
|
518
|
-
// }
|
519
|
-
params.filter[condition_column.column_name] = filter_value
|
520
|
-
}
|
521
614
|
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
615
|
+
// 访问接口获取数据
|
616
|
+
const response = await withDataFetch(params)
|
617
|
+
if (response.code === 0 && response.data.list) {
|
618
|
+
withDatas.push({
|
619
|
+
id: element.id,
|
620
|
+
data: response.data.list
|
621
|
+
})
|
622
|
+
}
|
529
623
|
}
|
530
624
|
}
|
531
|
-
}
|
532
625
|
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
626
|
+
// 构造计算公式
|
627
|
+
let formula;
|
628
|
+
if (withFill.value && withFill.value.length > 0) {
|
629
|
+
formula = withFill.value.map(item => {
|
630
|
+
let result = "";
|
631
|
+
const { insert, attributes } = item
|
632
|
+
if (typeof insert !== "string") {
|
633
|
+
if (insert?.span && attributes && attributes.tagKey && attributes.id) {
|
634
|
+
result = getParamValue(attributes.tagKey, attributes.id, fieldValues, withDatas)
|
635
|
+
if (Array.isArray(result)) {
|
636
|
+
if (Array.isArray(childIdentifier) && result.length > withFillIndex) {
|
637
|
+
result = result[withFillIndex]
|
638
|
+
}
|
639
|
+
if (typeof result === "object" && result !== null)
|
640
|
+
result = JSON.stringify(result)
|
545
641
|
}
|
546
|
-
if (typeof result === "object" && result !== null)
|
642
|
+
else if (typeof result === "object" && result !== null) {
|
547
643
|
result = JSON.stringify(result)
|
644
|
+
}
|
645
|
+
else if (result.length > 0) result = `"${result}"`
|
548
646
|
}
|
549
|
-
else if (typeof result === "object" && result !== null) {
|
550
|
-
result = JSON.stringify(result)
|
551
|
-
}
|
552
|
-
else if (result.length > 0) result = `"${result}"`
|
553
647
|
}
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
}
|
558
|
-
}
|
648
|
+
else result = insert
|
649
|
+
return result
|
650
|
+
})
|
651
|
+
}
|
559
652
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
653
|
+
if (formula && formula.length > 0) {
|
654
|
+
const formulaResult = evalFormula(formula);
|
655
|
+
console.log(`${childIdentifier} 计算公式:`, formula)
|
656
|
+
console.log(`${childIdentifier} 计算结果:`, formulaResult)
|
657
|
+
|
658
|
+
|
659
|
+
form.setFieldValue(childIdentifier, formulaResult)
|
660
|
+
await handleFieldsWith(childIdentifier, form.getFieldsValue(), false, targetFieldId)
|
661
|
+
}
|
662
|
+
} finally {
|
663
|
+
// 处理完毕后,从依赖路径中删除当前字段
|
664
|
+
// dependencyGraphRef.current.finishField();
|
566
665
|
}
|
567
666
|
}
|
568
667
|
|
@@ -606,6 +705,8 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
606
705
|
const delay = lockStatus.current === 1 ? 500 : 100;
|
607
706
|
|
608
707
|
timeoutRef.current = setTimeout(async () => {
|
708
|
+
// 开始新的更新周期
|
709
|
+
dependencyGraphRef.current.startNewCycle();
|
609
710
|
|
610
711
|
const fieldValues = form.getFieldsValue();
|
611
712
|
const lockStatus_ = lockStatus.current;
|
@@ -613,14 +714,25 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
613
714
|
let needRefresh = false;
|
614
715
|
if (!lastFormValues.current) lastFormValues.current = {}
|
615
716
|
|
717
|
+
// 创建已处理字段集合,用于避免多次处理同一字段
|
718
|
+
const processedFields = new Set();
|
719
|
+
|
616
720
|
for (let key in changedFieldsState.current) {
|
617
721
|
let field = changedFieldsState.current[key];
|
618
722
|
if (!isEqual(field.value || "", getLastFieldValue(field.name) || "")) {
|
619
723
|
if (lockStatus_ != 1) {
|
620
|
-
//
|
621
|
-
|
622
|
-
|
623
|
-
|
724
|
+
// 获取字段标识符(字符串形式)
|
725
|
+
const fieldId = Array.isArray(field.name)
|
726
|
+
? field.name.filter(item => typeof item == "string").join(".")
|
727
|
+
: field.name;
|
728
|
+
|
729
|
+
// 跳过已处理的字段
|
730
|
+
if (processedFields.has(fieldId)) continue;
|
731
|
+
processedFields.add(fieldId);
|
732
|
+
|
733
|
+
// 处理字段依赖关系,传递字段ID和依赖图谱
|
734
|
+
let needRefresh_ = await handleFieldsWith(field.name, fieldValues, false, fieldId);
|
735
|
+
needRefresh = needRefresh || needRefresh_;
|
624
736
|
}
|
625
737
|
lastFormValues.current[field.name] = field.value;
|
626
738
|
}
|
@@ -638,6 +750,8 @@ const FormContainer = forwardRef(({ cols = 1, children, mode = "view" }, ref) =>
|
|
638
750
|
if (field.name && field.name.length > 0) {
|
639
751
|
// const fieldKey = field.name.filter(item => typeof item == "string").join(".")
|
640
752
|
changedFieldsState.current[field.name] = field;
|
753
|
+
|
754
|
+
|
641
755
|
}
|
642
756
|
})
|
643
757
|
|