@tmagic/form 1.8.0-beta.1 → 1.8.0-beta.3

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.
@@ -21,10 +21,17 @@ import { createApp, defineComponent, h, nextTick, ref, watch } from "vue";
21
21
  * } catch (e) {
22
22
  * console.error(e);
23
23
  * }
24
+ *
25
+ * // 需要同时获取变更记录时:
26
+ * const { values, changeRecords } = await submitForm({
27
+ * config: [...],
28
+ * initValues: { name: 'foo' },
29
+ * returnChangeRecords: true,
30
+ * });
24
31
  * ```
25
32
  */
26
33
  var submitForm = (options) => {
27
- const { native, appContext, timeout = 1e4, ...formProps } = options;
34
+ const { native, appContext, timeout = 1e4, returnChangeRecords, ...formProps } = options;
28
35
  return new Promise((resolve, reject) => {
29
36
  const container = document.createElement("div");
30
37
  container.style.display = "none";
@@ -40,7 +47,12 @@ var submitForm = (options) => {
40
47
  stop();
41
48
  try {
42
49
  await nextTick();
43
- resolve(await formRef.value.submitForm(native));
50
+ const changeRecords = [...formRef.value.changeRecords ?? []];
51
+ const result = await formRef.value.submitForm(native);
52
+ resolve(returnChangeRecords ? {
53
+ values: result,
54
+ changeRecords
55
+ } : result);
44
56
  } catch (err) {
45
57
  reject(err);
46
58
  } finally {
package/dist/style.css CHANGED
@@ -10,7 +10,10 @@
10
10
  .m-form-container.has-tip .tmagic-design-form-item {
11
11
  flex: 1;
12
12
  }
13
- .m-form-container .tmagic-design-form-item.show-diff {
13
+ .m-form-container .tmagic-design-form-item.show-after-diff {
14
+ background: rgb(225, 243, 216);
15
+ }
16
+ .m-form-container .tmagic-design-form-item.show-before-diff {
14
17
  background: #f7dadd;
15
18
  }
16
19
 
@@ -38,6 +38,9 @@
38
38
  //#endregion
39
39
  dayjs = __toESM(dayjs, 1);
40
40
  dayjs_plugin_utc = __toESM(dayjs_plugin_utc, 1);
41
+ //#region packages/form/src/schema.ts
42
+ var FORM_DIFF_CONFIG_KEY = Symbol("mFormDiffConfig");
43
+ //#endregion
41
44
  //#region node_modules/.pnpm/lodash-es@4.17.21/node_modules/lodash-es/_freeGlobal.js
42
45
  /** Detect free variable `global` from Node.js. */
43
46
  var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
@@ -2889,7 +2892,8 @@
2889
2892
  var _hoisted_5$3 = ["innerHTML"];
2890
2893
  var _hoisted_6$1 = ["innerHTML"];
2891
2894
  var _hoisted_7$1 = ["innerHTML"];
2892
- var _hoisted_8$1 = {
2895
+ var _hoisted_8$1 = ["innerHTML"];
2896
+ var _hoisted_9 = {
2893
2897
  key: 5,
2894
2898
  style: { "text-align": "center" }
2895
2899
  };
@@ -2921,11 +2925,21 @@
2921
2925
  const props = __props;
2922
2926
  const emit = __emit;
2923
2927
  const mForm = (0, vue.inject)("mForm");
2928
+ const diffConfig = (0, vue.inject)(FORM_DIFF_CONFIG_KEY, {});
2924
2929
  const expand = (0, vue.ref)(false);
2925
2930
  const name = (0, vue.computed)(() => props.config.name || "");
2926
2931
  const showDiff = (0, vue.computed)(() => {
2927
2932
  if (!props.isCompare) return false;
2928
- return !isEqual(name.value ? props.model[name.value] : props.model, name.value ? props.lastValues[name.value] : props.lastValues);
2933
+ if (!name.value) return false;
2934
+ const curValue = props.model[name.value];
2935
+ const lastValue = props.lastValues[name.value];
2936
+ const customShowDiff = diffConfig.showDiff;
2937
+ if (typeof customShowDiff === "function") return Boolean(customShowDiff({
2938
+ curValue,
2939
+ lastValue,
2940
+ config: props.config
2941
+ }));
2942
+ return !isEqual(curValue, lastValue);
2929
2943
  });
2930
2944
  const items = (0, vue.computed)(() => props.config.items);
2931
2945
  const itemProp = (0, vue.computed)(() => {
@@ -2946,6 +2960,35 @@
2946
2960
  if (type.value === "component" && props.config.component) return props.config.component;
2947
2961
  return getField(type.value || "container") || `m-${items.value ? "form" : "fields"}-${type.value}`;
2948
2962
  });
2963
+ /**
2964
+ * 自接管对比的字段类型白名单。
2965
+ *
2966
+ * 这类字段在 `isCompare === true` 且存在差异时,不再由 Container 渲染前后两份独立组件来对比,
2967
+ * 而是只渲染一次组件,将 `model` / `lastValues` / `isCompare` 一并传给字段组件,
2968
+ * 由字段组件内部自行展示前后差异(典型场景:vs-code 字段使用 monaco 自带的 diff 编辑器)。
2969
+ *
2970
+ * 这样做的好处:
2971
+ * 1. 避免重型字段(如 monaco 编辑器)在对比模式下被实例化两次,节省资源;
2972
+ * 2. 提供更专业的对比视觉效果(如 monaco diff 的行级高亮、左右滚动同步等)。
2973
+ *
2974
+ * 注意:像 `event-select` / `code-select-col` 这类内部由列表 / 嵌套子表单组成的复合字段,若按默认逻辑
2975
+ * 渲染前后两份独立组件,会出现两套下拉框 + 两份参数表单(或两套「添加事件」按钮、两份完整面板),
2976
+ * 体验很差。这类字段在内部把 `is-compare`/`lastValues` 透传给子级容器,由子级逐项展示差异,
2977
+ * 因此同样归类为自接管对比字段。
2978
+ */
2979
+ const DEFAULT_SELF_DIFF_FIELD_TYPES = [
2980
+ "vs-code",
2981
+ "event-select",
2982
+ "code-select-col",
2983
+ "code-select"
2984
+ ];
2985
+ const effectiveSelfDiffFieldTypes = (0, vue.computed)(() => {
2986
+ const custom = diffConfig.selfDiffFieldTypes;
2987
+ if (typeof custom === "function") return new Set(custom([...DEFAULT_SELF_DIFF_FIELD_TYPES]));
2988
+ if (Array.isArray(custom)) return new Set([...DEFAULT_SELF_DIFF_FIELD_TYPES, ...custom]);
2989
+ return new Set(DEFAULT_SELF_DIFF_FIELD_TYPES);
2990
+ });
2991
+ const isSelfDiffField = (0, vue.computed)(() => effectiveSelfDiffFieldTypes.value.has(type.value));
2949
2992
  const disabled = (0, vue.computed)(() => props.disabled || filterFunction(mForm, props.config.disabled, props));
2950
2993
  const text = (0, vue.computed)(() => filterFunction(mForm, props.config.text, props));
2951
2994
  const tooltip = (0, vue.computed)(() => {
@@ -3114,7 +3157,13 @@
3114
3157
  "label-width",
3115
3158
  "style"
3116
3159
  ])) : 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 } }), {
3117
- label: (0, vue.withCtx)(() => [(0, vue.createVNode)(FormLabel_default, {
3160
+ label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
3161
+ config: __props.config,
3162
+ type: type.value,
3163
+ text: text.value,
3164
+ prop: itemProp.value,
3165
+ disabled: disabled.value
3166
+ }, () => [(0, vue.createVNode)(FormLabel_default, {
3118
3167
  tip: __props.config.tip,
3119
3168
  type: type.value,
3120
3169
  "use-label": __props.config.useLabel,
@@ -3126,7 +3175,7 @@
3126
3175
  "use-label",
3127
3176
  "label-title",
3128
3177
  "text"
3129
- ])]),
3178
+ ])])]),
3130
3179
  default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3131
3180
  key: 0,
3132
3181
  placement: tooltip.value.placement
@@ -3155,7 +3204,7 @@
3155
3204
  "last-values",
3156
3205
  "is-compare"
3157
3206
  ]))]),
3158
- _: 1
3207
+ _: 3
3159
3208
  }, 16, ["class"]), __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3160
3209
  key: 0,
3161
3210
  placement: "top"
@@ -3171,12 +3220,18 @@
3171
3220
  _: 1
3172
3221
  })) : (0, vue.createCommentVNode)("v-if", true)], 64)) : type.value && display$3.value && showDiff.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 3 }, [
3173
3222
  (0, vue.createCommentVNode)(" 对比 "),
3174
- (0, vue.createCommentVNode)(" 上次内容 "),
3175
- (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicFormItem), (0, vue.mergeProps)(formItemProps.value, { class: {
3223
+ (0, vue.createCommentVNode)(" 自接管对比的字段类型(如 vs-code):只渲染一次组件,由字段内部用 diff 编辑器/视图自行展示前后差异 "),
3224
+ isSelfDiffField.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicFormItem), (0, vue.mergeProps)({ key: 0 }, formItemProps.value, { class: {
3176
3225
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
3177
- "show-diff": true
3226
+ "self-diff": true
3178
3227
  } }), {
3179
- label: (0, vue.withCtx)(() => [(0, vue.createVNode)(FormLabel_default, {
3228
+ label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
3229
+ config: __props.config,
3230
+ type: type.value,
3231
+ text: text.value,
3232
+ prop: itemProp.value,
3233
+ disabled: disabled.value
3234
+ }, () => [(0, vue.createVNode)(FormLabel_default, {
3180
3235
  tip: __props.config.tip,
3181
3236
  type: type.value,
3182
3237
  "use-label": __props.config.useLabel,
@@ -3188,88 +3243,148 @@
3188
3243
  "use-label",
3189
3244
  "label-title",
3190
3245
  "text"
3191
- ])]),
3246
+ ])])]),
3192
3247
  default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3193
3248
  key: 0,
3194
3249
  placement: tooltip.value.placement
3195
3250
  }, {
3196
3251
  content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: tooltip.value.text }, null, 8, _hoisted_4$4)]),
3197
3252
  default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)(fieldsProps.value, {
3198
- model: __props.lastValues,
3253
+ model: __props.model,
3254
+ "last-values": __props.lastValues,
3255
+ "is-compare": __props.isCompare,
3199
3256
  onChange: onChangeHandler
3200
- }), null, 16, ["model"]))]),
3257
+ }), null, 16, [
3258
+ "model",
3259
+ "last-values",
3260
+ "is-compare"
3261
+ ]))]),
3201
3262
  _: 1
3202
3263
  }, 8, ["placement"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)({ key: 1 }, fieldsProps.value, {
3203
- model: __props.lastValues,
3264
+ model: __props.model,
3265
+ "last-values": __props.lastValues,
3266
+ "is-compare": __props.isCompare,
3204
3267
  onChange: onChangeHandler
3205
- }), null, 16, ["model"]))]),
3206
- _: 1
3207
- }, 16, ["class"]),
3208
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3209
- key: 0,
3210
- placement: "top"
3211
- }, {
3212
- content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: __props.config.tip }, null, 8, _hoisted_5$3)]),
3213
- default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicIcon), { style: {
3214
- "line-height": "40px",
3215
- "margin-left": "5px"
3216
- } }, {
3217
- default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_element_plus_icons_vue.WarningFilled))]),
3218
- _: 1
3219
- })]),
3220
- _: 1
3221
- })) : (0, vue.createCommentVNode)("v-if", true),
3222
- (0, vue.createCommentVNode)(" 当前内容 "),
3223
- (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicFormItem), (0, vue.mergeProps)(formItemProps.value, {
3224
- style: __props.config.tip ? "flex: 1" : "",
3225
- class: {
3268
+ }), null, 16, [
3269
+ "model",
3270
+ "last-values",
3271
+ "is-compare"
3272
+ ]))]),
3273
+ _: 3
3274
+ }, 16, ["class"])) : ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [
3275
+ (0, vue.createCommentVNode)(" 普通字段:渲染前后两份独立的组件用于对比 "),
3276
+ (0, vue.createCommentVNode)(" 上次内容 "),
3277
+ (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicFormItem), (0, vue.mergeProps)(formItemProps.value, { class: {
3226
3278
  "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
3227
- "show-diff": true
3228
- }
3229
- }), {
3230
- label: (0, vue.withCtx)(() => [(0, vue.createVNode)(FormLabel_default, {
3231
- tip: __props.config.tip,
3232
- type: type.value,
3233
- "use-label": __props.config.useLabel,
3234
- "label-title": __props.config.labelTitle,
3235
- text: text.value
3236
- }, null, 8, [
3237
- "tip",
3238
- "type",
3239
- "use-label",
3240
- "label-title",
3241
- "text"
3242
- ])]),
3243
- default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3279
+ "show-before-diff": true
3280
+ } }), {
3281
+ label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
3282
+ config: __props.config,
3283
+ type: type.value,
3284
+ text: text.value,
3285
+ prop: itemProp.value,
3286
+ disabled: disabled.value
3287
+ }, () => [(0, vue.createVNode)(FormLabel_default, {
3288
+ tip: __props.config.tip,
3289
+ type: type.value,
3290
+ "use-label": __props.config.useLabel,
3291
+ "label-title": __props.config.labelTitle,
3292
+ text: text.value
3293
+ }, null, 8, [
3294
+ "tip",
3295
+ "type",
3296
+ "use-label",
3297
+ "label-title",
3298
+ "text"
3299
+ ])])]),
3300
+ default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3301
+ key: 0,
3302
+ placement: tooltip.value.placement
3303
+ }, {
3304
+ content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: tooltip.value.text }, null, 8, _hoisted_5$3)]),
3305
+ default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)(fieldsProps.value, {
3306
+ model: __props.lastValues,
3307
+ onChange: onChangeHandler
3308
+ }), null, 16, ["model"]))]),
3309
+ _: 1
3310
+ }, 8, ["placement"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)({ key: 1 }, fieldsProps.value, {
3311
+ model: __props.lastValues,
3312
+ onChange: onChangeHandler
3313
+ }), null, 16, ["model"]))]),
3314
+ _: 3
3315
+ }, 16, ["class"]),
3316
+ __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3244
3317
  key: 0,
3245
- placement: tooltip.value.placement
3318
+ placement: "top"
3246
3319
  }, {
3247
- content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: tooltip.value.text }, null, 8, _hoisted_6$1)]),
3248
- default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)(fieldsProps.value, {
3320
+ content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: __props.config.tip }, null, 8, _hoisted_6$1)]),
3321
+ default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicIcon), { style: {
3322
+ "line-height": "40px",
3323
+ "margin-left": "5px"
3324
+ } }, {
3325
+ default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_element_plus_icons_vue.WarningFilled))]),
3326
+ _: 1
3327
+ })]),
3328
+ _: 1
3329
+ })) : (0, vue.createCommentVNode)("v-if", true),
3330
+ (0, vue.createCommentVNode)(" 当前内容 "),
3331
+ (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicFormItem), (0, vue.mergeProps)(formItemProps.value, {
3332
+ style: __props.config.tip ? "flex: 1" : "",
3333
+ class: {
3334
+ "tmagic-form-hidden": `${itemLabelWidth.value}` === "0" || !text.value,
3335
+ "show-after-diff": true
3336
+ }
3337
+ }), {
3338
+ label: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", {
3339
+ config: __props.config,
3340
+ type: type.value,
3341
+ text: text.value,
3342
+ prop: itemProp.value,
3343
+ disabled: disabled.value
3344
+ }, () => [(0, vue.createVNode)(FormLabel_default, {
3345
+ tip: __props.config.tip,
3346
+ type: type.value,
3347
+ "use-label": __props.config.useLabel,
3348
+ "label-title": __props.config.labelTitle,
3349
+ text: text.value
3350
+ }, null, 8, [
3351
+ "tip",
3352
+ "type",
3353
+ "use-label",
3354
+ "label-title",
3355
+ "text"
3356
+ ])])]),
3357
+ default: (0, vue.withCtx)(() => [tooltip.value.text ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3358
+ key: 0,
3359
+ placement: tooltip.value.placement
3360
+ }, {
3361
+ content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: tooltip.value.text }, null, 8, _hoisted_7$1)]),
3362
+ default: (0, vue.withCtx)(() => [((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)(fieldsProps.value, {
3363
+ model: __props.model,
3364
+ onChange: onChangeHandler
3365
+ }), null, 16, ["model"]))]),
3366
+ _: 1
3367
+ }, 8, ["placement"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)({ key: 1 }, fieldsProps.value, {
3249
3368
  model: __props.model,
3250
3369
  onChange: onChangeHandler
3251
3370
  }), null, 16, ["model"]))]),
3371
+ _: 3
3372
+ }, 16, ["style", "class"]),
3373
+ __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3374
+ key: 1,
3375
+ placement: "top"
3376
+ }, {
3377
+ content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: __props.config.tip }, null, 8, _hoisted_8$1)]),
3378
+ default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicIcon), { style: {
3379
+ "line-height": "40px",
3380
+ "margin-left": "5px"
3381
+ } }, {
3382
+ default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_element_plus_icons_vue.WarningFilled))]),
3383
+ _: 1
3384
+ })]),
3252
3385
  _: 1
3253
- }, 8, ["placement"])) : ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(tagName.value), (0, vue.mergeProps)({ key: 1 }, fieldsProps.value, {
3254
- model: __props.model,
3255
- onChange: onChangeHandler
3256
- }), null, 16, ["model"]))]),
3257
- _: 1
3258
- }, 16, ["style", "class"]),
3259
- __props.config.tip && type.value === "checkbox" && !__props.config.useLabel ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicTooltip), {
3260
- key: 1,
3261
- placement: "top"
3262
- }, {
3263
- content: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("div", { innerHTML: __props.config.tip }, null, 8, _hoisted_7$1)]),
3264
- default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicIcon), { style: {
3265
- "line-height": "40px",
3266
- "margin-left": "5px"
3267
- } }, {
3268
- default: (0, vue.withCtx)(() => [(0, vue.createVNode)((0, vue.unref)(_element_plus_icons_vue.WarningFilled))]),
3269
- _: 1
3270
- })]),
3271
- _: 1
3272
- })) : (0, vue.createCommentVNode)("v-if", true)
3386
+ })) : (0, vue.createCommentVNode)("v-if", true)
3387
+ ], 64))
3273
3388
  ], 64)) : items.value && display$3.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 4 }, [(isValidName() ? __props.model[name.value] : __props.model) ? ((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, { key: 0 }, (0, vue.renderList)(items.value, (item) => {
3274
3389
  return (0, vue.openBlock)(), (0, vue.createBlock)(_component_Container, {
3275
3390
  key: key(item),
@@ -3285,7 +3400,11 @@
3285
3400
  prop: itemProp.value,
3286
3401
  onChange: onChangeHandler,
3287
3402
  onAddDiffCount
3288
- }, null, 8, [
3403
+ }, (0, vue.createSlots)({ _: 2 }, [_ctx.$slots.label ? {
3404
+ name: "label",
3405
+ fn: (0, vue.withCtx)((labelProps) => [(0, vue.renderSlot)(_ctx.$slots, "label", (0, vue.mergeProps)({ ref_for: true }, labelProps))]),
3406
+ key: "0"
3407
+ } : void 0]), 1032, [
3289
3408
  "model",
3290
3409
  "last-values",
3291
3410
  "is-compare",
@@ -3297,7 +3416,7 @@
3297
3416
  "label-width",
3298
3417
  "prop"
3299
3418
  ]);
3300
- }), 128)) : (0, vue.createCommentVNode)("v-if", true)], 64)) : (0, vue.createCommentVNode)("v-if", true), __props.config.expand && type.value !== "fieldset" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_8$1, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
3419
+ }), 128)) : (0, vue.createCommentVNode)("v-if", true)], 64)) : (0, vue.createCommentVNode)("v-if", true), __props.config.expand && type.value !== "fieldset" ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_9, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
3301
3420
  type: "primary",
3302
3421
  size: "small",
3303
3422
  disabled: false,
@@ -3340,7 +3459,9 @@
3340
3459
  keyProp: { default: "__key" },
3341
3460
  popperClass: {},
3342
3461
  preventSubmitDefault: { type: Boolean },
3343
- extendState: {}
3462
+ extendState: {},
3463
+ showDiff: {},
3464
+ selfDiffFieldTypes: {}
3344
3465
  },
3345
3466
  emits: [
3346
3467
  "change",
@@ -3456,6 +3577,14 @@
3456
3577
  }
3457
3578
  });
3458
3579
  (0, vue.provide)("mForm", formState);
3580
+ (0, vue.provide)(FORM_DIFF_CONFIG_KEY, {
3581
+ get showDiff() {
3582
+ return props.showDiff;
3583
+ },
3584
+ get selfDiffFieldTypes() {
3585
+ return props.selfDiffFieldTypes;
3586
+ }
3587
+ });
3459
3588
  const changeRecords = (0, vue.shallowRef)([]);
3460
3589
  (0, vue.watch)([() => props.config, () => props.initValues], ([config], [preConfig]) => {
3461
3590
  changeRecords.value = [];
@@ -3572,7 +3701,11 @@
3572
3701
  "step-active": __props.stepActive,
3573
3702
  size: __props.size,
3574
3703
  onChange: changeHandler
3575
- }, null, 8, [
3704
+ }, (0, vue.createSlots)({ _: 2 }, [_ctx.$slots.label ? {
3705
+ name: "label",
3706
+ fn: (0, vue.withCtx)((labelProps) => [(0, vue.renderSlot)(_ctx.$slots, "label", (0, vue.mergeProps)({ ref_for: true }, labelProps))]),
3707
+ key: "0"
3708
+ } : void 0]), 1032, [
3576
3709
  "disabled",
3577
3710
  "config",
3578
3711
  "model",
@@ -3583,7 +3716,7 @@
3583
3716
  "size"
3584
3717
  ]);
3585
3718
  }), 128)) : (0, vue.createCommentVNode)("v-if", true)]),
3586
- _: 1
3719
+ _: 3
3587
3720
  }, 8, [
3588
3721
  "model",
3589
3722
  "label-width",
@@ -3616,10 +3749,17 @@
3616
3749
  * } catch (e) {
3617
3750
  * console.error(e);
3618
3751
  * }
3752
+ *
3753
+ * // 需要同时获取变更记录时:
3754
+ * const { values, changeRecords } = await submitForm({
3755
+ * config: [...],
3756
+ * initValues: { name: 'foo' },
3757
+ * returnChangeRecords: true,
3758
+ * });
3619
3759
  * ```
3620
3760
  */
3621
3761
  var submitForm = (options) => {
3622
- const { native, appContext, timeout = 1e4, ...formProps } = options;
3762
+ const { native, appContext, timeout = 1e4, returnChangeRecords, ...formProps } = options;
3623
3763
  return new Promise((resolve, reject) => {
3624
3764
  const container = document.createElement("div");
3625
3765
  container.style.display = "none";
@@ -3635,7 +3775,12 @@
3635
3775
  stop();
3636
3776
  try {
3637
3777
  await (0, vue.nextTick)();
3638
- resolve(await formRef.value.submitForm(native));
3778
+ const changeRecords = [...formRef.value.changeRecords ?? []];
3779
+ const result = await formRef.value.submitForm(native);
3780
+ resolve(returnChangeRecords ? {
3781
+ values: result,
3782
+ changeRecords
3783
+ } : result);
3639
3784
  } catch (err) {
3640
3785
  reject(err);
3641
3786
  } finally {
@@ -4234,6 +4379,7 @@
4234
4379
  const emit = __emit;
4235
4380
  const mForm = (0, vue.inject)("mForm");
4236
4381
  const name = (0, vue.computed)(() => props.config.name || "");
4382
+ const legend = (0, vue.computed)(() => filterFunction(mForm, props.config.legend, props));
4237
4383
  const checkboxName = (0, vue.computed)(() => {
4238
4384
  if (typeof props.config.checkbox === "object" && typeof props.config.checkbox.name === "string") return props.config.checkbox.name;
4239
4385
  return "value";
@@ -4273,7 +4419,7 @@
4273
4419
  "false-value": checkboxFalseValue.value,
4274
4420
  "onUpdate:modelValue": valueChangeHandler
4275
4421
  }, {
4276
- default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("span", { innerHTML: __props.config.legend }, null, 8, _hoisted_1$11), __props.config.extra ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
4422
+ default: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("span", { innerHTML: legend.value }, null, 8, _hoisted_1$11), __props.config.extra ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
4277
4423
  key: 0,
4278
4424
  innerHTML: __props.config.extra,
4279
4425
  class: "m-form-tip"
@@ -4286,7 +4432,7 @@
4286
4432
  "false-value"
4287
4433
  ])]),
4288
4434
  _: 1
4289
- })) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("legend", _hoisted_3$5, [(0, vue.createElementVNode)("span", { innerHTML: __props.config.legend }, null, 8, _hoisted_4$3), __props.config.extra ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
4435
+ })) : ((0, vue.openBlock)(), (0, vue.createElementBlock)("legend", _hoisted_3$5, [(0, vue.createElementVNode)("span", { innerHTML: legend.value }, null, 8, _hoisted_4$3), __props.config.extra ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
4290
4436
  key: 0,
4291
4437
  innerHTML: __props.config.extra,
4292
4438
  class: "m-form-tip"
@@ -4723,6 +4869,9 @@
4723
4869
  prop: props.prop
4724
4870
  });
4725
4871
  });
4872
+ (0, vue.watch)([() => props.model, () => props.lastValues], () => {
4873
+ diffCount.value = {};
4874
+ });
4726
4875
  const tabItems = (tab) => props.config.dynamic ? props.config.items : tab.items;
4727
4876
  const tabClickHandler = (tab) => {
4728
4877
  if (typeof tab === "object") tabClick(mForm, tab, props);
@@ -4797,7 +4946,7 @@
4797
4946
  default: (0, vue.withCtx)(() => [((0, vue.openBlock)(true), (0, vue.createElementBlock)(vue.Fragment, null, (0, vue.renderList)(tabs.value, (tab, tabIndex) => {
4798
4947
  return (0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)((0, vue.unref)(tabPaneComponent)?.component || "el-tab-pane"), (0, vue.mergeProps)({ key: tab[(0, vue.unref)(mForm)?.keyProp || "__key"] ?? tabIndex }, { ref_for: true }, (0, vue.unref)(tabPaneComponent)?.props({
4799
4948
  name: filter(tab.status) || tabIndex.toString(),
4800
- lazy: tab.lazy || false
4949
+ lazy: __props.isCompare ? false : tab.lazy || false
4801
4950
  }) || {}), {
4802
4951
  label: (0, vue.withCtx)(() => [(0, vue.createElementVNode)("span", null, [(0, vue.createTextVNode)((0, vue.toDisplayString)(filter(tab.title)), 1), (0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicBadge), {
4803
4952
  hidden: !diffCount.value[Number(tabIndex)],
@@ -4938,16 +5087,17 @@
4938
5087
  }), (0, vue.createElementVNode)("span", { innerHTML: title.value }, null, 8, _hoisted_1$9)]),
4939
5088
  _: 1
4940
5089
  }, 8, ["disabled"]),
4941
- (0, vue.withDirectives)((0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
5090
+ !__props.isCompare ? (0, vue.withDirectives)(((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), {
5091
+ key: 0,
4942
5092
  type: "danger",
4943
5093
  size: "small",
4944
5094
  link: "",
4945
5095
  icon: (0, vue.unref)(_element_plus_icons_vue.Delete),
4946
5096
  disabled: __props.disabled,
4947
5097
  onClick: removeHandler
4948
- }, null, 8, ["icon", "disabled"]), [[vue.vShow, showDelete.value]]),
4949
- copyable.value ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), {
4950
- key: 0,
5098
+ }, null, 8, ["icon", "disabled"])), [[vue.vShow, showDelete.value]]) : (0, vue.createCommentVNode)("v-if", true),
5099
+ copyable.value && !__props.isCompare ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), {
5100
+ key: 1,
4951
5101
  link: "",
4952
5102
  size: "small",
4953
5103
  type: "primary",
@@ -4958,7 +5108,7 @@
4958
5108
  default: (0, vue.withCtx)(() => [..._cache[6] || (_cache[6] = [(0, vue.createTextVNode)("复制", -1)])]),
4959
5109
  _: 1
4960
5110
  }, 8, ["icon", "disabled"])) : (0, vue.createCommentVNode)("v-if", true),
4961
- movable.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 1 }, [(0, vue.withDirectives)((0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
5111
+ movable.value && !__props.isCompare ? ((0, vue.openBlock)(), (0, vue.createElementBlock)(vue.Fragment, { key: 2 }, [(0, vue.withDirectives)((0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicButton), {
4962
5112
  link: "",
4963
5113
  size: "small",
4964
5114
  disabled: __props.disabled,
@@ -4977,8 +5127,8 @@
4977
5127
  default: (0, vue.withCtx)(() => [..._cache[8] || (_cache[8] = [(0, vue.createTextVNode)("下移", -1)])]),
4978
5128
  _: 1
4979
5129
  }, 8, ["disabled", "icon"]), [[vue.vShow, __props.index !== length.value - 1]])], 64)) : (0, vue.createCommentVNode)("v-if", true),
4980
- __props.config.moveSpecifyLocation ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicPopover), {
4981
- key: 2,
5130
+ __props.config.moveSpecifyLocation && !__props.isCompare ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicPopover), {
5131
+ key: 3,
4982
5132
  trigger: "click",
4983
5133
  placement: "top",
4984
5134
  width: "200",
@@ -5024,7 +5174,7 @@
5024
5174
  _: 1
5025
5175
  }, 8, ["visible"])) : (0, vue.createCommentVNode)("v-if", true),
5026
5176
  itemExtra.value ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("span", {
5027
- key: 3,
5177
+ key: 4,
5028
5178
  innerHTML: itemExtra.value,
5029
5179
  class: "m-form-tip"
5030
5180
  }, null, 8, _hoisted_3$3)) : (0, vue.createCommentVNode)("v-if", true)
@@ -5064,7 +5214,10 @@
5064
5214
  key: 1,
5065
5215
  class: "el-table__empty-block"
5066
5216
  };
5067
- var _hoisted_4$1 = { class: "m-fields-group-list-footer" };
5217
+ var _hoisted_4$1 = {
5218
+ key: 3,
5219
+ class: "m-fields-group-list-footer"
5220
+ };
5068
5221
  var _hoisted_5 = { style: {
5069
5222
  "display": "flex",
5070
5223
  "justify-content": "flex-end",
@@ -5149,7 +5302,7 @@
5149
5302
  "group-model"
5150
5303
  ]);
5151
5304
  }), 128)),
5152
- (0, vue.createElementVNode)("div", _hoisted_4$1, [(0, vue.renderSlot)(_ctx.$slots, "toggle-button"), (0, vue.createElementVNode)("div", _hoisted_5, [(0, vue.renderSlot)(_ctx.$slots, "add-button")])])
5305
+ !__props.isCompare ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4$1, [(0, vue.renderSlot)(_ctx.$slots, "toggle-button"), (0, vue.createElementVNode)("div", _hoisted_5, [(0, vue.renderSlot)(_ctx.$slots, "add-button")])])) : (0, vue.createCommentVNode)("v-if", true)
5153
5306
  ]);
5154
5307
  };
5155
5308
  }
@@ -5751,7 +5904,7 @@
5751
5904
  default: (0, vue.withCtx)(() => [(0, vue.createTextVNode)((0, vue.toDisplayString)((0, vue.unref)(isFullscreen) ? "退出全屏" : "全屏编辑"), 1)]),
5752
5905
  _: 1
5753
5906
  }, 8, ["icon", "onClick"])) : (0, vue.createCommentVNode)("v-if", true),
5754
- (0, vue.unref)(importable) ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicUpload), {
5907
+ (0, vue.unref)(importable) && !__props.isCompare ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicUpload), {
5755
5908
  key: 2,
5756
5909
  style: { "display": "inline-block" },
5757
5910
  ref: "excelBtn",
@@ -5771,7 +5924,7 @@
5771
5924
  }, 8, ["disabled"])]),
5772
5925
  _: 1
5773
5926
  }, 8, ["disabled", "on-change"])) : (0, vue.createCommentVNode)("v-if", true),
5774
- (0, vue.unref)(importable) ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), {
5927
+ (0, vue.unref)(importable) && !__props.isCompare ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.unref)(_tmagic_design.TMagicButton), {
5775
5928
  key: 3,
5776
5929
  size: "small",
5777
5930
  type: "warning",
@@ -5782,7 +5935,7 @@
5782
5935
  default: (0, vue.withCtx)(() => [..._cache[1] || (_cache[1] = [(0, vue.createTextVNode)("清空", -1)])]),
5783
5936
  _: 1
5784
5937
  }, 8, ["disabled", "onClick"])) : (0, vue.createCommentVNode)("v-if", true)
5785
- ]), (0, vue.renderSlot)(_ctx.$slots, "add-button")]),
5938
+ ]), !__props.isCompare ? (0, vue.renderSlot)(_ctx.$slots, "add-button", { key: 0 }) : (0, vue.createCommentVNode)("v-if", true)]),
5786
5939
  __props.config.pagination ? ((0, vue.openBlock)(), (0, vue.createElementBlock)("div", _hoisted_4, [(0, vue.createVNode)((0, vue.unref)(_tmagic_design.TMagicPagination), {
5787
5940
  layout: "total, sizes, prev, pager, next, jumper",
5788
5941
  "hide-on-single-page": __props.model[modelName.value].length < (0, vue.unref)(pageSize),
@@ -7861,6 +8014,7 @@
7861
8014
  } };
7862
8015
  var createForm = (config) => config;
7863
8016
  //#endregion
8017
+ exports.FORM_DIFF_CONFIG_KEY = FORM_DIFF_CONFIG_KEY;
7864
8018
  exports.MCascader = Cascader_default;
7865
8019
  exports.MCheckbox = Checkbox_default;
7866
8020
  exports.MCheckboxGroup = CheckboxGroup_default;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.8.0-beta.1",
2
+ "version": "1.8.0-beta.3",
3
3
  "name": "@tmagic/form",
4
4
  "type": "module",
5
5
  "sideEffects": [
@@ -52,9 +52,9 @@
52
52
  "peerDependencies": {
53
53
  "vue": "^3.5.34",
54
54
  "typescript": "^6.0.3",
55
- "@tmagic/design": "1.8.0-beta.1",
56
- "@tmagic/form-schema": "1.8.0-beta.1",
57
- "@tmagic/utils": "1.8.0-beta.1"
55
+ "@tmagic/utils": "1.8.0-beta.3",
56
+ "@tmagic/form-schema": "1.8.0-beta.3",
57
+ "@tmagic/design": "1.8.0-beta.3"
58
58
  },
59
59
  "peerDependenciesMeta": {
60
60
  "typescript": {