@openli1115/lowcode-edit-pro-table 1.0.88 → 1.0.90

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.
@@ -14,7 +14,38 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
14
14
  var _window$React = window.React,
15
15
  createElement = _window$React.createElement,
16
16
  useCallback = _window$React.useCallback,
17
+ useEffect = _window$React.useEffect,
17
18
  useMemo = _window$React.useMemo;
19
+ function toStr(v) {
20
+ if (v == null) return '';
21
+ return String(v);
22
+ }
23
+ function getNodeValue(node) {
24
+ if (!node || typeof node !== 'object') return '';
25
+ // 兼容 value/id/key 等常见字段
26
+ if (node.value != null) return toStr(node.value);
27
+ if (node.id != null) return toStr(node.id);
28
+ if (node.key != null) return toStr(node.key);
29
+ return '';
30
+ }
31
+ function getNodeLabel(node, fallback) {
32
+ if (fallback === void 0) {
33
+ fallback = '';
34
+ }
35
+ if (!node || typeof node !== 'object') return fallback;
36
+ if (node.label != null) return toStr(node.label);
37
+ if (node.name != null) return toStr(node.name);
38
+ if (node.title != null) return toStr(node.title);
39
+ return fallback;
40
+ }
41
+ function getNodeChildren(node) {
42
+ if (!node || typeof node !== 'object') return [];
43
+ // 兼容 children / options / childs 等结构
44
+ if (Array.isArray(node.children)) return node.children;
45
+ if (Array.isArray(node.options)) return node.options;
46
+ if (Array.isArray(node.childs)) return node.childs;
47
+ return [];
48
+ }
18
49
 
19
50
  /**
20
51
  * 按路径在树形 dataSource 上逐级匹配,取出每一层的 label(2 级、3 级…任意多级,长度由 pathValues 决定)。
@@ -26,39 +57,92 @@ function resolvePathLabels(dataSource, pathValues) {
26
57
  var _loop = function _loop() {
27
58
  var pv = _step.value;
28
59
  var node = level.find(function (n) {
29
- return String(n === null || n === void 0 ? void 0 : n.value) === String(pv);
60
+ return getNodeValue(n) === toStr(pv);
30
61
  });
31
62
  if (!node) return 1; // break
32
- labels.push(node.label != null ? String(node.label) : String(pv));
33
- var next = node.children;
34
- level = Array.isArray(next) ? next : [];
63
+ labels.push(getNodeLabel(node, toStr(pv)));
64
+ level = getNodeChildren(node);
35
65
  };
36
66
  for (var _iterator = _createForOfIteratorHelperLoose(pathValues), _step; !(_step = _iterator()).done;) {
37
67
  if (_loop()) break;
38
68
  }
39
69
  return labels;
40
70
  }
41
- function normalizeCascaderPath(v) {
71
+ function isValidPathInTree(dataSource, pathValues) {
72
+ if (!Array.isArray(dataSource) || pathValues.length === 0) return false;
73
+ var level = dataSource;
74
+ var _loop2 = function _loop2() {
75
+ var pv = _step2.value;
76
+ var node = level.find(function (n) {
77
+ return getNodeValue(n) === toStr(pv);
78
+ });
79
+ if (!node) return {
80
+ v: false
81
+ };
82
+ level = getNodeChildren(node);
83
+ },
84
+ _ret;
85
+ for (var _iterator2 = _createForOfIteratorHelperLoose(pathValues), _step2; !(_step2 = _iterator2()).done;) {
86
+ _ret = _loop2();
87
+ if (_ret) return _ret.v;
88
+ }
89
+ return true;
90
+ }
91
+
92
+ /** 回填仅有叶子 id(如 city=2977)时,递归反查完整路径 [provinceId, cityId] */
93
+ function findPathByNodeValue(dataSource, targetValue, parentPath) {
94
+ if (parentPath === void 0) {
95
+ parentPath = [];
96
+ }
97
+ if (!Array.isArray(dataSource) || targetValue === '') return [];
98
+ for (var _iterator3 = _createForOfIteratorHelperLoose(dataSource), _step3; !(_step3 = _iterator3()).done;) {
99
+ var node = _step3.value;
100
+ var curValue = getNodeValue(node);
101
+ if (!curValue) continue;
102
+ var nextPath = parentPath.concat(curValue);
103
+ if (curValue === toStr(targetValue)) {
104
+ return nextPath;
105
+ }
106
+ var hit = findPathByNodeValue(getNodeChildren(node), targetValue, nextPath);
107
+ if (hit.length > 0) return hit;
108
+ }
109
+ return [];
110
+ }
111
+ function normalizeCascaderPath(v, dataSource) {
112
+ var tryExpandByLeaf = function tryExpandByLeaf(leaf, fallback) {
113
+ if (fallback === void 0) {
114
+ fallback = [];
115
+ }
116
+ var fullPath = findPathByNodeValue(dataSource, leaf);
117
+ return fullPath.length > 0 ? fullPath : fallback;
118
+ };
42
119
  if (Array.isArray(v)) {
43
- return v.filter(function (x) {
120
+ var path = v.filter(function (x) {
44
121
  return x != null && x !== '';
45
122
  }).map(function (x) {
46
- return String(x);
123
+ return toStr(x);
47
124
  });
125
+ if (path.length === 0) return [];
126
+ if (isValidPathInTree(dataSource, path)) return path;
127
+ return tryExpandByLeaf(path[path.length - 1], path);
48
128
  }
49
129
  if (typeof v === 'number' && !Number.isNaN(v)) {
50
- /** 表单里有时是数字 id(2977),Fusion dataSource string 化,需对齐 */
51
- return [String(v)];
130
+ /** 表单里有时是数字 id(2977),需要根据 dataSource 找完整路径 */
131
+ return tryExpandByLeaf(toStr(v), [toStr(v)]);
52
132
  }
53
133
  if (typeof v === 'string' && v.trim()) {
54
134
  try {
55
135
  var parsed = JSON.parse(v);
56
- return Array.isArray(parsed) ? parsed.map(function (x) {
57
- return String(x);
58
- }) : [];
136
+ if (!Array.isArray(parsed)) return [];
137
+ var _path = parsed.map(function (x) {
138
+ return toStr(x);
139
+ });
140
+ if (_path.length === 0) return [];
141
+ if (isValidPathInTree(dataSource, _path)) return _path;
142
+ return tryExpandByLeaf(_path[_path.length - 1], _path);
59
143
  } catch (_unused) {
60
- /** 历史或单值存成非 JSON 字符串时,当作单选叶子 value */
61
- return [v];
144
+ /** 历史或接口单值回填时,当作叶子值反查完整路径 */
145
+ return tryExpandByLeaf(v, [v]);
62
146
  }
63
147
  }
64
148
  return [];
@@ -97,6 +181,7 @@ var ProCascaderSelect = function ProCascaderSelect(props) {
97
181
  screen_inner_id = props.screen_inner_id,
98
182
  range_inner_table = props.range_inner_table,
99
183
  dataSource = props.dataSource,
184
+ options = props.options,
100
185
  disableEdit = props.disableEdit,
101
186
  readOnlyProp = props.readOnly,
102
187
  disabledProp = props.disabled,
@@ -104,6 +189,7 @@ var ProCascaderSelect = function ProCascaderSelect(props) {
104
189
  schemaOnChange = props.onChange,
105
190
  defaultValue = props.defaultValue,
106
191
  multiple = props.multiple;
192
+ var isMultiple = multiple === true || multiple === 'true';
107
193
  var _resolveProScreenBind = (0, _utils.resolveProScreenBinding)({
108
194
  screen_structure: screen_structure,
109
195
  screen_structure_field: screen_structure_field,
@@ -116,34 +202,99 @@ var ProCascaderSelect = function ProCascaderSelect(props) {
116
202
  var _useProBoundValue = (0, _useProBoundValue2.useProBoundValue)(fieldPath, unboundInit, _useComponentContext.FORM_EMPTY_ARRAY),
117
203
  value = _useProBoundValue.value,
118
204
  commit = _useProBoundValue.commit;
205
+ // 优先 dataSource,兼容部分 schema 透传为 options
206
+ var cascaderOptions = useMemo(function () {
207
+ if (Array.isArray(dataSource)) return dataSource;
208
+ if (Array.isArray(options)) return options;
209
+ return [];
210
+ }, [dataSource, options]);
119
211
  var handleChange = function handleChange(newValue, _data, extra) {
120
212
  var next = cascaderChangeToPath(newValue, extra);
213
+ console.log('[ProCascaderSelect] onChange', {
214
+ fieldPath: fieldPath,
215
+ rawValue: newValue,
216
+ selectedPath: extra === null || extra === void 0 ? void 0 : extra.selectedPath,
217
+ normalizedPath: next
218
+ });
121
219
  commit(next);
122
220
  schemaOnChange === null || schemaOnChange === void 0 ? void 0 : schemaOnChange(next, structureName, structureField);
123
221
  };
124
222
 
125
- /** 表单/接口:完整路径 string[],如 ['2974','2975'] */
126
- var displayValue = normalizeCascaderPath(value);
223
+ /** 表单/接口:优先完整路径;若仅有叶子 id(如 2977)则由 dataSource 反查完整路径 */
224
+ var displayValue = useMemo(function () {
225
+ return normalizeCascaderPath(value, cascaderOptions);
226
+ }, [value, cascaderOptions]);
227
+ var incomingLeafId = useMemo(function () {
228
+ if (Array.isArray(value)) {
229
+ var cleaned = value.filter(function (x) {
230
+ return x != null && x !== '';
231
+ });
232
+ return cleaned.length > 0 ? toStr(cleaned[cleaned.length - 1]) : '';
233
+ }
234
+ if (typeof value === 'number' && !Number.isNaN(value)) return toStr(value);
235
+ if (typeof value === 'string' && value.trim()) {
236
+ try {
237
+ var parsed = JSON.parse(value);
238
+ if (Array.isArray(parsed) && parsed.length > 0) {
239
+ return toStr(parsed[parsed.length - 1]);
240
+ }
241
+ } catch (_unused2) {
242
+ return value;
243
+ }
244
+ return value;
245
+ }
246
+ return '';
247
+ }, [value]);
248
+ var packedPathFromLeaf = useMemo(function () {
249
+ if (!incomingLeafId) return [];
250
+ return findPathByNodeValue(cascaderOptions, incomingLeafId);
251
+ }, [cascaderOptions, incomingLeafId]);
127
252
 
128
253
  /**
129
- * Fusion 单选:官方约定受控 value 为 string[] | number[],且实现里只对数组取 value[0] 再查节点。
130
- * 若传入完整路径 [父,子],会把「父」当成选中项,文案只有一级。
131
- * 组件展示应传「叶子」单元素数组 [leaf],内部 getLabelPath(叶子节点) 会生成多级展示。
132
- * 多选仍传 Fusion 所需的多个 value(与表单存值一致)。
254
+ * 回显兼容:
255
+ * - 多选:沿用路径数组
256
+ * - 单选:传叶子值(字符串);部分 Fusion 版本单选不接受数组 value,传数组会不显示
133
257
  */
134
258
  var valueForFusion = useMemo(function () {
135
259
  var path = displayValue;
136
- if (multiple) {
260
+ if (isMultiple) {
137
261
  return path;
138
262
  }
139
- if (path.length === 0) return [];
140
- return [path[path.length - 1]];
141
- }, [displayValue, multiple]);
263
+ if (path.length === 0) return '';
264
+ return path[path.length - 1];
265
+ }, [displayValue, isMultiple]);
266
+ useEffect(function () {
267
+ var leaf = displayValue.length > 0 ? displayValue[displayValue.length - 1] : '';
268
+ var resolvedPathFromLeaf = leaf ? findPathByNodeValue(cascaderOptions, toStr(leaf)) : [];
269
+ console.log('[ProCascaderSelect] echo-id-and-path', {
270
+ fieldPath: fieldPath,
271
+ incomingLeafId: incomingLeafId,
272
+ packedPathFromLeaf: packedPathFromLeaf
273
+ });
274
+ console.log('[ProCascaderSelect] render-debug', {
275
+ fieldPath: fieldPath,
276
+ structureName: structureName,
277
+ structureField: structureField,
278
+ rawBoundValue: value,
279
+ normalizedDisplayPath: displayValue,
280
+ fusionValue: valueForFusion,
281
+ isMultiple: isMultiple,
282
+ optionsCount: cascaderOptions.length,
283
+ resolvedPathFromLeaf: resolvedPathFromLeaf,
284
+ optionsPreview: cascaderOptions.slice(0, 3).map(function (n) {
285
+ return {
286
+ value: getNodeValue(n),
287
+ label: getNodeLabel(n),
288
+ childrenCount: getNodeChildren(n).length
289
+ };
290
+ })
291
+ });
292
+ }, [fieldPath, structureName, structureField, value, displayValue, valueForFusion, isMultiple, cascaderOptions]);
142
293
 
143
294
  /** dataSource 未就绪或异步时,仍用自定义文案兜底 */
144
295
  var schemaDisplayRender = props.displayRender;
145
296
  var pathDisplayRender = useCallback(function (labels, data) {
146
- var fullLabels = resolvePathLabels(dataSource, normalizeCascaderPath(value));
297
+ var fullLabels = resolvePathLabels(cascaderOptions, displayValue);
147
298
  if (fullLabels.length > 0) {
148
299
  return fullLabels.join(' / ');
149
300
  }
@@ -151,13 +302,13 @@ var ProCascaderSelect = function ProCascaderSelect(props) {
151
302
  return schemaDisplayRender(labels, data);
152
303
  }
153
304
  return (labels && labels.length ? labels.join(' / ') : '') || ((data === null || data === void 0 ? void 0 : data.label) != null ? String(data.label) : '');
154
- }, [dataSource, value, schemaDisplayRender]);
305
+ }, [cascaderOptions, displayValue, schemaDisplayRender]);
155
306
  return /*#__PURE__*/React.createElement("span", {
156
307
  className: "field-wrapper " + (disableEdit ? 'disable-edit' : 'enable-edit')
157
308
  }, /*#__PURE__*/React.createElement(_cascaderSelect["default"], (0, _extends2["default"])({}, props, {
158
309
  readOnly: disableEdit ? true : readOnlyProp,
159
310
  disabled: disabledProp,
160
- dataSource: dataSource,
311
+ dataSource: cascaderOptions,
161
312
  value: valueForFusion,
162
313
  onChange: handleChange,
163
314
  displayRender: pathDisplayRender
@@ -108,6 +108,13 @@ var ConditionTable = function ConditionTable(_ref) {
108
108
  onChange: function onChange(v) {
109
109
  return update(row.id, 'option', v);
110
110
  }
111
+ // 关键:Modal 被挂到 window.top.document.body,但 Select 下拉默认使用当前 iframe 的 document.body,
112
+ // 会导致下拉被渲染到 iframe 内部并被 Modal 蒙层遮挡(显示在弹窗下方)。
113
+ // 将下拉容器固定到触发节点的父元素,保证下拉与 Select 同处 Modal 的 DOM 子树中,避免跨文档渲染被盖住。
114
+ ,
115
+ getPopupContainer: function getPopupContainer(triggerNode) {
116
+ return triggerNode && triggerNode.parentElement || document.body;
117
+ }
111
118
  }), /*#__PURE__*/React.createElement(_input["default"], {
112
119
  size: "small",
113
120
  style: {
@@ -380,15 +387,18 @@ var ProSearch = function ProSearch(_ref2) {
380
387
  });
381
388
  onSearch && onSearch(data);
382
389
  };
383
- var renderInput = function renderInput(field, key) {
390
+ var renderInput = function renderInput(field, key, displayCond) {
384
391
  var fv = fieldValues[field.id] || {
385
392
  low: '',
386
393
  high: '',
387
394
  conditions: []
388
395
  };
389
- var val = fv[key];
390
396
  var hasConditions = fv.conditions.length > 0;
391
397
  var disabled = hasConditions;
398
+ // 4.2 / 4.2a / 4.2b / 4.5 / 4.6:有多值条件时,字段行展示"首行代表"的 low/high 值
399
+ // - 4.2a BT(介于):起始值=low,到值=high 分别填入两个输入框
400
+ // - 非 BT 情况:到值留空,仅展示 low
401
+ var val = displayCond ? key === 'low' ? displayCond.low : displayCond.option === 'BT' ? displayCond.high : '' : fv[key];
392
402
  var _onChange = function onChange(v) {
393
403
  return updateVal(field.id, key, v);
394
404
  };
@@ -428,53 +438,59 @@ var ProSearch = function ProSearch(_ref2) {
428
438
  });
429
439
  };
430
440
 
431
- // Render summary of multi-value conditions on the input area
432
- var renderCondSummary = function renderCondSummary(fv) {
433
- var inc = fv.conditions.filter(function (c) {
434
- return c.sign === 'I' && (c.low || c.option);
441
+ /**
442
+ * 4.2 / 4.2a / 4.2b / 4.5 / 4.6:在起始值输入框前渲染选项比较符徽标。
443
+ * 规则:
444
+ * - 选择 tab(sign='I') 首行存在(含 4.6 两个 tab 都有值时):
445
+ * · 4.2 option 为空或 EQ → 不显示符号
446
+ * · 4.2b 其它 option → 显示「绿底」符号(GE=≥、LT=<、BT=~、CO=∋ 等)
447
+ * - 仅排除 tab(sign='E') 有值:
448
+ * · 4.5.1 任意 option → 显示「红底」符号
449
+ * · 4.5.2 option 为空或 EQ → 仍显示「红底」的「=」
450
+ */
451
+ var renderSignBadge = function renderSignBadge(fv) {
452
+ var firstInclude = fv.conditions.find(function (c) {
453
+ return c.sign === 'I';
435
454
  });
436
- var exc = fv.conditions.filter(function (c) {
437
- return c.sign === 'E' && (c.low || c.option);
455
+ var firstExclude = fv.conditions.find(function (c) {
456
+ return c.sign === 'E';
438
457
  });
439
- if (!inc.length && !exc.length) return null;
440
- return /*#__PURE__*/React.createElement("div", {
441
- style: {
442
- fontSize: 11,
443
- color: '#666',
444
- marginTop: 2,
445
- overflow: 'hidden',
446
- textOverflow: 'ellipsis',
447
- whiteSpace: 'nowrap'
448
- }
449
- }, inc.map(function (c, i) {
458
+ var badgeStyle = {
459
+ color: '#fff',
460
+ padding: '0 4px',
461
+ borderRadius: 2,
462
+ fontSize: 12,
463
+ lineHeight: '18px',
464
+ fontWeight: 'bold',
465
+ flexShrink: 0,
466
+ minWidth: 18,
467
+ textAlign: 'center',
468
+ display: 'inline-block'
469
+ };
470
+ // 4.6:两个 tab 都有值时,按选择 tab 首行规则显示(Include 优先)
471
+ if (firstInclude) {
472
+ var opt = firstInclude.option;
473
+ // 4.2:首行 option 为空或 EQ 不显示符号
474
+ if (!opt || opt === 'EQ') return null;
475
+ var sym = OPTION_SYMBOL[opt];
476
+ if (!sym) return null;
450
477
  return /*#__PURE__*/React.createElement("span", {
451
- key: i,
452
- style: {
453
- marginRight: 4
454
- }
455
- }, c.option && OPTION_SYMBOL[c.option] && /*#__PURE__*/React.createElement("span", {
456
- style: {
457
- background: '#1890ff',
458
- color: '#fff',
459
- padding: '0 2px',
460
- borderRadius: 2
461
- }
462
- }, OPTION_SYMBOL[c.option]), c.low, c.option === 'BT' && c.high ? "~" + c.high : '');
463
- }), exc.map(function (c, i) {
478
+ style: (0, _extends6["default"])({}, badgeStyle, {
479
+ background: '#52c41a'
480
+ })
481
+ }, sym);
482
+ }
483
+ if (firstExclude) {
484
+ var _opt = firstExclude.option;
485
+ // 4.5.2:空 / EQ 也要显示红底 "=" ;其它按 OPTION_SYMBOL 显示
486
+ var _sym = _opt && OPTION_SYMBOL[_opt] || '=';
464
487
  return /*#__PURE__*/React.createElement("span", {
465
- key: i,
466
- style: {
467
- marginRight: 4
468
- }
469
- }, c.option && OPTION_SYMBOL[c.option] && /*#__PURE__*/React.createElement("span", {
470
- style: {
471
- background: '#ff4d4f',
472
- color: '#fff',
473
- padding: '0 2px',
474
- borderRadius: 2
475
- }
476
- }, OPTION_SYMBOL[c.option]), c.low);
477
- }));
488
+ style: (0, _extends6["default"])({}, badgeStyle, {
489
+ background: '#ff4d4f'
490
+ })
491
+ }, _sym);
492
+ }
493
+ return null;
478
494
  };
479
495
  var headerSize = {
480
496
  fontWeight: headerBold ? 'bold' : 'normal',
@@ -544,7 +560,16 @@ var ProSearch = function ProSearch(_ref2) {
544
560
  high: '',
545
561
  conditions: []
546
562
  };
547
- var hasMulti = fv.conditions.length > 0;
563
+ // 4.3:多值按钮高亮条件 = 条件行数达到两行或以上
564
+ var hasMulti = fv.conditions.length >= 2;
565
+ // 4.6:"首行代表" —— 选择 tab 优先;仅排除 tab 有值时取排除 tab 首行
566
+ var firstInclude = fv.conditions.find(function (c) {
567
+ return c.sign === 'I';
568
+ });
569
+ var firstExclude = fv.conditions.find(function (c) {
570
+ return c.sign === 'E';
571
+ });
572
+ var displayCond = firstInclude || firstExclude || null;
548
573
  return /*#__PURE__*/React.createElement("div", {
549
574
  key: field.id,
550
575
  style: {
@@ -563,9 +588,17 @@ var ProSearch = function ProSearch(_ref2) {
563
588
  }
564
589
  }, field.fieldDesc), /*#__PURE__*/React.createElement("div", {
565
590
  style: {
566
- flex: 3
591
+ flex: 3,
592
+ display: 'flex',
593
+ alignItems: 'center',
594
+ gap: 4
595
+ }
596
+ }, renderSignBadge(fv), /*#__PURE__*/React.createElement("div", {
597
+ style: {
598
+ flex: 1,
599
+ minWidth: 0
567
600
  }
568
- }, renderInput(field, 'low'), renderCondSummary(fv)), showHighValue && /*#__PURE__*/React.createElement("div", {
601
+ }, renderInput(field, 'low', displayCond))), showHighValue && /*#__PURE__*/React.createElement("div", {
569
602
  style: {
570
603
  width: 24,
571
604
  textAlign: 'center',
@@ -576,7 +609,7 @@ var ProSearch = function ProSearch(_ref2) {
576
609
  style: {
577
610
  flex: 3
578
611
  }
579
- }, renderInput(field, 'high')), multiValue && /*#__PURE__*/React.createElement("div", {
612
+ }, renderInput(field, 'high', displayCond)), multiValue && /*#__PURE__*/React.createElement("div", {
580
613
  style: {
581
614
  width: 32,
582
615
  textAlign: 'center'
@@ -4,9 +4,5 @@ export declare function getFormContext(): any;
4
4
  export declare const FormProvider: React.FC<{
5
5
  initialValues?: Record<string, any>;
6
6
  onChange?: (values: Record<string, any>) => void;
7
- /** 由 preview 传入:最后一次 onChange(newStructures) 的引用;若与 initialValues 全等则本次为 store 回灌,勿再 merge(根治 #185) */
8
- lastOutboundStructuresRef?: {
9
- current: any;
10
- };
11
7
  children: React.ReactNode;
12
8
  }>;
@@ -39,47 +39,26 @@ var FormProvider = exports.FormProvider = function FormProvider(_ref) {
39
39
  var _ref$initialValues = _ref.initialValues,
40
40
  initialValues = _ref$initialValues === void 0 ? {} : _ref$initialValues,
41
41
  onChange = _ref.onChange,
42
- lastOutboundStructuresRef = _ref.lastOutboundStructuresRef,
43
42
  children = _ref.children;
44
43
  var FormContext = getFormContext();
45
44
 
46
45
  // 使用 ref 缓存初始值
47
46
  var initialValuesRef = useRef(initialValues);
48
- var _useState = useState(initialValues),
47
+
48
+ // 与外部 screenStructures 断开引用,避免逻辑流原地修改 window 对象时污染表单内部 state
49
+ var _useState = useState(function () {
50
+ return (0, _lodash.cloneDeep)(initialValues);
51
+ }),
49
52
  values = _useState[0],
50
53
  setValues = _useState[1];
51
54
 
52
- /** 每次渲染同步,供 initialValues effect 判断「store 是否只是回灌了当前表单已有数据」 */
53
- var valuesRef = useRef(values);
54
- valuesRef.current = values;
55
-
56
55
  /**
57
- * store 每次 dispatch 都会给新的 screenStructures 引用;previewStore 直接把 onChange 的 payload 设为 state(同引用)。
58
- * initialValues === 上次 handleFormChange 推出去的对象,说明只是「表单store → props」回灌,禁止再 merge,否则大表 + Fusion #185。
59
- * 逻辑流 / 接口改数会换对象引用,不会与 lastOutbound 全等。
60
- * 另:setFieldValue 会在微任务里 onChange,回灌前 lastOutbound 已同步为深拷贝对象;若 store 又克隆导致引用不一致,需用深比较兜底。
56
+ * 不能只用 !isEqual:store 对同引用 clone 回灌时,initialValues 是新引用,但与 initialValuesRef 旧对象深比较相等,
57
+ * 会误判「无变化」而不 merge;若表单 values 已是用户 cloneDeep 的副本,不会随原地修改更新逻辑流不回填。
58
+ * 用「引用是否变化」决定是否同步;再用 merged 深比较避免无谓 setState(减轻 Fusion #185)。
61
59
  */
62
60
  useEffect(function () {
63
- if (lastOutboundStructuresRef && initialValues === lastOutboundStructuresRef.current) {
64
- initialValuesRef.current = initialValues;
65
- if (typeof console !== 'undefined' && console.debug) {
66
- console.debug('[FormProvider] skip merge (store ref === last outbound from form)');
67
- }
68
- return;
69
- }
70
- if (lastOutboundStructuresRef !== null && lastOutboundStructuresRef !== void 0 && lastOutboundStructuresRef.current && (0, _lodash.isEqual)(initialValues, lastOutboundStructuresRef.current)) {
71
- initialValuesRef.current = initialValues;
72
- if (typeof console !== 'undefined' && console.debug) {
73
- console.debug('[FormProvider] skip merge (deep-equal to last outbound / store echo)');
74
- }
75
- return;
76
- }
77
- if ((0, _lodash.isEqual)(initialValues, valuesRef.current)) {
78
- initialValuesRef.current = initialValues;
79
- return;
80
- }
81
- if ((0, _lodash.isEqual)(initialValues, initialValuesRef.current)) {
82
- initialValuesRef.current = initialValues;
61
+ if (initialValues === initialValuesRef.current) {
83
62
  return;
84
63
  }
85
64
  console.log('[FormProvider] 🔄 useEffect triggered - initialValues:', initialValues);
@@ -93,7 +72,7 @@ var FormProvider = exports.FormProvider = function FormProvider(_ref) {
93
72
  });
94
73
  }, [initialValues]);
95
74
 
96
- // 优化 setFieldValue(lastOutbound 必须在 onChange 微任务之前写入,供 skip-merge 与 Fusion didUpdate 对齐)
75
+ // 优化 setFieldValue
97
76
  var setFieldValue = useCallback(function (path, value) {
98
77
  setValues(function (prev) {
99
78
  // 使用浅比较检查值是否实际变化
@@ -103,25 +82,19 @@ var FormProvider = exports.FormProvider = function FormProvider(_ref) {
103
82
  var newValues = (0, _lodash.cloneDeep)(prev);
104
83
  (0, _lodash.set)(newValues, path, value);
105
84
  console.log("[FormProvider] \uD83D\uDCDD Set field '" + path + "' to:", value);
106
- if (lastOutboundStructuresRef) {
107
- lastOutboundStructuresRef.current = newValues;
108
- }
85
+
86
+ // 触发 onChange 回调,把新值通知给外部
109
87
  if (onChange) {
88
+ // 对外回传使用副本,避免 preview/window 与 FormProvider 共用同一对象引用
89
+ var outboundValues = (0, _lodash.cloneDeep)(newValues);
90
+ // 使用微任务避免阻塞渲染
110
91
  Promise.resolve().then(function () {
111
- var rd = typeof window !== 'undefined' ? window.ReactDOM : undefined;
112
- var run = function run() {
113
- return onChange(newValues);
114
- };
115
- if (rd && typeof rd.unstable_batchedUpdates === 'function') {
116
- rd.unstable_batchedUpdates(run);
117
- } else {
118
- run();
119
- }
92
+ onChange(outboundValues);
120
93
  });
121
94
  }
122
95
  return newValues;
123
96
  });
124
- }, [onChange, lastOutboundStructuresRef]);
97
+ }, [onChange]);
125
98
 
126
99
  // 使用 useMemo 缓存 context 值
127
100
  var contextValue = useMemo(function () {
@@ -102,7 +102,7 @@ function fillRealVersion(meta, packageName, version, basicLibraryVersion) {
102
102
  packageName = '@openli1115/lowcode-edit-pro-table';
103
103
  }
104
104
  if (version === void 0) {
105
- version = '1.0.88';
105
+ version = '1.0.90';
106
106
  }
107
107
  if (basicLibraryVersion === void 0) {
108
108
  basicLibraryVersion = {
@@ -107,7 +107,7 @@ function fillRealVersion(meta, packageName, version, basicLibraryVersion) {
107
107
  packageName = '@openli1115/lowcode-edit-pro-table';
108
108
  }
109
109
  if (version === void 0) {
110
- version = '1.0.88';
110
+ version = '1.0.90';
111
111
  }
112
112
  if (basicLibraryVersion === void 0) {
113
113
  basicLibraryVersion = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openli1115/lowcode-edit-pro-table",
3
- "version": "1.0.88",
3
+ "version": "1.0.90",
4
4
  "description": "@openli1115/lowcode-edit-pro-table",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -101,10 +101,10 @@
101
101
  },
102
102
  "componentConfig": {
103
103
  "isComponentLibrary": true,
104
- "materialSchema": "https://unpkg.com/@openli1115/lowcode-edit-pro-table@1.0.88/build/lowcode/assets-prod.json"
104
+ "materialSchema": "https://unpkg.com/@openli1115/lowcode-edit-pro-table@1.0.90/build/lowcode/assets-prod.json"
105
105
  },
106
106
  "lcMeta": {
107
107
  "type": "component"
108
108
  },
109
- "homepage": "https://unpkg.com/@openli1115/lowcode-edit-pro-table@1.0.88/build/index.html"
109
+ "homepage": "https://unpkg.com/@openli1115/lowcode-edit-pro-table@1.0.90/build/index.html"
110
110
  }