@shwfed/config 2.9.11 → 2.9.13

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.
Files changed (65) hide show
  1. package/dist/mcp.mjs +112 -50
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{FieldGroup.vue_vue_type_script_setup_true_lang-CN4xD2hQ.js → FieldGroup.vue_vue_type_script_setup_true_lang-DZ_H-YRf.js} +1 -1
  4. package/dist/preview/assets/{badge-CzfW1Ked.js → badge-DoNuZh0A.js} +1 -1
  5. package/dist/preview/assets/{config-Bzwfqv6w.js → config-BDDuqAht.js} +1 -1
  6. package/dist/preview/assets/{config-CCXJvpik.js → config-Bhc_Vu67.js} +1 -1
  7. package/dist/preview/assets/{config-CPuERNUd.js → config-BrNZsgV0.js} +1 -1
  8. package/dist/preview/assets/{config-Op5IHwI_.js → config-C6Cm7DWx.js} +1 -1
  9. package/dist/preview/assets/{config-D37gWDMV.js → config-CIYui2J_.js} +1 -1
  10. package/dist/preview/assets/{config-DbNukLyq.js → config-CLsjWZz2.js} +1 -1
  11. package/dist/preview/assets/{config-e5aOGFb2.js → config-Cla0Qngs.js} +1 -1
  12. package/dist/preview/assets/{config-CDYZN7EX.js → config-D4rFsdGO.js} +1 -1
  13. package/dist/preview/assets/{config-BdX3zl4t.js → config-DTEJOYqA.js} +1 -1
  14. package/dist/preview/assets/{config-jJQ2fulH.js → config-YGBoSq6x.js} +1 -1
  15. package/dist/preview/assets/{config-C2y2XI2Q.js → config-tdZMdIN3.js} +1 -1
  16. package/dist/preview/assets/{config-jzfHh7bp.js → config-ugF_BOWz.js} +1 -1
  17. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-BgssDGxW.js → definition.vue_vue_type_script_setup_true_lang-CgNXv26P.js} +1 -1
  18. package/dist/preview/assets/index-B-QhiviS.js +1 -0
  19. package/dist/preview/assets/{index-CAIvIAWJ.js → index-C3FdepLE.js} +1 -1
  20. package/dist/preview/assets/{index-Cyjm-GKs.js → index-CWMhB7z4.js} +204 -203
  21. package/dist/preview/assets/index-CzzwZ7bp.css +1 -0
  22. package/dist/preview/assets/{item-CUoRMMz1.js → item-DecwNzYq.js} +1 -1
  23. package/dist/preview/assets/{runtime-CWt21RRo.js → runtime-BK7KNEyN.js} +1 -1
  24. package/dist/preview/assets/{runtime-DWKqftSK.js → runtime-C3dmOj9s.js} +1 -1
  25. package/dist/preview/assets/{runtime-D3TnRYXn.js → runtime-C5hqSHRW.js} +1 -1
  26. package/dist/preview/assets/{runtime-C_epees8.js → runtime-C8Ufkmiw.js} +1 -1
  27. package/dist/preview/assets/{runtime-V_usL1Fa.js → runtime-CYpXd7Pq.js} +1 -1
  28. package/dist/preview/assets/{runtime-CU5fYNMI.js → runtime-CjPtRd-T.js} +1 -1
  29. package/dist/preview/assets/{runtime-BALr-Cq0.js → runtime-DSUjc0Pk.js} +1 -1
  30. package/dist/preview/assets/{runtime-CHQwYQ80.js → runtime-DZ_AwduQ.js} +1 -1
  31. package/dist/preview/assets/{runtime-BvcTYin8.js → runtime-DtP98Km5.js} +1 -1
  32. package/dist/preview/assets/{runtime-wAz72cCJ.js → runtime-blb90Fhv.js} +1 -1
  33. package/dist/preview/assets/{schema-meta-DwWuSVqk.js → schema-meta-DWUHNP8E.js} +1 -1
  34. package/dist/preview/index.html +2 -2
  35. package/dist/runtime/components/actions/buttons/2026-05-15/com.shwfed.actions.button.event.dispatch/schema.d.ts +15 -0
  36. package/dist/runtime/components/actions/buttons/2026-05-15/com.shwfed.actions.button.event.dispatch/schema.js +57 -1
  37. package/dist/runtime/components/block-layout-editor/index.vue +10 -2
  38. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +134 -0
  39. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +134 -0
  40. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +134 -0
  41. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +134 -0
  42. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +195 -0
  43. package/dist/runtime/components/form/config.vue +38 -1
  44. package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.d.vue.ts +2 -0
  45. package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.vue.d.ts +2 -0
  46. package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/schema.d.ts +2 -0
  47. package/dist/runtime/components/form/index.vue +8 -1
  48. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/runtime.js +5 -3
  49. package/dist/runtime/components/operations/2026-06-11/com.shwfed.operation.http.request.json/schema.js +3 -2
  50. package/dist/runtime/components/table/config.d.vue.ts +3 -3
  51. package/dist/runtime/components/table/config.vue +62 -22
  52. package/dist/runtime/components/table/config.vue.d.ts +3 -3
  53. package/dist/runtime/components/table/index.d.vue.ts +2 -0
  54. package/dist/runtime/components/table/index.vue +12 -3
  55. package/dist/runtime/components/table/index.vue.d.ts +2 -0
  56. package/dist/runtime/components/table/schema.d.ts +263 -0
  57. package/dist/runtime/components/table/schema.js +8 -4
  58. package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +2 -2
  59. package/dist/runtime/components/ui/expression-editor/picker-entries.d.ts +1 -0
  60. package/dist/runtime/components/ui/expression-editor/picker-entries.js +12 -0
  61. package/dist/runtime/components/ui/expression-editor/scope-refs.js +1 -1
  62. package/dist/runtime/utils/cel-context.d.ts +21 -0
  63. package/package.json +1 -1
  64. package/dist/preview/assets/index-0vF7XQ-J.js +0 -1
  65. package/dist/preview/assets/index-D0eGXK5P.css +0 -1
@@ -145,6 +145,73 @@ export declare function schema(configure: (env: Environment) => void, _blockRef:
145
145
  readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
146
146
  }[];
147
147
  } | undefined;
148
+ readonly bottomActions?: {
149
+ readonly size: "default" | "sm" | "xs";
150
+ readonly style?: string | undefined;
151
+ readonly gap: number;
152
+ readonly items: readonly (import("../../../../actions/schema.js").RegistryItemValue | {
153
+ readonly disabled?: string | undefined;
154
+ readonly id: string;
155
+ readonly title: readonly [{
156
+ readonly locale: "zh";
157
+ readonly message: string;
158
+ }, ...{
159
+ readonly locale: "en" | "ja" | "ko";
160
+ readonly message: string;
161
+ }[]];
162
+ readonly icon?: string | undefined;
163
+ readonly hidden?: string | undefined;
164
+ readonly tooltip?: readonly [{
165
+ readonly locale: "zh";
166
+ readonly message: string;
167
+ }, ...{
168
+ readonly locale: "en" | "ja" | "ko";
169
+ readonly message: string;
170
+ }[]] | undefined;
171
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
172
+ readonly action?: any;
173
+ readonly groupId: string;
174
+ readonly hideTitle?: boolean | undefined;
175
+ } | {
176
+ readonly id: string;
177
+ readonly title: readonly [{
178
+ readonly locale: "zh";
179
+ readonly message: string;
180
+ }, ...{
181
+ readonly locale: "en" | "ja" | "ko";
182
+ readonly message: string;
183
+ }[]];
184
+ readonly icon?: string | undefined;
185
+ readonly items: readonly (import("../../../../actions/schema.js").RegistrySubItemValue | {
186
+ readonly disabled?: string | undefined;
187
+ readonly id: string;
188
+ readonly title: readonly [{
189
+ readonly locale: "zh";
190
+ readonly message: string;
191
+ }, ...{
192
+ readonly locale: "en" | "ja" | "ko";
193
+ readonly message: string;
194
+ }[]];
195
+ readonly icon?: string | undefined;
196
+ readonly hidden?: string | undefined;
197
+ readonly tooltip?: readonly [{
198
+ readonly locale: "zh";
199
+ readonly message: string;
200
+ }, ...{
201
+ readonly locale: "en" | "ja" | "ko";
202
+ readonly message: string;
203
+ }[]] | undefined;
204
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
205
+ readonly action?: any;
206
+ })[];
207
+ readonly groupId: string;
208
+ readonly hideTitle?: boolean | undefined;
209
+ })[];
210
+ readonly groups: readonly {
211
+ readonly id: string;
212
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
213
+ }[];
214
+ } | undefined;
148
215
  readonly rowKey?: string | undefined;
149
216
  readonly cellStyle?: string | undefined;
150
217
  readonly pagination?: {
@@ -352,6 +419,134 @@ export declare function schema(configure: (env: Environment) => void, _blockRef:
352
419
  readonly hideTitle?: boolean | undefined;
353
420
  }, never>>;
354
421
  }>>;
422
+ bottomActions: Schema.optional<Schema.Struct<{
423
+ size: Schema.optionalWith<Schema.Literal<["default", "sm", "xs"]>, {
424
+ default: () => "default";
425
+ }>;
426
+ gap: Schema.optionalWith<Schema.filter<Schema.filter<typeof Schema.Number>>, {
427
+ default: () => number;
428
+ }>;
429
+ style: Schema.optional<typeof Schema.String>;
430
+ groups: Schema.Array$<Schema.Struct<{
431
+ id: Schema.refine<string, typeof Schema.String>;
432
+ variant: Schema.optional<Schema.Literal<["default", "primary", "destructive", "ghost", "link"]>>;
433
+ }>>;
434
+ items: Schema.Array$<Schema.Schema<import("../../../../actions/schema.js").RegistryItemValue | {
435
+ readonly disabled?: string | undefined;
436
+ readonly id: string;
437
+ readonly title: readonly [{
438
+ readonly locale: "zh";
439
+ readonly message: string;
440
+ }, ...{
441
+ readonly locale: "en" | "ja" | "ko";
442
+ readonly message: string;
443
+ }[]];
444
+ readonly icon?: string | undefined;
445
+ readonly hidden?: string | undefined;
446
+ readonly tooltip?: readonly [{
447
+ readonly locale: "zh";
448
+ readonly message: string;
449
+ }, ...{
450
+ readonly locale: "en" | "ja" | "ko";
451
+ readonly message: string;
452
+ }[]] | undefined;
453
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
454
+ readonly action?: any;
455
+ readonly groupId: string;
456
+ readonly hideTitle?: boolean | undefined;
457
+ } | {
458
+ readonly id: string;
459
+ readonly title: readonly [{
460
+ readonly locale: "zh";
461
+ readonly message: string;
462
+ }, ...{
463
+ readonly locale: "en" | "ja" | "ko";
464
+ readonly message: string;
465
+ }[]];
466
+ readonly icon?: string | undefined;
467
+ readonly items: readonly (import("../../../../actions/schema.js").RegistrySubItemValue | {
468
+ readonly disabled?: string | undefined;
469
+ readonly id: string;
470
+ readonly title: readonly [{
471
+ readonly locale: "zh";
472
+ readonly message: string;
473
+ }, ...{
474
+ readonly locale: "en" | "ja" | "ko";
475
+ readonly message: string;
476
+ }[]];
477
+ readonly icon?: string | undefined;
478
+ readonly hidden?: string | undefined;
479
+ readonly tooltip?: readonly [{
480
+ readonly locale: "zh";
481
+ readonly message: string;
482
+ }, ...{
483
+ readonly locale: "en" | "ja" | "ko";
484
+ readonly message: string;
485
+ }[]] | undefined;
486
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
487
+ readonly action?: any;
488
+ })[];
489
+ readonly groupId: string;
490
+ readonly hideTitle?: boolean | undefined;
491
+ }, import("../../../../actions/schema.js").RegistryItemValue | {
492
+ readonly id: string;
493
+ readonly title: readonly [{
494
+ readonly locale: "zh";
495
+ readonly message: string;
496
+ }, ...{
497
+ readonly locale: "en" | "ja" | "ko";
498
+ readonly message: string;
499
+ }[]];
500
+ readonly groupId: string;
501
+ readonly disabled?: string | undefined;
502
+ readonly icon?: string | undefined;
503
+ readonly hidden?: string | undefined;
504
+ readonly tooltip?: readonly [{
505
+ readonly locale: "zh";
506
+ readonly message: string;
507
+ }, ...{
508
+ readonly locale: "en" | "ja" | "ko";
509
+ readonly message: string;
510
+ }[]] | undefined;
511
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
512
+ readonly action?: any;
513
+ readonly hideTitle?: boolean | undefined;
514
+ } | {
515
+ readonly id: string;
516
+ readonly title: readonly [{
517
+ readonly locale: "zh";
518
+ readonly message: string;
519
+ }, ...{
520
+ readonly locale: "en" | "ja" | "ko";
521
+ readonly message: string;
522
+ }[]];
523
+ readonly items: readonly (import("../../../../actions/schema.js").RegistrySubItemValue | {
524
+ readonly id: string;
525
+ readonly title: readonly [{
526
+ readonly locale: "zh";
527
+ readonly message: string;
528
+ }, ...{
529
+ readonly locale: "en" | "ja" | "ko";
530
+ readonly message: string;
531
+ }[]];
532
+ readonly disabled?: string | undefined;
533
+ readonly icon?: string | undefined;
534
+ readonly hidden?: string | undefined;
535
+ readonly tooltip?: readonly [{
536
+ readonly locale: "zh";
537
+ readonly message: string;
538
+ }, ...{
539
+ readonly locale: "en" | "ja" | "ko";
540
+ readonly message: string;
541
+ }[]] | undefined;
542
+ readonly variant?: "default" | "link" | "destructive" | "primary" | "ghost" | undefined;
543
+ readonly action?: any;
544
+ })[];
545
+ readonly groupId: string;
546
+ readonly icon?: string | undefined;
547
+ readonly hideTitle?: boolean | undefined;
548
+ }, never>>;
549
+ }>>;
355
550
  query: Schema.optional<Schema.refine<{
356
551
  readonly style?: string | undefined;
357
552
  readonly id?: string | undefined;
@@ -1,6 +1,8 @@
1
1
  <script setup>
2
2
  import { computed, ref } from "vue";
3
- import { provideCELContext } from "../../utils/cel-context";
3
+ import { provideCELContext, provideScopeAncestor, SELECTIONS_VAR } from "../../utils/cel-context";
4
+ import { getLocalizedText } from "../../share/locale";
5
+ import { findField } from "./utils/resolve";
4
6
  import { ExpressionEditor } from "../ui/expression-editor";
5
7
  import { Field, FieldLabel } from "../ui/field";
6
8
  import { Input } from "../ui/input";
@@ -45,6 +47,41 @@ const formEventAncestor = computed(() => {
45
47
  };
46
48
  });
47
49
  provideEventAncestor(formEventAncestor);
50
+ function selectionFieldLabel(f) {
51
+ const fa = f;
52
+ if (typeof fa.displayName === "string" && fa.displayName.length > 0) return fa.displayName;
53
+ return getLocalizedText(fa.label, "zh") ?? "\u672A\u547D\u540D\u5B57\u6BB5";
54
+ }
55
+ const formScopeAncestor = computed(() => {
56
+ const id = config.value.id;
57
+ if (!id) return null;
58
+ const displayName = config.value.displayName;
59
+ const selectionMembers = config.value.fields.filter((f) => findField(f.type, f.compatibilityDate)?.metadata?.selection).map((f) => ({
60
+ key: `${SELECTIONS_VAR}[${JSON.stringify(f.id)}]`,
61
+ // Addressed key is the bracket lookup, but it mirrors the relative
62
+ // `selections` map — so the picker offers it only where a nearer row /
63
+ // subform shadows `selections`, not to a plain sibling field of this form.
64
+ shortcut: SELECTIONS_VAR,
65
+ label: selectionFieldLabel(f),
66
+ type: "dyn",
67
+ description: "\u8BE5\u9009\u62E9\u5B57\u6BB5\u5F53\u524D\u9009\u4E2D\u9879\u7684\u5B8C\u6574\u5BF9\u8C61\uFF08\u542B key \u4EE5\u5916\u7684\u5B57\u6BB5\uFF09"
68
+ }));
69
+ return {
70
+ id,
71
+ name: displayName && displayName.length > 0 ? displayName : void 0,
72
+ typeName: formMetadata.name,
73
+ typeIcon: formMetadata.icon,
74
+ members: [
75
+ { key: "form", label: "\u8868\u5355\u503C", type: "dyn", description: "\u8BE5\u8868\u5355\u7684\u5F53\u524D\u6574\u4F53\u72B6\u6001" },
76
+ ...selectionMembers
77
+ ],
78
+ // The form unconditionally rebinds both `form` and `selections` for its
79
+ // subtree (index.vue), so declare them explicitly rather than deriving from
80
+ // `members` — a form with no selection field still shadows `selections`.
81
+ shadows: ["form", SELECTIONS_VAR]
82
+ };
83
+ });
84
+ provideScopeAncestor(formScopeAncestor);
48
85
  const unitModel = computed({
49
86
  get: () => ({ fields: config.value.fields, layouts: config.value.layouts }),
50
87
  set: (next) => {
@@ -25,6 +25,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
25
25
  total?: string;
26
26
  }>;
27
27
  actions?: import("../../../../table/schema.js").TableActionsValue;
28
+ bottomActions?: import("../../../../table/schema.js").TableActionsValue;
28
29
  query?: import("../../../schema.js").FormConfigValue;
29
30
  rowKey?: string;
30
31
  cellStyle?: string;
@@ -101,6 +102,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
101
102
  total?: string;
102
103
  }>;
103
104
  actions?: import("../../../../table/schema.js").TableActionsValue;
105
+ bottomActions?: import("../../../../table/schema.js").TableActionsValue;
104
106
  query?: import("../../../schema.js").FormConfigValue;
105
107
  rowKey?: string;
106
108
  cellStyle?: string;
@@ -25,6 +25,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
25
25
  total?: string;
26
26
  }>;
27
27
  actions?: import("../../../../table/schema.js").TableActionsValue;
28
+ bottomActions?: import("../../../../table/schema.js").TableActionsValue;
28
29
  query?: import("../../../schema.js").FormConfigValue;
29
30
  rowKey?: string;
30
31
  cellStyle?: string;
@@ -101,6 +102,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
101
102
  total?: string;
102
103
  }>;
103
104
  actions?: import("../../../../table/schema.js").TableActionsValue;
105
+ bottomActions?: import("../../../../table/schema.js").TableActionsValue;
104
106
  query?: import("../../../schema.js").FormConfigValue;
105
107
  rowKey?: string;
106
108
  cellStyle?: string;
@@ -42,6 +42,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
42
42
  groups: ReadonlyArray<import("../../../../table/schema.js").ColumnGroupValue>;
43
43
  dataSource?: import("../../../../table/schema.js").DataSourceValue;
44
44
  actions?: import("../../../../table/schema.js").TableActionsValue;
45
+ bottomActions?: import("../../../../table/schema.js").TableActionsValue;
45
46
  query?: import("../../../schema.js").FormConfigValue;
46
47
  rowKey?: string;
47
48
  cellStyle?: string;
@@ -78,6 +79,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
78
79
  groups: ReadonlyArray<import("../../../../table/schema.js").ColumnGroupValue>;
79
80
  dataSource?: import("../../../../table/schema.js").DataSourceValue;
80
81
  actions?: import("../../../../table/schema.js").TableActionsValue;
82
+ bottomActions?: import("../../../../table/schema.js").TableActionsValue;
81
83
  query?: import("../../../schema.js").FormConfigValue;
82
84
  rowKey?: string;
83
85
  cellStyle?: string;
@@ -7,7 +7,8 @@ import { computed } from "vue";
7
7
  import {
8
8
  celBindings,
9
9
  injectCELContext,
10
- provideCELContext
10
+ provideCELContext,
11
+ provideScopeAddress
11
12
  } from "../../utils/cel-context";
12
13
  import FormUnitRenderer from "./FormUnitRenderer.vue";
13
14
  import { buildFormRuntimeScope } from "./utils/cel-scope";
@@ -39,6 +40,12 @@ provideCELContext(buildFormRuntimeScope({
39
40
  redoable: () => formHistory.canRedo.value,
40
41
  selections: () => selections.entries.value
41
42
  }));
43
+ if (config.value.id) {
44
+ provideScopeAddress(config.value.id, {
45
+ form: () => state.value ?? {},
46
+ selections: () => selections.entries.value
47
+ });
48
+ }
42
49
  const inherited = injectCELContext();
43
50
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
44
51
  const formState = provideFormState(state);
@@ -26,9 +26,11 @@ export const handler = (params, ctx) => {
26
26
  const kind = TOAST_STYLES.has(result) ? result : "success";
27
27
  if (titleExpression !== void 0) {
28
28
  const title = yield* ctx.cel(titleExpression, { json, result, steps });
29
- const raw = getLocalizedText(description, ctx.locale()) ?? "";
30
- const body = raw.length === 0 ? void 0 : interpolateMarkdown(raw, ctx.cel, { json, result, steps });
31
- toast[kind](title, body === void 0 ? void 0 : { description: body });
29
+ if (title.length > 0) {
30
+ const raw = getLocalizedText(description, ctx.locale()) ?? "";
31
+ const body = raw.length === 0 ? void 0 : interpolateMarkdown(raw, ctx.cel, { json, result, steps });
32
+ toast[kind](title, body === void 0 ? void 0 : { description: body });
33
+ }
32
34
  }
33
35
  if (Either.isLeft(outcome)) {
34
36
  if (import.meta.dev) console.warn("[shwfed-operations] http request failed", outcome.left);
@@ -53,7 +53,8 @@ export function schema(configure) {
53
53
  titleExpression: Schema.optional(CelToastString.annotations({
54
54
  title: "\u63D0\u793A\u6807\u9898",
55
55
  description: md`
56
- 配置后,作为提示的标题向用户展示。
56
+ 配置后,作为提示的标题向用户展示。求值为空字符串时不提示——
57
+ 可按 \`result\` 分支实现仅部分结果下提示,如 \`result == 'error' ? '请求失败' : ''\`。
57
58
  `
58
59
  })),
59
60
  description: Schema.optional(Locale.annotations({
@@ -70,7 +71,7 @@ export function schema(configure) {
70
71
  调用多个接口——前一个失败后,后续操作不再执行。后面的步骤可经 \`steps["<步骤标识>"]\`
71
72
  引用前面步骤的响应。
72
73
 
73
- toast 完全由「提示标题」「提示内容」决定(含失败场景);不配置标题则静默。
74
+ toast 完全由「提示标题」「提示内容」决定(含失败场景);不配置标题、或标题求值为空字符串则静默。
74
75
  `
75
76
  });
76
77
  }
@@ -9,11 +9,11 @@ type __VLS_ModelProps = {
9
9
  modelValue: AnyRecord;
10
10
  };
11
11
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
12
- declare var __VLS_219: {}, __VLS_221: {};
12
+ declare var __VLS_224: {}, __VLS_226: {};
13
13
  type __VLS_Slots = {} & {
14
- 'general-grid-extra'?: (props: typeof __VLS_219) => any;
14
+ 'general-grid-extra'?: (props: typeof __VLS_224) => any;
15
15
  } & {
16
- 'general-extra'?: (props: typeof __VLS_221) => any;
16
+ 'general-extra'?: (props: typeof __VLS_226) => any;
17
17
  };
18
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
19
  "update:modelValue": (value: AnyRecord) => any;
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
2
  import { computed, defineComponent, inject, onBeforeUnmount, provide, ref, watch } from "vue";
3
- import { provideCELContext, provideScopeAncestor, provideSelectionRoster } from "../../utils/cel-context";
3
+ import { provideCELContext, provideScopeAncestor, provideSelectionRoster, SELECTIONS_VAR } from "../../utils/cel-context";
4
4
  import { BREADCRUMB_EXTENSION_KEY } from "../config/breadcrumb-extension";
5
5
  import { TABLE_COLUMN_LAYOUT_KEY } from "./column-layout";
6
6
  import { Icon } from "@iconify/vue";
@@ -254,6 +254,7 @@ watch(
254
254
  );
255
255
  const selectedGeneral = computed(() => selected.value.kind === "general");
256
256
  const selectedActions = computed(() => selected.value.kind === "actions");
257
+ const selectedBottomActions = computed(() => selected.value.kind === "bottomActions");
257
258
  const selectedQuery = computed(() => selected.value.kind === "query");
258
259
  const columnFullPane = ref(false);
259
260
  provide(TABLE_COLUMN_LAYOUT_KEY, { fullPane: columnFullPane });
@@ -284,12 +285,18 @@ const tableScopeAncestor = computed(() => {
284
285
  members: [
285
286
  { key: "row", label: "\u5F53\u524D\u884C", type: "dyn", description: "\u8BE5\u8868\u683C\u5F53\u524D\u884C\u7684\u6574\u884C\u6570\u636E" },
286
287
  { key: "index", label: "\u884C\u5E8F\u53F7", type: "number", description: "\u8BE5\u8868\u683C\u5F53\u524D\u884C\u7684\u5E8F\u53F7\uFF0C\u4ECE `0` \u5F00\u59CB" }
287
- ]
288
+ ],
289
+ // Each row-provider rebinds the relative `selections` to its own per-row
290
+ // registry (see row-provider.vue), so a table row shadows an enclosing
291
+ // form's selection options even though the table exposes no `selections`
292
+ // member of its own — list it here so that form's options stay offerable to
293
+ // a cell expression inside this table.
294
+ shadows: ["row", "index", SELECTIONS_VAR]
288
295
  };
289
296
  });
290
297
  provideScopeAncestor(tableScopeAncestor);
291
298
  const isDrilled = computed(
292
- () => selectedActions.value || selectedQuery.value || columnFullPane.value
299
+ () => selectedActions.value || selectedBottomActions.value || selectedQuery.value || columnFullPane.value
293
300
  );
294
301
  function findGroup(id) {
295
302
  return editingGroups.value.find((g) => g.id === id) ?? null;
@@ -504,6 +511,7 @@ function resolveSelection() {
504
511
  const s = selected.value;
505
512
  if (s.kind === "general") return;
506
513
  if (s.kind === "actions") return;
514
+ if (s.kind === "bottomActions") return;
507
515
  if (s.kind === "query") return;
508
516
  if (s.kind === "group" && findGroup(s.id)) return;
509
517
  if (s.kind === "column" && findColumn(s.id)) return;
@@ -515,6 +523,9 @@ function selectGeneral() {
515
523
  function selectActions() {
516
524
  selected.value = { kind: "actions" };
517
525
  }
526
+ function selectBottomActions() {
527
+ selected.value = { kind: "bottomActions" };
528
+ }
518
529
  function selectQuery() {
519
530
  selected.value = { kind: "query" };
520
531
  }
@@ -533,6 +544,9 @@ if (breadcrumbExt) {
533
544
  if (s.kind === "actions") {
534
545
  crumb.label.value = generalFieldTitle("actions");
535
546
  crumb.back.value = selectGeneral;
547
+ } else if (s.kind === "bottomActions") {
548
+ crumb.label.value = generalFieldTitle("bottomActions");
549
+ crumb.back.value = selectGeneral;
536
550
  } else if (s.kind === "query") {
537
551
  crumb.label.value = generalFieldTitle("query");
538
552
  crumb.back.value = selectGeneral;
@@ -957,9 +971,9 @@ function setPaginationLocale(key, value) {
957
971
  function getError(fieldPath) {
958
972
  return fieldErrors.value[fieldPath];
959
973
  }
960
- const tableActionsValue = computed({
974
+ const makeTableActionsValue = (key) => computed({
961
975
  get: () => {
962
- const a = editingGeneralConfig.value.actions ?? {};
976
+ const a = editingGeneralConfig.value[key] ?? {};
963
977
  return {
964
978
  kind: "shwfed.component.action",
965
979
  size: a.size ?? "default",
@@ -974,18 +988,19 @@ const tableActionsValue = computed({
974
988
  const hasContent = groups && groups.length > 0 || items && items.length > 0 || typeof style === "string" && style.length > 0 || size !== void 0 && size !== "default";
975
989
  if (!hasContent) {
976
990
  const cur = readGeneral();
977
- const { actions: _drop, ...rest } = cur;
991
+ const { [key]: _drop, ...rest } = cur;
978
992
  const merged = normalizeForEmit(rest);
979
- const cleared = { ...config.value, ...merged };
980
- delete cleared.actions;
993
+ const { [key]: _stale, ...cleared } = { ...config.value, ...merged };
981
994
  config.value = cleared;
982
995
  return;
983
996
  }
984
997
  const actions = { size, gap, groups, items };
985
998
  if (style !== void 0) actions.style = style;
986
- writeGeneralPatch({ actions });
999
+ writeGeneralPatch({ [key]: actions });
987
1000
  }
988
1001
  });
1002
+ const tableActionsValue = makeTableActionsValue("actions");
1003
+ const tableBottomActionsValue = makeTableActionsValue("bottomActions");
989
1004
  const tableQueryValue = computed({
990
1005
  get: () => {
991
1006
  const q = editingGeneralConfig.value.query;
@@ -1030,6 +1045,20 @@ const tableQueryValue = computed({
1030
1045
  <span class="flex-1 truncate">通用配置</span>
1031
1046
  </div>
1032
1047
 
1048
+ <div
1049
+ class="row general-row pl-2"
1050
+ :class="[
1051
+ selectedQuery ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-600 hover:bg-zinc-50'
1052
+ ]"
1053
+ @click.stop="selectQuery()"
1054
+ >
1055
+ <Icon
1056
+ icon="fluent:form-new-20-regular"
1057
+ class="size-4 shrink-0"
1058
+ />
1059
+ <span class="flex-1 truncate">{{ generalFieldTitle("query") }}</span>
1060
+ </div>
1061
+
1033
1062
  <div
1034
1063
  class="row general-row pl-2"
1035
1064
  :class="[
@@ -1047,15 +1076,15 @@ const tableQueryValue = computed({
1047
1076
  <div
1048
1077
  class="row general-row pl-2"
1049
1078
  :class="[
1050
- selectedQuery ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-600 hover:bg-zinc-50'
1079
+ selectedBottomActions ? 'bg-[color-mix(in_srgb,var(--primary)_10%,white)] text-(--primary)' : 'text-zinc-600 hover:bg-zinc-50'
1051
1080
  ]"
1052
- @click.stop="selectQuery()"
1081
+ @click.stop="selectBottomActions()"
1053
1082
  >
1054
1083
  <Icon
1055
- icon="fluent:form-new-20-regular"
1084
+ icon="fluent:table-bottom-row-20-regular"
1056
1085
  class="size-4 shrink-0"
1057
1086
  />
1058
- <span class="flex-1 truncate">{{ generalFieldTitle("query") }}</span>
1087
+ <span class="flex-1 truncate">{{ generalFieldTitle("bottomActions") }}</span>
1059
1088
  </div>
1060
1089
  </div>
1061
1090
 
@@ -1477,22 +1506,26 @@ const tableQueryValue = computed({
1477
1506
  <Separator />
1478
1507
 
1479
1508
  <div class="flex items-center gap-2">
1480
- <h3 class="text-xs font-medium text-zinc-500">
1509
+ <FieldLabel class="text-xs text-zinc-500">
1510
+ <template
1511
+ v-if="generalFieldDescription('persistQuery')"
1512
+ #tooltip
1513
+ >
1514
+ <Markdown
1515
+ :source="generalFieldDescription('persistQuery')"
1516
+ block
1517
+ class="prose prose-sm prose-zinc"
1518
+ />
1519
+ </template>
1481
1520
  {{ generalFieldTitle("persistQuery") }}
1482
- </h3>
1521
+ </FieldLabel>
1483
1522
  <Switch
1484
1523
  size="sm"
1485
1524
  :model-value="editingGeneralConfig.persistQuery === true"
1486
- aria-label="搜索条件持久化"
1525
+ aria-label="保留搜索条件"
1487
1526
  @update:model-value="setPersistQueryEnabled"
1488
1527
  />
1489
1528
  </div>
1490
- <p
1491
- v-if="generalFieldDescription('persistQuery')"
1492
- class="text-xs text-zinc-400"
1493
- >
1494
- {{ generalFieldDescription("persistQuery") }}
1495
- </p>
1496
1529
 
1497
1530
  <Separator />
1498
1531
 
@@ -1558,6 +1591,13 @@ const tableQueryValue = computed({
1558
1591
  />
1559
1592
  </TableActionsCELContext>
1560
1593
 
1594
+ <TableActionsCELContext v-else-if="selectedBottomActions">
1595
+ <ActionsConfigEditor
1596
+ v-model="tableBottomActionsValue"
1597
+ :configure="configureTableActions"
1598
+ />
1599
+ </TableActionsCELContext>
1600
+
1561
1601
  <ShwfedFormConfig
1562
1602
  v-else-if="selectedQuery"
1563
1603
  v-model="tableQueryValue"
@@ -9,11 +9,11 @@ type __VLS_ModelProps = {
9
9
  modelValue: AnyRecord;
10
10
  };
11
11
  type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
12
- declare var __VLS_219: {}, __VLS_221: {};
12
+ declare var __VLS_224: {}, __VLS_226: {};
13
13
  type __VLS_Slots = {} & {
14
- 'general-grid-extra'?: (props: typeof __VLS_219) => any;
14
+ 'general-grid-extra'?: (props: typeof __VLS_224) => any;
15
15
  } & {
16
- 'general-extra'?: (props: typeof __VLS_221) => any;
16
+ 'general-extra'?: (props: typeof __VLS_226) => any;
17
17
  };
18
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
19
19
  "update:modelValue": (value: AnyRecord) => any;
@@ -26,6 +26,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
26
26
  total?: string;
27
27
  }>;
28
28
  actions?: import("./schema.js").TableActionsValue;
29
+ bottomActions?: import("./schema.js").TableActionsValue;
29
30
  query?: import("../form/schema.js").FormConfigValue;
30
31
  rowKey?: string;
31
32
  cellStyle?: string;
@@ -72,6 +73,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
72
73
  total?: string;
73
74
  }>;
74
75
  actions?: import("./schema.js").TableActionsValue;
76
+ bottomActions?: import("./schema.js").TableActionsValue;
75
77
  query?: import("../form/schema.js").FormConfigValue;
76
78
  rowKey?: string;
77
79
  cellStyle?: string;
@@ -166,8 +166,7 @@ const columns = computed(() => {
166
166
  if (current) out.push(makeGroupColumn(current.group, current.children));
167
167
  return out;
168
168
  });
169
- const tableActionsConfig = computed(() => {
170
- const a = config.value?.actions;
169
+ const toActionsConfig = (a) => {
171
170
  if (!a) return void 0;
172
171
  if ((a.groups?.length ?? 0) === 0 && (a.items?.length ?? 0) === 0) return void 0;
173
172
  return {
@@ -178,7 +177,9 @@ const tableActionsConfig = computed(() => {
178
177
  groups: a.groups.map((g) => ({ ...g, variant: g.variant ?? "default" })),
179
178
  items: a.items
180
179
  };
181
- });
180
+ };
181
+ const tableActionsConfig = computed(() => toActionsConfig(config.value?.actions));
182
+ const tableBottomActionsConfig = computed(() => toActionsConfig(config.value?.bottomActions));
182
183
  const isPaginationEnabled = computed(() => config.value?.pagination !== void 0);
183
184
  const isManualPagination = computed(() => isPaginationEnabled.value && config.value?.dataSource?.total !== void 0);
184
185
  const totalItems = computed(() => isManualPagination.value ? serverTotal.value ?? 0 : rowData.value.length);
@@ -1058,5 +1059,13 @@ export { TableConfig, createTableConfig, getColumnTechnicalKey } from "./schema"
1058
1059
  </div>
1059
1060
  </ClientOnly>
1060
1061
  </div>
1062
+ <nav
1063
+ v-if="tableBottomActionsConfig"
1064
+ class="flex items-center justify-between"
1065
+ >
1066
+ <ShwfedActions
1067
+ :config="tableBottomActionsConfig"
1068
+ />
1069
+ </nav>
1061
1070
  </div>
1062
1071
  </template>
@@ -26,6 +26,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
26
26
  total?: string;
27
27
  }>;
28
28
  actions?: import("./schema.js").TableActionsValue;
29
+ bottomActions?: import("./schema.js").TableActionsValue;
29
30
  query?: import("../form/schema.js").FormConfigValue;
30
31
  rowKey?: string;
31
32
  cellStyle?: string;
@@ -72,6 +73,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
72
73
  total?: string;
73
74
  }>;
74
75
  actions?: import("./schema.js").TableActionsValue;
76
+ bottomActions?: import("./schema.js").TableActionsValue;
75
77
  query?: import("../form/schema.js").FormConfigValue;
76
78
  rowKey?: string;
77
79
  cellStyle?: string;