@dckj-npm/dc-material 0.1.378 → 0.1.379

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.
@@ -111,6 +111,13 @@ export interface SubmitMappingItem {
111
111
  /** 模板字符串(同 computedFields 格式,与 field 二选一),如 "{package_name},{guest_count}人" */
112
112
  template?: string;
113
113
  }
114
+ /** rename 模式:单条字段重命名规则 */
115
+ export interface FieldRenameItem {
116
+ /** 表单字段名(源) */
117
+ fromField: string;
118
+ /** API 参数名(目标) */
119
+ toField: string;
120
+ }
114
121
  /**
115
122
  * 操作按钮配置项(阶段四新增)
116
123
  * 表单底部可配置多个按钮,每个按钮均可独立设置操作类型与数据源。
@@ -138,15 +145,28 @@ export interface OperationItem {
138
145
  buttonProps?: Record<string, any>;
139
146
  }
140
147
  /**
141
- * 提交映射配置(阶段二)
142
- * 配置后,提交时自动将指定字段组装为 { columnName, columnValue }[] 格式并写入 finalValues。
143
- * 消灭手写 onSubmitClick 中的 itemList 拼接逻辑。
148
+ * 提交参数配置(阶段五扩展)
149
+ *
150
+ * 三种工作模式(mode):
151
+ * - 'passthrough':直接将 finalValues 作为请求参数,无需任何配置(字段名与 API 参数名相同时使用)。
152
+ * - 'rename':按 fieldRenameMap 规则重命名指定字段,未列出的字段保持原名透传;
153
+ * 适合字段名与 API 参数名不一致的标准 REST 接口。
154
+ * - 'itemList':将字段转换为动态表单格式 [{columnName, columnValue}],
155
+ * 适合 /source/api/dynamicFormTableRecord/ 等动态表单接口。
156
+ *
157
+ * 向后兼容:未设置 mode 时,若 items 不为空则自动识别为 'itemList' 模式,否则等同于 'passthrough'。
144
158
  */
145
159
  export interface SubmitMapping {
146
- /** 写入 finalValues 的目标字段名,默认 'itemList' */
160
+ /**
161
+ * 参数构建模式,默认 'passthrough'(无 items 时)或 'itemList'(有 items 时,向后兼容)。
162
+ */
163
+ mode?: 'passthrough' | 'rename' | 'itemList';
164
+ /** rename 模式:字段重命名规则列表,未列出的字段按原名透传 */
165
+ fieldRenameMap?: FieldRenameItem[];
166
+ /** itemList 模式:组装结果写入 finalValues 的目标字段名,默认 'itemList' */
147
167
  targetField?: string;
148
- /** 映射规则数组 */
149
- items: SubmitMappingItem[];
168
+ /** itemList 模式:字段映射规则 */
169
+ items?: SubmitMappingItem[];
150
170
  }
151
171
  export interface CustomFormProps extends Omit<FormProps, 'onSubmit' | 'onChange'> {
152
172
  columns?: number;
@@ -10,7 +10,8 @@ import _Select from "@alifd/next/es/select";
10
10
  import _Input from "@alifd/next/es/input";
11
11
  import _ResponsiveGrid from "@alifd/next/es/responsive-grid";
12
12
  import _Form from "@alifd/next/es/form";
13
- var _excluded = ["columns", "spacing", "emptyContent", "formItems", "initialValues", "computedFields", "fieldLinkage", "submitMapping", "fullWidth", "showSubmit", "submitText", "submitValidate", "submitDataSource", "submitButtonProps", "showReset", "resetText", "resetButtonProps", "operations", "operationAlign", "onSubmit", "onSubmitFailed", "onChange", "onReset", "children", "labelAlign", "labelCol", "size"];
13
+ var _excluded = ["format", "showTime"],
14
+ _excluded2 = ["columns", "spacing", "emptyContent", "formItems", "initialValues", "computedFields", "fieldLinkage", "submitMapping", "fullWidth", "showSubmit", "submitText", "submitValidate", "submitDataSource", "submitButtonProps", "showReset", "resetText", "resetButtonProps", "operations", "operationAlign", "onSubmit", "onSubmitFailed", "onChange", "onReset", "children", "labelAlign", "labelCol", "size"];
14
15
  /**
15
16
  * CustomForm v0.5
16
17
  * 阶段一新增能力:
@@ -88,15 +89,24 @@ var UploadAny = _Upload;
88
89
 
89
90
  /** 提交映射 item(阶段二) */
90
91
 
92
+ /** rename 模式:单条字段重命名规则 */
93
+
91
94
  /**
92
95
  * 操作按钮配置项(阶段四新增)
93
96
  * 表单底部可配置多个按钮,每个按钮均可独立设置操作类型与数据源。
94
97
  */
95
98
 
96
99
  /**
97
- * 提交映射配置(阶段二)
98
- * 配置后,提交时自动将指定字段组装为 { columnName, columnValue }[] 格式并写入 finalValues。
99
- * 消灭手写 onSubmitClick 中的 itemList 拼接逻辑。
100
+ * 提交参数配置(阶段五扩展)
101
+ *
102
+ * 三种工作模式(mode):
103
+ * - 'passthrough':直接将 finalValues 作为请求参数,无需任何配置(字段名与 API 参数名相同时使用)。
104
+ * - 'rename':按 fieldRenameMap 规则重命名指定字段,未列出的字段保持原名透传;
105
+ * 适合字段名与 API 参数名不一致的标准 REST 接口。
106
+ * - 'itemList':将字段转换为动态表单格式 [{columnName, columnValue}],
107
+ * 适合 /source/api/dynamicFormTableRecord/ 等动态表单接口。
108
+ *
109
+ * 向后兼容:未设置 mode 时,若 items 不为空则自动识别为 'itemList' 模式,否则等同于 'passthrough'。
100
110
  */
101
111
 
102
112
  // ─── 工具:模板字符串渲染 ─────────────────────────────────────────────────────
@@ -166,6 +176,13 @@ var runSubmitDataSource = function runSubmitDataSource(submitDataSource, values,
166
176
  submitDataSource(values, errors, field);
167
177
  return;
168
178
  }
179
+ // lowcode-engine 数据源对象(this.dataSourceMap.xxx)使用 .load(params) 触发请求。
180
+ // params 会与数据源静态 options.params 合并覆盖;
181
+ // 若 submitMapping 已配置,values 中包含 itemList,可直接覆盖接口默认参数。
182
+ if (typeof (submitDataSource === null || submitDataSource === void 0 ? void 0 : submitDataSource.load) === 'function') {
183
+ submitDataSource.load(values);
184
+ return;
185
+ }
169
186
  if (typeof (submitDataSource === null || submitDataSource === void 0 ? void 0 : submitDataSource.run) === 'function') {
170
187
  submitDataSource.run(values, errors, field);
171
188
  return;
@@ -205,13 +222,29 @@ var renderFormItemComponent = function renderFormItemComponent(item) {
205
222
  case 'NumberPicker':
206
223
  return /*#__PURE__*/React.createElement(NumberPickerAny, componentProps);
207
224
  case 'DatePicker':
208
- return /*#__PURE__*/React.createElement(DatePickerAny, componentProps);
209
- case 'DateTimePicker':
210
- // 日期时间选择器:showTime 开启,格式化为 YYYY-MM-DD HH:mm
211
225
  return /*#__PURE__*/React.createElement(DatePickerAny, _extends({
212
- showTime: true,
213
- format: "YYYY-MM-DD HH:mm"
226
+ format: "YYYY-MM-DD"
214
227
  }, componentProps));
228
+ case 'DateTimePicker':
229
+ {
230
+ // 将 format / showTime 从 componentProps 中单独析构,防止 spread 覆盖我们的计算值
231
+ var cpFormat = componentProps.format,
232
+ _ignoredShowTime = componentProps.showTime,
233
+ restCp = _objectWithoutPropertiesLoose(componentProps, _excluded);
234
+ var dtFmt = cpFormat || 'YYYY-MM-DD HH:mm:ss';
235
+ // 提取日期部分(空格前)和时间部分(空格后)
236
+ // @alifd/next DatePicker 会将 format(日期)与 showTime.format(时间)拼接显示
237
+ // 若把含时间的完整格式传给 format,再传 showTime.format,会导致时间重复显示
238
+ var spaceIdx = dtFmt.indexOf(' ');
239
+ var dateFmt = spaceIdx !== -1 ? dtFmt.slice(0, spaceIdx) : dtFmt;
240
+ var timeFmt = spaceIdx !== -1 ? dtFmt.slice(spaceIdx + 1) : 'HH:mm:ss';
241
+ return /*#__PURE__*/React.createElement(DatePickerAny, _extends({}, restCp, {
242
+ format: dateFmt,
243
+ showTime: {
244
+ format: timeFmt
245
+ }
246
+ }));
247
+ }
215
248
  case 'Upload':
216
249
  return /*#__PURE__*/React.createElement(UploadAny, componentProps);
217
250
  case 'Input':
@@ -257,7 +290,7 @@ var CustomForm = function CustomForm(_ref) {
257
290
  labelAlign = _ref.labelAlign,
258
291
  labelCol = _ref.labelCol,
259
292
  globalSize = _ref.size,
260
- otherProps = _objectWithoutPropertiesLoose(_ref, _excluded);
293
+ otherProps = _objectWithoutPropertiesLoose(_ref, _excluded2);
261
294
  // ─── 直接传递列数,通过 device="desktop" 锁定成桌面模式,防止 ResponsiveGrid 根据视口自动缩列
262
295
  // ResponsiveGrid columns 只接受 number/string,不接受 breakpoint 对象
263
296
  var fixedColumns = columns;
@@ -283,9 +316,9 @@ var CustomForm = function CustomForm(_ref) {
283
316
  var valuesRef = useRef(resolvedInitialValues ? _extends({}, resolvedInitialValues) : {});
284
317
 
285
318
  // ─── 联动回填触发器:用 state 驱动组件重渲染以更新受控字段 ───────────────
286
- var _useState = useState(function () {
287
- return resolvedInitialValues ? _extends({}, resolvedInitialValues) : {};
288
- }),
319
+ // 注意:不预填 resolvedInitialValues,初始值通过 defaultValue(非受控)处理
320
+ // 预填会导致所有有初始值的字段变为受控组件,用户改值后因 linkageValues 未更新而回显旧值
321
+ var _useState = useState({}),
289
322
  linkageValues = _useState[0],
290
323
  setLinkageValues = _useState[1];
291
324
 
@@ -397,27 +430,47 @@ var CustomForm = function CustomForm(_ref) {
397
430
  // 追加 computedFields 衍生字段
398
431
  var finalValues = applyComputedFields(mergedValues, resolvedComputedFields);
399
432
 
400
- // submitMapping:自动组装 itemList 格式(阶段二)
401
- if (submitMapping && submitMapping.items && submitMapping.items.length > 0) {
402
- var _extends3;
403
- var targetField = submitMapping.targetField || 'itemList';
404
- var itemList = submitMapping.items.map(function (mappingItem) {
405
- var columnValue;
406
- if (mappingItem.field) {
407
- var _finalValues$mappingI;
408
- columnValue = (_finalValues$mappingI = finalValues[mappingItem.field]) !== null && _finalValues$mappingI !== void 0 ? _finalValues$mappingI : '';
409
- } else if (mappingItem.template) {
410
- columnValue = renderTemplate(mappingItem.template, finalValues);
411
- } else {
412
- columnValue = '';
413
- }
414
- return {
415
- columnName: mappingItem.columnName,
416
- columnValue: columnValue
417
- };
418
- });
419
- finalValues = _extends({}, finalValues, (_extends3 = {}, _extends3[targetField] = itemList, _extends3));
420
- cfLog('submitMapping', "\u5DF2\u751F\u6210 " + targetField, itemList);
433
+ // submitMapping:按 mode 构建请求参数(阶段五)
434
+ if (submitMapping) {
435
+ var _submitMapping$mode, _submitMapping$items, _submitMapping$fieldR, _submitMapping$items2;
436
+ // 向后兼容:未设置 mode 时,有 items 数组则默认 itemList,否则 passthrough
437
+ var mode = (_submitMapping$mode = submitMapping.mode) !== null && _submitMapping$mode !== void 0 ? _submitMapping$mode : (_submitMapping$items = submitMapping.items) !== null && _submitMapping$items !== void 0 && _submitMapping$items.length ? 'itemList' : 'passthrough';
438
+ if (mode === 'rename' && (_submitMapping$fieldR = submitMapping.fieldRenameMap) !== null && _submitMapping$fieldR !== void 0 && _submitMapping$fieldR.length) {
439
+ // ── rename:重命名指定字段,其余字段按原名透传
440
+ var renamed = _extends({}, finalValues);
441
+ submitMapping.fieldRenameMap.forEach(function (_ref3) {
442
+ var fromField = _ref3.fromField,
443
+ toField = _ref3.toField;
444
+ if (fromField && toField && fromField in renamed) {
445
+ renamed[toField] = renamed[fromField];
446
+ if (fromField !== toField) delete renamed[fromField];
447
+ }
448
+ });
449
+ finalValues = renamed;
450
+ cfLog('submitMapping', 'rename 模式字段重命名完成', finalValues);
451
+ } else if (mode === 'itemList' && (_submitMapping$items2 = submitMapping.items) !== null && _submitMapping$items2 !== void 0 && _submitMapping$items2.length) {
452
+ var _extends3;
453
+ // ── itemList:转换为动态表单格式 [{columnName, columnValue}]
454
+ var targetField = submitMapping.targetField || 'itemList';
455
+ var itemList = submitMapping.items.map(function (mappingItem) {
456
+ var columnValue;
457
+ if (mappingItem.field) {
458
+ var _finalValues$mappingI;
459
+ columnValue = (_finalValues$mappingI = finalValues[mappingItem.field]) !== null && _finalValues$mappingI !== void 0 ? _finalValues$mappingI : '';
460
+ } else if (mappingItem.template) {
461
+ columnValue = renderTemplate(mappingItem.template, finalValues);
462
+ } else {
463
+ columnValue = '';
464
+ }
465
+ return {
466
+ columnName: mappingItem.columnName,
467
+ columnValue: columnValue
468
+ };
469
+ });
470
+ finalValues = _extends({}, finalValues, (_extends3 = {}, _extends3[targetField] = itemList, _extends3));
471
+ cfLog('submitMapping', "itemList \u6A21\u5F0F\u5DF2\u751F\u6210 " + targetField, itemList);
472
+ }
473
+ // passthrough: finalValues 直接作为请求参数,无需处理
421
474
  }
422
475
  cfLog('submit', '提交触发', {
423
476
  rawValues: values,
@@ -467,7 +520,14 @@ var CustomForm = function CustomForm(_ref) {
467
520
  if (typeof ((_item$componentProps2 = item.componentProps) === null || _item$componentProps2 === void 0 ? void 0 : _item$componentProps2.onChange) === 'function') {
468
521
  item.componentProps.onChange(value);
469
522
  }
470
- handleFieldChange(item.field, value);
523
+ // DatePicker / DateTimePicker 的 onChange 返回 Moment 对象,需格式化为字符串后再存储
524
+ var storedValue = value;
525
+ if (['DatePicker', 'DateTimePicker'].includes(item.componentType) && value && typeof value.format === 'function') {
526
+ var _item$componentProps3;
527
+ var fmt = ((_item$componentProps3 = item.componentProps) === null || _item$componentProps3 === void 0 ? void 0 : _item$componentProps3.format) || (item.componentType === 'DateTimePicker' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD');
528
+ storedValue = value.format(fmt);
529
+ }
530
+ handleFieldChange(item.field, storedValue);
471
531
  }
472
532
  });
473
533
 
@@ -111,6 +111,13 @@ export interface SubmitMappingItem {
111
111
  /** 模板字符串(同 computedFields 格式,与 field 二选一),如 "{package_name},{guest_count}人" */
112
112
  template?: string;
113
113
  }
114
+ /** rename 模式:单条字段重命名规则 */
115
+ export interface FieldRenameItem {
116
+ /** 表单字段名(源) */
117
+ fromField: string;
118
+ /** API 参数名(目标) */
119
+ toField: string;
120
+ }
114
121
  /**
115
122
  * 操作按钮配置项(阶段四新增)
116
123
  * 表单底部可配置多个按钮,每个按钮均可独立设置操作类型与数据源。
@@ -138,15 +145,28 @@ export interface OperationItem {
138
145
  buttonProps?: Record<string, any>;
139
146
  }
140
147
  /**
141
- * 提交映射配置(阶段二)
142
- * 配置后,提交时自动将指定字段组装为 { columnName, columnValue }[] 格式并写入 finalValues。
143
- * 消灭手写 onSubmitClick 中的 itemList 拼接逻辑。
148
+ * 提交参数配置(阶段五扩展)
149
+ *
150
+ * 三种工作模式(mode):
151
+ * - 'passthrough':直接将 finalValues 作为请求参数,无需任何配置(字段名与 API 参数名相同时使用)。
152
+ * - 'rename':按 fieldRenameMap 规则重命名指定字段,未列出的字段保持原名透传;
153
+ * 适合字段名与 API 参数名不一致的标准 REST 接口。
154
+ * - 'itemList':将字段转换为动态表单格式 [{columnName, columnValue}],
155
+ * 适合 /source/api/dynamicFormTableRecord/ 等动态表单接口。
156
+ *
157
+ * 向后兼容:未设置 mode 时,若 items 不为空则自动识别为 'itemList' 模式,否则等同于 'passthrough'。
144
158
  */
145
159
  export interface SubmitMapping {
146
- /** 写入 finalValues 的目标字段名,默认 'itemList' */
160
+ /**
161
+ * 参数构建模式,默认 'passthrough'(无 items 时)或 'itemList'(有 items 时,向后兼容)。
162
+ */
163
+ mode?: 'passthrough' | 'rename' | 'itemList';
164
+ /** rename 模式:字段重命名规则列表,未列出的字段按原名透传 */
165
+ fieldRenameMap?: FieldRenameItem[];
166
+ /** itemList 模式:组装结果写入 finalValues 的目标字段名,默认 'itemList' */
147
167
  targetField?: string;
148
- /** 映射规则数组 */
149
- items: SubmitMappingItem[];
168
+ /** itemList 模式:字段映射规则 */
169
+ items?: SubmitMappingItem[];
150
170
  }
151
171
  export interface CustomFormProps extends Omit<FormProps, 'onSubmit' | 'onChange'> {
152
172
  columns?: number;
@@ -17,7 +17,8 @@ var _responsiveGrid = _interopRequireDefault(require("@alifd/next/lib/responsive
17
17
  var _form = _interopRequireDefault(require("@alifd/next/lib/form"));
18
18
  var _react = _interopRequireWildcard(require("react"));
19
19
  require("./index.scss");
20
- var _excluded = ["columns", "spacing", "emptyContent", "formItems", "initialValues", "computedFields", "fieldLinkage", "submitMapping", "fullWidth", "showSubmit", "submitText", "submitValidate", "submitDataSource", "submitButtonProps", "showReset", "resetText", "resetButtonProps", "operations", "operationAlign", "onSubmit", "onSubmitFailed", "onChange", "onReset", "children", "labelAlign", "labelCol", "size"];
20
+ var _excluded = ["format", "showTime"],
21
+ _excluded2 = ["columns", "spacing", "emptyContent", "formItems", "initialValues", "computedFields", "fieldLinkage", "submitMapping", "fullWidth", "showSubmit", "submitText", "submitValidate", "submitDataSource", "submitButtonProps", "showReset", "resetText", "resetButtonProps", "operations", "operationAlign", "onSubmit", "onSubmitFailed", "onChange", "onReset", "children", "labelAlign", "labelCol", "size"];
21
22
  /**
22
23
  * CustomForm v0.5
23
24
  * 阶段一新增能力:
@@ -94,15 +95,24 @@ var UploadAny = _upload["default"];
94
95
 
95
96
  /** 提交映射 item(阶段二) */
96
97
 
98
+ /** rename 模式:单条字段重命名规则 */
99
+
97
100
  /**
98
101
  * 操作按钮配置项(阶段四新增)
99
102
  * 表单底部可配置多个按钮,每个按钮均可独立设置操作类型与数据源。
100
103
  */
101
104
 
102
105
  /**
103
- * 提交映射配置(阶段二)
104
- * 配置后,提交时自动将指定字段组装为 { columnName, columnValue }[] 格式并写入 finalValues。
105
- * 消灭手写 onSubmitClick 中的 itemList 拼接逻辑。
106
+ * 提交参数配置(阶段五扩展)
107
+ *
108
+ * 三种工作模式(mode):
109
+ * - 'passthrough':直接将 finalValues 作为请求参数,无需任何配置(字段名与 API 参数名相同时使用)。
110
+ * - 'rename':按 fieldRenameMap 规则重命名指定字段,未列出的字段保持原名透传;
111
+ * 适合字段名与 API 参数名不一致的标准 REST 接口。
112
+ * - 'itemList':将字段转换为动态表单格式 [{columnName, columnValue}],
113
+ * 适合 /source/api/dynamicFormTableRecord/ 等动态表单接口。
114
+ *
115
+ * 向后兼容:未设置 mode 时,若 items 不为空则自动识别为 'itemList' 模式,否则等同于 'passthrough'。
106
116
  */
107
117
 
108
118
  // ─── 工具:模板字符串渲染 ─────────────────────────────────────────────────────
@@ -172,6 +182,13 @@ var runSubmitDataSource = function runSubmitDataSource(submitDataSource, values,
172
182
  submitDataSource(values, errors, field);
173
183
  return;
174
184
  }
185
+ // lowcode-engine 数据源对象(this.dataSourceMap.xxx)使用 .load(params) 触发请求。
186
+ // params 会与数据源静态 options.params 合并覆盖;
187
+ // 若 submitMapping 已配置,values 中包含 itemList,可直接覆盖接口默认参数。
188
+ if (typeof (submitDataSource === null || submitDataSource === void 0 ? void 0 : submitDataSource.load) === 'function') {
189
+ submitDataSource.load(values);
190
+ return;
191
+ }
175
192
  if (typeof (submitDataSource === null || submitDataSource === void 0 ? void 0 : submitDataSource.run) === 'function') {
176
193
  submitDataSource.run(values, errors, field);
177
194
  return;
@@ -211,13 +228,29 @@ var renderFormItemComponent = function renderFormItemComponent(item) {
211
228
  case 'NumberPicker':
212
229
  return /*#__PURE__*/_react["default"].createElement(NumberPickerAny, componentProps);
213
230
  case 'DatePicker':
214
- return /*#__PURE__*/_react["default"].createElement(DatePickerAny, componentProps);
215
- case 'DateTimePicker':
216
- // 日期时间选择器:showTime 开启,格式化为 YYYY-MM-DD HH:mm
217
231
  return /*#__PURE__*/_react["default"].createElement(DatePickerAny, (0, _extends4["default"])({
218
- showTime: true,
219
- format: "YYYY-MM-DD HH:mm"
232
+ format: "YYYY-MM-DD"
220
233
  }, componentProps));
234
+ case 'DateTimePicker':
235
+ {
236
+ // 将 format / showTime 从 componentProps 中单独析构,防止 spread 覆盖我们的计算值
237
+ var cpFormat = componentProps.format,
238
+ _ignoredShowTime = componentProps.showTime,
239
+ restCp = (0, _objectWithoutPropertiesLoose2["default"])(componentProps, _excluded);
240
+ var dtFmt = cpFormat || 'YYYY-MM-DD HH:mm:ss';
241
+ // 提取日期部分(空格前)和时间部分(空格后)
242
+ // @alifd/next DatePicker 会将 format(日期)与 showTime.format(时间)拼接显示
243
+ // 若把含时间的完整格式传给 format,再传 showTime.format,会导致时间重复显示
244
+ var spaceIdx = dtFmt.indexOf(' ');
245
+ var dateFmt = spaceIdx !== -1 ? dtFmt.slice(0, spaceIdx) : dtFmt;
246
+ var timeFmt = spaceIdx !== -1 ? dtFmt.slice(spaceIdx + 1) : 'HH:mm:ss';
247
+ return /*#__PURE__*/_react["default"].createElement(DatePickerAny, (0, _extends4["default"])({}, restCp, {
248
+ format: dateFmt,
249
+ showTime: {
250
+ format: timeFmt
251
+ }
252
+ }));
253
+ }
221
254
  case 'Upload':
222
255
  return /*#__PURE__*/_react["default"].createElement(UploadAny, componentProps);
223
256
  case 'Input':
@@ -263,7 +296,7 @@ var CustomForm = function CustomForm(_ref) {
263
296
  labelAlign = _ref.labelAlign,
264
297
  labelCol = _ref.labelCol,
265
298
  globalSize = _ref.size,
266
- otherProps = (0, _objectWithoutPropertiesLoose2["default"])(_ref, _excluded);
299
+ otherProps = (0, _objectWithoutPropertiesLoose2["default"])(_ref, _excluded2);
267
300
  // ─── 直接传递列数,通过 device="desktop" 锁定成桌面模式,防止 ResponsiveGrid 根据视口自动缩列
268
301
  // ResponsiveGrid columns 只接受 number/string,不接受 breakpoint 对象
269
302
  var fixedColumns = columns;
@@ -289,9 +322,9 @@ var CustomForm = function CustomForm(_ref) {
289
322
  var valuesRef = (0, _react.useRef)(resolvedInitialValues ? (0, _extends4["default"])({}, resolvedInitialValues) : {});
290
323
 
291
324
  // ─── 联动回填触发器:用 state 驱动组件重渲染以更新受控字段 ───────────────
292
- var _useState = (0, _react.useState)(function () {
293
- return resolvedInitialValues ? (0, _extends4["default"])({}, resolvedInitialValues) : {};
294
- }),
325
+ // 注意:不预填 resolvedInitialValues,初始值通过 defaultValue(非受控)处理
326
+ // 预填会导致所有有初始值的字段变为受控组件,用户改值后因 linkageValues 未更新而回显旧值
327
+ var _useState = (0, _react.useState)({}),
295
328
  linkageValues = _useState[0],
296
329
  setLinkageValues = _useState[1];
297
330
 
@@ -403,27 +436,47 @@ var CustomForm = function CustomForm(_ref) {
403
436
  // 追加 computedFields 衍生字段
404
437
  var finalValues = applyComputedFields(mergedValues, resolvedComputedFields);
405
438
 
406
- // submitMapping:自动组装 itemList 格式(阶段二)
407
- if (submitMapping && submitMapping.items && submitMapping.items.length > 0) {
408
- var _extends3;
409
- var targetField = submitMapping.targetField || 'itemList';
410
- var itemList = submitMapping.items.map(function (mappingItem) {
411
- var columnValue;
412
- if (mappingItem.field) {
413
- var _finalValues$mappingI;
414
- columnValue = (_finalValues$mappingI = finalValues[mappingItem.field]) !== null && _finalValues$mappingI !== void 0 ? _finalValues$mappingI : '';
415
- } else if (mappingItem.template) {
416
- columnValue = renderTemplate(mappingItem.template, finalValues);
417
- } else {
418
- columnValue = '';
419
- }
420
- return {
421
- columnName: mappingItem.columnName,
422
- columnValue: columnValue
423
- };
424
- });
425
- finalValues = (0, _extends4["default"])({}, finalValues, (_extends3 = {}, _extends3[targetField] = itemList, _extends3));
426
- cfLog('submitMapping', "\u5DF2\u751F\u6210 " + targetField, itemList);
439
+ // submitMapping:按 mode 构建请求参数(阶段五)
440
+ if (submitMapping) {
441
+ var _submitMapping$mode, _submitMapping$items, _submitMapping$fieldR, _submitMapping$items2;
442
+ // 向后兼容:未设置 mode 时,有 items 数组则默认 itemList,否则 passthrough
443
+ var mode = (_submitMapping$mode = submitMapping.mode) !== null && _submitMapping$mode !== void 0 ? _submitMapping$mode : (_submitMapping$items = submitMapping.items) !== null && _submitMapping$items !== void 0 && _submitMapping$items.length ? 'itemList' : 'passthrough';
444
+ if (mode === 'rename' && (_submitMapping$fieldR = submitMapping.fieldRenameMap) !== null && _submitMapping$fieldR !== void 0 && _submitMapping$fieldR.length) {
445
+ // ── rename:重命名指定字段,其余字段按原名透传
446
+ var renamed = (0, _extends4["default"])({}, finalValues);
447
+ submitMapping.fieldRenameMap.forEach(function (_ref3) {
448
+ var fromField = _ref3.fromField,
449
+ toField = _ref3.toField;
450
+ if (fromField && toField && fromField in renamed) {
451
+ renamed[toField] = renamed[fromField];
452
+ if (fromField !== toField) delete renamed[fromField];
453
+ }
454
+ });
455
+ finalValues = renamed;
456
+ cfLog('submitMapping', 'rename 模式字段重命名完成', finalValues);
457
+ } else if (mode === 'itemList' && (_submitMapping$items2 = submitMapping.items) !== null && _submitMapping$items2 !== void 0 && _submitMapping$items2.length) {
458
+ var _extends3;
459
+ // ── itemList:转换为动态表单格式 [{columnName, columnValue}]
460
+ var targetField = submitMapping.targetField || 'itemList';
461
+ var itemList = submitMapping.items.map(function (mappingItem) {
462
+ var columnValue;
463
+ if (mappingItem.field) {
464
+ var _finalValues$mappingI;
465
+ columnValue = (_finalValues$mappingI = finalValues[mappingItem.field]) !== null && _finalValues$mappingI !== void 0 ? _finalValues$mappingI : '';
466
+ } else if (mappingItem.template) {
467
+ columnValue = renderTemplate(mappingItem.template, finalValues);
468
+ } else {
469
+ columnValue = '';
470
+ }
471
+ return {
472
+ columnName: mappingItem.columnName,
473
+ columnValue: columnValue
474
+ };
475
+ });
476
+ finalValues = (0, _extends4["default"])({}, finalValues, (_extends3 = {}, _extends3[targetField] = itemList, _extends3));
477
+ cfLog('submitMapping', "itemList \u6A21\u5F0F\u5DF2\u751F\u6210 " + targetField, itemList);
478
+ }
479
+ // passthrough: finalValues 直接作为请求参数,无需处理
427
480
  }
428
481
  cfLog('submit', '提交触发', {
429
482
  rawValues: values,
@@ -473,7 +526,14 @@ var CustomForm = function CustomForm(_ref) {
473
526
  if (typeof ((_item$componentProps2 = item.componentProps) === null || _item$componentProps2 === void 0 ? void 0 : _item$componentProps2.onChange) === 'function') {
474
527
  item.componentProps.onChange(value);
475
528
  }
476
- handleFieldChange(item.field, value);
529
+ // DatePicker / DateTimePicker 的 onChange 返回 Moment 对象,需格式化为字符串后再存储
530
+ var storedValue = value;
531
+ if (['DatePicker', 'DateTimePicker'].includes(item.componentType) && value && typeof value.format === 'function') {
532
+ var _item$componentProps3;
533
+ var fmt = ((_item$componentProps3 = item.componentProps) === null || _item$componentProps3 === void 0 ? void 0 : _item$componentProps3.format) || (item.componentType === 'DateTimePicker' ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD');
534
+ storedValue = value.format(fmt);
535
+ }
536
+ handleFieldChange(item.field, storedValue);
477
537
  }
478
538
  });
479
539