@shwfed/config 1.0.0 → 1.1.0

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 (48) hide show
  1. package/README.md +1 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +169 -23
  4. package/dist/runtime/components/config/footer.vue +0 -2
  5. package/dist/runtime/components/config/index.vue +13 -3
  6. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.d.vue.ts +2 -2
  7. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue +85 -10
  8. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/config.vue.d.ts +2 -2
  9. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/runtime.vue +18 -6
  10. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.d.ts +1 -1
  11. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.daterange/schema.js +11 -4
  12. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.d.vue.ts +2 -2
  13. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue +85 -10
  14. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/config.vue.d.ts +2 -2
  15. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/runtime.vue +18 -6
  16. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.d.ts +1 -1
  17. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.datetimerange/schema.js +11 -4
  18. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.d.vue.ts +2 -2
  19. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue +87 -11
  20. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/config.vue.d.ts +2 -2
  21. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/runtime.vue +18 -6
  22. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/schema.d.ts +1 -1
  23. package/dist/runtime/components/form/fields/2026-04-27/com.shwfed.form.field.timerange/schema.js +11 -4
  24. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/config.vue +3 -0
  25. package/dist/runtime/components/form/fields/2026-05-12/com.shwfed.form.field.upload/runtime.vue +8 -0
  26. package/dist/runtime/components/form/index.vue +2 -2
  27. package/dist/runtime/components/table/ai/columns-button.vue +91 -98
  28. package/dist/runtime/components/table/ai/data-source-button.vue +88 -95
  29. package/dist/runtime/components/table/index.vue +5 -7
  30. package/dist/runtime/plugins/ai/index.d.ts +1 -5
  31. package/dist/runtime/plugins/ai/index.js +185 -441
  32. package/dist/runtime/plugins/cel/index.js +7 -0
  33. package/dist/runtime/vendor/cel-js/PROMPT.md +8 -0
  34. package/package.json +4 -4
  35. package/dist/chunks/index.mjs +0 -212742
  36. package/dist/runtime/components/ai/byok-button.d.vue.ts +0 -3
  37. package/dist/runtime/components/ai/byok-button.vue +0 -48
  38. package/dist/runtime/components/ai/byok-button.vue.d.ts +0 -3
  39. package/dist/runtime/components/ai/byok-settings.d.vue.ts +0 -3
  40. package/dist/runtime/components/ai/byok-settings.vue +0 -282
  41. package/dist/runtime/components/ai/byok-settings.vue.d.ts +0 -3
  42. package/dist/runtime/plugins/ai/gate.d.ts +0 -1
  43. package/dist/runtime/plugins/ai/gate.js +0 -8
  44. package/dist/runtime/plugins/ai/settings-state.d.ts +0 -1
  45. package/dist/runtime/plugins/ai/settings-state.js +0 -2
  46. package/dist/runtime/plugins/ai/store.d.ts +0 -17
  47. package/dist/runtime/plugins/ai/store.js +0 -40
  48. package/dist/shared/config.DW2OtAXe.mjs +0 -86529
@@ -71,20 +71,32 @@ function asRange(raw) {
71
71
  if (a.length === 0 || b.length === 0) return void 0;
72
72
  return [a, b];
73
73
  }
74
+ function asString(raw) {
75
+ return typeof raw === "string" && raw.length > 0 ? raw : void 0;
76
+ }
74
77
  const uncontrolled = ref(void 0);
75
78
  const model = computed({
76
79
  get: () => {
77
- const path = props.config.binding;
78
- if (path == null) return uncontrolled.value;
79
- return asRange(getAt(path));
80
+ const binding = props.config.binding;
81
+ if (binding == null) return uncontrolled.value;
82
+ if (typeof binding === "string") return asRange(getAt(binding));
83
+ const a = asString(getAt(binding[0]));
84
+ const b = asString(getAt(binding[1]));
85
+ if (a == null || b == null) return void 0;
86
+ return [a, b];
80
87
  },
81
88
  set: (next) => {
82
- const path = props.config.binding;
83
- if (path == null) {
89
+ const binding = props.config.binding;
90
+ if (binding == null) {
84
91
  uncontrolled.value = next;
85
92
  return;
86
93
  }
87
- setAt(path, next);
94
+ if (typeof binding === "string") {
95
+ setAt(binding, next);
96
+ return;
97
+ }
98
+ setAt(binding[0], next?.[0]);
99
+ setAt(binding[1], next?.[1]);
88
100
  }
89
101
  });
90
102
  const readonlyText = computed(() => {
@@ -68,7 +68,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
68
68
  message: Schema.SchemaClass<string, string, never>;
69
69
  }>]>>;
70
70
  orientation: Schema.optional<Schema.Literal<["vertical", "floating"]>>;
71
- binding: Schema.optional<Schema.refine<string, typeof Schema.String>>;
71
+ binding: Schema.optional<Schema.Union<[Schema.filter<typeof Schema.String>, Schema.filter<Schema.Tuple2<Schema.filter<typeof Schema.String>, Schema.filter<typeof Schema.String>>>]>>;
72
72
  disabled: Schema.optional<Schema.Schema<string, string, never>>;
73
73
  readonly: Schema.optional<Schema.Schema<string, string, never>>;
74
74
  format: Schema.optional<Schema.refine<string, typeof Schema.String>>;
@@ -4,6 +4,16 @@ import { Locale } from "../../../../../share/locale.js";
4
4
  import { commonFieldFields, FieldOrientationSchema } from "../../../utils/common.js";
5
5
  export const type = "com.shwfed.form.field.datetimerange";
6
6
  export const compatibilityDate = "2026-04-27";
7
+ const BindingPath = Schema.String.pipe(Schema.minLength(1));
8
+ const SplitBinding = Schema.Tuple(BindingPath, BindingPath).pipe(
9
+ Schema.filter(([a, b]) => a !== b, {
10
+ message: () => "\u8D77\u59CB\u4E0E\u7ED3\u675F\u7ED1\u5B9A\u8DEF\u5F84\u4E0D\u80FD\u76F8\u540C"
11
+ })
12
+ );
13
+ const bindingSchema = Schema.Union(BindingPath, SplitBinding).annotations({
14
+ title: "\u7ED1\u5B9A\u8DEF\u5F84",
15
+ description: "\u5199\u5165\u8868\u5355\u72B6\u6001\u7684 `dot-prop` \u8DEF\u5F84\uFF1B\u586B\u5199\u5355\u4E2A\u8DEF\u5F84\u65F6\u5199\u5165 `[start, end]` \u5B57\u7B26\u4E32\u6570\u7EC4\uFF0C\u4F8B\u5982 `event.range`\uFF1B\u586B\u5199 `[\u8D77\u59CB\u8DEF\u5F84, \u7ED3\u675F\u8DEF\u5F84]` \u5143\u7EC4\u65F6\u5206\u522B\u5199\u5165\u4E24\u7AEF\uFF1B\u7559\u7A7A\u5219\u4E3A\u975E\u53D7\u63A7\u5B57\u6BB5"
16
+ });
7
17
  export const metadata = {
8
18
  name: "\u65E5\u671F\u65F6\u95F4\u8303\u56F4",
9
19
  icon: "fluent:calendar-clock-20-regular",
@@ -64,10 +74,7 @@ export function schema(configure) {
64
74
  description: "\u9F20\u6807\u60AC\u505C\u5728\u6807\u7B7E\u4E0A\u65F6\u5C55\u793A\u7684\u8BF4\u660E"
65
75
  })),
66
76
  orientation: Schema.optional(FieldOrientationSchema),
67
- binding: Schema.optional(Schema.String.pipe(Schema.minLength(1)).annotations({
68
- title: "\u7ED1\u5B9A\u8DEF\u5F84",
69
- description: "\u5199\u5165\u8868\u5355\u72B6\u6001\u7684 `dot-prop` \u8DEF\u5F84\uFF0C\u4F8B\u5982 `event.range`\uFF1B\u5199\u5165\u503C\u4E3A `[start, end]` \u5B57\u7B26\u4E32\u6570\u7EC4\uFF1B\u7559\u7A7A\u5219\u4E3A\u975E\u53D7\u63A7\u5B57\u6BB5"
70
- })),
77
+ binding: Schema.optional(bindingSchema),
71
78
  disabled: Schema.optional(CelBool.annotations({
72
79
  title: "\u7981\u7528\u6761\u4EF6",
73
80
  description: "\u8FD4\u56DE `true` \u65F6\u8F93\u5165\u6846\u4ECD\u7136\u6E32\u67D3\u4F46\u4E0D\u53EF\u7F16\u8F91"
@@ -30,7 +30,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
30
30
  readonly valueFormat?: string | undefined;
31
31
  readonly timeGranularity?: "second" | "minute" | "hour" | undefined;
32
32
  readonly rangeSeparatorIcon?: string | undefined;
33
- readonly binding?: string | undefined;
33
+ readonly binding?: string | readonly [string, string] | undefined;
34
34
  }) => any;
35
35
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
36
36
  "onUpdate:modelValue"?: ((value: {
@@ -60,7 +60,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
60
60
  readonly valueFormat?: string | undefined;
61
61
  readonly timeGranularity?: "second" | "minute" | "hour" | undefined;
62
62
  readonly rangeSeparatorIcon?: string | undefined;
63
- readonly binding?: string | undefined;
63
+ readonly binding?: string | readonly [string, string] | undefined;
64
64
  }) => any) | undefined;
65
65
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
66
66
  declare const _default: typeof __VLS_export;
@@ -1,10 +1,11 @@
1
1
  <script setup>
2
+ import { Icon } from "@iconify/vue";
2
3
  import { computed } from "vue";
3
4
  import { format as formatDate } from "date-fns";
4
5
  import { ExpressionEditor } from "../../../../ui/expression-editor";
5
6
  import { Field, FieldLabel } from "../../../../ui/field";
6
7
  import { IconPicker } from "../../../../ui/icon-picker";
7
- import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText } from "../../../../ui/input-group";
8
+ import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText } from "../../../../ui/input-group";
8
9
  import { Locale as LocaleField } from "../../../../ui/locale";
9
10
  import { Markdown } from "../../../../ui/markdown";
10
11
  import {
@@ -23,8 +24,11 @@ const fieldSchema = schema(() => {
23
24
  });
24
25
  const fieldTitle = (f) => getStructFieldTitle(fieldSchema, f) ?? f;
25
26
  const fieldDescription = (f) => getStructFieldDescription(fieldSchema, f);
26
- const pathText = computed({
27
- get: () => value.value.binding ?? "",
27
+ const bindingMode = computed(
28
+ () => Array.isArray(value.value.binding) ? "split" : "single"
29
+ );
30
+ const singlePathText = computed({
31
+ get: () => typeof value.value.binding === "string" ? value.value.binding : "",
28
32
  set: (next) => {
29
33
  const trimmed = next.trim();
30
34
  if (trimmed.length === 0) {
@@ -35,6 +39,28 @@ const pathText = computed({
35
39
  }
36
40
  }
37
41
  });
42
+ const splitStartText = computed(
43
+ () => Array.isArray(value.value.binding) ? value.value.binding[0] : ""
44
+ );
45
+ const splitEndText = computed(
46
+ () => Array.isArray(value.value.binding) ? value.value.binding[1] : ""
47
+ );
48
+ function setSplitStart(next) {
49
+ const cur = Array.isArray(value.value.binding) ? value.value.binding : ["", ""];
50
+ value.value = { ...value.value, binding: [next.trim(), cur[1]] };
51
+ }
52
+ function setSplitEnd(next) {
53
+ const cur = Array.isArray(value.value.binding) ? value.value.binding : ["", ""];
54
+ value.value = { ...value.value, binding: [cur[0], next.trim()] };
55
+ }
56
+ function toggleBindingMode() {
57
+ if (bindingMode.value === "single") {
58
+ value.value = { ...value.value, binding: ["", ""] };
59
+ } else {
60
+ const { binding: _omit, ...rest } = value.value;
61
+ value.value = rest;
62
+ }
63
+ }
38
64
  const valueFormatText = computed({
39
65
  get: () => value.value.valueFormat ?? "",
40
66
  set: (next) => {
@@ -122,20 +148,70 @@ const valueFormatExample = computed(() => {
122
148
  <FieldLabel class="text-xs text-zinc-500">
123
149
  <template #tooltip>
124
150
  <Markdown
125
- source="写入表单状态的嵌套键路径,使用 `.` 分隔;写入值为 `[start, end]` 字符串数组"
151
+ source="写入表单状态的嵌套键路径,使用 `.` 分隔。单路径模式写入 `[start, end]` 字符串数组;拆分模式分别写入起始与结束两端"
126
152
  block
127
153
  class="prose prose-sm prose-zinc"
128
154
  />
129
155
  </template>
130
156
  {{ fieldTitle("binding") }}
131
157
  </FieldLabel>
132
- <InputGroup>
133
- <InputGroupInput
134
- v-model="pathText"
135
- placeholder="例:meeting.timeRange"
136
- class="font-mono"
137
- />
138
- </InputGroup>
158
+ <template v-if="bindingMode === 'single'">
159
+ <InputGroup>
160
+ <InputGroupInput
161
+ v-model="singlePathText"
162
+ placeholder="例:meeting.timeRange"
163
+ class="font-mono"
164
+ />
165
+ <InputGroupAddon align="inline-end">
166
+ <InputGroupButton
167
+ size="icon-xs"
168
+ aria-label="拆分起止绑定路径"
169
+ @click="toggleBindingMode"
170
+ >
171
+ <Icon icon="fluent:split-horizontal-20-regular" />
172
+ </InputGroupButton>
173
+ </InputGroupAddon>
174
+ </InputGroup>
175
+ </template>
176
+ <template v-else>
177
+ <div class="grid grid-cols-2 gap-2">
178
+ <InputGroup>
179
+ <InputGroupAddon align="inline-start">
180
+ <InputGroupText class="text-xs text-zinc-400">
181
+
182
+ </InputGroupText>
183
+ </InputGroupAddon>
184
+ <InputGroupInput
185
+ :model-value="splitStartText"
186
+ placeholder="例:meeting.startTime"
187
+ class="font-mono"
188
+ @update:model-value="(v) => setSplitStart(String(v ?? ''))"
189
+ />
190
+ </InputGroup>
191
+ <InputGroup>
192
+ <InputGroupAddon align="inline-start">
193
+ <InputGroupText class="text-xs text-zinc-400">
194
+
195
+ </InputGroupText>
196
+ </InputGroupAddon>
197
+ <InputGroupInput
198
+ :model-value="splitEndText"
199
+ placeholder="例:meeting.endTime"
200
+ class="font-mono"
201
+ @update:model-value="(v) => setSplitEnd(String(v ?? ''))"
202
+ />
203
+ <InputGroupAddon align="inline-end">
204
+ <InputGroupButton
205
+ size="icon-xs"
206
+ aria-label="合并起止绑定路径"
207
+ @click="toggleBindingMode"
208
+ >
209
+ <Icon icon="fluent:merge-vertical-20-regular" />
210
+ </InputGroupButton>
211
+ </InputGroupAddon>
212
+ </InputGroup>
213
+ </div>
214
+ </template>
139
215
  </Field>
140
216
  </div>
141
217
 
@@ -30,7 +30,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
30
30
  readonly valueFormat?: string | undefined;
31
31
  readonly timeGranularity?: "second" | "minute" | "hour" | undefined;
32
32
  readonly rangeSeparatorIcon?: string | undefined;
33
- readonly binding?: string | undefined;
33
+ readonly binding?: string | readonly [string, string] | undefined;
34
34
  }) => any;
35
35
  }, string, import("vue").PublicProps, Readonly<__VLS_ModelProps> & Readonly<{
36
36
  "onUpdate:modelValue"?: ((value: {
@@ -60,7 +60,7 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_ModelProps, {},
60
60
  readonly valueFormat?: string | undefined;
61
61
  readonly timeGranularity?: "second" | "minute" | "hour" | undefined;
62
62
  readonly rangeSeparatorIcon?: string | undefined;
63
- readonly binding?: string | undefined;
63
+ readonly binding?: string | readonly [string, string] | undefined;
64
64
  }) => any) | undefined;
65
65
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
66
66
  declare const _default: typeof __VLS_export;
@@ -41,20 +41,32 @@ function asRange(raw) {
41
41
  if (a.length === 0 || b.length === 0) return void 0;
42
42
  return [a, b];
43
43
  }
44
+ function asString(raw) {
45
+ return typeof raw === "string" && raw.length > 0 ? raw : void 0;
46
+ }
44
47
  const uncontrolled = ref(void 0);
45
48
  const model = computed({
46
49
  get: () => {
47
- const path = props.config.binding;
48
- if (path == null) return uncontrolled.value;
49
- return asRange(getAt(path));
50
+ const binding = props.config.binding;
51
+ if (binding == null) return uncontrolled.value;
52
+ if (typeof binding === "string") return asRange(getAt(binding));
53
+ const a = asString(getAt(binding[0]));
54
+ const b = asString(getAt(binding[1]));
55
+ if (a == null || b == null) return void 0;
56
+ return [a, b];
50
57
  },
51
58
  set: (next) => {
52
- const path = props.config.binding;
53
- if (path == null) {
59
+ const binding = props.config.binding;
60
+ if (binding == null) {
54
61
  uncontrolled.value = next;
55
62
  return;
56
63
  }
57
- setAt(path, next);
64
+ if (typeof binding === "string") {
65
+ setAt(binding, next);
66
+ return;
67
+ }
68
+ setAt(binding[0], next?.[0]);
69
+ setAt(binding[1], next?.[1]);
58
70
  }
59
71
  });
60
72
  const readonlyText = computed(() => {
@@ -42,7 +42,7 @@ export declare function schema(configure: (env: Environment) => void): Schema.St
42
42
  message: Schema.SchemaClass<string, string, never>;
43
43
  }>]>>;
44
44
  orientation: Schema.optional<Schema.Literal<["vertical", "floating"]>>;
45
- binding: Schema.optional<Schema.refine<string, typeof Schema.String>>;
45
+ binding: Schema.optional<Schema.Union<[Schema.filter<typeof Schema.String>, Schema.filter<Schema.Tuple2<Schema.filter<typeof Schema.String>, Schema.filter<typeof Schema.String>>>]>>;
46
46
  disabled: Schema.optional<Schema.Schema<string, string, never>>;
47
47
  readonly: Schema.optional<Schema.Schema<string, string, never>>;
48
48
  valueFormat: Schema.optional<Schema.refine<string, typeof Schema.String>>;
@@ -4,6 +4,16 @@ import { Locale } from "../../../../../share/locale.js";
4
4
  import { commonFieldFields, FieldOrientationSchema } from "../../../utils/common.js";
5
5
  export const type = "com.shwfed.form.field.timerange";
6
6
  export const compatibilityDate = "2026-04-27";
7
+ const BindingPath = Schema.String.pipe(Schema.minLength(1));
8
+ const SplitBinding = Schema.Tuple(BindingPath, BindingPath).pipe(
9
+ Schema.filter(([a, b]) => a !== b, {
10
+ message: () => "\u8D77\u59CB\u4E0E\u7ED3\u675F\u7ED1\u5B9A\u8DEF\u5F84\u4E0D\u80FD\u76F8\u540C"
11
+ })
12
+ );
13
+ const bindingSchema = Schema.Union(BindingPath, SplitBinding).annotations({
14
+ title: "\u7ED1\u5B9A\u8DEF\u5F84",
15
+ description: "\u5199\u5165\u8868\u5355\u72B6\u6001\u7684 `dot-prop` \u8DEF\u5F84\uFF1B\u586B\u5199\u5355\u4E2A\u8DEF\u5F84\u65F6\u5199\u5165 `[start, end]` \u5B57\u7B26\u4E32\u6570\u7EC4\uFF0C\u4F8B\u5982 `meeting.timeRange`\uFF1B\u586B\u5199 `[\u8D77\u59CB\u8DEF\u5F84, \u7ED3\u675F\u8DEF\u5F84]` \u5143\u7EC4\u65F6\u5206\u522B\u5199\u5165\u4E24\u7AEF\uFF1B\u7559\u7A7A\u5219\u4E3A\u975E\u53D7\u63A7\u5B57\u6BB5"
16
+ });
7
17
  export const metadata = {
8
18
  name: "\u65F6\u95F4\u8303\u56F4",
9
19
  icon: "fluent:clock-arrow-download-20-regular",
@@ -35,10 +45,7 @@ export function schema(configure) {
35
45
  description: "\u9F20\u6807\u60AC\u505C\u5728\u6807\u7B7E\u4E0A\u65F6\u5C55\u793A\u7684\u8BF4\u660E"
36
46
  })),
37
47
  orientation: Schema.optional(FieldOrientationSchema),
38
- binding: Schema.optional(Schema.String.pipe(Schema.minLength(1)).annotations({
39
- title: "\u7ED1\u5B9A\u8DEF\u5F84",
40
- description: "\u5199\u5165\u8868\u5355\u72B6\u6001\u7684 `dot-prop` \u8DEF\u5F84\uFF0C\u4F8B\u5982 `meeting.timeRange`\uFF1B\u5199\u5165\u503C\u4E3A `[start, end]` \u5B57\u7B26\u4E32\u6570\u7EC4\uFF1B\u7559\u7A7A\u5219\u4E3A\u975E\u53D7\u63A7\u5B57\u6BB5"
41
- })),
48
+ binding: Schema.optional(bindingSchema),
42
49
  disabled: Schema.optional(CelBool.annotations({
43
50
  title: "\u7981\u7528\u6761\u4EF6",
44
51
  description: "\u8FD4\u56DE `true` \u65F6\u8F93\u5165\u6846\u4ECD\u7136\u6E32\u67D3\u4F46\u4E0D\u53EF\u7F16\u8F91"
@@ -77,7 +77,10 @@ const MIME_GROUPS = [
77
77
  { id: "doc", label: "DOC", mimes: ["application/msword"] },
78
78
  { id: "xlsx", label: "XLSX", mimes: ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] },
79
79
  { id: "xls", label: "XLS", mimes: ["application/vnd.ms-excel"] },
80
+ { id: "pptx", label: "PPTX", mimes: ["application/vnd.openxmlformats-officedocument.presentationml.presentation"] },
81
+ { id: "ppt", label: "PPT", mimes: ["application/vnd.ms-powerpoint"] },
80
82
  { id: "zip", label: "ZIP", mimes: ["application/zip", "application/x-zip-compressed"] },
83
+ { id: "rar", label: "RAR", mimes: ["application/vnd.rar", "application/x-rar-compressed"] },
81
84
  { id: "ofd", label: "OFD", mimes: ["application/ofd"] },
82
85
  { id: "xml", label: "XML", mimes: ["application/xml"] },
83
86
  { id: "png", label: "PNG", mimes: ["image/png"] },
@@ -15,8 +15,12 @@ import { useFormState } from "../../../utils/state";
15
15
  const ICONS = {
16
16
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "vscode-icons:file-type-excel",
17
17
  "application/vnd.ms-excel": "vscode-icons:file-type-excel",
18
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "vscode-icons:file-type-powerpoint",
19
+ "application/vnd.ms-powerpoint": "vscode-icons:file-type-powerpoint",
18
20
  "application/zip": "vscode-icons:file-type-zip",
19
21
  "application/x-zip-compressed": "vscode-icons:file-type-zip",
22
+ "application/vnd.rar": "vscode-icons:file-type-zip",
23
+ "application/x-rar-compressed": "vscode-icons:file-type-zip",
20
24
  "application/pdf": "vscode-icons:file-type-pdf2",
21
25
  "application/ofd": "vscode-icons:file-type-ofd",
22
26
  "application/xml": "vscode-icons:file-type-xml",
@@ -29,8 +33,12 @@ const ICONS = {
29
33
  const SHORT_NAMES = {
30
34
  "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "XLSX",
31
35
  "application/vnd.ms-excel": "XLS",
36
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation": "PPTX",
37
+ "application/vnd.ms-powerpoint": "PPT",
32
38
  "application/zip": "ZIP",
33
39
  "application/x-zip-compressed": "ZIP",
40
+ "application/vnd.rar": "RAR",
41
+ "application/x-rar-compressed": "RAR",
34
42
  "application/pdf": "PDF",
35
43
  "application/ofd": "OFD",
36
44
  "application/xml": "XML",
@@ -20,8 +20,6 @@ const configure = props.configure ?? (() => {
20
20
  });
21
21
  void configure;
22
22
  const { $cel: _rawCel } = useNuxtApp();
23
- const inherited = injectCELContext();
24
- const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
25
23
  provideCELContext({
26
24
  form: {
27
25
  type: "dyn",
@@ -40,6 +38,8 @@ provideCELContext({
40
38
  value: () => new TZDate()
41
39
  }
42
40
  });
41
+ const inherited = injectCELContext();
42
+ const $cel = (expression, context) => _rawCel(expression, { ...celBindings(inherited), ...context });
43
43
  provideFormState(state);
44
44
  const seeded = (() => {
45
45
  const current = state.value ?? {};
@@ -157,13 +157,8 @@ const description = [
157
157
  "",
158
158
  "AI \u4F1A**\u6574\u5217\u66FF\u6362**\u5F53\u524D\u7684\u5217\u914D\u7F6E \u2014 \u672A\u5728\u63CF\u8FF0\u4E2D\u63D0\u5230\u7684\u5217\u4F1A\u88AB\u79FB\u9664\uFF0C\u8BF7\u628A\u6240\u6709\u9700\u8981\u4FDD\u7559\u7684\u5217\u4E5F\u4E00\u5E76\u63CF\u8FF0\u51FA\u6765\u3002"
159
159
  ].join("\n");
160
- const visible = computed(() => $ai.available.value);
161
160
  const canSubmit = computed(() => !submitting.value && context.value.trim().length > 0);
162
161
  function onTrigger() {
163
- if (!$ai.available.value) {
164
- $ai.openSettings();
165
- return;
166
- }
167
162
  open.value = true;
168
163
  }
169
164
  const CEL_FIELDS_BY_TYPE = {
@@ -391,107 +386,105 @@ ${renderRegisterables()}`;
391
386
  </script>
392
387
 
393
388
  <template>
394
- <template v-if="visible">
395
- <Tooltip :delay-duration="180">
396
- <TooltipTrigger as-child>
397
- <InputGroupButton
398
- size="icon-xs"
399
- variant="ghost"
400
- as-child
389
+ <Tooltip :delay-duration="180">
390
+ <TooltipTrigger as-child>
391
+ <InputGroupButton
392
+ size="icon-xs"
393
+ variant="ghost"
394
+ as-child
395
+ >
396
+ <button
397
+ type="button"
398
+ :disabled="submitting"
399
+ class="-ml-4"
400
+ @click="onTrigger"
401
401
  >
402
- <button
403
- type="button"
404
- :disabled="submitting"
405
- class="-ml-4"
406
- @click="onTrigger"
407
- >
408
- <Icon
409
- icon="fluent:magic-wand-20-regular"
410
- class="size-4"
411
- />
412
- </button>
413
- </InputGroupButton>
414
- </TooltipTrigger>
415
- <TooltipContent side="top">
416
- AI 生成列
417
- </TooltipContent>
418
- </Tooltip>
419
-
420
- <ShwfedModal
421
- v-model:open="open"
422
- content-width="48rem"
423
- :dismissible="!submitting"
424
- >
425
- <template #title>
426
- <span class="flex items-center gap-2">
427
402
  <Icon
428
403
  icon="fluent:magic-wand-20-regular"
429
- class="size-5"
404
+ class="size-4"
430
405
  />
431
- AI 生成列
432
- </span>
433
- </template>
434
- <template #description>
435
- <Markdown
436
- :source="description"
437
- block
438
- class="prose prose-sm prose-zinc max-w-none"
439
- />
440
- </template>
406
+ </button>
407
+ </InputGroupButton>
408
+ </TooltipTrigger>
409
+ <TooltipContent side="top">
410
+ AI 生成列
411
+ </TooltipContent>
412
+ </Tooltip>
441
413
 
442
- <form
443
- class="flex flex-col gap-2 py-2"
444
- @submit.prevent="onSubmit"
445
- >
446
- <Textarea
447
- v-model="context"
448
- placeholder="任意上下文,建议包含:&#10;- 想要的列:例如「显示姓名、邮箱、注册时间」&#10;- 字段含义或示例响应(JSON)&#10;- 列宽 / 对齐 / 复制等额外要求"
449
- wrap="soft"
450
- class="field-sizing-fixed h-72 max-h-[60vh] resize-none overflow-auto break-all whitespace-pre-wrap font-mono text-xs"
451
- :disabled="submitting"
414
+ <ShwfedModal
415
+ v-model:open="open"
416
+ content-width="48rem"
417
+ :dismissible="!submitting"
418
+ >
419
+ <template #title>
420
+ <span class="flex items-center gap-2">
421
+ <Icon
422
+ icon="fluent:magic-wand-20-regular"
423
+ class="size-5"
452
424
  />
453
- </form>
425
+ AI 生成列
426
+ </span>
427
+ </template>
428
+ <template #description>
429
+ <Markdown
430
+ :source="description"
431
+ block
432
+ class="prose prose-sm prose-zinc max-w-none"
433
+ />
434
+ </template>
454
435
 
455
- <template #footer>
456
- <div class="flex items-center gap-2">
457
- <div
458
- v-if="submitting"
459
- class="mr-auto flex items-center gap-2 text-xs text-muted-foreground"
460
- aria-live="polite"
461
- >
462
- <span
463
- :key="tick"
464
- class="ai-progress-dot"
465
- :class="tick > 0 ? 'is-streaming' : 'is-waiting'"
466
- />
467
- <span>{{ tick > 0 ? "\u6B63\u5728\u63A5\u6536\u6A21\u578B\u8F93\u51FA\u2026" : "\u6B63\u5728\u8BF7\u6C42\u6A21\u578B\u2026" }}</span>
468
- </div>
469
- <Button
470
- type="button"
471
- size="sm"
472
- :disabled="submitting"
473
- @click="open = false"
474
- >
475
- <Icon icon="fluent:dismiss-20-regular" />
476
- 取消
477
- </Button>
478
- <Button
479
- type="button"
480
- variant="primary"
481
- size="sm"
482
- :disabled="!canSubmit"
483
- @click="onSubmit"
484
- >
485
- <Icon
486
- :icon="submitting ? 'fluent:arrow-sync-20-regular' : 'fluent:sparkle-20-regular'"
487
- :class="submitting ? 'animate-spin' : ''"
488
- />
489
- 生成
490
- </Button>
436
+ <form
437
+ class="flex flex-col gap-2 py-2"
438
+ @submit.prevent="onSubmit"
439
+ >
440
+ <Textarea
441
+ v-model="context"
442
+ placeholder="任意上下文,建议包含:&#10;- 想要的列:例如「显示姓名、邮箱、注册时间」&#10;- 字段含义或示例响应(JSON)&#10;- 列宽 / 对齐 / 复制等额外要求"
443
+ wrap="soft"
444
+ class="field-sizing-fixed h-72 max-h-[60vh] resize-none overflow-auto break-all whitespace-pre-wrap font-mono text-xs"
445
+ :disabled="submitting"
446
+ />
447
+ </form>
448
+
449
+ <template #footer>
450
+ <div class="flex items-center gap-2">
451
+ <div
452
+ v-if="submitting"
453
+ class="mr-auto flex items-center gap-2 text-xs text-muted-foreground"
454
+ aria-live="polite"
455
+ >
456
+ <span
457
+ :key="tick"
458
+ class="ai-progress-dot"
459
+ :class="tick > 0 ? 'is-streaming' : 'is-waiting'"
460
+ />
461
+ <span>{{ tick > 0 ? "\u6B63\u5728\u63A5\u6536\u6A21\u578B\u8F93\u51FA\u2026" : "\u6B63\u5728\u8BF7\u6C42\u6A21\u578B\u2026" }}</span>
491
462
  </div>
492
- </template>
493
- </ShwfedModal>
494
- </template>
463
+ <Button
464
+ type="button"
465
+ size="sm"
466
+ :disabled="submitting"
467
+ @click="open = false"
468
+ >
469
+ <Icon icon="fluent:dismiss-20-regular" />
470
+ 取消
471
+ </Button>
472
+ <Button
473
+ type="button"
474
+ variant="primary"
475
+ size="sm"
476
+ :disabled="!canSubmit"
477
+ @click="onSubmit"
478
+ >
479
+ <Icon
480
+ :icon="submitting ? 'fluent:arrow-sync-20-regular' : 'fluent:sparkle-20-regular'"
481
+ :class="submitting ? 'animate-spin' : ''"
482
+ />
483
+ 生成
484
+ </Button>
485
+ </div>
486
+ </template>
487
+ </ShwfedModal>
495
488
  </template>
496
489
 
497
490
  <style scoped>