@shwfed/config 3.0.12 → 3.0.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 (75) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/config.d.vue.ts +18 -18
  3. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/config.vue.d.ts +18 -18
  4. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/runtime.d.vue.ts +18 -18
  5. package/dist/runtime/components/config/blocks/2026-06-17/com.shwfed.block.tree.single/runtime.vue.d.ts +18 -18
  6. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/config.d.vue.ts +8 -8
  7. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/config.vue +264 -286
  8. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/config.vue.d.ts +8 -8
  9. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/runtime.d.vue.ts +8 -8
  10. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/runtime.vue +91 -291
  11. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/runtime.vue.d.ts +8 -8
  12. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/schema.d.ts +3 -28
  13. package/dist/runtime/components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital/schema.js +9 -33
  14. package/dist/runtime/components/config/index.d.vue.ts +2 -2
  15. package/dist/runtime/components/config/index.vue.d.ts +2 -2
  16. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.d.vue.ts +2 -2
  17. package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue.d.ts +2 -2
  18. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +26 -26
  19. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +26 -26
  20. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +26 -26
  21. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +26 -26
  22. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +26 -26
  23. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +26 -26
  24. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +26 -26
  25. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +26 -26
  26. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +26 -26
  27. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +26 -26
  28. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.d.vue.ts +26 -26
  29. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.multi/config.vue.d.ts +26 -26
  30. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.d.vue.ts +26 -26
  31. package/dist/runtime/components/form/fields/2026-05-28/com.shwfed.form.field.tree.single/config.vue.d.ts +26 -26
  32. package/dist/runtime/components/form/utils/validation.js +9 -7
  33. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +8 -8
  34. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +8 -8
  35. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +8 -8
  36. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +8 -8
  37. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +8 -8
  38. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +8 -8
  39. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +8 -8
  40. package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +8 -8
  41. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +8 -8
  42. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +8 -8
  43. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +8 -8
  44. package/dist/runtime/components/table/columns/2026-06-14/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +8 -8
  45. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/config.vue +57 -247
  46. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/prompt.md +2 -2
  47. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/runtime.vue +21 -124
  48. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/schema.d.ts +5 -27
  49. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/schema.js +10 -37
  50. package/dist/runtime/components/ui/invoice/InvoiceSheet.d.vue.ts +66 -0
  51. package/dist/runtime/components/ui/invoice/InvoiceSheet.vue +182 -0
  52. package/dist/runtime/components/ui/invoice/InvoiceSheet.vue.d.ts +66 -0
  53. package/dist/runtime/components/ui/invoice/index.d.ts +1 -0
  54. package/dist/runtime/components/ui/invoice/index.js +1 -0
  55. package/dist/runtime/components/ui/invoice-config/InvoiceConfigShell.d.vue.ts +36 -0
  56. package/dist/runtime/components/ui/invoice-config/InvoiceConfigShell.vue +41 -0
  57. package/dist/runtime/components/ui/invoice-config/InvoiceConfigShell.vue.d.ts +36 -0
  58. package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/expr-field.vue → ui/invoice-config/InvoiceExprField.vue} +4 -4
  59. package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/json-scope-provider.vue → ui/invoice-config/InvoiceJsonScope.vue} +3 -3
  60. package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/row-scope-provider.vue → ui/invoice-config/InvoiceRowScope.vue} +2 -2
  61. package/dist/runtime/components/ui/invoice-config/index.d.ts +4 -0
  62. package/dist/runtime/components/ui/invoice-config/index.js +4 -0
  63. package/dist/runtime/share/invoice-eval.d.ts +13 -0
  64. package/dist/runtime/share/invoice-eval.js +88 -0
  65. package/dist/runtime/share/invoice.d.ts +68 -0
  66. package/dist/runtime/share/invoice.js +35 -0
  67. package/package.json +1 -1
  68. /package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/expr-field.d.vue.ts → ui/invoice-config/InvoiceExprField.d.vue.ts} +0 -0
  69. /package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/expr-field.vue.d.ts → ui/invoice-config/InvoiceExprField.vue.d.ts} +0 -0
  70. /package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/json-scope-provider.d.vue.ts → ui/invoice-config/InvoiceJsonScope.d.vue.ts} +0 -0
  71. /package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/json-scope-provider.vue.d.ts → ui/invoice-config/InvoiceJsonScope.vue.d.ts} +0 -0
  72. /package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/row-scope-provider.d.vue.ts → ui/invoice-config/InvoiceRowScope.d.vue.ts} +0 -0
  73. /package/dist/runtime/components/{config/blocks/2026-07-17/com.shwfed.block.invoice.digital/row-scope-provider.vue.d.ts → ui/invoice-config/InvoiceRowScope.vue.d.ts} +0 -0
  74. /package/dist/runtime/{components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital → share}/rmb.d.ts +0 -0
  75. /package/dist/runtime/{components/config/blocks/2026-07-17/com.shwfed.block.invoice.digital → share}/rmb.js +0 -0
@@ -36,15 +36,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
36
36
  }[]] | undefined;
37
37
  readonly keywords?: string | undefined;
38
38
  readonly readonly?: string | undefined;
39
+ readonly dataSource: {
40
+ readonly data: string;
41
+ readonly request?: string | undefined;
42
+ };
39
43
  readonly binding: string;
40
44
  readonly derived?: {
41
45
  readonly mode: "formula" | "prefill";
42
46
  readonly expression: string;
43
47
  } | undefined;
44
- readonly dataSource: {
45
- readonly data: string;
46
- readonly request?: string | undefined;
47
- };
48
48
  readonly nodeKey: string;
49
49
  readonly nodeChildren: string;
50
50
  readonly nodeLabel: string;
@@ -95,15 +95,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
95
95
  }[]] | undefined;
96
96
  readonly keywords?: string | undefined;
97
97
  readonly readonly?: string | undefined;
98
+ readonly dataSource: {
99
+ readonly data: string;
100
+ readonly request?: string | undefined;
101
+ };
98
102
  readonly binding: string;
99
103
  readonly derived?: {
100
104
  readonly mode: "formula" | "prefill";
101
105
  readonly expression: string;
102
106
  } | undefined;
103
- readonly dataSource: {
104
- readonly data: string;
105
- readonly request?: string | undefined;
106
- };
107
107
  readonly nodeKey: string;
108
108
  readonly nodeChildren: string;
109
109
  readonly nodeLabel: string;
@@ -36,15 +36,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
36
36
  }[]] | undefined;
37
37
  readonly keywords?: string | undefined;
38
38
  readonly readonly?: string | undefined;
39
+ readonly dataSource: {
40
+ readonly data: string;
41
+ readonly request?: string | undefined;
42
+ };
39
43
  readonly binding: string;
40
44
  readonly derived?: {
41
45
  readonly mode: "formula" | "prefill";
42
46
  readonly expression: string;
43
47
  } | undefined;
44
- readonly dataSource: {
45
- readonly data: string;
46
- readonly request?: string | undefined;
47
- };
48
48
  readonly nodeKey: string;
49
49
  readonly nodeChildren: string;
50
50
  readonly nodeLabel: string;
@@ -95,15 +95,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
95
95
  }[]] | undefined;
96
96
  readonly keywords?: string | undefined;
97
97
  readonly readonly?: string | undefined;
98
+ readonly dataSource: {
99
+ readonly data: string;
100
+ readonly request?: string | undefined;
101
+ };
98
102
  readonly binding: string;
99
103
  readonly derived?: {
100
104
  readonly mode: "formula" | "prefill";
101
105
  readonly expression: string;
102
106
  } | undefined;
103
- readonly dataSource: {
104
- readonly data: string;
105
- readonly request?: string | undefined;
106
- };
107
107
  readonly nodeKey: string;
108
108
  readonly nodeChildren: string;
109
109
  readonly nodeLabel: string;
@@ -36,15 +36,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
36
36
  }[]] | undefined;
37
37
  readonly keywords?: string | undefined;
38
38
  readonly readonly?: string | undefined;
39
+ readonly dataSource: {
40
+ readonly data: string;
41
+ readonly request?: string | undefined;
42
+ };
39
43
  readonly binding: string;
40
44
  readonly derived?: {
41
45
  readonly mode: "formula" | "prefill";
42
46
  readonly expression: string;
43
47
  } | undefined;
44
- readonly dataSource: {
45
- readonly data: string;
46
- readonly request?: string | undefined;
47
- };
48
48
  readonly nodeKey: string;
49
49
  readonly nodeChildren: string;
50
50
  readonly nodeLabel: string;
@@ -94,15 +94,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
94
94
  }[]] | undefined;
95
95
  readonly keywords?: string | undefined;
96
96
  readonly readonly?: string | undefined;
97
+ readonly dataSource: {
98
+ readonly data: string;
99
+ readonly request?: string | undefined;
100
+ };
97
101
  readonly binding: string;
98
102
  readonly derived?: {
99
103
  readonly mode: "formula" | "prefill";
100
104
  readonly expression: string;
101
105
  } | undefined;
102
- readonly dataSource: {
103
- readonly data: string;
104
- readonly request?: string | undefined;
105
- };
106
106
  readonly nodeKey: string;
107
107
  readonly nodeChildren: string;
108
108
  readonly nodeLabel: string;
@@ -36,15 +36,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
36
36
  }[]] | undefined;
37
37
  readonly keywords?: string | undefined;
38
38
  readonly readonly?: string | undefined;
39
+ readonly dataSource: {
40
+ readonly data: string;
41
+ readonly request?: string | undefined;
42
+ };
39
43
  readonly binding: string;
40
44
  readonly derived?: {
41
45
  readonly mode: "formula" | "prefill";
42
46
  readonly expression: string;
43
47
  } | undefined;
44
- readonly dataSource: {
45
- readonly data: string;
46
- readonly request?: string | undefined;
47
- };
48
48
  readonly nodeKey: string;
49
49
  readonly nodeChildren: string;
50
50
  readonly nodeLabel: string;
@@ -94,15 +94,15 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
94
94
  }[]] | undefined;
95
95
  readonly keywords?: string | undefined;
96
96
  readonly readonly?: string | undefined;
97
+ readonly dataSource: {
98
+ readonly data: string;
99
+ readonly request?: string | undefined;
100
+ };
97
101
  readonly binding: string;
98
102
  readonly derived?: {
99
103
  readonly mode: "formula" | "prefill";
100
104
  readonly expression: string;
101
105
  } | undefined;
102
- readonly dataSource: {
103
- readonly data: string;
104
- readonly request?: string | undefined;
105
- };
106
106
  readonly nodeKey: string;
107
107
  readonly nodeChildren: string;
108
108
  readonly nodeLabel: string;
@@ -1,15 +1,11 @@
1
1
  <script setup>
2
- import { computed, defineComponent, ref, watch } from "vue";
2
+ import { computed, defineComponent, ref } from "vue";
3
3
  import { Icon } from "@iconify/vue";
4
- import {
5
- useTreeDnd
6
- } from "../../../../../composables/useTreeDnd";
7
4
  import { provideCELContext } from "../../../../../utils/cel-context";
8
5
  import TriggersField from "../../../../actions/components/triggers-field.vue";
9
6
  import { ExpressionEditor } from "../../../../ui/expression-editor";
10
7
  import { Separator } from "../../../../ui/separator";
11
8
  import { Switch } from "../../../../ui/switch";
12
- import { Button } from "../../../../ui/button";
13
9
  import { Field, FieldLabel } from "../../../../ui/field";
14
10
  import { IconPicker } from "../../../../ui/icon-picker";
15
11
  import { Locale } from "../../../../ui/locale";
@@ -35,7 +31,7 @@ import {
35
31
  SelectValue
36
32
  } from "../../../../ui/select";
37
33
  import { getStructFieldDescription, getStructFieldTitle } from "../../../utils/schema-meta";
38
- import { FILE_VAR, FILES_VAR, JSON_VAR, UPLOAD_JSON_VAR, schema } from "./schema";
34
+ import { FILE_VAR, FILES_VAR, UPLOAD_JSON_VAR, schema } from "./schema";
39
35
  defineOptions({ name: "ShwfedTableUploadRendererConfig" });
40
36
  const value = defineModel({ type: Object, ...{ required: true } });
41
37
  const fieldSchema = schema(() => {
@@ -49,7 +45,6 @@ const ROW_VARS = {
49
45
  const UPLOAD_REQUEST_VARS = { ...ROW_VARS, files: FILES_VAR };
50
46
  const UPLOAD_HANDLE_VARS = { ...ROW_VARS, json: UPLOAD_JSON_VAR };
51
47
  const UPLOAD_FILENAME_VARS = { ...ROW_VARS, file: FILE_VAR };
52
- const TEMPLATE_DOWNLOAD_VARS = { ...ROW_VARS, json: JSON_VAR };
53
48
  const bindingText = computed({
54
49
  get: () => value.value.binding ?? "",
55
50
  set: (next) => {
@@ -131,110 +126,22 @@ const uploadFilenameText = computed({
131
126
  }
132
127
  }
133
128
  });
134
- const templates = computed(() => value.value.templates ?? []);
135
- function setTemplates(next) {
136
- if (next.length === 0) {
137
- const { templates: _omit, ...rest } = value.value;
129
+ function updateAddIcon(icon) {
130
+ const trimmed = icon.trim();
131
+ if (trimmed.length === 0) {
132
+ const { addIcon: _omit, ...rest } = value.value;
138
133
  value.value = rest;
139
134
  } else {
140
- value.value = { ...value.value, templates: next };
135
+ value.value = { ...value.value, addIcon: trimmed };
141
136
  }
142
137
  }
143
- function makeId() {
144
- if (typeof crypto !== "undefined" && "randomUUID" in crypto) return crypto.randomUUID();
145
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
146
- const r = Math.random() * 16 | 0;
147
- return (c === "x" ? r : r & 3 | 8).toString(16);
148
- });
149
- }
150
- const rowKeys = ref([]);
151
- watch(
152
- () => templates.value.length,
153
- (len) => {
154
- if (len === rowKeys.value.length) return;
155
- rowKeys.value = Array.from({ length: len }, () => makeId());
156
- },
157
- { immediate: true }
158
- );
159
- function addTemplate() {
160
- setTemplates([...templates.value, { request: "" }]);
161
- rowKeys.value = [...rowKeys.value, makeId()];
162
- }
163
- function removeTemplate(index) {
164
- setTemplates(templates.value.filter((_, i) => i !== index));
165
- rowKeys.value = rowKeys.value.filter((_, i) => i !== index);
166
- }
167
- function move(from, to) {
168
- if (from === to) return;
169
- if (from < 0 || to < 0 || from >= templates.value.length || to >= templates.value.length) return;
170
- const next = [...templates.value];
171
- const [entry] = next.splice(from, 1);
172
- if (!entry) return;
173
- next.splice(to, 0, entry);
174
- setTemplates(next);
175
- const keys = [...rowKeys.value];
176
- const [key] = keys.splice(from, 1);
177
- if (!key) return;
178
- keys.splice(to, 0, key);
179
- rowKeys.value = keys;
180
- }
181
- function patchTemplate(index, patch) {
182
- setTemplates(templates.value.map((entry, i) => i === index ? patch(entry) : entry));
183
- }
184
- const TEMPLATE_ROW_KIND = "shwfed-table-upload-template";
185
- const rowId = (i) => rowKeys.value[i] ?? `idx-${i}`;
186
- function onTemplateRowDrop(e) {
187
- if (e.source.kind !== TEMPLATE_ROW_KIND || e.target.kind !== TEMPLATE_ROW_KIND) return;
188
- const from = rowKeys.value.findIndex((k) => k === e.source.id);
189
- const to = rowKeys.value.findIndex((k) => k === e.target.id);
190
- if (from < 0 || to < 0) return;
191
- if (e.instruction === "reorder-above") move(from, from < to ? to - 1 : to);
192
- else if (e.instruction === "reorder-below") move(from, from <= to ? to : to + 1);
193
- }
194
- const templateDnd = useTreeDnd({ onRowDrop: onTemplateRowDrop });
195
- const pickDragHandle = (el) => el.querySelector(".drag-handle");
196
- function templateRowConfig(i) {
197
- return {
198
- kind: TEMPLATE_ROW_KIND,
199
- canDrop: (src) => src.kind === TEMPLATE_ROW_KIND,
200
- blockInstructions: (src) => {
201
- const block = ["make-child", "reparent"];
202
- if (src.id === rowId(i)) block.push("reorder-above", "reorder-below");
203
- return block;
204
- },
205
- dragHandle: pickDragHandle
206
- };
207
- }
208
- function updateTemplateRequest(index, request) {
209
- patchTemplate(index, (entry) => ({ ...entry, request }));
210
- }
211
- function updateTemplateDownload(index, download) {
212
- patchTemplate(index, (entry) => {
213
- if (download.length === 0) {
214
- const { download: _omit, ...rest } = entry;
215
- return rest;
216
- }
217
- return { ...entry, download };
218
- });
219
- }
220
- function updateTemplateIcon(index, icon) {
221
- patchTemplate(index, (entry) => {
222
- const trimmed = icon.trim();
223
- if (trimmed.length === 0) {
224
- const { icon: _omit, ...rest } = entry;
225
- return rest;
226
- }
227
- return { ...entry, icon: trimmed };
228
- });
229
- }
230
- function updateTemplateLabel(index, label) {
231
- patchTemplate(index, (entry) => {
232
- if (label == null || label.length === 0) {
233
- const { label: _omit, ...rest } = entry;
234
- return rest;
235
- }
236
- return { ...entry, label };
237
- });
138
+ function updateAddLabel(label) {
139
+ if (label == null || label.length === 0) {
140
+ const { addLabel: _omit, ...rest } = value.value;
141
+ value.value = rest;
142
+ } else {
143
+ value.value = { ...value.value, addLabel: label };
144
+ }
238
145
  }
239
146
  const MIME_GROUPS = [
240
147
  { id: "pdf", label: "PDF", mimes: ["application/pdf"] },
@@ -424,25 +331,6 @@ const DownloadScope = defineComponent({
424
331
  @update:model-value="(v) => value = { ...value, tooltip: v }"
425
332
  />
426
333
  </Field>
427
- <Field orientation="vertical">
428
- <FieldLabel class="text-xs text-zinc-500">
429
- <template
430
- v-if="fieldDescription('placeholder')"
431
- #tooltip
432
- >
433
- <Markdown
434
- :source="fieldDescription('placeholder')"
435
- block
436
- class="prose prose-sm prose-zinc"
437
- />
438
- </template>
439
- {{ fieldTitle("placeholder") }}
440
- </FieldLabel>
441
- <Locale
442
- :model-value="value.placeholder"
443
- @update:model-value="(v) => value = { ...value, placeholder: v }"
444
- />
445
- </Field>
446
334
  </div>
447
335
 
448
336
  <div class="grid grid-cols-3 gap-x-6 gap-y-4">
@@ -622,6 +510,49 @@ const DownloadScope = defineComponent({
622
510
  </Field>
623
511
  </div>
624
512
 
513
+ <!-- Add button appearance -->
514
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
515
+ <Field orientation="vertical">
516
+ <FieldLabel class="text-xs text-zinc-500">
517
+ <template
518
+ v-if="fieldDescription('addIcon')"
519
+ #tooltip
520
+ >
521
+ <Markdown
522
+ :source="fieldDescription('addIcon')"
523
+ block
524
+ class="prose prose-sm prose-zinc"
525
+ />
526
+ </template>
527
+ {{ fieldTitle("addIcon") }}
528
+ </FieldLabel>
529
+ <IconPicker
530
+ :model-value="value.addIcon ?? ''"
531
+ @update:model-value="updateAddIcon"
532
+ />
533
+ </Field>
534
+
535
+ <Field orientation="vertical">
536
+ <FieldLabel class="text-xs text-zinc-500">
537
+ <template
538
+ v-if="fieldDescription('addLabel')"
539
+ #tooltip
540
+ >
541
+ <Markdown
542
+ :source="fieldDescription('addLabel')"
543
+ block
544
+ class="prose prose-sm prose-zinc"
545
+ />
546
+ </template>
547
+ {{ fieldTitle("addLabel") }}
548
+ </FieldLabel>
549
+ <Locale
550
+ :model-value="value.addLabel"
551
+ @update:model-value="updateAddLabel"
552
+ />
553
+ </Field>
554
+ </div>
555
+
625
556
  <Separator />
626
557
 
627
558
  <!-- Immediate upload -->
@@ -772,127 +703,6 @@ const DownloadScope = defineComponent({
772
703
 
773
704
  <Separator />
774
705
 
775
- <!-- Download templates -->
776
- <Field orientation="vertical">
777
- <FieldLabel class="text-xs text-zinc-500">
778
- <template #tooltip>
779
- <Markdown
780
- :source="fieldDescription('templates') ?? '\u4E0B\u8F7D\u6A21\u677F\u5217\u8868\uFF1B\u6BCF\u4E00\u9879\u6E32\u67D3\u4E00\u4E2A\u4E0B\u8F7D\u6309\u94AE'"
781
- block
782
- class="prose prose-sm prose-zinc"
783
- />
784
- </template>
785
- {{ fieldTitle("templates") }}
786
- </FieldLabel>
787
-
788
- <div class="flex flex-col gap-2">
789
- <div
790
- v-for="(template, index) in templates"
791
- :key="rowKeys[index]"
792
- :ref="templateDnd.rowRef(rowId(index), templateRowConfig(index))"
793
- data-slot="upload-template"
794
- class="relative flex items-start gap-2 rounded border border-zinc-200 bg-zinc-50/40 p-2"
795
- :data-instruction="templateDnd.instructionFor(rowId(index)) ?? void 0"
796
- >
797
- <Icon
798
- icon="fluent:re-order-dots-vertical-20-regular"
799
- class="drag-handle mt-2.5 size-4 shrink-0 cursor-grab text-zinc-400"
800
- data-slot="upload-template-drag-handle"
801
- />
802
-
803
- <div class="flex min-w-0 flex-1 flex-col gap-2">
804
- <div class="grid grid-cols-2 gap-2">
805
- <Field orientation="vertical">
806
- <FieldLabel class="text-xs text-zinc-500">
807
- <template #tooltip>
808
- <Markdown
809
- source="返回 `HttpRequest` 的 CEL 表达式。未配置「下载请求」时直接发起并下载其响应"
810
- block
811
- class="prose prose-sm prose-zinc"
812
- />
813
- </template>
814
- 请求
815
- </FieldLabel>
816
- <ExpressionEditor
817
- :model-value="template.request"
818
- placeholder="例:http.get('https://api.example.com/template.xlsx')"
819
- result-type="HttpRequest"
820
- :extra-vars="ROW_VARS"
821
- class="min-h-10"
822
- @update:model-value="(v) => updateTemplateRequest(index, v)"
823
- />
824
- </Field>
825
-
826
- <Field orientation="vertical">
827
- <FieldLabel class="text-xs text-zinc-500">
828
- <template #tooltip>
829
- <Markdown
830
- source="可选的第二步:用第一步响应 `json` 中的凭据构造真正的下载请求,例如 `json.data.key`"
831
- block
832
- class="prose prose-sm prose-zinc"
833
- />
834
- </template>
835
- 下载请求
836
- </FieldLabel>
837
- <ExpressionEditor
838
- :model-value="template.download ?? ''"
839
- placeholder="例:http.get('https://api.example.com/download').query('key', json.data.key)"
840
- result-type="HttpRequest"
841
- :extra-vars="TEMPLATE_DOWNLOAD_VARS"
842
- class="min-h-10"
843
- @update:model-value="(v) => updateTemplateDownload(index, v)"
844
- />
845
- </Field>
846
- </div>
847
-
848
- <div class="grid grid-cols-2 gap-2">
849
- <Field orientation="vertical">
850
- <FieldLabel class="text-xs text-zinc-500">
851
- 模板按钮图标
852
- </FieldLabel>
853
- <IconPicker
854
- :model-value="template.icon ?? ''"
855
- @update:model-value="(v) => updateTemplateIcon(index, v)"
856
- />
857
- </Field>
858
-
859
- <Field orientation="vertical">
860
- <FieldLabel class="text-xs text-zinc-500">
861
- 模板按钮文本
862
- </FieldLabel>
863
- <Locale
864
- :model-value="template.label"
865
- @update:model-value="(v) => updateTemplateLabel(index, v)"
866
- />
867
- </Field>
868
- </div>
869
- </div>
870
-
871
- <Button
872
- variant="ghost"
873
- size="sm"
874
- class="absolute top-1 right-1 size-6 p-0 text-red-600 hover:text-red-700"
875
- aria-label="移除模板"
876
- @click="removeTemplate(index)"
877
- >
878
- <Icon icon="fluent:delete-20-regular" />
879
- </Button>
880
- </div>
881
-
882
- <Button
883
- type="button"
884
- data-slot="upload-template-add"
885
- class="w-full justify-center"
886
- @click="addTemplate"
887
- >
888
- <Icon icon="fluent:add-20-regular" />
889
- <span>增加</span>
890
- </Button>
891
- </div>
892
- </Field>
893
-
894
- <Separator />
895
-
896
706
  <div class="grid grid-cols-2 gap-x-6 gap-y-4">
897
707
  <Field orientation="vertical">
898
708
  <FieldLabel class="text-xs text-zinc-500">
@@ -9,11 +9,11 @@
9
9
 
10
10
  三个表达式各有各的变量:`request` 见 `files`(本次选择)、`handle` 见 `json`(上传响应)、`filename` 见 `file`(单个存量项)——都在行作用域(`row`/`index`)之上,不要混用。
11
11
 
12
- `templates` 在上传区旁渲染「下载模板」按钮:只配 `request` 则直接下载其响应;再配 `download` 则是两步式——第二步经 `json` 引用第一步响应(如用 `json.data.key` 拼真正的下载地址)。
13
-
14
12
  `download`(文件下载)给每个**文件项**渲染一个下载按钮,点击时执行一条「触发操作」列表(复用 actions 的操作子系统),列表里的表达式可用 `file` 引用被点击的那一项。分两种情况:
15
13
 
16
14
  - **已上传/回填的对象项**:走操作列表,如放一个 `http.download` 操作、请求写 `http.get('/api/file').query('key', file.cacheKey)`;或两步式——先一个 `发送请求` 行取凭据、再一个 `下载文件` 行经 `steps[?"<步骤标识>"]` 引用其响应。凡下载要用到的字段,都必须已由 `upload.handle` 落进文件项。
17
15
  - **尚未上传的本地文件**(延迟模式刚选中的原始 `File`):内存里没有服务端标识,故绕过列表、直接从 blob 下载。
18
16
 
19
17
  下载按钮在只读表格/表单里仍显示(查看已提交记录并下载附件是主要场景)。约束类字段(`accept` / `maxFileSize` / `maxTotalSize` / `maxFiles` / `multiple`)按需设置即可。`disabled` / `readonly` 是行作用域 CEL(返回 `bool`)。
18
+
19
+ 单元格只有一个「添加文件」按钮(无拖放区,单元格高度只有一行):`addLabel` / `addIcon` 可改其文案与图标。数量达上限即隐藏该按钮——不开 `multiple` 时上限就是 1,要换文件得先删除已有的那个。