@tmagic/form 1.8.0-beta.27 → 1.8.0-beta.29

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,15 +1,15 @@
1
+ import { getGroupListHeaderVars } from "../utils/tableGroupList.js";
1
2
  import GroupListItem_default from "./GroupListItem.js";
2
- import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, defineComponent, mergeProps, normalizeClass, openBlock, renderList, renderSlot, toDisplayString, withCtx } from "vue";
3
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, defineComponent, mergeProps, normalizeClass, normalizeStyle, openBlock, renderList, renderSlot, toDisplayString, withCtx } from "vue";
3
4
  import { cloneDeep } from "lodash-es";
4
5
  //#region packages/form/src/containers/GroupList.vue?vue&type=script&setup=true&lang.ts
5
- var _hoisted_1 = { class: "m-fields-group-list" };
6
- var _hoisted_2 = ["innerHTML"];
7
- var _hoisted_3 = {
6
+ var _hoisted_1 = ["innerHTML"];
7
+ var _hoisted_2 = {
8
8
  key: 1,
9
9
  class: "el-table__empty-block"
10
10
  };
11
- var _hoisted_4 = { class: "el-table__empty-text t-table__empty" };
12
- var _hoisted_5 = { style: {
11
+ var _hoisted_3 = { class: "el-table__empty-text t-table__empty" };
12
+ var _hoisted_4 = { style: {
13
13
  "display": "flex",
14
14
  "justify-content": "flex-end",
15
15
  "flex": "1"
@@ -54,6 +54,14 @@ var GroupList_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
54
54
  };
55
55
  const onAddDiffCount = () => emit("addDiffCount");
56
56
  const asList = (value) => Array.isArray(value) ? value : [];
57
+ const headerVars = computed(() => getGroupListHeaderVars(props.config.header));
58
+ /**
59
+ * 取 `$slots` 而不是 `useSlots()`:宿主切换 `addable` 时插槽会增删,
60
+ * computed 缓存不随插槽变化失效,只有在渲染期读才拿得到最新的。
61
+ */
62
+ const hasFooter = (slots) => !props.isCompare && Boolean(slots["toggle-button"] || slots["add-button"]);
63
+ /** 只有真的渲染出吸底 footer,内层列表才需要为它让位 */
64
+ const isFooterSticky = (slots) => hasFooter(slots) && Boolean(props.config.addButtonConfig?.sticky);
57
65
  const currentList = computed(() => asList(props.model[props.name]));
58
66
  /** 对比时按当前/历史较长一侧对齐,已删除的项也能渲染出来 */
59
67
  const displayItems = computed(() => {
@@ -71,13 +79,19 @@ var GroupList_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
71
79
  }));
72
80
  });
73
81
  return (_ctx, _cache) => {
74
- return openBlock(), createElementBlock("div", _hoisted_1, [
82
+ return openBlock(), createElementBlock("div", {
83
+ class: normalizeClass(["m-fields-group-list", {
84
+ "is-header-sticky": Boolean(__props.config.header?.sticky),
85
+ "is-footer-sticky": isFooterSticky(_ctx.$slots)
86
+ }]),
87
+ style: normalizeStyle(headerVars.value)
88
+ }, [
75
89
  __props.config.extra ? (openBlock(), createElementBlock("div", {
76
90
  key: 0,
77
91
  innerHTML: __props.config.extra,
78
92
  style: { "color": "rgba(0, 0, 0, 0.45)" }
79
- }, null, 8, _hoisted_2)) : createCommentVNode("v-if", true),
80
- !displayItems.value.length ? (openBlock(), createElementBlock("div", _hoisted_3, [createElementVNode("span", _hoisted_4, "暂无" + toDisplayString(__props.config.titlePrefix || "") + "数据", 1)])) : (openBlock(true), createElementBlock(Fragment, { key: 2 }, renderList(displayItems.value, (entry) => {
93
+ }, null, 8, _hoisted_1)) : createCommentVNode("v-if", true),
94
+ !displayItems.value.length ? (openBlock(), createElementBlock("div", _hoisted_2, [createElementVNode("span", _hoisted_3, "暂无" + toDisplayString(__props.config.titlePrefix || "") + "数据", 1)])) : (openBlock(true), createElementBlock(Fragment, { key: 2 }, renderList(displayItems.value, (entry) => {
81
95
  return openBlock(), createBlock(GroupListItem_default, {
82
96
  key: entry.index,
83
97
  model: entry.item,
@@ -114,11 +128,11 @@ var GroupList_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
114
128
  "group-model"
115
129
  ]);
116
130
  }), 128)),
117
- !__props.isCompare && (_ctx.$slots["toggle-button"] || _ctx.$slots["add-button"]) ? (openBlock(), createElementBlock("div", {
131
+ hasFooter(_ctx.$slots) ? (openBlock(), createElementBlock("div", {
118
132
  key: 3,
119
133
  class: normalizeClass(["m-fields-group-list-footer", { "is-sticky-full": Boolean(__props.config.addButtonConfig?.sticky) }])
120
- }, [renderSlot(_ctx.$slots, "toggle-button"), createElementVNode("div", _hoisted_5, [renderSlot(_ctx.$slots, "add-button")])], 2)) : createCommentVNode("v-if", true)
121
- ]);
134
+ }, [renderSlot(_ctx.$slots, "toggle-button"), createElementVNode("div", _hoisted_4, [renderSlot(_ctx.$slots, "add-button")])], 2)) : createCommentVNode("v-if", true)
135
+ ], 6);
122
136
  };
123
137
  }
124
138
  });
@@ -120,14 +120,17 @@ var Text_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
120
120
  const ctrl = navigator.platform.match("Mac") ? $event.metaKey : $event.ctrlKey;
121
121
  const shift = $event.shiftKey;
122
122
  const alt = $event.altKey;
123
- if (arrowUp) if (ctrl) num += 100;
124
- else if (alt) num = (num * 1e4 + 1e3) / 1e4;
125
- else if (shift) num = num + 10;
126
- else num += 1;
127
- else if (arrowDown) if (ctrl) num -= 100;
128
- else if (alt) num = (num * 1e4 - 1e3) / 1e4;
129
- else if (shift) num -= 10;
130
- else num -= 1;
123
+ if (arrowUp) {
124
+ if (ctrl) num += 100;
125
+ else if (alt) num = (num * 1e4 + 1e3) / 1e4;
126
+ else if (shift) num = num + 10;
127
+ else num += 1;
128
+ } else if (arrowDown) {
129
+ if (ctrl) num -= 100;
130
+ else if (alt) num = (num * 1e4 - 1e3) / 1e4;
131
+ else if (shift) num -= 10;
132
+ else num -= 1;
133
+ }
131
134
  props.model[props.name] = `${num}${unit || ""}`;
132
135
  emit("change", props.model[props.name]);
133
136
  };
package/dist/es/style.css CHANGED
@@ -333,18 +333,48 @@ fieldset.m-fieldset .m-form-tip {
333
333
  flex-shrink: 0;
334
334
  gap: 8px;
335
335
  }
336
- .m-fields-group-list .m-fields-group-list-item > .el-card__header,
337
- .m-fields-group-list .m-fields-group-list-item > .t-card__header {
336
+ .m-fields-group-list > .m-fields-group-list-item {
337
+ --m-group-list-item-footer-bottom: var(
338
+ --m-group-list-nested-footer-bottom,
339
+ 0px
340
+ );
341
+ }
342
+ .m-fields-group-list.is-footer-sticky > .m-fields-group-list-item {
343
+ --m-group-list-item-footer-bottom: calc(
344
+ var(--m-group-list-nested-footer-bottom, 0px) +
345
+ var(--m-group-list-footer-height)
346
+ );
347
+ }
348
+ .m-fields-group-list .m-fields-group-list-item .m-fields-group-list {
349
+ --m-group-list-nested-footer-bottom: var(
350
+ --m-group-list-item-footer-bottom,
351
+ 0px
352
+ );
353
+ }
354
+ .m-fields-group-list.is-header-sticky {
355
+ --m-group-list-nested-sticky-top: var(--m-group-list-child-list-sticky-top);
356
+ --m-group-list-nested-header-z: var(--m-group-list-child-list-header-z);
357
+ }
358
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item {
359
+ --m-group-list-item-sticky-top: var(
360
+ --m-group-list-nested-sticky-top,
361
+ var(--m-group-list-header-sticky-top, 0px)
362
+ );
363
+ --m-group-list-item-header-z: var(--m-group-list-nested-header-z, 7);
364
+ --m-group-list-child-list-sticky-top: calc(
365
+ var(--m-group-list-item-sticky-top) + var(--m-group-list-header-height)
366
+ );
367
+ --m-group-list-child-list-header-z: calc(
368
+ var(--m-group-list-item-header-z) - 1
369
+ );
370
+ }
371
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .el-card__header,
372
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .t-card__header {
338
373
  position: sticky;
339
- top: var(--m-group-list-header-sticky-top, 0px);
340
- z-index: 7;
374
+ top: var(--m-group-list-item-sticky-top);
375
+ z-index: var(--m-group-list-item-header-z);
341
376
  background-color: var(--m-group-list-header-bg, #fff);
342
377
  }
343
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .el-card__header,
344
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .t-card__header {
345
- top: calc(var(--m-group-list-header-sticky-top, 0px) + var(--m-group-list-header-height));
346
- z-index: 6;
347
- }
348
378
  .m-fields-group-list .el-table__empty-block {
349
379
  width: 100%;
350
380
  min-height: 0;
@@ -362,7 +392,7 @@ fieldset.m-fieldset .m-form-tip {
362
392
  }
363
393
  .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
364
394
  position: sticky;
365
- bottom: 0;
395
+ bottom: var(--m-group-list-nested-footer-bottom, 0px);
366
396
  z-index: 7;
367
397
  margin-bottom: 0;
368
398
  padding: var(--m-group-list-footer-padding-top) 0 var(--m-group-list-footer-padding-bottom);
@@ -376,10 +406,6 @@ fieldset.m-fieldset .m-form-tip {
376
406
  width: 100%;
377
407
  height: var(--m-group-list-footer-button-height);
378
408
  }
379
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
380
- bottom: var(--m-group-list-footer-height);
381
- z-index: 7;
382
- }
383
409
 
384
410
  /** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
385
411
  .m-container-group-list.outer-gorup_list > .m-fields-group-list > .m-fields-group-list-item {
@@ -192,16 +192,20 @@ var resolveItemType = (mForm, config, props) => {
192
192
  return type?.replace(/([A-Z])/g, "-$1").toLowerCase() || (config?.items ? "" : "text");
193
193
  };
194
194
  var filterFunction = (mForm, config, props) => {
195
- if (typeof config === "function") return config(mForm, {
196
- values: readonly(mForm?.initValues || {}),
197
- model: readonly(props.model),
198
- parent: readonly(mForm?.parentValues || {}),
199
- formValue: readonly(mForm?.values || props.model),
200
- prop: props.prop,
201
- config: props.config,
202
- index: props.index,
203
- getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
204
- });
195
+ if (typeof config === "function") {
196
+ const formValue = readonly(mForm?.values || props.model);
197
+ return config(mForm, {
198
+ values: readonly(mForm?.initValues || {}),
199
+ model: readonly(props.model),
200
+ parent: readonly(mForm?.parentValues || {}),
201
+ formValue,
202
+ formValues: formValue,
203
+ prop: props.prop,
204
+ config: props.config,
205
+ index: props.index,
206
+ getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
207
+ });
208
+ }
205
209
  return config;
206
210
  };
207
211
  var display = function(mForm, config, props) {
@@ -1,4 +1,5 @@
1
1
  import { cloneDeep } from "lodash-es";
2
+ import { isNumber } from "@tmagic/utils";
2
3
  //#region packages/form/src/utils/tableGroupList.ts
3
4
  /**
4
5
  * table / group-list 是同一份配置的两种展示形态,可以互相切换(`TableGroupList.vue`)。
@@ -9,6 +10,24 @@ import { cloneDeep } from "lodash-es";
9
10
  */
10
11
  /** group-list 形态的 type(兼容驼峰与中划线两种写法) */
11
12
  var isGroupListType = (type) => type === "groupList" || type === "group-list";
13
+ /**
14
+ * 归一成带单位的 CSS 长度。
15
+ *
16
+ * 配置常常来自 JSON 或表单输入,`'48'` 这类无单位数字串很常见;直接写进 CSS 变量会让
17
+ * 嵌套层的 `calc()` 整体失效、吸顶静默失灵,所以纯数字一律补 `px`。
18
+ */
19
+ var toCssLength = (height) => {
20
+ const value = `${height ?? ""}`.trim();
21
+ if (!value) return void 0;
22
+ if (isNumber(value)) return `${value}px`;
23
+ return typeof height === "number" ? void 0 : value;
24
+ };
25
+ /** header.sticky 开启时把 height 写成 CSS 变量,给嵌套吸顶偏移用 */
26
+ var getGroupListHeaderVars = (header) => {
27
+ if (!header?.sticky) return void 0;
28
+ const height = toCssLength(header.height);
29
+ return height ? { "--m-group-list-header-height": height } : void 0;
30
+ };
12
31
  /** 按 label 文案长度估算 label 宽度(中文按 20px、其他按 8px,最小 80px) */
13
32
  var calcLabelWidth = (label) => {
14
33
  if (!label) return "0px";
@@ -82,4 +101,4 @@ var makeTableColumnConfig = (column, row) => {
82
101
  return newConfig;
83
102
  };
84
103
  //#endregion
85
- export { calcLabelWidth, getGroupListRowConfig, isGroupListType, isTableColumnRendered, makeTableColumnConfig, toGroupListConfig, toTableConfig };
104
+ export { calcLabelWidth, getGroupListHeaderVars, getGroupListRowConfig, isGroupListType, isTableColumnRendered, makeTableColumnConfig, toGroupListConfig, toTableConfig };
@@ -8,6 +8,14 @@ dayjs.extend(customParseFormat);
8
8
  var extraTypeMatchRules = /* @__PURE__ */ new Map();
9
9
  var builtInTypeMatchRules = /* @__PURE__ */ new Map();
10
10
  var isPromise = (value) => typeof value === "object" && value !== null && typeof value.then === "function";
11
+ /**
12
+ * 同步校验无法等待 Promise。调用方会丢掉返回值,这里挂上空 handler,避免变成未捕获 rejection。
13
+ */
14
+ var ignorePromise = (value) => {
15
+ if (!isPromise(value)) return false;
16
+ value.then(() => {}, () => {});
17
+ return true;
18
+ };
11
19
  /** 注册或覆盖某个字段 type 的 typeMatch 校验规则。`builtIn` 登记不受 `clearTypeMatchRules` / `deleteTypeMatchRule` 影响。 */
12
20
  var registerTypeMatchRule = (type, validator, builtIn = false) => {
13
21
  (builtIn ? builtInTypeMatchRules : extraTypeMatchRules).set(toLine(type), validator);
@@ -25,16 +33,20 @@ var clearTypeMatchRules = () => {
25
33
  };
26
34
  /** 本地解析配置函数,避免与 form.ts 循环依赖 */
27
35
  var resolveConfig = (mForm, config, props) => {
28
- if (typeof config === "function") return config(mForm, {
29
- values: readonly(mForm?.initValues || {}),
30
- model: readonly(props.model),
31
- parent: readonly(mForm?.parentValues || {}),
32
- formValue: readonly(mForm?.values || props.model),
33
- prop: props.prop,
34
- config: props.config,
35
- index: props.index,
36
- getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
37
- });
36
+ if (typeof config === "function") {
37
+ const formValue = readonly(mForm?.values || props.model);
38
+ return config(mForm, {
39
+ values: readonly(mForm?.initValues || {}),
40
+ model: readonly(props.model),
41
+ parent: readonly(mForm?.parentValues || {}),
42
+ formValue,
43
+ formValues: formValue,
44
+ prop: props.prop,
45
+ config: props.config,
46
+ index: props.index,
47
+ getFormValue: (prop) => getValueByKeyPath(prop, mForm?.values || props.model)
48
+ });
49
+ }
38
50
  return config;
39
51
  };
40
52
  var SKIP_TYPES = /* @__PURE__ */ new Set([
@@ -126,7 +138,7 @@ var resolveFieldDefaultValue = (mForm, props) => {
126
138
  const { defaultValue } = props.config || {};
127
139
  if (typeof defaultValue === "undefined" || defaultValue === "undefined") return void 0;
128
140
  const resolvedDefaultValue = resolveConfig(mForm, defaultValue, props);
129
- if (isPromise(resolvedDefaultValue)) return;
141
+ if (ignorePromise(resolvedDefaultValue)) return;
130
142
  return resolvedDefaultValue;
131
143
  };
132
144
  var isNumberValue = (value) => typeof value === "number" && !Number.isNaN(value);
@@ -203,9 +215,21 @@ var flattenSelectOptions = (options) => {
203
215
  });
204
216
  return values;
205
217
  };
206
- var resolveOptions = (props) => {
207
- const { options } = props.config || {};
208
- return Array.isArray(options) ? options : [];
218
+ /**
219
+ * 解析字段 options:静态数组原样返回;函数型与 `display` / `type` 一样当场求值。
220
+ *
221
+ * 函数返回 Promise、非数组或抛错时当作「还没有可选项」,交由调用方按空 options 跳过枚举。
222
+ * `remote` / `allowCreate` 仍由 `validateSelectValue` 单独放行,不在这里区分。
223
+ */
224
+ var resolveOptions = (mForm, props) => {
225
+ let resolved;
226
+ try {
227
+ resolved = resolveConfig(mForm, props.config?.options, props);
228
+ } catch {
229
+ return [];
230
+ }
231
+ if (ignorePromise(resolved) || !Array.isArray(resolved)) return [];
232
+ return resolved;
209
233
  };
210
234
  var includesOptionValue = (optionValues, value) => optionValues.some((item) => Object.is(item, value));
211
235
  var collectCascaderLeafValues = (options, result = []) => {
@@ -267,19 +291,18 @@ var validateSelectValue = (value, config, optionValues, message) => {
267
291
  if (typeof value === "object") return defaultMessage(message, `${value} 类型不合法`, optionExampleSuggestion(optionValues, "\"文本内容\" 或 123", false));
268
292
  return;
269
293
  }
270
- const isStaticOptions = Array.isArray(config.options);
271
294
  if (config.multiple) {
272
295
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
273
- if (isStaticOptions && value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
296
+ if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
274
297
  return;
275
298
  }
276
- if (isStaticOptions && !includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
299
+ if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
277
300
  };
278
301
  var validateCascaderValue = (value, config, props, mForm, message) => {
279
- const options = resolveOptions(props);
302
+ const options = resolveOptions(mForm, props);
280
303
  if (!options.length) return;
281
304
  const valueSeparator = resolveConfig(mForm, config.valueSeparator, props);
282
- if (isPromise(valueSeparator)) return;
305
+ if (ignorePromise(valueSeparator)) return;
283
306
  const emitPath = config.emitPath !== false;
284
307
  const multiple = Boolean(config.multiple);
285
308
  const cascaderExample = (fallbackExample) => cascaderExampleSuggestion(options, config, valueSeparator, fallbackExample);
@@ -336,15 +359,15 @@ var validateBuiltinTypeMatch = (value, fieldType, mForm, props, message) => {
336
359
  if (!Object.is(value, activeValue) && !Object.is(value, inactiveValue)) return defaultMessage(message, `${value} 不在合法开关值中`, toggleSuggestion(activeValue, inactiveValue));
337
360
  return;
338
361
  }
339
- if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(props)), message);
362
+ if (fieldType === "select") return validateSelectValue(value, config, flattenSelectOptions(resolveOptions(mForm, props)), message);
340
363
  if (fieldType === "radio-group") {
341
- const optionValues = flattenSelectOptions(resolveOptions(props));
364
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
342
365
  if (optionValues.length === 0) return;
343
366
  if (!includesOptionValue(optionValues, value)) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
344
367
  return;
345
368
  }
346
369
  if (fieldType === "checkbox-group") {
347
- const optionValues = flattenSelectOptions(resolveOptions(props));
370
+ const optionValues = flattenSelectOptions(resolveOptions(mForm, props));
348
371
  if (optionValues.length === 0) return;
349
372
  if (!Array.isArray(value)) return defaultMessage(message, `${value} 类型应为数组`, optionExampleSuggestion(optionValues, "[\"选项1\", \"选项2\"]", true));
350
373
  if (value.some((item) => !includesOptionValue(optionValues, item))) return defaultMessage(message, `${value} 不在可选项中`, optionSuggestion(optionValues));
@@ -371,8 +394,14 @@ var validateTypeMatch = (value, mForm, props, message) => {
371
394
  if (isEmptyValue(value) || isEmptyArray(value)) return;
372
395
  if (!props.config?.name) return;
373
396
  const rawFieldType = "type" in (props.config || {}) ? props.config.type : "";
374
- if (typeof rawFieldType !== "string" || !rawFieldType) return;
375
- const fieldType = toLine(rawFieldType);
397
+ let resolvedType;
398
+ try {
399
+ resolvedType = resolveConfig(mForm, rawFieldType, props);
400
+ } catch {
401
+ return;
402
+ }
403
+ if (ignorePromise(resolvedType) || typeof resolvedType !== "string" || !resolvedType) return;
404
+ const fieldType = toLine(resolvedType);
376
405
  const customValidator = getTypeMatchRule(fieldType);
377
406
  if (customValidator) return customValidator(value, {
378
407
  fieldType,
package/dist/style.css CHANGED
@@ -333,18 +333,48 @@ fieldset.m-fieldset .m-form-tip {
333
333
  flex-shrink: 0;
334
334
  gap: 8px;
335
335
  }
336
- .m-fields-group-list .m-fields-group-list-item > .el-card__header,
337
- .m-fields-group-list .m-fields-group-list-item > .t-card__header {
336
+ .m-fields-group-list > .m-fields-group-list-item {
337
+ --m-group-list-item-footer-bottom: var(
338
+ --m-group-list-nested-footer-bottom,
339
+ 0px
340
+ );
341
+ }
342
+ .m-fields-group-list.is-footer-sticky > .m-fields-group-list-item {
343
+ --m-group-list-item-footer-bottom: calc(
344
+ var(--m-group-list-nested-footer-bottom, 0px) +
345
+ var(--m-group-list-footer-height)
346
+ );
347
+ }
348
+ .m-fields-group-list .m-fields-group-list-item .m-fields-group-list {
349
+ --m-group-list-nested-footer-bottom: var(
350
+ --m-group-list-item-footer-bottom,
351
+ 0px
352
+ );
353
+ }
354
+ .m-fields-group-list.is-header-sticky {
355
+ --m-group-list-nested-sticky-top: var(--m-group-list-child-list-sticky-top);
356
+ --m-group-list-nested-header-z: var(--m-group-list-child-list-header-z);
357
+ }
358
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item {
359
+ --m-group-list-item-sticky-top: var(
360
+ --m-group-list-nested-sticky-top,
361
+ var(--m-group-list-header-sticky-top, 0px)
362
+ );
363
+ --m-group-list-item-header-z: var(--m-group-list-nested-header-z, 7);
364
+ --m-group-list-child-list-sticky-top: calc(
365
+ var(--m-group-list-item-sticky-top) + var(--m-group-list-header-height)
366
+ );
367
+ --m-group-list-child-list-header-z: calc(
368
+ var(--m-group-list-item-header-z) - 1
369
+ );
370
+ }
371
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .el-card__header,
372
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .t-card__header {
338
373
  position: sticky;
339
- top: var(--m-group-list-header-sticky-top, 0px);
340
- z-index: 7;
374
+ top: var(--m-group-list-item-sticky-top);
375
+ z-index: var(--m-group-list-item-header-z);
341
376
  background-color: var(--m-group-list-header-bg, #fff);
342
377
  }
343
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .el-card__header,
344
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .t-card__header {
345
- top: calc(var(--m-group-list-header-sticky-top, 0px) + var(--m-group-list-header-height));
346
- z-index: 6;
347
- }
348
378
  .m-fields-group-list .el-table__empty-block {
349
379
  width: 100%;
350
380
  min-height: 0;
@@ -362,7 +392,7 @@ fieldset.m-fieldset .m-form-tip {
362
392
  }
363
393
  .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
364
394
  position: sticky;
365
- bottom: 0;
395
+ bottom: var(--m-group-list-nested-footer-bottom, 0px);
366
396
  z-index: 7;
367
397
  margin-bottom: 0;
368
398
  padding: var(--m-group-list-footer-padding-top) 0 var(--m-group-list-footer-padding-bottom);
@@ -376,10 +406,6 @@ fieldset.m-fieldset .m-form-tip {
376
406
  width: 100%;
377
407
  height: var(--m-group-list-footer-button-height);
378
408
  }
379
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
380
- bottom: var(--m-group-list-footer-height);
381
- z-index: 7;
382
- }
383
409
 
384
410
  /** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
385
411
  .m-container-group-list.outer-gorup_list > .m-fields-group-list > .m-fields-group-list-item {
@@ -333,18 +333,48 @@ fieldset.m-fieldset .m-form-tip {
333
333
  flex-shrink: 0;
334
334
  gap: 8px;
335
335
  }
336
- .m-fields-group-list .m-fields-group-list-item > .el-card__header,
337
- .m-fields-group-list .m-fields-group-list-item > .t-card__header {
336
+ .m-fields-group-list > .m-fields-group-list-item {
337
+ --m-group-list-item-footer-bottom: var(
338
+ --m-group-list-nested-footer-bottom,
339
+ 0px
340
+ );
341
+ }
342
+ .m-fields-group-list.is-footer-sticky > .m-fields-group-list-item {
343
+ --m-group-list-item-footer-bottom: calc(
344
+ var(--m-group-list-nested-footer-bottom, 0px) +
345
+ var(--m-group-list-footer-height)
346
+ );
347
+ }
348
+ .m-fields-group-list .m-fields-group-list-item .m-fields-group-list {
349
+ --m-group-list-nested-footer-bottom: var(
350
+ --m-group-list-item-footer-bottom,
351
+ 0px
352
+ );
353
+ }
354
+ .m-fields-group-list.is-header-sticky {
355
+ --m-group-list-nested-sticky-top: var(--m-group-list-child-list-sticky-top);
356
+ --m-group-list-nested-header-z: var(--m-group-list-child-list-header-z);
357
+ }
358
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item {
359
+ --m-group-list-item-sticky-top: var(
360
+ --m-group-list-nested-sticky-top,
361
+ var(--m-group-list-header-sticky-top, 0px)
362
+ );
363
+ --m-group-list-item-header-z: var(--m-group-list-nested-header-z, 7);
364
+ --m-group-list-child-list-sticky-top: calc(
365
+ var(--m-group-list-item-sticky-top) + var(--m-group-list-header-height)
366
+ );
367
+ --m-group-list-child-list-header-z: calc(
368
+ var(--m-group-list-item-header-z) - 1
369
+ );
370
+ }
371
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .el-card__header,
372
+ .m-fields-group-list.is-header-sticky > .m-fields-group-list-item > .t-card__header {
338
373
  position: sticky;
339
- top: var(--m-group-list-header-sticky-top, 0px);
340
- z-index: 7;
374
+ top: var(--m-group-list-item-sticky-top);
375
+ z-index: var(--m-group-list-item-header-z);
341
376
  background-color: var(--m-group-list-header-bg, #fff);
342
377
  }
343
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .el-card__header,
344
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list-item > .t-card__header {
345
- top: calc(var(--m-group-list-header-sticky-top, 0px) + var(--m-group-list-header-height));
346
- z-index: 6;
347
- }
348
378
  .m-fields-group-list .el-table__empty-block {
349
379
  width: 100%;
350
380
  min-height: 0;
@@ -362,7 +392,7 @@ fieldset.m-fieldset .m-form-tip {
362
392
  }
363
393
  .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
364
394
  position: sticky;
365
- bottom: 0;
395
+ bottom: var(--m-group-list-nested-footer-bottom, 0px);
366
396
  z-index: 7;
367
397
  margin-bottom: 0;
368
398
  padding: var(--m-group-list-footer-padding-top) 0 var(--m-group-list-footer-padding-bottom);
@@ -376,10 +406,6 @@ fieldset.m-fieldset .m-form-tip {
376
406
  width: 100%;
377
407
  height: var(--m-group-list-footer-button-height);
378
408
  }
379
- .m-fields-group-list .m-fields-group-list-item .m-fields-group-list > .m-fields-group-list-footer.is-sticky-full {
380
- bottom: var(--m-group-list-footer-height);
381
- z-index: 7;
382
- }
383
409
 
384
410
  /** 最外层的groupList需要每个item需要增加空白区域界限时,增加outer-gorup_list可以实现 */
385
411
  .m-container-group-list.outer-gorup_list > .m-fields-group-list > .m-fields-group-list-item {