@tmagic/form 1.8.0-beta.23 → 1.8.0-beta.25

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.
@@ -1,7 +1,8 @@
1
- import { FORM_DIFF_CONFIG_KEY, FORM_TYPE_MATCH_VALID_KEY } from "../schema.js";
1
+ import { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY } from "../schema.js";
2
2
  import { createObjectProp, display, filterFunction, getRules } from "../utils/form.js";
3
3
  import Hidden_default from "../fields/Hidden.js";
4
4
  import { getField } from "../utils/config.js";
5
+ import { getSilentLeafFieldTypes } from "../utils/silentLeafFieldTypes.js";
5
6
  import FormLabel_default from "./FormLabel.js";
6
7
  import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, inject, mergeProps, normalizeClass, normalizeStyle, openBlock, provide, readonly, ref, renderList, renderSlot, resolveComponent, resolveDynamicComponent, toDisplayString, toRaw, unref, watch, watchEffect, withCtx } from "vue";
7
8
  import { isEqual } from "lodash-es";
@@ -117,6 +118,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
117
118
  return new Set(DEFAULT_SELF_DIFF_FIELD_TYPES);
118
119
  });
119
120
  const isSelfDiffField = computed(() => effectiveSelfDiffFieldTypes.value.has(type.value));
121
+ const silentMode = inject(FORM_SILENT_MODE_KEY, false);
122
+ const shouldRenderLeafField = computed(() => !silentMode || !getSilentLeafFieldTypes().has(type.value));
120
123
  const disabled = computed(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
121
124
  const text = computed(() => filterFunction(mForm, props.config.text, props));
122
125
  const tooltip = computed(() => {
@@ -292,7 +295,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
292
295
  "label-width",
293
296
  "style"
294
297
  ])) : type.value && display$1.value && !showDiff.value ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(unref(TMagicFormItem), mergeProps(formItemProps.value, { class: { "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value } }), {
295
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
298
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
296
299
  config: __props.config,
297
300
  type: type.value,
298
301
  text: text.value,
@@ -310,8 +313,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
310
313
  "use-label",
311
314
  "label-title",
312
315
  "text"
313
- ]), __props.config.titleExtra && __props.config.labelPosition === "top" ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(__props.config.titleExtra), 1)) : createCommentVNode("v-if", true)])]),
314
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
316
+ ]), __props.config.titleExtra && __props.config.labelPosition === "top" ? (openBlock(), createElementBlock("span", _hoisted_2, toDisplayString(__props.config.titleExtra), 1)) : createCommentVNode("v-if", true)], void 0, 0) : createCommentVNode("v-if", true)]),
317
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
315
318
  key: 0,
316
319
  placement: tooltip.value.placement
317
320
  }, {
@@ -338,9 +341,9 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
338
341
  "model",
339
342
  "last-values",
340
343
  "is-compare"
341
- ]))]),
344
+ ]))], 64)) : createCommentVNode("v-if", true)]),
342
345
  _: 3
343
- }, 16, ["class"]), __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
346
+ }, 16, ["class"]), shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
344
347
  key: 0,
345
348
  placement: "top"
346
349
  }, {
@@ -360,7 +363,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
360
363
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
361
364
  "self-diff": true
362
365
  } }), {
363
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
366
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
364
367
  config: __props.config,
365
368
  type: type.value,
366
369
  text: text.value,
@@ -378,8 +381,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
378
381
  "use-label",
379
382
  "label-title",
380
383
  "text"
381
- ])])]),
382
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
384
+ ])], void 0, 0) : createCommentVNode("v-if", true)]),
385
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
383
386
  key: 0,
384
387
  placement: tooltip.value.placement
385
388
  }, {
@@ -404,7 +407,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
404
407
  "model",
405
408
  "last-values",
406
409
  "is-compare"
407
- ]))]),
410
+ ]))], 64)) : createCommentVNode("v-if", true)]),
408
411
  _: 3
409
412
  }, 16, ["class"])) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
410
413
  createCommentVNode(" 普通字段:渲染前后两份独立的组件用于对比 "),
@@ -413,7 +416,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
413
416
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
414
417
  "show-before-diff": true
415
418
  } }), {
416
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
419
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
417
420
  config: __props.config,
418
421
  type: type.value,
419
422
  text: text.value,
@@ -431,8 +434,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
431
434
  "use-label",
432
435
  "label-title",
433
436
  "text"
434
- ])])]),
435
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
437
+ ])], void 0, 0) : createCommentVNode("v-if", true)]),
438
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
436
439
  key: 0,
437
440
  placement: tooltip.value.placement
438
441
  }, {
@@ -445,10 +448,10 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
445
448
  }, 8, ["placement"])) : (openBlock(), createBlock(resolveDynamicComponent(tagName.value), mergeProps({ key: 1 }, fieldsProps.value, {
446
449
  model: __props.lastValues,
447
450
  onChange: onChangeHandler
448
- }), null, 16, ["model"]))]),
451
+ }), null, 16, ["model"]))], 64)) : createCommentVNode("v-if", true)]),
449
452
  _: 3
450
453
  }, 16, ["class"]),
451
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
454
+ shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
452
455
  key: 0,
453
456
  placement: "top"
454
457
  }, {
@@ -470,7 +473,7 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
470
473
  "show-after-diff": true
471
474
  }
472
475
  }), {
473
- label: withCtx(() => [renderSlot(_ctx.$slots, "label", {
476
+ label: withCtx(() => [shouldRenderLeafField.value ? renderSlot(_ctx.$slots, "label", {
474
477
  config: __props.config,
475
478
  type: type.value,
476
479
  text: text.value,
@@ -488,8 +491,8 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
488
491
  "use-label",
489
492
  "label-title",
490
493
  "text"
491
- ])])]),
492
- default: withCtx(() => [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
494
+ ])], void 0, 0) : createCommentVNode("v-if", true)]),
495
+ default: withCtx(() => [shouldRenderLeafField.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [tooltip.value.text ? (openBlock(), createBlock(unref(TMagicTooltip), {
493
496
  key: 0,
494
497
  placement: tooltip.value.placement
495
498
  }, {
@@ -502,10 +505,10 @@ var Container_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
502
505
  }, 8, ["placement"])) : (openBlock(), createBlock(resolveDynamicComponent(tagName.value), mergeProps({ key: 1 }, fieldsProps.value, {
503
506
  model: __props.model,
504
507
  onChange: onChangeHandler
505
- }), null, 16, ["model"]))]),
508
+ }), null, 16, ["model"]))], 64)) : createCommentVNode("v-if", true)]),
506
509
  _: 3
507
510
  }, 16, ["style", "class"]),
508
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
511
+ shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? (openBlock(), createBlock(unref(TMagicTooltip), {
509
512
  key: 1,
510
513
  placement: "top"
511
514
  }, {
package/dist/es/index.js CHANGED
@@ -4,6 +4,7 @@ import { adaptFormValidator, applyExtendState, createObjectProp, createValues, d
4
4
  import { useAddField } from "./utils/useAddField.js";
5
5
  import Hidden_default from "./fields/Hidden.js";
6
6
  import { deleteField, getField, registerField } from "./utils/config.js";
7
+ import { clearSilentLeafFieldTypes, getSilentLeafFieldTypes, registerSilentLeafFieldTypes } from "./utils/silentLeafFieldTypes.js";
7
8
  import Container_default from "./containers/Container.js";
8
9
  import Form_default from "./Form.js";
9
10
  import { stripTabItemsLazy, submitForm, validateForm } from "./submitForm.js";
@@ -40,4 +41,4 @@ export * from "@tmagic/form-schema";
40
41
  //#region packages/form/src/index.ts
41
42
  var createForm = (config) => config;
42
43
  //#endregion
43
- export { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, MAX_SUGGESTION_OPTIONS, Cascader_default as MCascader, Checkbox_default as MCheckbox, CheckboxGroup_default as MCheckboxGroup, ColorPicker_default as MColorPicker, Container_default as MContainer, Date_default as MDate, DateTime_default as MDateTime, Daterange_default as MDaterange, Display_default as MDisplay, DynamicField_default as MDynamicField, Fieldset_default as MFieldset, FlexLayout_default as MFlexLayout, Form_default as MForm, FormBox_default as MFormBox, FormDialog_default as MFormDialog, FormDrawer_default as MFormDrawer, TableGroupList_default as MGroupList, Hidden_default as MHidden, Link_default as MLink, Number_default as MNumber, NumberRange_default as MNumberRange, Panel_default as MPanel, RadioGroup_default as MRadioGroup, Row_default as MRow, Select_default as MSelect, Switch_default as MSwitch, TableGroupList_default as MTable, TableGroupList_default as MTableGroupList, Tabs_default as MTabs, Text_default as MText, Textarea_default as MTextarea, Time_default as MTime, Timerange_default as MTimerange, adaptFormValidator, applyExtendState, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, plugin_default as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
44
+ export { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, MAX_SUGGESTION_OPTIONS, Cascader_default as MCascader, Checkbox_default as MCheckbox, CheckboxGroup_default as MCheckboxGroup, ColorPicker_default as MColorPicker, Container_default as MContainer, Date_default as MDate, DateTime_default as MDateTime, Daterange_default as MDaterange, Display_default as MDisplay, DynamicField_default as MDynamicField, Fieldset_default as MFieldset, FlexLayout_default as MFlexLayout, Form_default as MForm, FormBox_default as MFormBox, FormDialog_default as MFormDialog, FormDrawer_default as MFormDrawer, TableGroupList_default as MGroupList, Hidden_default as MHidden, Link_default as MLink, Number_default as MNumber, NumberRange_default as MNumberRange, Panel_default as MPanel, RadioGroup_default as MRadioGroup, Row_default as MRow, Select_default as MSelect, Switch_default as MSwitch, TableGroupList_default as MTable, TableGroupList_default as MTableGroupList, Tabs_default as MTabs, Text_default as MText, Textarea_default as MTextarea, Time_default as MTime, Timerange_default as MTimerange, adaptFormValidator, applyExtendState, clearSilentLeafFieldTypes, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, plugin_default as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getSilentLeafFieldTypes, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerSilentLeafFieldTypes, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
package/dist/es/schema.js CHANGED
@@ -5,11 +5,12 @@ var FORM_TYPE_MATCH_VALID_KEY = Symbol("mFormTypeMatchValid");
5
5
  /**
6
6
  * 静默模式标记,由 `submitForm` / `validateForm` 以隐藏方式挂载临时表单时 provide(debug 弹层模式不提供)。
7
7
  *
8
- * 重型字段组件(如 vs-code)可 inject 该标记并跳过自身渲染:字段校验由 FormItem 基于 model 值完成,
9
- * 与叶子 UI 组件实例无关,跳过可省去无谓的实例化开销(如 monaco worker / model 的创建)。
8
+ * Container 会基于该标记,并对照 `getSilentLeafFieldTypes()`(默认 `LEAF_FIELD_TYPES`)
9
+ * 跳过叶子字段的渲染,只保留 FormItem:字段校验由 FormItem 基于 model 值完成,与叶子 UI 组件实例无关。
10
+ * 重型字段组件(如 vs-code)也可 inject 该标记跳过自身渲染,省去无谓的实例化开销。
10
11
  *
11
12
  * 注意:仅「挂载无值副作用」(不在 onMounted/watch immediate 中 emit change、不依赖 DOM 计算值)的
12
- * 字段组件可以安全跳过,接入前需逐一审计。
13
+ * 字段组件可以安全跳过,接入前需逐一审计;业务扩展请使用 `registerSilentLeafFieldTypes`。
13
14
  */
14
15
  var FORM_SILENT_MODE_KEY = Symbol("mFormSilentMode");
15
16
  //#endregion
package/dist/es/style.css CHANGED
@@ -427,7 +427,11 @@ fieldset.m-fieldset .m-form-tip {
427
427
  .m-form-box .el-box__header {
428
428
  margin: 0;
429
429
  }
430
+ .m-form-box .m-box-body {
431
+ min-height: 0;
432
+ }
430
433
  .m-form-box .dialog-footer {
434
+ flex-shrink: 0;
431
435
  display: flex;
432
436
  align-items: center;
433
437
  justify-content: space-between;
@@ -0,0 +1,49 @@
1
+ import { toLine } from "@tmagic/utils";
2
+ //#region packages/form/src/utils/silentLeafFieldTypes.ts
3
+ /**
4
+ * 可在静默校验模式下跳过渲染的内置叶子字段(默认集合)。
5
+ *
6
+ * 这些字段只渲染一个输入控件,内部没有嵌套 FormItem,且不会依赖组件挂载修改 model;
7
+ * 字段值由初始化逻辑处理(包括 defaultValue),因此跳过不影响校验结果。
8
+ *
9
+ * 业务侧可通过 `registerSilentLeafFieldTypes` 追加已审计的安全自定义字段。
10
+ */
11
+ var LEAF_FIELD_TYPES = /* @__PURE__ */ new Set([
12
+ "text",
13
+ "textarea",
14
+ "number",
15
+ "time",
16
+ "daterange",
17
+ "timerange",
18
+ "checkbox",
19
+ "radio-group",
20
+ "switch",
21
+ "select",
22
+ "cascader",
23
+ "color-picker",
24
+ "link"
25
+ ]);
26
+ /** 业务侧追加的静默叶子字段(不含内置默认集合) */
27
+ var extraSilentLeafFieldTypes = /* @__PURE__ */ new Set();
28
+ /**
29
+ * 注册可在静默校验中跳过渲染的叶子字段 type(追加到默认 `LEAF_FIELD_TYPES` 之上)。
30
+ *
31
+ * 仅应纳入「无嵌套 FormItem、无挂载值副作用」的字段;复合 / 动态子表单不可加入。
32
+ */
33
+ var registerSilentLeafFieldTypes = (types) => {
34
+ for (const type of types) {
35
+ if (typeof type !== "string" || !type) continue;
36
+ extraSilentLeafFieldTypes.add(toLine(type));
37
+ }
38
+ };
39
+ /** 当前生效的静默叶子字段集合:内置默认 ∪ 已注册扩展 */
40
+ var getSilentLeafFieldTypes = () => {
41
+ if (extraSilentLeafFieldTypes.size === 0) return LEAF_FIELD_TYPES;
42
+ return /* @__PURE__ */ new Set([...LEAF_FIELD_TYPES, ...extraSilentLeafFieldTypes]);
43
+ };
44
+ /** 清空业务侧追加的静默叶子字段(不影响内置默认集合;主要用于单测) */
45
+ var clearSilentLeafFieldTypes = () => {
46
+ extraSilentLeafFieldTypes.clear();
47
+ };
48
+ //#endregion
49
+ export { LEAF_FIELD_TYPES, clearSilentLeafFieldTypes, getSilentLeafFieldTypes, registerSilentLeafFieldTypes };
package/dist/style.css CHANGED
@@ -427,7 +427,11 @@ fieldset.m-fieldset .m-form-tip {
427
427
  .m-form-box .el-box__header {
428
428
  margin: 0;
429
429
  }
430
+ .m-form-box .m-box-body {
431
+ min-height: 0;
432
+ }
430
433
  .m-form-box .dialog-footer {
434
+ flex-shrink: 0;
431
435
  display: flex;
432
436
  align-items: center;
433
437
  justify-content: space-between;
@@ -427,7 +427,11 @@ fieldset.m-fieldset .m-form-tip {
427
427
  .m-form-box .el-box__header {
428
428
  margin: 0;
429
429
  }
430
+ .m-form-box .m-box-body {
431
+ min-height: 0;
432
+ }
430
433
  .m-form-box .dialog-footer {
434
+ flex-shrink: 0;
431
435
  display: flex;
432
436
  align-items: center;
433
437
  justify-content: space-between;
@@ -46,11 +46,12 @@
46
46
  /**
47
47
  * 静默模式标记,由 `submitForm` / `validateForm` 以隐藏方式挂载临时表单时 provide(debug 弹层模式不提供)。
48
48
  *
49
- * 重型字段组件(如 vs-code)可 inject 该标记并跳过自身渲染:字段校验由 FormItem 基于 model 值完成,
50
- * 与叶子 UI 组件实例无关,跳过可省去无谓的实例化开销(如 monaco worker / model 的创建)。
49
+ * Container 会基于该标记,并对照 `getSilentLeafFieldTypes()`(默认 `LEAF_FIELD_TYPES`)
50
+ * 跳过叶子字段的渲染,只保留 FormItem:字段校验由 FormItem 基于 model 值完成,与叶子 UI 组件实例无关。
51
+ * 重型字段组件(如 vs-code)也可 inject 该标记跳过自身渲染,省去无谓的实例化开销。
51
52
  *
52
53
  * 注意:仅「挂载无值副作用」(不在 onMounted/watch immediate 中 emit change、不依赖 DOM 计算值)的
53
- * 字段组件可以安全跳过,接入前需逐一审计。
54
+ * 字段组件可以安全跳过,接入前需逐一审计;业务扩展请使用 `registerSilentLeafFieldTypes`。
54
55
  */
55
56
  var FORM_SILENT_MODE_KEY = Symbol("mFormSilentMode");
56
57
  //#endregion
@@ -3507,6 +3508,53 @@
3507
3508
  var getField = (tagName) => fieldRegistry.get(tagName);
3508
3509
  var deleteField = (tagName) => fieldRegistry.delete(tagName);
3509
3510
  //#endregion
3511
+ //#region packages/form/src/utils/silentLeafFieldTypes.ts
3512
+ /**
3513
+ * 可在静默校验模式下跳过渲染的内置叶子字段(默认集合)。
3514
+ *
3515
+ * 这些字段只渲染一个输入控件,内部没有嵌套 FormItem,且不会依赖组件挂载修改 model;
3516
+ * 字段值由初始化逻辑处理(包括 defaultValue),因此跳过不影响校验结果。
3517
+ *
3518
+ * 业务侧可通过 `registerSilentLeafFieldTypes` 追加已审计的安全自定义字段。
3519
+ */
3520
+ var LEAF_FIELD_TYPES = /* @__PURE__ */ new Set([
3521
+ "text",
3522
+ "textarea",
3523
+ "number",
3524
+ "time",
3525
+ "daterange",
3526
+ "timerange",
3527
+ "checkbox",
3528
+ "radio-group",
3529
+ "switch",
3530
+ "select",
3531
+ "cascader",
3532
+ "color-picker",
3533
+ "link"
3534
+ ]);
3535
+ /** 业务侧追加的静默叶子字段(不含内置默认集合) */
3536
+ var extraSilentLeafFieldTypes = /* @__PURE__ */ new Set();
3537
+ /**
3538
+ * 注册可在静默校验中跳过渲染的叶子字段 type(追加到默认 `LEAF_FIELD_TYPES` 之上)。
3539
+ *
3540
+ * 仅应纳入「无嵌套 FormItem、无挂载值副作用」的字段;复合 / 动态子表单不可加入。
3541
+ */
3542
+ var registerSilentLeafFieldTypes = (types) => {
3543
+ for (const type of types) {
3544
+ if (typeof type !== "string" || !type) continue;
3545
+ extraSilentLeafFieldTypes.add((0, _tmagic_utils.toLine)(type));
3546
+ }
3547
+ };
3548
+ /** 当前生效的静默叶子字段集合:内置默认 ∪ 已注册扩展 */
3549
+ var getSilentLeafFieldTypes = () => {
3550
+ if (extraSilentLeafFieldTypes.size === 0) return LEAF_FIELD_TYPES;
3551
+ return /* @__PURE__ */ new Set([...LEAF_FIELD_TYPES, ...extraSilentLeafFieldTypes]);
3552
+ };
3553
+ /** 清空业务侧追加的静默叶子字段(不影响内置默认集合;主要用于单测) */
3554
+ var clearSilentLeafFieldTypes = () => {
3555
+ extraSilentLeafFieldTypes.clear();
3556
+ };
3557
+ //#endregion
3510
3558
  //#region packages/form/src/containers/FormLabel.vue?vue&type=script&setup=true&lang.ts
3511
3559
  var _hoisted_1$15 = {
3512
3560
  key: 0,
@@ -3667,6 +3715,8 @@
3667
3715
  return new Set(DEFAULT_SELF_DIFF_FIELD_TYPES);
3668
3716
  });
3669
3717
  const isSelfDiffField = (0, vue.computed)(() => effectiveSelfDiffFieldTypes.value.has(type.value));
3718
+ const silentMode = (0, vue.inject)(FORM_SILENT_MODE_KEY, false);
3719
+ const shouldRenderLeafField = (0, vue.computed)(() => !silentMode || !getSilentLeafFieldTypes().has(type.value));
3670
3720
  const disabled = (0, vue.computed)(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
3671
3721
  const text = (0, vue.computed)(() => filterFunction(mForm, props.config.text, props));
3672
3722
  const tooltip = (0, vue.computed)(() => {
@@ -3842,7 +3892,7 @@
3842
3892
  "label-width",
3843
3893
  "style"
3844
3894
  ])) : type.value && display$3.value && !showDiff.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicFormItem), (0, vue.mergeProps)(formItemProps.value, { class: { "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value } }), {
3845
- label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
3895
+ label: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? (0, vue.renderSlot)(_ctx.$slots, "label", {
3846
3896
  config: __props.config,
3847
3897
  type: type.value,
3848
3898
  text: text.value,
@@ -3860,8 +3910,8 @@
3860
3910
  "use-label",
3861
3911
  "label-title",
3862
3912
  "text"
3863
- ]), __props.config.titleExtra && __props.config.labelPosition === "top" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_2$8, (0, vue.toDisplayString)(__props.config.titleExtra), 1)) : (0, vue.createCommentVNode)("v-if", true)])]),
3864
- default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3913
+ ]), __props.config.titleExtra && __props.config.labelPosition === "top" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", _hoisted_2$8, (0, vue.toDisplayString)(__props.config.titleExtra), 1)) : (0, vue.createCommentVNode)("v-if", true)], void 0, 0) : (0, vue.createCommentVNode)("v-if", true)]),
3914
+ default: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3865
3915
  key: 0,
3866
3916
  placement: tooltip.value.placement
3867
3917
  }, {
@@ -3888,9 +3938,9 @@
3888
3938
  "model",
3889
3939
  "last-values",
3890
3940
  "is-compare"
3891
- ]))]),
3941
+ ]))], 64)) : (0, vue.createCommentVNode)("v-if", true)]),
3892
3942
  _: 3
3893
- }, 16, ["class"]), __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3943
+ }, 16, ["class"]), shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3894
3944
  key: 0,
3895
3945
  placement: "top"
3896
3946
  }, {
@@ -3910,7 +3960,7 @@
3910
3960
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
3911
3961
  "self-diff": true
3912
3962
  } }), {
3913
- label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
3963
+ label: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? (0, vue.renderSlot)(_ctx.$slots, "label", {
3914
3964
  config: __props.config,
3915
3965
  type: type.value,
3916
3966
  text: text.value,
@@ -3928,8 +3978,8 @@
3928
3978
  "use-label",
3929
3979
  "label-title",
3930
3980
  "text"
3931
- ])])]),
3932
- default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3981
+ ])], void 0, 0) : (0, vue.createCommentVNode)("v-if", true)]),
3982
+ default: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3933
3983
  key: 0,
3934
3984
  placement: tooltip.value.placement
3935
3985
  }, {
@@ -3954,7 +4004,7 @@
3954
4004
  "model",
3955
4005
  "last-values",
3956
4006
  "is-compare"
3957
- ]))]),
4007
+ ]))], 64)) : (0, vue.createCommentVNode)("v-if", true)]),
3958
4008
  _: 3
3959
4009
  }, 16, ["class"])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [
3960
4010
  (0, vue.createCommentVNode)(" 普通字段:渲染前后两份独立的组件用于对比 "),
@@ -3963,7 +4013,7 @@
3963
4013
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
3964
4014
  "show-before-diff": true
3965
4015
  } }), {
3966
- label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
4016
+ label: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? (0, vue.renderSlot)(_ctx.$slots, "label", {
3967
4017
  config: __props.config,
3968
4018
  type: type.value,
3969
4019
  text: text.value,
@@ -3981,8 +4031,8 @@
3981
4031
  "use-label",
3982
4032
  "label-title",
3983
4033
  "text"
3984
- ])])]),
3985
- default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4034
+ ])], void 0, 0) : (0, vue.createCommentVNode)("v-if", true)]),
4035
+ default: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3986
4036
  key: 0,
3987
4037
  placement: tooltip.value.placement
3988
4038
  }, {
@@ -3995,10 +4045,10 @@
3995
4045
  }, 8, ["placement"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)({ key: 1 }, fieldsProps.value, {
3996
4046
  model: __props.lastValues,
3997
4047
  onChange: onChangeHandler
3998
- }), null, 16, ["model"]))]),
4048
+ }), null, 16, ["model"]))], 64)) : (0, vue.createCommentVNode)("v-if", true)]),
3999
4049
  _: 3
4000
4050
  }, 16, ["class"]),
4001
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4051
+ shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4002
4052
  key: 0,
4003
4053
  placement: "top"
4004
4054
  }, {
@@ -4020,7 +4070,7 @@
4020
4070
  "show-after-diff": true
4021
4071
  }
4022
4072
  }), {
4023
- label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
4073
+ label: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? (0, vue.renderSlot)(_ctx.$slots, "label", {
4024
4074
  config: __props.config,
4025
4075
  type: type.value,
4026
4076
  text: text.value,
@@ -4038,8 +4088,8 @@
4038
4088
  "use-label",
4039
4089
  "label-title",
4040
4090
  "text"
4041
- ])])]),
4042
- default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4091
+ ])], void 0, 0) : (0, vue.createCommentVNode)("v-if", true)]),
4092
+ default: (0, vue.withCtx)(() => [shouldRenderLeafField.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4043
4093
  key: 0,
4044
4094
  placement: tooltip.value.placement
4045
4095
  }, {
@@ -4052,10 +4102,10 @@
4052
4102
  }, 8, ["placement"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)({ key: 1 }, fieldsProps.value, {
4053
4103
  model: __props.model,
4054
4104
  onChange: onChangeHandler
4055
- }), null, 16, ["model"]))]),
4105
+ }), null, 16, ["model"]))], 64)) : (0, vue.createCommentVNode)("v-if", true)]),
4056
4106
  _: 3
4057
4107
  }, 16, ["style", "class"]),
4058
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4108
+ shouldRenderLeafField.value && __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
4059
4109
  key: 1,
4060
4110
  placement: "top"
4061
4111
  }, {
@@ -9410,6 +9460,7 @@
9410
9460
  exports.MTimerange = Timerange_default;
9411
9461
  exports.adaptFormValidator = adaptFormValidator;
9412
9462
  exports.applyExtendState = applyExtendState;
9463
+ exports.clearSilentLeafFieldTypes = clearSilentLeafFieldTypes;
9413
9464
  exports.clearTypeMatchRules = clearTypeMatchRules;
9414
9465
  exports.createForm = createForm;
9415
9466
  exports.createObjectProp = createObjectProp;
@@ -9423,10 +9474,12 @@
9423
9474
  exports.getDataByPage = getDataByPage;
9424
9475
  exports.getFormField = getField;
9425
9476
  exports.getRules = getRules;
9477
+ exports.getSilentLeafFieldTypes = getSilentLeafFieldTypes;
9426
9478
  exports.getTypeMatchRule = getTypeMatchRule;
9427
9479
  exports.initValue = initValue;
9428
9480
  exports.optionSuggestion = optionSuggestion;
9429
9481
  exports.registerFormField = registerField;
9482
+ exports.registerSilentLeafFieldTypes = registerSilentLeafFieldTypes;
9430
9483
  exports.registerTypeMatchRule = registerTypeMatchRule;
9431
9484
  exports.registerTypeMatchRules = registerTypeMatchRules;
9432
9485
  exports.sortArray = sortArray;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0-beta.23",
2
+ "version": "1.8.0-beta.25",
3
3
  "name": "@tmagic/form",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -51,10 +51,10 @@
51
51
  },
52
52
  "peerDependencies": {
53
53
  "typescript": "^6.0.3",
54
- "vue": "^3.5.40",
55
- "@tmagic/design": "1.8.0-beta.23",
56
- "@tmagic/form-schema": "1.8.0-beta.23",
57
- "@tmagic/utils": "1.8.0-beta.23"
54
+ "vue": "^3.5.41",
55
+ "@tmagic/form-schema": "1.8.0-beta.25",
56
+ "@tmagic/design": "1.8.0-beta.25",
57
+ "@tmagic/utils": "1.8.0-beta.25"
58
58
  },
59
59
  "peerDependenciesMeta": {
60
60
  "typescript": {
@@ -27,7 +27,15 @@
27
27
  <template v-else-if="type && display && !showDiff">
28
28
  <TMagicFormItem v-bind="formItemProps" :class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text }">
29
29
  <template #label>
30
- <slot name="label" :config="config" :type="type" :text="text" :prop="itemProp" :disabled="disabled">
30
+ <slot
31
+ v-if="shouldRenderLeafField"
32
+ name="label"
33
+ :config="config"
34
+ :type="type"
35
+ :text="text"
36
+ :prop="itemProp"
37
+ :disabled="disabled"
38
+ >
31
39
  <FormLabel
32
40
  :tip="config.tip"
33
41
  :type="type"
@@ -41,8 +49,25 @@
41
49
  </slot>
42
50
  </template>
43
51
 
44
- <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
52
+ <!-- 静默校验时只保留 FormItem:校验依赖其 prop / rules 与 model 值,与字段组件实例无关 -->
53
+ <template v-if="shouldRenderLeafField">
54
+ <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
55
+ <component
56
+ v-bind="fieldsProps"
57
+ :is="tagName"
58
+ :model="model"
59
+ :last-values="lastValues"
60
+ :is-compare="isCompare"
61
+ @change="onChangeHandler"
62
+ @addDiffCount="onAddDiffCount"
63
+ ></component>
64
+ <template #content>
65
+ <div v-html="tooltip.text"></div>
66
+ </template>
67
+ </TMagicTooltip>
68
+
45
69
  <component
70
+ v-else
46
71
  v-bind="fieldsProps"
47
72
  :is="tagName"
48
73
  :model="model"
@@ -51,24 +76,13 @@
51
76
  @change="onChangeHandler"
52
77
  @addDiffCount="onAddDiffCount"
53
78
  ></component>
54
- <template #content>
55
- <div v-html="tooltip.text"></div>
56
- </template>
57
- </TMagicTooltip>
58
-
59
- <component
60
- v-else
61
- v-bind="fieldsProps"
62
- :is="tagName"
63
- :model="model"
64
- :last-values="lastValues"
65
- :is-compare="isCompare"
66
- @change="onChangeHandler"
67
- @addDiffCount="onAddDiffCount"
68
- ></component>
79
+ </template>
69
80
  </TMagicFormItem>
70
81
 
71
- <TMagicTooltip v-if="config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel" placement="top">
82
+ <TMagicTooltip
83
+ v-if="shouldRenderLeafField && config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel"
84
+ placement="top"
85
+ >
72
86
  <TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
73
87
  <template #content>
74
88
  <div v-html="config.tip"></div>
@@ -88,7 +102,15 @@
88
102
  }"
89
103
  >
90
104
  <template #label>
91
- <slot name="label" :config="config" :type="type" :text="text" :prop="itemProp" :disabled="disabled">
105
+ <slot
106
+ v-if="shouldRenderLeafField"
107
+ name="label"
108
+ :config="config"
109
+ :type="type"
110
+ :text="text"
111
+ :prop="itemProp"
112
+ :disabled="disabled"
113
+ >
92
114
  <FormLabel
93
115
  :tip="config.tip"
94
116
  :type="type"
@@ -98,8 +120,23 @@
98
120
  ></FormLabel>
99
121
  </slot>
100
122
  </template>
101
- <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
123
+ <template v-if="shouldRenderLeafField">
124
+ <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
125
+ <component
126
+ v-bind="fieldsProps"
127
+ :is="tagName"
128
+ :model="model"
129
+ :last-values="lastValues"
130
+ :is-compare="isCompare"
131
+ @change="onChangeHandler"
132
+ ></component>
133
+ <template #content>
134
+ <div v-html="tooltip.text"></div>
135
+ </template>
136
+ </TMagicTooltip>
137
+
102
138
  <component
139
+ v-else
103
140
  v-bind="fieldsProps"
104
141
  :is="tagName"
105
142
  :model="model"
@@ -107,20 +144,7 @@
107
144
  :is-compare="isCompare"
108
145
  @change="onChangeHandler"
109
146
  ></component>
110
- <template #content>
111
- <div v-html="tooltip.text"></div>
112
- </template>
113
- </TMagicTooltip>
114
-
115
- <component
116
- v-else
117
- v-bind="fieldsProps"
118
- :is="tagName"
119
- :model="model"
120
- :last-values="lastValues"
121
- :is-compare="isCompare"
122
- @change="onChangeHandler"
123
- ></component>
147
+ </template>
124
148
  </TMagicFormItem>
125
149
 
126
150
  <!-- 普通字段:渲染前后两份独立的组件用于对比 -->
@@ -131,7 +155,15 @@
131
155
  :class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text, 'show-before-diff': true }"
132
156
  >
133
157
  <template #label>
134
- <slot name="label" :config="config" :type="type" :text="text" :prop="itemProp" :disabled="disabled">
158
+ <slot
159
+ v-if="shouldRenderLeafField"
160
+ name="label"
161
+ :config="config"
162
+ :type="type"
163
+ :text="text"
164
+ :prop="itemProp"
165
+ :disabled="disabled"
166
+ >
135
167
  <FormLabel
136
168
  :tip="config.tip"
137
169
  :type="type"
@@ -141,23 +173,28 @@
141
173
  ></FormLabel>
142
174
  </slot>
143
175
  </template>
144
- <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
145
- <component v-bind="fieldsProps" :is="tagName" :model="lastValues" @change="onChangeHandler"></component>
146
- <template #content>
147
- <div v-html="tooltip.text"></div>
148
- </template>
149
- </TMagicTooltip>
150
-
151
- <component
152
- v-else
153
- v-bind="fieldsProps"
154
- :is="tagName"
155
- :model="lastValues"
156
- @change="onChangeHandler"
157
- ></component>
176
+ <template v-if="shouldRenderLeafField">
177
+ <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
178
+ <component v-bind="fieldsProps" :is="tagName" :model="lastValues" @change="onChangeHandler"></component>
179
+ <template #content>
180
+ <div v-html="tooltip.text"></div>
181
+ </template>
182
+ </TMagicTooltip>
183
+
184
+ <component
185
+ v-else
186
+ v-bind="fieldsProps"
187
+ :is="tagName"
188
+ :model="lastValues"
189
+ @change="onChangeHandler"
190
+ ></component>
191
+ </template>
158
192
  </TMagicFormItem>
159
193
 
160
- <TMagicTooltip v-if="config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel" placement="top">
194
+ <TMagicTooltip
195
+ v-if="shouldRenderLeafField && config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel"
196
+ placement="top"
197
+ >
161
198
  <TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
162
199
  <template #content>
163
200
  <div v-html="config.tip"></div>
@@ -171,7 +208,15 @@
171
208
  :class="{ 'tmagic-form-hidden': `${itemLabelWidth}` === '0' || !text, 'show-after-diff': true }"
172
209
  >
173
210
  <template #label>
174
- <slot name="label" :config="config" :type="type" :text="text" :prop="itemProp" :disabled="disabled">
211
+ <slot
212
+ v-if="shouldRenderLeafField"
213
+ name="label"
214
+ :config="config"
215
+ :type="type"
216
+ :text="text"
217
+ :prop="itemProp"
218
+ :disabled="disabled"
219
+ >
175
220
  <FormLabel
176
221
  :tip="config.tip"
177
222
  :type="type"
@@ -181,17 +226,22 @@
181
226
  ></FormLabel>
182
227
  </slot>
183
228
  </template>
184
- <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
185
- <component v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
186
- <template #content>
187
- <div v-html="tooltip.text"></div>
188
- </template>
189
- </TMagicTooltip>
190
-
191
- <component v-else v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
229
+ <template v-if="shouldRenderLeafField">
230
+ <TMagicTooltip v-if="tooltip.text" :placement="tooltip.placement">
231
+ <component v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
232
+ <template #content>
233
+ <div v-html="tooltip.text"></div>
234
+ </template>
235
+ </TMagicTooltip>
236
+
237
+ <component v-else v-bind="fieldsProps" :is="tagName" :model="model" @change="onChangeHandler"></component>
238
+ </template>
192
239
  </TMagicFormItem>
193
240
 
194
- <TMagicTooltip v-if="config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel" placement="top">
241
+ <TMagicTooltip
242
+ v-if="shouldRenderLeafField && config.tip && type === 'checkbox' && !(config as CheckboxConfig).useLabel"
243
+ placement="top"
244
+ >
195
245
  <TMagicIcon style="line-height: 40px; margin-left: 5px"><warning-filled /></TMagicIcon>
196
246
  <template #content>
197
247
  <div v-html="config.tip"></div>
@@ -260,9 +310,10 @@ import type {
260
310
  FormValue,
261
311
  ToolTipConfigType,
262
312
  } from '../schema';
263
- import { FORM_DIFF_CONFIG_KEY, FORM_TYPE_MATCH_VALID_KEY } from '../schema';
313
+ import { FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY } from '../schema';
264
314
  import { getField } from '../utils/config';
265
315
  import { createObjectProp, display as displayFunction, filterFunction, getRules } from '../utils/form';
316
+ import { getSilentLeafFieldTypes } from '../utils/silentLeafFieldTypes';
266
317
 
267
318
  import FormLabel from './FormLabel.vue';
268
319
 
@@ -407,6 +458,11 @@ const effectiveSelfDiffFieldTypes = computed<Set<string>>(() => {
407
458
 
408
459
  const isSelfDiffField = computed(() => effectiveSelfDiffFieldTypes.value.has(type.value));
409
460
 
461
+ // 静默模式下仅白名单叶子字段跳过渲染;扩展字段通过 registerSilentLeafFieldTypes 注册
462
+ const silentMode = inject(FORM_SILENT_MODE_KEY, false);
463
+
464
+ const shouldRenderLeafField = computed(() => !silentMode || !getSilentLeafFieldTypes().has(type.value));
465
+
410
466
  const disabled = computed(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
411
467
 
412
468
  const text = computed(() => filterFunction(mForm, props.config.text, props));
package/src/index.ts CHANGED
@@ -63,6 +63,12 @@ export {
63
63
  registerField as registerFormField,
64
64
  } from './utils/config';
65
65
 
66
+ export {
67
+ clearSilentLeafFieldTypes,
68
+ getSilentLeafFieldTypes,
69
+ registerSilentLeafFieldTypes,
70
+ } from './utils/silentLeafFieldTypes';
71
+
66
72
  export {
67
73
  clearTypeMatchRules,
68
74
  deleteTypeMatchRule,
package/src/schema.ts CHANGED
@@ -32,11 +32,12 @@ export const FORM_TYPE_MATCH_VALID_KEY: InjectionKey<ComputedRef<boolean>> = Sym
32
32
  /**
33
33
  * 静默模式标记,由 `submitForm` / `validateForm` 以隐藏方式挂载临时表单时 provide(debug 弹层模式不提供)。
34
34
  *
35
- * 重型字段组件(如 vs-code)可 inject 该标记并跳过自身渲染:字段校验由 FormItem 基于 model 值完成,
36
- * 与叶子 UI 组件实例无关,跳过可省去无谓的实例化开销(如 monaco worker / model 的创建)。
35
+ * Container 会基于该标记,并对照 `getSilentLeafFieldTypes()`(默认 `LEAF_FIELD_TYPES`)
36
+ * 跳过叶子字段的渲染,只保留 FormItem:字段校验由 FormItem 基于 model 值完成,与叶子 UI 组件实例无关。
37
+ * 重型字段组件(如 vs-code)也可 inject 该标记跳过自身渲染,省去无谓的实例化开销。
37
38
  *
38
39
  * 注意:仅「挂载无值副作用」(不在 onMounted/watch immediate 中 emit change、不依赖 DOM 计算值)的
39
- * 字段组件可以安全跳过,接入前需逐一审计。
40
+ * 字段组件可以安全跳过,接入前需逐一审计;业务扩展请使用 `registerSilentLeafFieldTypes`。
40
41
  */
41
42
  export const FORM_SILENT_MODE_KEY: InjectionKey<boolean> = Symbol('mFormSilentMode');
42
43
 
@@ -5,7 +5,12 @@
5
5
  margin: 0;
6
6
  }
7
7
 
8
+ .m-box-body {
9
+ min-height: 0;
10
+ }
11
+
8
12
  .dialog-footer {
13
+ flex-shrink: 0;
9
14
  display: flex;
10
15
  align-items: center;
11
16
  justify-content: space-between;
@@ -0,0 +1,71 @@
1
+ /*
2
+ * Tencent is pleased to support the open source community by making TMagicEditor available.
3
+ *
4
+ * Copyright (C) 2025 Tencent. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ import { toLine } from '@tmagic/utils';
20
+
21
+ /**
22
+ * 可在静默校验模式下跳过渲染的内置叶子字段(默认集合)。
23
+ *
24
+ * 这些字段只渲染一个输入控件,内部没有嵌套 FormItem,且不会依赖组件挂载修改 model;
25
+ * 字段值由初始化逻辑处理(包括 defaultValue),因此跳过不影响校验结果。
26
+ *
27
+ * 业务侧可通过 `registerSilentLeafFieldTypes` 追加已审计的安全自定义字段。
28
+ */
29
+ export const LEAF_FIELD_TYPES: ReadonlySet<string> = new Set([
30
+ 'text',
31
+ 'textarea',
32
+ 'number',
33
+ 'time',
34
+ 'daterange',
35
+ 'timerange',
36
+ 'checkbox',
37
+ 'radio-group',
38
+ 'switch',
39
+ 'select',
40
+ 'cascader',
41
+ 'color-picker',
42
+ 'link',
43
+ ]);
44
+
45
+ /** 业务侧追加的静默叶子字段(不含内置默认集合) */
46
+ const extraSilentLeafFieldTypes = new Set<string>();
47
+
48
+ /**
49
+ * 注册可在静默校验中跳过渲染的叶子字段 type(追加到默认 `LEAF_FIELD_TYPES` 之上)。
50
+ *
51
+ * 仅应纳入「无嵌套 FormItem、无挂载值副作用」的字段;复合 / 动态子表单不可加入。
52
+ */
53
+ export const registerSilentLeafFieldTypes = (types: Iterable<string>): void => {
54
+ for (const type of types) {
55
+ if (typeof type !== 'string' || !type) continue;
56
+ extraSilentLeafFieldTypes.add(toLine(type));
57
+ }
58
+ };
59
+
60
+ /** 当前生效的静默叶子字段集合:内置默认 ∪ 已注册扩展 */
61
+ export const getSilentLeafFieldTypes = (): ReadonlySet<string> => {
62
+ if (extraSilentLeafFieldTypes.size === 0) {
63
+ return LEAF_FIELD_TYPES;
64
+ }
65
+ return new Set([...LEAF_FIELD_TYPES, ...extraSilentLeafFieldTypes]);
66
+ };
67
+
68
+ /** 清空业务侧追加的静默叶子字段(不影响内置默认集合;主要用于单测) */
69
+ export const clearSilentLeafFieldTypes = (): void => {
70
+ extraSilentLeafFieldTypes.clear();
71
+ };
package/types/index.d.ts CHANGED
@@ -35,11 +35,12 @@ declare const FORM_TYPE_MATCH_VALID_KEY: InjectionKey<ComputedRef<boolean>>;
35
35
  /**
36
36
  * 静默模式标记,由 `submitForm` / `validateForm` 以隐藏方式挂载临时表单时 provide(debug 弹层模式不提供)。
37
37
  *
38
- * 重型字段组件(如 vs-code)可 inject 该标记并跳过自身渲染:字段校验由 FormItem 基于 model 值完成,
39
- * 与叶子 UI 组件实例无关,跳过可省去无谓的实例化开销(如 monaco worker / model 的创建)。
38
+ * Container 会基于该标记,并对照 `getSilentLeafFieldTypes()`(默认 `LEAF_FIELD_TYPES`)
39
+ * 跳过叶子字段的渲染,只保留 FormItem:字段校验由 FormItem 基于 model 值完成,与叶子 UI 组件实例无关。
40
+ * 重型字段组件(如 vs-code)也可 inject 该标记跳过自身渲染,省去无谓的实例化开销。
40
41
  *
41
42
  * 注意:仅「挂载无值副作用」(不在 onMounted/watch immediate 中 emit change、不依赖 DOM 计算值)的
42
- * 字段组件可以安全跳过,接入前需逐一审计。
43
+ * 字段组件可以安全跳过,接入前需逐一审计;业务扩展请使用 `registerSilentLeafFieldTypes`。
43
44
  */
44
45
  declare const FORM_SILENT_MODE_KEY: InjectionKey<boolean>;
45
46
  interface ValidateError {
@@ -2256,6 +2257,18 @@ declare const registerField: (tagName: string, component: Component) => void;
2256
2257
  declare const getField: (tagName: string) => Component | undefined;
2257
2258
  declare const deleteField: (tagName: string) => boolean;
2258
2259
  //#endregion
2260
+ //#region temp/packages/form/src/utils/silentLeafFieldTypes.d.ts
2261
+ /**
2262
+ * 注册可在静默校验中跳过渲染的叶子字段 type(追加到默认 `LEAF_FIELD_TYPES` 之上)。
2263
+ *
2264
+ * 仅应纳入「无嵌套 FormItem、无挂载值副作用」的字段;复合 / 动态子表单不可加入。
2265
+ */
2266
+ declare const registerSilentLeafFieldTypes: (types: Iterable<string>) => void;
2267
+ /** 当前生效的静默叶子字段集合:内置默认 ∪ 已注册扩展 */
2268
+ declare const getSilentLeafFieldTypes: () => ReadonlySet<string>;
2269
+ /** 清空业务侧追加的静默叶子字段(不影响内置默认集合;主要用于单测) */
2270
+ declare const clearSilentLeafFieldTypes: () => void;
2271
+ //#endregion
2259
2272
  //#region temp/packages/form/src/utils/typeMatch.d.ts
2260
2273
  interface TypeMatchValidateContext {
2261
2274
  fieldType: string;
@@ -2308,8 +2321,8 @@ declare const _default$31: {
2308
2321
  install(app: App, opt?: FormInstallOptions): void;
2309
2322
  };
2310
2323
  declare namespace index_d_exports {
2311
- export { ChangeRecord, ContainerChangeEventData, FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, FormDiffConfig, FormInstallOptions, FormLabelSlotProps, FormSlots, MAX_SUGGESTION_OPTIONS, _default as MCascader, _default$1 as MCheckbox, _default$2 as MCheckboxGroup, _default$3 as MColorPicker, _default$4 as MContainer, _default$5 as MDate, _default$6 as MDateTime, _default$7 as MDaterange, _default$8 as MDisplay, _default$9 as MDynamicField, _default$10 as MFieldset, _default$11 as MFlexLayout, _default$12 as MForm, _default$13 as MFormBox, _default$14 as MFormDialog, _default$15 as MFormDrawer, _default$16 as MGroupList, _default$17 as MHidden, _default$18 as MLink, _default$19 as MNumber, _default$20 as MNumberRange, _default$21 as MPanel, _default$22 as MRadioGroup, _default$23 as MRow, _default$24 as MSelect, _default$25 as MSwitch, _default$16 as MTable, _default$16 as MTableGroupList, _default$26 as MTabs, _default$27 as MText, _default$28 as MTextarea, _default$29 as MTime, _default$30 as MTimerange, SubmitFormOptions, SubmitFormResult, TypeMatchValidateContext, TypeMatchValidator, ValidateError, ValidateFormOptions, adaptFormValidator, applyExtendState, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, _default$31 as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
2324
+ export { ChangeRecord, ContainerChangeEventData, FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, FormDiffConfig, FormInstallOptions, FormLabelSlotProps, FormSlots, MAX_SUGGESTION_OPTIONS, _default as MCascader, _default$1 as MCheckbox, _default$2 as MCheckboxGroup, _default$3 as MColorPicker, _default$4 as MContainer, _default$5 as MDate, _default$6 as MDateTime, _default$7 as MDaterange, _default$8 as MDisplay, _default$9 as MDynamicField, _default$10 as MFieldset, _default$11 as MFlexLayout, _default$12 as MForm, _default$13 as MFormBox, _default$14 as MFormDialog, _default$15 as MFormDrawer, _default$16 as MGroupList, _default$17 as MHidden, _default$18 as MLink, _default$19 as MNumber, _default$20 as MNumberRange, _default$21 as MPanel, _default$22 as MRadioGroup, _default$23 as MRow, _default$24 as MSelect, _default$25 as MSwitch, _default$16 as MTable, _default$16 as MTableGroupList, _default$26 as MTabs, _default$27 as MText, _default$28 as MTextarea, _default$29 as MTime, _default$30 as MTimerange, SubmitFormOptions, SubmitFormResult, TypeMatchValidateContext, TypeMatchValidator, ValidateError, ValidateFormOptions, adaptFormValidator, applyExtendState, clearSilentLeafFieldTypes, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, _default$31 as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getSilentLeafFieldTypes, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerSilentLeafFieldTypes, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
2312
2325
  }
2313
2326
  declare const createForm: <T extends [] = []>(config: schema_d_exports.FormConfig | T) => schema_d_exports.FormConfig | T;
2314
2327
  //#endregion
2315
- export { ChangeRecord, ContainerChangeEventData, FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, FormDiffConfig, type FormInstallOptions, FormLabelSlotProps, FormSlots, MAX_SUGGESTION_OPTIONS, _default as MCascader, _default$1 as MCheckbox, _default$2 as MCheckboxGroup, _default$3 as MColorPicker, _default$4 as MContainer, _default$5 as MDate, _default$6 as MDateTime, _default$7 as MDaterange, _default$8 as MDisplay, _default$9 as MDynamicField, _default$10 as MFieldset, _default$11 as MFlexLayout, _default$12 as MForm, _default$13 as MFormBox, _default$14 as MFormDialog, _default$15 as MFormDrawer, _default$16 as MGroupList, _default$16 as MTable, _default$16 as MTableGroupList, _default$17 as MHidden, _default$18 as MLink, _default$19 as MNumber, _default$20 as MNumberRange, _default$21 as MPanel, _default$22 as MRadioGroup, _default$23 as MRow, _default$24 as MSelect, _default$25 as MSwitch, _default$26 as MTabs, _default$27 as MText, _default$28 as MTextarea, _default$29 as MTime, _default$30 as MTimerange, SubmitFormOptions, SubmitFormResult, type TypeMatchValidateContext, type TypeMatchValidator, ValidateError, ValidateFormOptions, adaptFormValidator, applyExtendState, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, _default$31 as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };
2328
+ export { ChangeRecord, ContainerChangeEventData, FORM_DIFF_CONFIG_KEY, FORM_SILENT_MODE_KEY, FORM_TYPE_MATCH_VALID_KEY, FormDiffConfig, type FormInstallOptions, FormLabelSlotProps, FormSlots, MAX_SUGGESTION_OPTIONS, _default as MCascader, _default$1 as MCheckbox, _default$2 as MCheckboxGroup, _default$3 as MColorPicker, _default$4 as MContainer, _default$5 as MDate, _default$6 as MDateTime, _default$7 as MDaterange, _default$8 as MDisplay, _default$9 as MDynamicField, _default$10 as MFieldset, _default$11 as MFlexLayout, _default$12 as MForm, _default$13 as MFormBox, _default$14 as MFormDialog, _default$15 as MFormDrawer, _default$16 as MGroupList, _default$16 as MTable, _default$16 as MTableGroupList, _default$17 as MHidden, _default$18 as MLink, _default$19 as MNumber, _default$20 as MNumberRange, _default$21 as MPanel, _default$22 as MRadioGroup, _default$23 as MRow, _default$24 as MSelect, _default$25 as MSwitch, _default$26 as MTabs, _default$27 as MText, _default$28 as MTextarea, _default$29 as MTime, _default$30 as MTimerange, SubmitFormOptions, SubmitFormResult, type TypeMatchValidateContext, type TypeMatchValidator, ValidateError, ValidateFormOptions, adaptFormValidator, applyExtendState, clearSilentLeafFieldTypes, clearTypeMatchRules, createForm, createObjectProp, createValues, datetimeFormatter, _default$31 as default, deleteField as deleteFormField, deleteTypeMatchRule, display, filterFunction, getDataByPage, getField as getFormField, getRules, getSilentLeafFieldTypes, getTypeMatchRule, initValue, optionSuggestion, registerField as registerFormField, registerSilentLeafFieldTypes, registerTypeMatchRule, registerTypeMatchRules, sortArray, sortChange, stringifyExampleValue, stripTabItemsLazy, submitForm, useAddField, validateForm, validateTypeMatch };