@shwfed/config 2.3.23 → 2.3.24

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 (43) hide show
  1. package/dist/mcp.mjs +996 -587
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{config-pVNUrcvS.js → config-B-6Htwv0.js} +1 -1
  4. package/dist/preview/assets/{config-f66PEpZ5.js → config-B2KjxFl5.js} +1 -1
  5. package/dist/preview/assets/{config-5rB9Rnmf.js → config-B3at5Bue.js} +1 -1
  6. package/dist/preview/assets/{config-EtlOM9yx.js → config-Bi9uFh4Y.js} +1 -1
  7. package/dist/preview/assets/{config-DUNvg-mJ.js → config-CBHKrOP5.js} +1 -1
  8. package/dist/preview/assets/{config-BWMtPN22.js → config-CWZxlCMJ.js} +1 -1
  9. package/dist/preview/assets/{config-CJADmi-_.js → config-CaZpOvHG.js} +1 -1
  10. package/dist/preview/assets/{config-BLxl7ROb.js → config-D5Kfssb7.js} +1 -1
  11. package/dist/preview/assets/{config-C-EOrL-v.js → config-DYAEfkYR.js} +1 -1
  12. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-DUu-CoTZ.js → definition.vue_vue_type_script_setup_true_lang-8BVrrrak.js} +1 -1
  13. package/dist/preview/assets/index-B3wadvvl.js +1 -0
  14. package/dist/preview/assets/index-DTsYYECD.js +643 -0
  15. package/dist/preview/assets/{runtime-P99-0gRD.js → runtime-C1iENPNJ.js} +1 -1
  16. package/dist/preview/assets/{runtime-CUBGWRtC.js → runtime-C5CCMnHt.js} +1 -1
  17. package/dist/preview/assets/{runtime-CFPeFbAB.js → runtime-CEP42oTV.js} +1 -1
  18. package/dist/preview/assets/{runtime-DcqfhaaX.js → runtime-CRHn61GX.js} +1 -1
  19. package/dist/preview/assets/{runtime-qQ5mJdRv.js → runtime-CoRrnGx1.js} +1 -1
  20. package/dist/preview/assets/{runtime-C0v-S40R.js → runtime-CqciI2ST.js} +1 -1
  21. package/dist/preview/assets/{runtime-DoLJtHV2.js → runtime-Hvzx1ucy.js} +1 -1
  22. package/dist/preview/assets/{runtime-B9GkQToM.js → runtime-aBsBSCeg.js} +1 -1
  23. package/dist/preview/assets/{runtime-CI38ypkY.js → runtime-jrsJfwMb.js} +1 -1
  24. package/dist/preview/index.html +1 -1
  25. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.d.vue.ts +163 -0
  26. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue +709 -0
  27. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/config.vue.d.ts +163 -0
  28. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/runtime.d.vue.ts +9 -0
  29. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/runtime.vue +368 -0
  30. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/runtime.vue.d.ts +9 -0
  31. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/schema.d.ts +225 -0
  32. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi/schema.js +175 -0
  33. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +167 -0
  34. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue +740 -0
  35. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +167 -0
  36. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/runtime.d.vue.ts +9 -0
  37. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/runtime.vue +402 -0
  38. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/runtime.vue.d.ts +9 -0
  39. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/schema.d.ts +227 -0
  40. package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/schema.js +227 -0
  41. package/package.json +1 -1
  42. package/dist/preview/assets/index-B4xolIUJ.js +0 -643
  43. package/dist/preview/assets/index-DFYLO8qf.js +0 -1
@@ -0,0 +1,709 @@
1
+ <script setup>
2
+ import { computed } from "vue";
3
+ import { Icon } from "@iconify/vue";
4
+ import { Button } from "../../../../ui/button";
5
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "../../../../ui/dropdown-menu";
6
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
7
+ import { Switch } from "../../../../ui/switch";
8
+ import { Separator } from "../../../../ui/separator";
9
+ import { Field, FieldLabel } from "../../../../ui/field";
10
+ import { Locale } from "../../../../ui/locale";
11
+ import {
12
+ InputGroup,
13
+ InputGroupAddon,
14
+ InputGroupButton,
15
+ InputGroupInput,
16
+ InputGroupNumberField
17
+ } from "../../../../ui/input-group";
18
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../../../ui/tabs";
19
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../utils/schema-meta";
20
+ import { Markdown } from "../../../../ui/markdown";
21
+ import DerivedValueEditor from "../../../../form/DerivedValueEditor.vue";
22
+ import { itemSchema, optionsSchema, schema } from "./schema";
23
+ defineOptions({ name: "ShwfedTableComboboxMultiRendererConfig" });
24
+ const value = defineModel({ type: null, ...{ required: true } });
25
+ const fieldSchema = schema(() => {
26
+ });
27
+ const fieldTitle = (field) => getStructFieldTitle(fieldSchema, field) ?? field;
28
+ const fieldDescription = (field) => getStructFieldDescription(fieldSchema, field);
29
+ const itemFieldSchema = itemSchema(() => {
30
+ });
31
+ const itemFieldTitle = (f) => getStructFieldTitle(itemFieldSchema, f) ?? f;
32
+ const itemFieldDescription = (f) => getStructFieldDescription(itemFieldSchema, f);
33
+ const optionsUnion = optionsSchema(() => {
34
+ });
35
+ const remoteFieldTitle = (f) => {
36
+ const _schema = optionsUnion;
37
+ const members = _schema.members ?? [];
38
+ const remote = members.find((m) => m?.fields?.kind?.literals?.[0] === "remote");
39
+ return remote?.fields?.[f]?.ast?.annotations?.[Symbol.for("effect/annotation/Title")] ?? f;
40
+ };
41
+ const remoteFieldDescription = (f) => {
42
+ const _schema = optionsUnion;
43
+ const members = _schema.members ?? [];
44
+ const remote = members.find((m) => m?.fields?.kind?.literals?.[0] === "remote");
45
+ return remote?.fields?.[f]?.ast?.annotations?.[Symbol.for("effect/annotation/Description")];
46
+ };
47
+ const ROW_VARS = {
48
+ row: { type: "dyn", label: "\u5F53\u524D\u884C\u6570\u636E" },
49
+ index: { type: "number", label: "\u884C\u7D22\u5F15" }
50
+ };
51
+ const ROW_JSON_VARS = {
52
+ ...ROW_VARS,
53
+ json: { type: "dyn", label: "HTTP \u54CD\u5E94\u4F53\uFF08\u5DF2\u89E3\u6790 JSON\uFF09" }
54
+ };
55
+ const ROW_OPTION_VARS = {
56
+ ...ROW_VARS,
57
+ option: { type: "dyn", label: "\u5F53\u524D\u9009\u9879" }
58
+ };
59
+ const bindingText = computed({
60
+ get: () => value.value.binding ?? "",
61
+ set: (v) => {
62
+ const trimmed = v.trim();
63
+ if (trimmed === "") {
64
+ const { binding: _omit, ...rest } = value.value;
65
+ value.value = rest;
66
+ } else {
67
+ value.value = { ...value.value, binding: trimmed };
68
+ }
69
+ }
70
+ });
71
+ function celModel(field) {
72
+ return computed({
73
+ get: () => value.value[field] ?? "",
74
+ set: (v) => {
75
+ if (v === "") {
76
+ const { [field]: _omit, ...rest } = value.value;
77
+ value.value = rest;
78
+ } else {
79
+ value.value = { ...value.value, [field]: v };
80
+ }
81
+ }
82
+ });
83
+ }
84
+ const hiddenModel = celModel("hidden");
85
+ const disabledModel = celModel("disabled");
86
+ const readonlyModel = celModel("readonly");
87
+ const derivedModel = computed({
88
+ get: () => value.value.derived,
89
+ set: (v) => {
90
+ if (v == null) {
91
+ const { derived: _omit, ...rest } = value.value;
92
+ value.value = rest;
93
+ } else {
94
+ value.value = { ...value.value, derived: v };
95
+ }
96
+ }
97
+ });
98
+ const optionsKind = computed(() => value.value.options.kind);
99
+ function emptyStatic() {
100
+ return { kind: "static", items: [] };
101
+ }
102
+ function emptyRemote() {
103
+ return {
104
+ kind: "remote",
105
+ request: "",
106
+ options: "",
107
+ optionValue: "option",
108
+ optionLabel: [{ locale: "zh", message: "" }]
109
+ };
110
+ }
111
+ function setKind(kind) {
112
+ if (value.value.options.kind === kind) return;
113
+ value.value = {
114
+ ...value.value,
115
+ options: kind === "static" ? emptyStatic() : emptyRemote()
116
+ };
117
+ }
118
+ const items = computed(() => {
119
+ return value.value.options.kind === "static" ? value.value.options.items : [];
120
+ });
121
+ function patchStatic(patch) {
122
+ if (value.value.options.kind !== "static") return;
123
+ value.value = {
124
+ ...value.value,
125
+ options: { ...value.value.options, ...patch }
126
+ };
127
+ }
128
+ function patchRemote(patch) {
129
+ if (value.value.options.kind !== "remote") return;
130
+ value.value = {
131
+ ...value.value,
132
+ options: { ...value.value.options, ...patch }
133
+ };
134
+ }
135
+ const requestModel = computed({
136
+ get: () => value.value.options.kind === "remote" ? value.value.options.request : "",
137
+ set: (v) => patchRemote({ request: v })
138
+ });
139
+ const optionsExprModel = computed({
140
+ get: () => value.value.options.kind === "remote" ? value.value.options.options : "",
141
+ set: (v) => patchRemote({ options: v })
142
+ });
143
+ const optionValueModel = computed({
144
+ get: () => value.value.options.kind === "remote" ? value.value.options.optionValue : "option",
145
+ set: (v) => patchRemote({ optionValue: v })
146
+ });
147
+ const optionLabelModel = computed({
148
+ get: () => value.value.options.kind === "remote" ? value.value.options.optionLabel : [{ locale: "zh", message: "" }],
149
+ set: (v) => patchRemote({ optionLabel: v })
150
+ });
151
+ function newId() {
152
+ return typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
153
+ const r = Math.random() * 16 | 0;
154
+ const v = c === "x" ? r : r & 3 | 8;
155
+ return v.toString(16);
156
+ });
157
+ }
158
+ function newItem() {
159
+ return {
160
+ id: newId(),
161
+ label: [{ locale: "zh", message: "" }],
162
+ value: { kind: "text", value: "" }
163
+ };
164
+ }
165
+ function patchItem(index, patch) {
166
+ if (value.value.options.kind !== "static") return;
167
+ const next = [...value.value.options.items];
168
+ const cur = next[index];
169
+ if (!cur) return;
170
+ next[index] = { ...cur, ...patch };
171
+ patchStatic({ items: next });
172
+ }
173
+ function addItem() {
174
+ if (value.value.options.kind !== "static") return;
175
+ patchStatic({ items: [...value.value.options.items, newItem()] });
176
+ }
177
+ function removeItem(index) {
178
+ if (value.value.options.kind !== "static") return;
179
+ const next = [...value.value.options.items];
180
+ next.splice(index, 1);
181
+ patchStatic({ items: next });
182
+ }
183
+ function setItemKind(index, kind) {
184
+ if (value.value.options.kind !== "static") return;
185
+ const cur = value.value.options.items[index];
186
+ if (!cur || cur.value.kind === kind) return;
187
+ patchItem(index, {
188
+ value: kind === "text" ? { kind: "text", value: "" } : { kind: "number", value: 0 }
189
+ });
190
+ }
191
+ function setItemTextValue(index, text) {
192
+ patchItem(index, { value: { kind: "text", value: text } });
193
+ }
194
+ function setItemNumberValue(index, n) {
195
+ patchItem(index, {
196
+ value: {
197
+ kind: "number",
198
+ value: typeof n === "number" && Number.isFinite(n) ? n : 0
199
+ }
200
+ });
201
+ }
202
+ function setItemLabel(index, label) {
203
+ patchItem(index, { label });
204
+ }
205
+ function setItemTooltip(index, tooltip) {
206
+ const isEmpty = !tooltip || tooltip.every((l) => l.message.trim().length === 0);
207
+ if (value.value.options.kind !== "static") return;
208
+ if (isEmpty) {
209
+ const cur = value.value.options.items[index];
210
+ if (!cur) return;
211
+ const { tooltip: _omit, ...rest } = cur;
212
+ const next = [...value.value.options.items];
213
+ next[index] = rest;
214
+ patchStatic({ items: next });
215
+ } else {
216
+ patchItem(index, { tooltip });
217
+ }
218
+ }
219
+ </script>
220
+
221
+ <template>
222
+ <div class="space-y-5">
223
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
224
+ <Field orientation="vertical">
225
+ <FieldLabel class="text-xs text-zinc-500">
226
+ <template
227
+ v-if="fieldDescription('title')"
228
+ #tooltip
229
+ >
230
+ <Markdown
231
+ :source="fieldDescription('title')"
232
+ block
233
+ class="prose prose-sm prose-zinc"
234
+ />
235
+ </template>
236
+ {{ fieldTitle("title") }}
237
+ </FieldLabel>
238
+ <Locale v-model="value.title" />
239
+ </Field>
240
+ <Field orientation="vertical">
241
+ <FieldLabel class="text-xs text-zinc-500">
242
+ <template
243
+ v-if="fieldDescription('tooltip')"
244
+ #tooltip
245
+ >
246
+ <Markdown
247
+ :source="fieldDescription('tooltip')"
248
+ block
249
+ class="prose prose-sm prose-zinc"
250
+ />
251
+ </template>
252
+ {{ fieldTitle("tooltip") }}
253
+ </FieldLabel>
254
+ <Locale
255
+ v-model="value.tooltip"
256
+ markdown
257
+ />
258
+ </Field>
259
+ </div>
260
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
261
+ <Field orientation="vertical">
262
+ <FieldLabel class="text-xs text-zinc-500">
263
+ <template
264
+ v-if="fieldDescription('binding')"
265
+ #tooltip
266
+ >
267
+ <Markdown
268
+ :source="fieldDescription('binding')"
269
+ block
270
+ class="prose prose-sm prose-zinc"
271
+ />
272
+ </template>
273
+ {{ fieldTitle("binding") }}
274
+ </FieldLabel>
275
+ <InputGroup>
276
+ <InputGroupInput
277
+ v-model="bindingText"
278
+ placeholder="例:roles"
279
+ class="font-mono"
280
+ />
281
+ </InputGroup>
282
+ </Field>
283
+ <Field orientation="vertical">
284
+ <FieldLabel class="text-xs text-zinc-500">
285
+ <template
286
+ v-if="fieldDescription('placeholder')"
287
+ #tooltip
288
+ >
289
+ <Markdown
290
+ :source="fieldDescription('placeholder')"
291
+ block
292
+ class="prose prose-sm prose-zinc"
293
+ />
294
+ </template>
295
+ {{ fieldTitle("placeholder") }}
296
+ </FieldLabel>
297
+ <Locale v-model="value.placeholder" />
298
+ </Field>
299
+ <Field orientation="vertical">
300
+ <FieldLabel class="text-xs text-zinc-500">
301
+ <template
302
+ v-if="fieldDescription('size')"
303
+ #tooltip
304
+ >
305
+ <Markdown
306
+ :source="fieldDescription('size')"
307
+ block
308
+ class="prose prose-sm prose-zinc"
309
+ />
310
+ </template>
311
+ {{ fieldTitle("size") }}
312
+ </FieldLabel>
313
+ <InputGroup>
314
+ <InputGroupNumberField
315
+ :model-value="value.size"
316
+ :disabled="value.grow"
317
+ :min="0"
318
+ @update:model-value="(v) => value = { ...value, size: v }"
319
+ />
320
+ <InputGroupAddon align="inline-end">
321
+ <InputGroupButton
322
+ :variant="value.grow ? 'primary' : 'ghost'"
323
+ size="xs"
324
+ @click="value = { ...value, grow: !value.grow }"
325
+ >
326
+ <Icon :icon="value.grow ? 'fluent:lock-closed-20-regular' : 'fluent:arrow-autofit-width-20-regular'" />
327
+ {{ fieldTitle("grow") }}
328
+ </InputGroupButton>
329
+ </InputGroupAddon>
330
+ </InputGroup>
331
+ </Field>
332
+ </div>
333
+
334
+ <Field orientation="vertical">
335
+ <FieldLabel class="text-xs text-zinc-500">
336
+ <template #tooltip>
337
+ <Markdown
338
+ source="选项可以是静态配置的固定列表,也可以由远程接口实时加载"
339
+ block
340
+ class="prose prose-sm prose-zinc"
341
+ />
342
+ </template>
343
+ 选项来源
344
+ </FieldLabel>
345
+
346
+ <Tabs
347
+ :model-value="optionsKind"
348
+ @update:model-value="(v) => {
349
+ if (v === 'static' || v === 'remote') setKind(v);
350
+ }"
351
+ >
352
+ <TabsList>
353
+ <TabsTrigger value="static">
354
+ 静态
355
+ </TabsTrigger>
356
+ <TabsTrigger value="remote">
357
+ 远程
358
+ </TabsTrigger>
359
+ </TabsList>
360
+ <TabsContent
361
+ value="static"
362
+ class="outline-none"
363
+ >
364
+ <div class="flex flex-col gap-3 pt-3">
365
+ <div
366
+ v-for="(item, index) in items"
367
+ :key="item.id"
368
+ data-slot="combobox-multi-item"
369
+ class="relative pt-8 grid grid-cols-3 gap-3 rounded border border-zinc-200 bg-zinc-50/40 p-3"
370
+ >
371
+ <InputGroupButton
372
+ variant="destructive"
373
+ size="icon-xs"
374
+ data-slot="combobox-multi-item-delete"
375
+ aria-label="删除选项"
376
+ class="absolute right-2 top-2 z-10"
377
+ @click="removeItem(index)"
378
+ >
379
+ <Icon icon="fluent:delete-20-regular" />
380
+ </InputGroupButton>
381
+
382
+ <Field orientation="vertical">
383
+ <FieldLabel class="text-xs text-zinc-500">
384
+ <template
385
+ v-if="itemFieldDescription('label')"
386
+ #tooltip
387
+ >
388
+ <Markdown
389
+ :source="itemFieldDescription('label')"
390
+ block
391
+ class="prose prose-sm prose-zinc"
392
+ />
393
+ </template>
394
+ {{ itemFieldTitle("label") }}
395
+ </FieldLabel>
396
+ <Locale
397
+ markdown
398
+ translate-hint="combobox option label"
399
+ :model-value="item.label"
400
+ @update:model-value="(v) => setItemLabel(index, v)"
401
+ />
402
+ </Field>
403
+
404
+ <Field orientation="vertical">
405
+ <FieldLabel class="text-xs text-zinc-500">
406
+ <template
407
+ v-if="itemFieldDescription('value')"
408
+ #tooltip
409
+ >
410
+ <Markdown
411
+ :source="itemFieldDescription('value')"
412
+ block
413
+ class="prose prose-sm prose-zinc"
414
+ />
415
+ </template>
416
+ {{ itemFieldTitle("value") }}
417
+ </FieldLabel>
418
+ <InputGroup>
419
+ <InputGroupAddon align="inline-start">
420
+ <DropdownMenu>
421
+ <DropdownMenuTrigger as-child>
422
+ <InputGroupButton
423
+ size="icon-sm"
424
+ as-child
425
+ >
426
+ <button
427
+ type="button"
428
+ data-slot="combobox-multi-item-kind-trigger"
429
+ class="text-zinc-500 transition-colors hover:text-zinc-700 [&_svg:not([class*='size-'])]:size-3.5"
430
+ aria-label="切换值类型"
431
+ >
432
+ <Icon
433
+ :icon="item.value.kind === 'number' ? 'fluent:number-symbol-20-regular' : 'fluent:textbox-20-regular'"
434
+ />
435
+ </button>
436
+ </InputGroupButton>
437
+ </DropdownMenuTrigger>
438
+ <DropdownMenuContent align="start">
439
+ <DropdownMenuItem @select="setItemKind(index, 'text')">
440
+ <Icon icon="fluent:textbox-20-regular" />
441
+ <span>文本</span>
442
+ </DropdownMenuItem>
443
+ <DropdownMenuItem @select="setItemKind(index, 'number')">
444
+ <Icon icon="fluent:number-symbol-20-regular" />
445
+ <span>数字</span>
446
+ </DropdownMenuItem>
447
+ </DropdownMenuContent>
448
+ </DropdownMenu>
449
+ </InputGroupAddon>
450
+
451
+ <InputGroupInput
452
+ v-if="item.value.kind === 'text'"
453
+ :model-value="item.value.value"
454
+ placeholder="例:admin"
455
+ @update:model-value="(v) => setItemTextValue(index, String(v ?? ''))"
456
+ />
457
+ <InputGroupNumberField
458
+ v-else
459
+ :model-value="item.value.value"
460
+ @update:model-value="(v) => setItemNumberValue(index, v)"
461
+ />
462
+ </InputGroup>
463
+ </Field>
464
+
465
+ <Field orientation="vertical">
466
+ <FieldLabel class="text-xs text-zinc-500">
467
+ <template
468
+ v-if="itemFieldDescription('tooltip')"
469
+ #tooltip
470
+ >
471
+ <Markdown
472
+ :source="itemFieldDescription('tooltip')"
473
+ block
474
+ class="prose prose-sm prose-zinc"
475
+ />
476
+ </template>
477
+ {{ itemFieldTitle("tooltip") }}
478
+ </FieldLabel>
479
+ <Locale
480
+ markdown
481
+ translate-hint="combobox option tooltip"
482
+ :model-value="item.tooltip"
483
+ @update:model-value="(v) => setItemTooltip(index, v)"
484
+ />
485
+ </Field>
486
+ </div>
487
+
488
+ <Button
489
+ type="button"
490
+ data-slot="combobox-multi-add-item"
491
+ class="w-full justify-center"
492
+ @click="addItem"
493
+ >
494
+ <Icon icon="fluent:add-20-regular" />
495
+ <span>增加选项</span>
496
+ </Button>
497
+ </div>
498
+ </TabsContent>
499
+ <TabsContent
500
+ value="remote"
501
+ class="outline-none"
502
+ >
503
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4 pt-3">
504
+ <Field orientation="vertical">
505
+ <FieldLabel class="text-xs text-zinc-500">
506
+ <template
507
+ v-if="remoteFieldDescription('request')"
508
+ #tooltip
509
+ >
510
+ <Markdown
511
+ :source="remoteFieldDescription('request')"
512
+ block
513
+ class="prose prose-sm prose-zinc"
514
+ />
515
+ </template>
516
+ {{ remoteFieldTitle("request") }}
517
+ </FieldLabel>
518
+ <ExpressionEditor
519
+ v-model="requestModel"
520
+ placeholder="如 http.get('/api/roles')"
521
+ result-type="HttpRequest"
522
+ :extra-vars="ROW_VARS"
523
+ multiline
524
+ />
525
+ </Field>
526
+ <Field orientation="vertical">
527
+ <FieldLabel class="text-xs text-zinc-500">
528
+ <template
529
+ v-if="remoteFieldDescription('options')"
530
+ #tooltip
531
+ >
532
+ <Markdown
533
+ :source="remoteFieldDescription('options')"
534
+ block
535
+ class="prose prose-sm prose-zinc"
536
+ />
537
+ </template>
538
+ {{ remoteFieldTitle("options") }}
539
+ </FieldLabel>
540
+ <ExpressionEditor
541
+ v-model="optionsExprModel"
542
+ placeholder="如 json.data"
543
+ result-type="dyn"
544
+ :extra-vars="ROW_JSON_VARS"
545
+ multiline
546
+ />
547
+ </Field>
548
+ <Field orientation="vertical">
549
+ <FieldLabel class="text-xs text-zinc-500">
550
+ <template
551
+ v-if="remoteFieldDescription('optionValue')"
552
+ #tooltip
553
+ >
554
+ <Markdown
555
+ :source="remoteFieldDescription('optionValue')"
556
+ block
557
+ class="prose prose-sm prose-zinc"
558
+ />
559
+ </template>
560
+ {{ remoteFieldTitle("optionValue") }}
561
+ </FieldLabel>
562
+ <ExpressionEditor
563
+ v-model="optionValueModel"
564
+ placeholder="如 option.id"
565
+ result-type="dyn"
566
+ :extra-vars="ROW_OPTION_VARS"
567
+ />
568
+ </Field>
569
+ <Field orientation="vertical">
570
+ <FieldLabel class="text-xs text-zinc-500">
571
+ <template
572
+ v-if="remoteFieldDescription('optionLabel')"
573
+ #tooltip
574
+ >
575
+ <Markdown
576
+ :source="remoteFieldDescription('optionLabel')"
577
+ block
578
+ class="prose prose-sm prose-zinc"
579
+ />
580
+ </template>
581
+ {{ remoteFieldTitle("optionLabel") }}
582
+ </FieldLabel>
583
+ <Locale
584
+ :model-value="optionLabelModel"
585
+ markdown
586
+ translate-hint="combobox option label"
587
+ @update:model-value="(v) => optionLabelModel = v"
588
+ />
589
+ </Field>
590
+ </div>
591
+ </TabsContent>
592
+ </Tabs>
593
+ </Field>
594
+
595
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
596
+ <Field orientation="vertical">
597
+ <FieldLabel class="text-xs text-zinc-500">
598
+ <template
599
+ v-if="fieldDescription('hidden')"
600
+ #tooltip
601
+ >
602
+ <Markdown
603
+ :source="fieldDescription('hidden')"
604
+ block
605
+ class="prose prose-sm prose-zinc"
606
+ />
607
+ </template>
608
+ {{ fieldTitle("hidden") }}
609
+ </FieldLabel>
610
+ <ExpressionEditor
611
+ v-model="hiddenModel"
612
+ placeholder="例:row.archived"
613
+ result-type="bool"
614
+ :extra-vars="ROW_VARS"
615
+ />
616
+ </Field>
617
+ <Field orientation="vertical">
618
+ <FieldLabel class="text-xs text-zinc-500">
619
+ <template
620
+ v-if="fieldDescription('disabled')"
621
+ #tooltip
622
+ >
623
+ <Markdown
624
+ :source="fieldDescription('disabled')"
625
+ block
626
+ class="prose prose-sm prose-zinc"
627
+ />
628
+ </template>
629
+ {{ fieldTitle("disabled") }}
630
+ </FieldLabel>
631
+ <ExpressionEditor
632
+ v-model="disabledModel"
633
+ placeholder="例:row.locked"
634
+ result-type="bool"
635
+ :extra-vars="ROW_VARS"
636
+ />
637
+ </Field>
638
+ <Field orientation="vertical">
639
+ <FieldLabel class="text-xs text-zinc-500">
640
+ <template
641
+ v-if="fieldDescription('readonly')"
642
+ #tooltip
643
+ >
644
+ <Markdown
645
+ :source="fieldDescription('readonly')"
646
+ block
647
+ class="prose prose-sm prose-zinc"
648
+ />
649
+ </template>
650
+ {{ fieldTitle("readonly") }}
651
+ </FieldLabel>
652
+ <ExpressionEditor
653
+ v-model="readonlyModel"
654
+ placeholder="例:row.id != null"
655
+ result-type="bool"
656
+ :extra-vars="ROW_VARS"
657
+ />
658
+ </Field>
659
+ <Field
660
+ orientation="vertical"
661
+ class="col-span-2"
662
+ >
663
+ <FieldLabel class="text-xs text-zinc-500">
664
+ <template
665
+ v-if="fieldDescription('derived')"
666
+ #tooltip
667
+ >
668
+ <Markdown
669
+ :source="fieldDescription('derived')"
670
+ block
671
+ class="prose prose-sm prose-zinc"
672
+ />
673
+ </template>
674
+ {{ fieldTitle("derived") }}
675
+ </FieldLabel>
676
+ <DerivedValueEditor
677
+ v-model="derivedModel"
678
+ result-type="dyn"
679
+ placeholder="例:form.defaults[row.kind]"
680
+ />
681
+ </Field>
682
+ </div>
683
+ <Separator />
684
+ <div class="flex flex-wrap gap-x-8 gap-y-3">
685
+ <Field
686
+ orientation="horizontal"
687
+ class="w-auto gap-2"
688
+ >
689
+ <Switch
690
+ :model-value="value.enableSorting ?? false"
691
+ @update:model-value="(v) => value = { ...value, enableSorting: v }"
692
+ />
693
+ <FieldLabel class="text-sm text-zinc-600">
694
+ <template
695
+ v-if="fieldDescription('enableSorting')"
696
+ #tooltip
697
+ >
698
+ <Markdown
699
+ :source="fieldDescription('enableSorting')"
700
+ block
701
+ class="prose prose-sm prose-zinc"
702
+ />
703
+ </template>
704
+ {{ fieldTitle("enableSorting") }}
705
+ </FieldLabel>
706
+ </Field>
707
+ </div>
708
+ </div>
709
+ </template>