@shwfed/config 3.0.10 → 3.0.11

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 (40) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.d.vue.ts +16 -16
  3. package/dist/runtime/components/form/fields/2026-04-24/com.shwfed.form.field.combobox.single/config.vue.d.ts +16 -16
  4. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +6 -6
  5. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +6 -6
  6. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +8 -8
  7. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +8 -8
  8. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  9. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  10. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.d.vue.ts +16 -16
  11. package/dist/runtime/components/form/fields/2026-05-13/com.shwfed.form.field.combobox.single.remote/config.vue.d.ts +16 -16
  12. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.d.vue.ts +6 -6
  13. package/dist/runtime/components/form/fields/2026-05-24/com.shwfed.form.field.monthrange/config.vue.d.ts +6 -6
  14. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.d.vue.ts +16 -16
  15. package/dist/runtime/components/form/fields/2026-05-25/com.shwfed.form.field.combobox.multi/config.vue.d.ts +16 -16
  16. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/config.d.vue.ts +34 -0
  17. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/config.vue +109 -1
  18. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/config.vue.d.ts +34 -0
  19. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/prompt.md +7 -0
  20. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/runtime.vue +66 -22
  21. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/schema.d.ts +23 -0
  22. package/dist/runtime/components/form/fields/2026-06-09/com.shwfed.form.field.upload/schema.js +26 -0
  23. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/config.d.vue.ts +10 -0
  24. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/config.vue +1004 -0
  25. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/config.vue.d.ts +10 -0
  26. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/prompt.md +19 -0
  27. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/runtime.d.vue.ts +9 -0
  28. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/runtime.vue +503 -0
  29. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/runtime.vue.d.ts +9 -0
  30. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/schema.d.ts +138 -0
  31. package/dist/runtime/components/table/columns/2026-07-16/com.shwfed.table.column.upload/schema.js +181 -0
  32. package/dist/runtime/components/ui/date-picker/DatePickerInput.d.vue.ts +1 -1
  33. package/dist/runtime/components/ui/date-picker/DatePickerInput.vue.d.ts +1 -1
  34. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.d.vue.ts +1 -1
  35. package/dist/runtime/components/ui/date-picker/DatePickerTimeInput.vue.d.ts +1 -1
  36. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.d.vue.ts +1 -1
  37. package/dist/runtime/components/ui/date-range-picker/DateRangePickerInput.vue.d.ts +1 -1
  38. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.d.vue.ts +2 -2
  39. package/dist/runtime/components/ui/date-range-picker/DateRangePickerTimeInput.vue.d.ts +2 -2
  40. package/package.json +1 -1
@@ -40,6 +40,14 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
40
40
  readonly mode: "formula" | "prefill";
41
41
  readonly expression: string;
42
42
  } | undefined;
43
+ readonly optionValue: string;
44
+ readonly optionLabel: readonly [{
45
+ readonly locale: "zh";
46
+ readonly message: string;
47
+ }, ...{
48
+ readonly locale: "en" | "ja" | "ko";
49
+ readonly message: string;
50
+ }[]];
43
51
  readonly validations?: readonly {
44
52
  readonly message: readonly [{
45
53
  readonly locale: "zh";
@@ -51,14 +59,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
51
59
  readonly warning?: boolean | undefined;
52
60
  readonly when: string;
53
61
  }[] | undefined;
54
- readonly optionValue: string;
55
- readonly optionLabel: readonly [{
56
- readonly locale: "zh";
57
- readonly message: string;
58
- }, ...{
59
- readonly locale: "en" | "ja" | "ko";
60
- readonly message: string;
61
- }[]];
62
62
  }) => any;
63
63
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
64
64
  "onUpdate:modelValue"?: ((value: {
@@ -98,6 +98,14 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
98
98
  readonly mode: "formula" | "prefill";
99
99
  readonly expression: string;
100
100
  } | undefined;
101
+ readonly optionValue: string;
102
+ readonly optionLabel: readonly [{
103
+ readonly locale: "zh";
104
+ readonly message: string;
105
+ }, ...{
106
+ readonly locale: "en" | "ja" | "ko";
107
+ readonly message: string;
108
+ }[]];
101
109
  readonly validations?: readonly {
102
110
  readonly message: readonly [{
103
111
  readonly locale: "zh";
@@ -109,14 +117,6 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
109
117
  readonly warning?: boolean | undefined;
110
118
  readonly when: string;
111
119
  }[] | undefined;
112
- readonly optionValue: string;
113
- readonly optionLabel: readonly [{
114
- readonly locale: "zh";
115
- readonly message: string;
116
- }, ...{
117
- readonly locale: "en" | "ja" | "ko";
118
- readonly message: string;
119
- }[]];
120
120
  }) => any) | undefined;
121
121
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
122
122
  declare const _default: typeof __VLS_export;
@@ -32,6 +32,23 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
32
32
  }[]] | undefined;
33
33
  readonly required?: string | undefined;
34
34
  readonly displayName?: string | undefined;
35
+ readonly download?: {
36
+ readonly label?: readonly [{
37
+ readonly locale: "zh";
38
+ readonly message: string;
39
+ }, ...{
40
+ readonly locale: "en" | "ja" | "ko";
41
+ readonly message: string;
42
+ }[]] | undefined;
43
+ readonly icon?: string | undefined;
44
+ readonly operations: readonly {
45
+ readonly id?: string | undefined;
46
+ readonly params?: unknown;
47
+ readonly compatibilityDate?: string | undefined;
48
+ readonly target: string;
49
+ readonly operation: string;
50
+ }[];
51
+ } | undefined;
35
52
  readonly compatibilityDate: "2026-06-09";
36
53
  readonly orientation?: "vertical" | "floating" | undefined;
37
54
  readonly placeholder?: readonly [{
@@ -106,6 +123,23 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
106
123
  }[]] | undefined;
107
124
  readonly required?: string | undefined;
108
125
  readonly displayName?: string | undefined;
126
+ readonly download?: {
127
+ readonly label?: readonly [{
128
+ readonly locale: "zh";
129
+ readonly message: string;
130
+ }, ...{
131
+ readonly locale: "en" | "ja" | "ko";
132
+ readonly message: string;
133
+ }[]] | undefined;
134
+ readonly icon?: string | undefined;
135
+ readonly operations: readonly {
136
+ readonly id?: string | undefined;
137
+ readonly params?: unknown;
138
+ readonly compatibilityDate?: string | undefined;
139
+ readonly target: string;
140
+ readonly operation: string;
141
+ }[];
142
+ } | undefined;
109
143
  readonly compatibilityDate: "2026-06-09";
110
144
  readonly orientation?: "vertical" | "floating" | undefined;
111
145
  readonly placeholder?: readonly [{
@@ -1,9 +1,11 @@
1
1
  <script setup>
2
2
  import { Icon } from "@iconify/vue";
3
- import { computed, ref, watch } from "vue";
3
+ import { computed, defineComponent, ref, watch } from "vue";
4
4
  import {
5
5
  useTreeDnd
6
6
  } from "../../../../../composables/useTreeDnd";
7
+ import TriggersField from "../../../../actions/components/triggers-field.vue";
8
+ import { provideCELContext } from "../../../../../utils/cel-context";
7
9
  import {
8
10
  DropdownMenu,
9
11
  DropdownMenuContent,
@@ -273,6 +275,52 @@ function setMultiple(v) {
273
275
  value.value = { ...value.value, multiple: true };
274
276
  }
275
277
  }
278
+ const downloadEnabled = computed(() => value.value.download != null);
279
+ function setDownloadEnabled(on) {
280
+ if (on) {
281
+ if (value.value.download) return;
282
+ value.value = { ...value.value, download: { operations: [] } };
283
+ } else {
284
+ const { download: _omit, ...rest } = value.value;
285
+ value.value = rest;
286
+ }
287
+ }
288
+ const downloadOperations = computed(() => value.value.download?.operations ?? []);
289
+ function updateDownloadOperations(next) {
290
+ const current = value.value.download;
291
+ if (!current) return;
292
+ value.value = { ...value.value, download: { ...current, operations: next } };
293
+ }
294
+ function updateDownloadIcon(icon) {
295
+ const current = value.value.download;
296
+ if (!current) return;
297
+ const trimmed = icon.trim();
298
+ if (trimmed.length === 0) {
299
+ const { icon: _omit, ...rest } = current;
300
+ value.value = { ...value.value, download: rest };
301
+ } else {
302
+ value.value = { ...value.value, download: { ...current, icon: trimmed } };
303
+ }
304
+ }
305
+ function updateDownloadLabel(label) {
306
+ const current = value.value.download;
307
+ if (!current) return;
308
+ if (label == null || label.length === 0) {
309
+ const { label: _omit, ...rest } = current;
310
+ value.value = { ...value.value, download: rest };
311
+ } else {
312
+ value.value = { ...value.value, download: { ...current, label } };
313
+ }
314
+ }
315
+ const DownloadScope = defineComponent({
316
+ name: "ShwfedUploadDownloadScope",
317
+ setup(_, { slots }) {
318
+ provideCELContext({
319
+ file: { type: FILE_VAR.type, label: FILE_VAR.label, description: FILE_VAR.description, value: () => void 0 }
320
+ });
321
+ return () => slots.default?.();
322
+ }
323
+ });
276
324
  </script>
277
325
 
278
326
  <template>
@@ -693,6 +741,66 @@ function setMultiple(v) {
693
741
  </Field>
694
742
  </div>
695
743
 
744
+ <!-- Per-file download -->
745
+ <div class="flex items-center gap-2">
746
+ <h3 class="text-xs font-medium text-zinc-500">
747
+ {{ fieldTitle("download") }}
748
+ </h3>
749
+ <Switch
750
+ size="sm"
751
+ :model-value="downloadEnabled"
752
+ aria-label="启用文件下载"
753
+ @update:model-value="setDownloadEnabled"
754
+ />
755
+ </div>
756
+
757
+ <div
758
+ v-if="downloadEnabled"
759
+ class="flex flex-col gap-3"
760
+ >
761
+ <div class="grid grid-cols-2 gap-3">
762
+ <Field orientation="vertical">
763
+ <FieldLabel class="text-xs text-zinc-500">
764
+ 下载按钮图标
765
+ </FieldLabel>
766
+ <IconPicker
767
+ :model-value="value.download?.icon ?? ''"
768
+ @update:model-value="updateDownloadIcon"
769
+ />
770
+ </Field>
771
+
772
+ <Field orientation="vertical">
773
+ <FieldLabel class="text-xs text-zinc-500">
774
+ 下载按钮文本
775
+ </FieldLabel>
776
+ <LocaleField
777
+ translate-hint="file download button label"
778
+ :model-value="value.download?.label"
779
+ @update:model-value="updateDownloadLabel"
780
+ />
781
+ </Field>
782
+ </div>
783
+
784
+ <Field orientation="vertical">
785
+ <FieldLabel class="text-xs text-zinc-500">
786
+ <template #tooltip>
787
+ <Markdown
788
+ source="点击文件项的下载按钮时按顺序执行的操作;可用 `file` 引用该文件项。尚未上传的本地文件会直接从内存下载,不经过此列表"
789
+ block
790
+ class="prose prose-sm prose-zinc"
791
+ />
792
+ </template>
793
+ 触发操作
794
+ </FieldLabel>
795
+ <DownloadScope>
796
+ <TriggersField
797
+ :triggers="downloadOperations"
798
+ @update:triggers="updateDownloadOperations"
799
+ />
800
+ </DownloadScope>
801
+ </Field>
802
+ </div>
803
+
696
804
  <!-- Download templates -->
697
805
  <Field orientation="vertical">
698
806
  <FieldLabel class="text-xs text-zinc-500">
@@ -32,6 +32,23 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
32
32
  }[]] | undefined;
33
33
  readonly required?: string | undefined;
34
34
  readonly displayName?: string | undefined;
35
+ readonly download?: {
36
+ readonly label?: readonly [{
37
+ readonly locale: "zh";
38
+ readonly message: string;
39
+ }, ...{
40
+ readonly locale: "en" | "ja" | "ko";
41
+ readonly message: string;
42
+ }[]] | undefined;
43
+ readonly icon?: string | undefined;
44
+ readonly operations: readonly {
45
+ readonly id?: string | undefined;
46
+ readonly params?: unknown;
47
+ readonly compatibilityDate?: string | undefined;
48
+ readonly target: string;
49
+ readonly operation: string;
50
+ }[];
51
+ } | undefined;
35
52
  readonly compatibilityDate: "2026-06-09";
36
53
  readonly orientation?: "vertical" | "floating" | undefined;
37
54
  readonly placeholder?: readonly [{
@@ -106,6 +123,23 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
106
123
  }[]] | undefined;
107
124
  readonly required?: string | undefined;
108
125
  readonly displayName?: string | undefined;
126
+ readonly download?: {
127
+ readonly label?: readonly [{
128
+ readonly locale: "zh";
129
+ readonly message: string;
130
+ }, ...{
131
+ readonly locale: "en" | "ja" | "ko";
132
+ readonly message: string;
133
+ }[]] | undefined;
134
+ readonly icon?: string | undefined;
135
+ readonly operations: readonly {
136
+ readonly id?: string | undefined;
137
+ readonly params?: unknown;
138
+ readonly compatibilityDate?: string | undefined;
139
+ readonly target: string;
140
+ readonly operation: string;
141
+ }[];
142
+ } | undefined;
109
143
  readonly compatibilityDate: "2026-06-09";
110
144
  readonly orientation?: "vertical" | "floating" | undefined;
111
145
  readonly placeholder?: readonly [{
@@ -9,4 +9,11 @@
9
9
 
10
10
  `templates` 在上传区旁渲染「下载模板」按钮:只配 `request` 则直接下载其响应;再配 `download` 则是两步式——第二步经 `json` 引用第一步响应(如用 `json.data.key` 拼真正的下载地址)。
11
11
 
12
+ `download`(文件下载)给每个**文件项**渲染一个下载按钮,点击时执行一条「触发操作」列表(复用 actions 的操作子系统,与 state.write 同款),列表里的表达式可用 `file` 引用被点击的那一项。分两种情况:
13
+
14
+ - **已上传/回填的对象项**(即时上传结果,或编辑时服务端回填的记录):走操作列表,如放一个 `http.download` 操作、请求写 `http.get('/api/file').query('key', file.cacheKey)`;或两步式——先一个 `发送请求` 行取凭据、再一个 `下载文件` 行经 `steps[?"<步骤标识>"]` 引用其响应。凡下载要用到的字段,都必须已由 `upload.handle` 落进文件项(原始上传 `json` 在 `handle` 之后即失效,只有落进项里的字段才随保存/回填留存,从而让本会话上传的与编辑回填的文件项行为一致)。
15
+ - **尚未上传的本地文件**(延迟模式刚选中的原始 `File`):内存里没有服务端标识、也没有能表达“存这个本地 blob”的操作,故绕过列表、直接从 blob 下载。
16
+
17
+ 下载按钮在只读表单里仍显示(查看已提交记录并下载附件是主要场景)。`download.icon` / `download.label` 定制按钮图标与无障碍文本。
18
+
12
19
  约束类字段(`accept` / `maxFileSize` / `maxTotalSize` / `maxFiles` / `multiple`)按需设置即可。
@@ -6,7 +6,8 @@ import { computed, ref } from "vue";
6
6
  import { useI18n } from "vue-i18n";
7
7
  import { toast } from "vue-sonner";
8
8
  import { cel as _rawCel } from "../../../../../utils/cel";
9
- import { celBindings, injectCELContext } from "../../../../../utils/cel-context";
9
+ import { celBindings, celScope, injectCELContext } from "../../../../../utils/cel-context";
10
+ import { dispatchTriggers, useEventChannel } from "../../../../../share/event-bus";
10
11
  import { getLocalizedText } from "../../../../../share/locale";
11
12
  import { interpolateMarkdown } from "../../../../table/utils/runtime";
12
13
  import { Button } from "../../../../ui/button";
@@ -112,6 +113,7 @@ const { locale, t } = useI18n({
112
113
  });
113
114
  const { getAt, setAt } = useFormState();
114
115
  const formScope = useFormScope();
116
+ const eventChannel = useEventChannel();
115
117
  const inherited = injectCELContext();
116
118
  const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
117
119
  const labelText = computed(
@@ -304,6 +306,16 @@ function onDelete(index) {
304
306
  next.splice(index, 1);
305
307
  entries.value = next;
306
308
  }
309
+ function saveFile(file) {
310
+ const url = URL.createObjectURL(file);
311
+ const a = document.createElement("a");
312
+ a.href = url;
313
+ a.download = file.name;
314
+ document.body.appendChild(a);
315
+ a.click();
316
+ a.remove();
317
+ URL.revokeObjectURL(url);
318
+ }
307
319
  const templates = computed(() => props.config.templates ?? []);
308
320
  function templateIcon(template) {
309
321
  return template.icon ?? "fluent:arrow-download-20-regular";
@@ -328,18 +340,36 @@ async function onDownloadTemplate(template) {
328
340
  console.error(`[shwfed-form] template request for ${props.fieldId} did not produce a File`);
329
341
  return;
330
342
  }
331
- const url = URL.createObjectURL(file);
332
- const a = document.createElement("a");
333
- a.href = url;
334
- a.download = file.name;
335
- document.body.appendChild(a);
336
- a.click();
337
- a.remove();
338
- URL.revokeObjectURL(url);
343
+ saveFile(file);
339
344
  } catch (err) {
340
345
  console.error(`[shwfed-form] failed to download template for ${props.fieldId}:`, err);
341
346
  }
342
347
  }
348
+ const downloadEnabled = computed(() => props.config.download != null);
349
+ const downloadIcon = computed(() => props.config.download?.icon ?? "fluent:arrow-download-20-regular");
350
+ const downloadLabel = computed(
351
+ () => (props.config.download?.label ? getLocalizedText(props.config.download.label, locale.value) : void 0) ?? "\u4E0B\u8F7D"
352
+ );
353
+ function canDownload(entry) {
354
+ if (!downloadEnabled.value) return false;
355
+ if (entry instanceof File) return true;
356
+ return (props.config.download?.operations.length ?? 0) > 0;
357
+ }
358
+ async function onDownloadEntry(entry) {
359
+ if (!downloadEnabled.value) return;
360
+ if (entry instanceof File) {
361
+ saveFile(entry);
362
+ return;
363
+ }
364
+ const download = props.config.download;
365
+ if (!download || download.operations.length === 0) return;
366
+ const triggerCel = (expression, context) => _rawCel(expression, celScope(inherited, { form: formScope.state.value ?? {}, file: entry, ...context }));
367
+ try {
368
+ await Effect.runPromise(dispatchTriggers(eventChannel, download.operations, triggerCel));
369
+ } catch (err) {
370
+ if (import.meta.dev) console.warn(`[shwfed-form] download operations halted for ${props.fieldId}:`, err);
371
+ }
372
+ }
343
373
  </script>
344
374
 
345
375
  <template>
@@ -446,19 +476,33 @@ async function onDownloadTemplate(template) {
446
476
  />
447
477
  <span class="truncate text-zinc-700">{{ entryName(entry) }}</span>
448
478
  </span>
449
- <Button
450
- v-if="!isDisabled && !isReadonly"
451
- type="button"
452
- variant="ghost"
453
- size="sm"
454
- data-slot="upload-zone-delete"
455
- class="size-6 p-0 text-zinc-500 hover:bg-red-50 hover:text-red-600"
456
- :disabled="uploading"
457
- :aria-label="`\u5220\u9664\uFF1A${entryName(entry)}`"
458
- @click="onDelete(index)"
459
- >
460
- <Icon icon="fluent:delete-20-regular" />
461
- </Button>
479
+ <span class="flex shrink-0 items-center gap-0.5">
480
+ <Button
481
+ v-if="canDownload(entry)"
482
+ type="button"
483
+ variant="ghost"
484
+ size="sm"
485
+ data-slot="upload-zone-download"
486
+ class="size-6 p-0 text-zinc-500 hover:bg-zinc-100 hover:text-zinc-700"
487
+ :aria-label="`${downloadLabel}\uFF1A${entryName(entry)}`"
488
+ @click="onDownloadEntry(entry)"
489
+ >
490
+ <Icon :icon="downloadIcon" />
491
+ </Button>
492
+ <Button
493
+ v-if="!isDisabled && !isReadonly"
494
+ type="button"
495
+ variant="ghost"
496
+ size="sm"
497
+ data-slot="upload-zone-delete"
498
+ class="size-6 p-0 text-zinc-500 hover:bg-red-50 hover:text-red-600"
499
+ :disabled="uploading"
500
+ :aria-label="`\u5220\u9664\uFF1A${entryName(entry)}`"
501
+ @click="onDelete(index)"
502
+ >
503
+ <Icon icon="fluent:delete-20-regular" />
504
+ </Button>
505
+ </span>
462
506
  </li>
463
507
  </ul>
464
508
 
@@ -135,6 +135,29 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
135
135
  readonly message: string;
136
136
  }[]], never>>;
137
137
  }>>>;
138
+ download: Schema.optional<Schema.Struct<{
139
+ operations: Schema.Array$<Schema.Struct<{
140
+ id: Schema.optional<Schema.refine<string, typeof Schema.String>>;
141
+ target: Schema.refine<string, typeof Schema.String>;
142
+ operation: Schema.SchemaClass<string, string, never>;
143
+ compatibilityDate: Schema.optional<Schema.SchemaClass<string, string, never>>;
144
+ params: Schema.optional<Schema.SchemaClass<unknown, unknown, never>>;
145
+ }>>;
146
+ icon: Schema.optional<Schema.refine<string, typeof Schema.String>>;
147
+ label: Schema.optional<Schema.suspend<readonly [{
148
+ readonly locale: "zh";
149
+ readonly message: string;
150
+ }, ...{
151
+ readonly locale: "en" | "ja" | "ko";
152
+ readonly message: string;
153
+ }[]], string | readonly [{
154
+ readonly locale: "zh";
155
+ readonly message: string;
156
+ }, ...{
157
+ readonly locale: "en" | "ja" | "ko";
158
+ readonly message: string;
159
+ }[]], never>>;
160
+ }>>;
138
161
  id: Schema.refine<string, typeof Schema.String>;
139
162
  displayName: Schema.optional<Schema.SchemaClass<string, string, never>>;
140
163
  hidden: Schema.optional<Schema.Schema<string, string, never>>;
@@ -1,5 +1,6 @@
1
1
  import { Effect, Schema } from "effect";
2
2
  import { Expression, LocaleMarkdown } from "../../../../../share/expression.js";
3
+ import { Triggers } from "../../../../../share/event-bus.js";
3
4
  import { Locale } from "../../../../../share/locale.js";
4
5
  import { commonFieldFields, FieldOrientationSchema } from "../../../utils/common.js";
5
6
  export const type = "com.shwfed.form.field.upload";
@@ -144,6 +145,31 @@ export function schema(configure) {
144
145
  })).annotations({
145
146
  title: "\u4E0B\u8F7D\u6A21\u677F",
146
147
  description: "\u4E0B\u8F7D\u6A21\u677F\u5217\u8868\uFF1B\u6BCF\u4E00\u9879\u5728\u4E0A\u4F20\u533A\u57DF\u65C1\u6E32\u67D3\u4E00\u4E2A\u4E0B\u8F7D\u6309\u94AE"
148
+ })),
149
+ // Per-file download — a 触发操作 (trigger-operation) list run when the user
150
+ // clicks a file item's 下载 button, with the clicked stored item in scope as
151
+ // `file` (the same `FILE_VAR` as `upload.filename`). Object entries
152
+ // (immediate-upload results or server-backfilled records) download via these
153
+ // operations — e.g. an `http.download` op reading `file.cacheKey`, or a
154
+ // two-step `http.request` → `http.download` chain. A freshly-picked,
155
+ // not-yet-uploaded native `File` bypasses the list and downloads from its
156
+ // in-memory blob directly, since no operation can express "save this local
157
+ // blob". `params` on each row stay opaque here (validated by the target
158
+ // operation's own schema in the editor); `file` typing is advertised to the
159
+ // op editors at config time via `provideCELContext`, not by this schema.
160
+ download: Schema.optional(Schema.Struct({
161
+ operations: Triggers,
162
+ icon: Schema.optional(Schema.String.pipe(Schema.minLength(1)).annotations({
163
+ title: "\u4E0B\u8F7D\u6309\u94AE\u56FE\u6807",
164
+ description: "Iconify \u56FE\u6807\u6807\u8BC6\u7B26\uFF0C\u4F8B\u5982 `fluent:arrow-download-20-regular`\uFF1B\u7559\u7A7A\u65F6\u4F7F\u7528\u9ED8\u8BA4\u56FE\u6807"
165
+ })),
166
+ label: Schema.optional(Locale.annotations({
167
+ title: "\u4E0B\u8F7D\u6309\u94AE\u6587\u672C",
168
+ description: "\u6BCF\u4E2A\u6587\u4EF6\u9879\u4E0B\u8F7D\u6309\u94AE\u7684\u672C\u5730\u5316\u65E0\u969C\u788D\u6807\u7B7E\uFF1B\u7559\u7A7A\u65F6\u4F7F\u7528\u300C\u4E0B\u8F7D\u300D"
169
+ }))
170
+ }).annotations({
171
+ title: "\u6587\u4EF6\u4E0B\u8F7D",
172
+ description: "\u914D\u7F6E\u540E\u6BCF\u4E2A\u6587\u4EF6\u9879\u65C1\u6E32\u67D3\u4E0B\u8F7D\u6309\u94AE\uFF1A\u5DF2\u4E0A\u4F20/\u56DE\u586B\u7684\u5BF9\u8C61\u9879\u6309\u300C\u89E6\u53D1\u64CD\u4F5C\u300D\u5217\u8868\u4E0B\u8F7D\uFF08`file` \u4E3A\u8BE5\u6587\u4EF6\u9879\uFF09\uFF1B\u5C1A\u672A\u4E0A\u4F20\u7684\u672C\u5730\u6587\u4EF6\u76F4\u63A5\u4ECE\u5185\u5B58\u4E0B\u8F7D\uFF0C\u4E0D\u7ECF\u8FC7\u8BE5\u5217\u8868"
147
173
  }))
148
174
  }).annotations({
149
175
  title: "UploadField",
@@ -0,0 +1,10 @@
1
+ type __VLS_ModelProps = {
2
+ modelValue: Record<string, any>;
3
+ };
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
5
+ "update:modelValue": (value: Record<string, any>) => any;
6
+ }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
7
+ "onUpdate:modelValue"?: ((value: Record<string, any>) => any) | undefined;
8
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;