@shwfed/config 2.3.27 → 2.3.28

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 (80) hide show
  1. package/dist/mcp.mjs +1211 -701
  2. package/dist/module.json +1 -1
  3. package/dist/preview/assets/{config-C45AT0tt.js → config--PcXQV_r.js} +1 -1
  4. package/dist/preview/assets/{config-CXaH7a2G.js → config-5KVDXgUF.js} +1 -1
  5. package/dist/preview/assets/{config-CIcy6Jwg.js → config-B5avpKJE.js} +1 -1
  6. package/dist/preview/assets/{config-l3KurfL5.js → config-CJHPt8Gx.js} +1 -1
  7. package/dist/preview/assets/{config-D-i-AFgH.js → config-CNo3isHa.js} +1 -1
  8. package/dist/preview/assets/{config-DrpESRR5.js → config-CQHS6cZe.js} +1 -1
  9. package/dist/preview/assets/{config-Bv_hUugV.js → config-D0_1yZdF.js} +1 -1
  10. package/dist/preview/assets/{config-D0YS2Bpj.js → config-DDfTl9Cs.js} +1 -1
  11. package/dist/preview/assets/{config-CRqRJ0oF.js → config-fvkC2rB8.js} +1 -1
  12. package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-Ck8Pbwem.js → definition.vue_vue_type_script_setup_true_lang-RM-qDh0R.js} +1 -1
  13. package/dist/preview/assets/index-DNd8J9Zv.js +643 -0
  14. package/dist/preview/assets/index-DrIMqXAa.js +1 -0
  15. package/dist/preview/assets/index-a2QwAots.css +1 -0
  16. package/dist/preview/assets/{runtime-CvuGnDIa.js → runtime-BGTWf-O7.js} +1 -1
  17. package/dist/preview/assets/{runtime-tobnPKdV.js → runtime-BPjZQmcY.js} +1 -1
  18. package/dist/preview/assets/{runtime-DUyUjFqF.js → runtime-Bq3fmxeF.js} +1 -1
  19. package/dist/preview/assets/{runtime-z_QPMN-R.js → runtime-CCbyrqQT.js} +1 -1
  20. package/dist/preview/assets/{runtime-D42ecZyC.js → runtime-C_XX6a0C.js} +1 -1
  21. package/dist/preview/assets/{runtime-D6twt5H_.js → runtime-CtqwtTE_.js} +1 -1
  22. package/dist/preview/assets/{runtime-CmCvUWLV.js → runtime-DcrzodsN.js} +1 -1
  23. package/dist/preview/assets/{runtime-Df715bRA.js → runtime-Dr_10emf.js} +1 -1
  24. package/dist/preview/assets/{runtime-BSASeqgI.js → runtime-Dy4ZmQ-n.js} +1 -1
  25. package/dist/preview/index.html +2 -2
  26. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.d.vue.ts +2 -0
  27. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.vue +57 -3
  28. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/config.vue.d.ts +2 -0
  29. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.d.vue.ts +2 -0
  30. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.vue +1 -0
  31. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/runtime.vue.d.ts +2 -0
  32. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/schema.d.ts +2 -0
  33. package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.tabs/schema.js +4 -0
  34. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.d.vue.ts +4 -4
  35. package/dist/runtime/components/form/fields/2026-05-23/com.shwfed.form.field.tree.multi/config.vue.d.ts +4 -4
  36. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.d.vue.ts +127 -0
  37. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue +593 -0
  38. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/config.vue.d.ts +127 -0
  39. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.d.vue.ts +8 -0
  40. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue +465 -0
  41. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/runtime.vue.d.ts +8 -0
  42. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/schema.d.ts +95 -0
  43. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.multi/schema.js +112 -0
  44. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.d.vue.ts +125 -0
  45. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue +525 -0
  46. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/config.vue.d.ts +125 -0
  47. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.d.vue.ts +8 -0
  48. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue +460 -0
  49. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/runtime.vue.d.ts +8 -0
  50. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/schema.d.ts +92 -0
  51. package/dist/runtime/components/form/fields/2026-05-26/com.shwfed.form.field.tree.combobox.single/schema.js +104 -0
  52. package/dist/runtime/components/form/fields/2026-05-26/tree-combobox-shared.d.ts +35 -0
  53. package/dist/runtime/components/form/fields/2026-05-26/tree-combobox-shared.js +31 -0
  54. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.d.vue.ts +131 -0
  55. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue +607 -0
  56. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/config.vue.d.ts +131 -0
  57. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.d.vue.ts +9 -0
  58. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.vue +447 -0
  59. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/runtime.vue.d.ts +9 -0
  60. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.d.ts +90 -0
  61. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-multi/schema.js +143 -0
  62. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.d.vue.ts +129 -0
  63. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue +538 -0
  64. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/config.vue.d.ts +129 -0
  65. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.d.vue.ts +9 -0
  66. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.vue +429 -0
  67. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/runtime.vue.d.ts +9 -0
  68. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.d.ts +87 -0
  69. package/dist/runtime/components/table/columns/2026-05-27/com.shwfed.table.column.tree-combobox-single/schema.js +135 -0
  70. package/dist/runtime/components/table/columns/2026-05-27/tree-combobox-shared.d.ts +35 -0
  71. package/dist/runtime/components/table/columns/2026-05-27/tree-combobox-shared.js +31 -0
  72. package/dist/runtime/components/table/config.vue +29 -0
  73. package/dist/runtime/components/ui/tree/Tree.d.vue.ts +2 -0
  74. package/dist/runtime/components/ui/tree/Tree.vue +7 -2
  75. package/dist/runtime/components/ui/tree/Tree.vue.d.ts +2 -0
  76. package/dist/runtime/components/ui/tree/TreeNode.vue +16 -26
  77. package/package.json +1 -1
  78. package/dist/preview/assets/index-BCE-G4Ha.css +0 -1
  79. package/dist/preview/assets/index-C3Ycah5_.js +0 -643
  80. package/dist/preview/assets/index-hWT4_I5k.js +0 -1
@@ -0,0 +1,607 @@
1
+ <script setup>
2
+ import { computed, ref, watch } from "vue";
3
+ import { Icon } from "@iconify/vue";
4
+ import { ExpressionEditor } from "../../../../ui/expression-editor";
5
+ import { Field, FieldLabel } from "../../../../ui/field";
6
+ import {
7
+ InputGroup,
8
+ InputGroupAddon,
9
+ InputGroupButton,
10
+ InputGroupInput,
11
+ InputGroupNumberField
12
+ } from "../../../../ui/input-group";
13
+ import { Locale as LocaleField } from "../../../../ui/locale";
14
+ import { Markdown } from "../../../../ui/markdown";
15
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../../ui/select";
16
+ import { Separator } from "../../../../ui/separator";
17
+ import { Switch } from "../../../../ui/switch";
18
+ import DerivedValueEditor from "../../../../form/DerivedValueEditor.vue";
19
+ import { DataSource } from "../../../schema";
20
+ import { getStructFieldDescription, getStructFieldTitle } from "../../../utils/schema-meta";
21
+ import { schema } from "./schema";
22
+ defineOptions({ name: "ShwfedTableTreeComboboxMultiRendererConfig" });
23
+ const value = defineModel({ type: null, ...{ required: true } });
24
+ const fieldSchema = schema(() => {
25
+ });
26
+ const fieldTitle = (f) => getStructFieldTitle(fieldSchema, f) ?? f;
27
+ const fieldDescription = (f) => getStructFieldDescription(fieldSchema, f);
28
+ const dataSourceSchema = DataSource(() => {
29
+ });
30
+ const dataSourceFieldTitle = (f) => getStructFieldTitle(dataSourceSchema, f) ?? f;
31
+ const dataSourceFieldDescription = (f) => getStructFieldDescription(dataSourceSchema, f);
32
+ const ROW_VARS = {
33
+ row: { type: "dyn", label: "\u5F53\u524D\u884C\u6570\u636E" },
34
+ index: { type: "number", label: "\u884C\u7D22\u5F15" }
35
+ };
36
+ const ROW_NODE_VARS = {
37
+ ...ROW_VARS,
38
+ node: {
39
+ type: "dyn",
40
+ label: "\u5F53\u524D\u8282\u70B9",
41
+ description: "\u7531 `\u6570\u636E` \u8868\u8FBE\u5F0F\u8FD4\u56DE\u7684\u6BCF\u4E00\u9879\uFF1B\u7C7B\u578B\u5728\u914D\u7F6E\u65F6\u672A\u77E5\uFF08`dyn`\uFF09"
42
+ }
43
+ };
44
+ const ROW_JSON_VARS = {
45
+ ...ROW_VARS,
46
+ json: {
47
+ type: "optional<dyn>",
48
+ label: "HTTP \u54CD\u5E94\u4F53",
49
+ description: "\u5DF2\u89E3\u6790\u7684 JSON \u54CD\u5E94\uFF1B\u672A\u914D\u7F6E `request` \u65F6\u4E3A `none`"
50
+ }
51
+ };
52
+ const CASCADE_OPTIONS = [
53
+ {
54
+ value: "independent",
55
+ label: "\u72EC\u7ACB",
56
+ description: "\u52FE\u9009 / \u53D6\u6D88\u53EA\u4F5C\u7528\u4E8E\u5F53\u524D\u8282\u70B9\uFF1B\u7236\u5B50\u4E92\u4E0D\u5F71\u54CD"
57
+ },
58
+ {
59
+ value: "cascade-down",
60
+ label: "\u5411\u4E0B\u7EA7\u8054",
61
+ description: "\u52FE\u9009\u7236\u8282\u70B9\u81EA\u52A8\u52FE\u9009\u5176\u5168\u90E8\u53EF\u9009\u540E\u4EE3\uFF1B\u53D6\u6D88\u65F6\u540C\u7406\u3002\u7236\u8282\u70B9\u7684\u52FE\u9009\u72B6\u6001\u72EC\u7ACB\u8FFD\u8E2A"
62
+ },
63
+ {
64
+ value: "cascade-both",
65
+ label: "\u53CC\u5411\u7EA7\u8054",
66
+ description: "\u5728\u5411\u4E0B\u7EA7\u8054\u57FA\u7840\u4E0A\uFF0C\u7236\u8282\u70B9\u53CD\u6620\u540E\u4EE3\u52FE\u9009\u72B6\u6001\uFF08\u5168\u9009\u2192\u9009\u4E2D\u3001\u90E8\u5206\u2192\u534A\u9009\u3001\u5168\u4E0D\u9009\u2192\u672A\u9009\uFF09"
67
+ }
68
+ ];
69
+ const cascadeOpen = ref(false);
70
+ const hoveredCascade = ref(null);
71
+ watch(cascadeOpen, (isOpen) => {
72
+ hoveredCascade.value = isOpen ? value.value.cascade ?? "independent" : null;
73
+ });
74
+ const hoveredCascadeDescription = computed(
75
+ () => CASCADE_OPTIONS.find((o) => o.value === hoveredCascade.value)?.description
76
+ );
77
+ const bindingText = computed({
78
+ get: () => value.value.binding ?? "",
79
+ set: (v) => {
80
+ const trimmed = v.trim();
81
+ if (trimmed === "") {
82
+ const { binding: _omit, ...rest } = value.value;
83
+ value.value = rest;
84
+ } else {
85
+ value.value = { ...value.value, binding: trimmed };
86
+ }
87
+ }
88
+ });
89
+ function setOptionalExpression(key, next) {
90
+ if (next.length === 0) {
91
+ const { [key]: _omit, ...rest } = value.value;
92
+ value.value = rest;
93
+ } else {
94
+ value.value = { ...value.value, [key]: next };
95
+ }
96
+ }
97
+ function setDataSourceData(next) {
98
+ value.value = {
99
+ ...value.value,
100
+ dataSource: { ...value.value.dataSource, data: next }
101
+ };
102
+ }
103
+ function setDataSourceRequest(next) {
104
+ const trimmed = next.trim();
105
+ if (trimmed.length === 0) {
106
+ const { request: _omit, ...rest } = value.value.dataSource;
107
+ value.value = { ...value.value, dataSource: rest };
108
+ } else {
109
+ value.value = {
110
+ ...value.value,
111
+ dataSource: { ...value.value.dataSource, request: next }
112
+ };
113
+ }
114
+ }
115
+ const derivedModel = computed({
116
+ get: () => value.value.derived,
117
+ set: (v) => {
118
+ if (v == null) {
119
+ const { derived: _omit, ...rest } = value.value;
120
+ value.value = rest;
121
+ } else {
122
+ value.value = { ...value.value, derived: v };
123
+ }
124
+ }
125
+ });
126
+ </script>
127
+
128
+ <template>
129
+ <div class="space-y-5">
130
+ <!-- Identity: title + binding + placeholder + size -->
131
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
132
+ <Field orientation="vertical">
133
+ <FieldLabel class="text-xs text-zinc-500">
134
+ <template
135
+ v-if="fieldDescription('title')"
136
+ #tooltip
137
+ >
138
+ <Markdown
139
+ :source="fieldDescription('title')"
140
+ block
141
+ class="prose prose-sm prose-zinc"
142
+ />
143
+ </template>
144
+ {{ fieldTitle("title") }}
145
+ </FieldLabel>
146
+ <LocaleField v-model="value.title" />
147
+ </Field>
148
+ <Field orientation="vertical">
149
+ <FieldLabel class="text-xs text-zinc-500">
150
+ <template
151
+ v-if="fieldDescription('tooltip')"
152
+ #tooltip
153
+ >
154
+ <Markdown
155
+ :source="fieldDescription('tooltip')"
156
+ block
157
+ class="prose prose-sm prose-zinc"
158
+ />
159
+ </template>
160
+ {{ fieldTitle("tooltip") }}
161
+ </FieldLabel>
162
+ <LocaleField
163
+ v-model="value.tooltip"
164
+ markdown
165
+ />
166
+ </Field>
167
+ </div>
168
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
169
+ <Field orientation="vertical">
170
+ <FieldLabel class="text-xs text-zinc-500">
171
+ <template
172
+ v-if="fieldDescription('binding')"
173
+ #tooltip
174
+ >
175
+ <Markdown
176
+ :source="fieldDescription('binding')"
177
+ block
178
+ class="prose prose-sm prose-zinc"
179
+ />
180
+ </template>
181
+ {{ fieldTitle("binding") }}
182
+ </FieldLabel>
183
+ <InputGroup>
184
+ <InputGroupInput
185
+ v-model="bindingText"
186
+ placeholder="例:user.departmentIds"
187
+ class="font-mono"
188
+ />
189
+ </InputGroup>
190
+ </Field>
191
+ <Field orientation="vertical">
192
+ <FieldLabel class="text-xs text-zinc-500">
193
+ <template
194
+ v-if="fieldDescription('placeholder')"
195
+ #tooltip
196
+ >
197
+ <Markdown
198
+ :source="fieldDescription('placeholder')"
199
+ block
200
+ class="prose prose-sm prose-zinc"
201
+ />
202
+ </template>
203
+ {{ fieldTitle("placeholder") }}
204
+ </FieldLabel>
205
+ <LocaleField v-model="value.placeholder" />
206
+ </Field>
207
+ <Field orientation="vertical">
208
+ <FieldLabel class="text-xs text-zinc-500">
209
+ <template
210
+ v-if="fieldDescription('size')"
211
+ #tooltip
212
+ >
213
+ <Markdown
214
+ :source="fieldDescription('size')"
215
+ block
216
+ class="prose prose-sm prose-zinc"
217
+ />
218
+ </template>
219
+ {{ fieldTitle("size") }}
220
+ </FieldLabel>
221
+ <InputGroup>
222
+ <InputGroupNumberField
223
+ :model-value="value.size"
224
+ :disabled="value.grow"
225
+ :min="0"
226
+ @update:model-value="(v) => value = { ...value, size: v }"
227
+ />
228
+ <InputGroupAddon align="inline-end">
229
+ <InputGroupButton
230
+ :variant="value.grow ? 'primary' : 'ghost'"
231
+ size="xs"
232
+ @click="value = { ...value, grow: !value.grow }"
233
+ >
234
+ <Icon :icon="value.grow ? 'fluent:lock-closed-20-regular' : 'fluent:arrow-autofit-width-20-regular'" />
235
+ {{ fieldTitle("grow") }}
236
+ </InputGroupButton>
237
+ </InputGroupAddon>
238
+ </InputGroup>
239
+ </Field>
240
+ </div>
241
+
242
+ <!-- 数据源 -->
243
+ <h3 class="text-xs font-medium text-zinc-500">
244
+ {{ fieldTitle("dataSource") }}
245
+ </h3>
246
+
247
+ <Field orientation="vertical">
248
+ <FieldLabel class="text-xs text-zinc-500">
249
+ <template
250
+ v-if="dataSourceFieldDescription('request')"
251
+ #tooltip
252
+ >
253
+ <Markdown
254
+ :source="dataSourceFieldDescription('request')"
255
+ block
256
+ class="prose prose-sm prose-zinc"
257
+ />
258
+ </template>
259
+ {{ dataSourceFieldTitle("request") }}
260
+ </FieldLabel>
261
+ <ExpressionEditor
262
+ :model-value="value.dataSource.request ?? ''"
263
+ placeholder="如 http.get('/api/departments/tree')"
264
+ result-type="HttpRequest"
265
+ :extra-vars="ROW_VARS"
266
+ multiline
267
+ class="min-h-20"
268
+ @update:model-value="setDataSourceRequest"
269
+ />
270
+ </Field>
271
+
272
+ <Field orientation="vertical">
273
+ <FieldLabel class="text-xs text-zinc-500">
274
+ <template
275
+ v-if="dataSourceFieldDescription('data')"
276
+ #tooltip
277
+ >
278
+ <Markdown
279
+ :source="dataSourceFieldDescription('data')"
280
+ block
281
+ class="prose prose-sm prose-zinc"
282
+ />
283
+ </template>
284
+ {{ dataSourceFieldTitle("data") }}
285
+ </FieldLabel>
286
+ <ExpressionEditor
287
+ :model-value="value.dataSource.data"
288
+ placeholder="如 json.?value.roots.orValue([])"
289
+ result-type="list"
290
+ :extra-vars="ROW_JSON_VARS"
291
+ @update:model-value="setDataSourceData"
292
+ />
293
+ </Field>
294
+
295
+ <!-- 节点 -->
296
+ <h3 class="text-xs font-medium text-zinc-500">
297
+ 节点
298
+ </h3>
299
+
300
+ <div class="grid grid-cols-2 gap-3">
301
+ <Field orientation="vertical">
302
+ <FieldLabel class="text-xs text-zinc-500">
303
+ <template
304
+ v-if="fieldDescription('nodeKey')"
305
+ #tooltip
306
+ >
307
+ <Markdown
308
+ :source="fieldDescription('nodeKey')"
309
+ block
310
+ class="prose prose-sm prose-zinc"
311
+ />
312
+ </template>
313
+ {{ fieldTitle("nodeKey") }}
314
+ </FieldLabel>
315
+ <ExpressionEditor
316
+ :model-value="value.nodeKey"
317
+ placeholder="例:string(node.id)"
318
+ :result-type="['string', 'number', 'dyn']"
319
+ :extra-vars="ROW_NODE_VARS"
320
+ class="min-h-10"
321
+ @update:model-value="(v) => value = { ...value, nodeKey: v }"
322
+ />
323
+ </Field>
324
+
325
+ <Field orientation="vertical">
326
+ <FieldLabel class="text-xs text-zinc-500">
327
+ <template
328
+ v-if="fieldDescription('nodeChildren')"
329
+ #tooltip
330
+ >
331
+ <Markdown
332
+ :source="fieldDescription('nodeChildren')"
333
+ block
334
+ class="prose prose-sm prose-zinc"
335
+ />
336
+ </template>
337
+ {{ fieldTitle("nodeChildren") }}
338
+ </FieldLabel>
339
+ <ExpressionEditor
340
+ :model-value="value.nodeChildren"
341
+ placeholder="例:has(node.children) ? node.children : null"
342
+ result-type="list"
343
+ :extra-vars="ROW_NODE_VARS"
344
+ class="min-h-10"
345
+ @update:model-value="(v) => value = { ...value, nodeChildren: v }"
346
+ />
347
+ </Field>
348
+ </div>
349
+
350
+ <div class="grid grid-cols-2 gap-3">
351
+ <Field orientation="vertical">
352
+ <FieldLabel class="text-xs text-zinc-500">
353
+ <template
354
+ v-if="fieldDescription('nodeLabel')"
355
+ #tooltip
356
+ >
357
+ <Markdown
358
+ :source="fieldDescription('nodeLabel')"
359
+ block
360
+ class="prose prose-sm prose-zinc"
361
+ />
362
+ </template>
363
+ {{ fieldTitle("nodeLabel") }}
364
+ </FieldLabel>
365
+ <LocaleField
366
+ markdown
367
+ translate-hint="tree node label"
368
+ :model-value="value.nodeLabel"
369
+ @update:model-value="(v) => value = { ...value, nodeLabel: v }"
370
+ />
371
+ </Field>
372
+
373
+ <Field orientation="vertical">
374
+ <FieldLabel class="text-xs text-zinc-500">
375
+ <template
376
+ v-if="fieldDescription('nodeTooltip')"
377
+ #tooltip
378
+ >
379
+ <Markdown
380
+ :source="fieldDescription('nodeTooltip')"
381
+ block
382
+ class="prose prose-sm prose-zinc"
383
+ />
384
+ </template>
385
+ {{ fieldTitle("nodeTooltip") }}
386
+ </FieldLabel>
387
+ <LocaleField
388
+ markdown
389
+ translate-hint="tree node tooltip"
390
+ :model-value="value.nodeTooltip"
391
+ @update:model-value="(v) => value = { ...value, nodeTooltip: v }"
392
+ />
393
+ </Field>
394
+ </div>
395
+
396
+ <!-- 行为: 节点可选条件 + 级联模式 + 默认全部展开 -->
397
+ <div class="grid grid-cols-3 gap-3">
398
+ <Field orientation="vertical">
399
+ <FieldLabel class="text-xs text-zinc-500">
400
+ <template
401
+ v-if="fieldDescription('nodeSelectable')"
402
+ #tooltip
403
+ >
404
+ <Markdown
405
+ :source="fieldDescription('nodeSelectable')"
406
+ block
407
+ class="prose prose-sm prose-zinc"
408
+ />
409
+ </template>
410
+ {{ fieldTitle("nodeSelectable") }}
411
+ </FieldLabel>
412
+ <ExpressionEditor
413
+ :model-value="value.nodeSelectable ?? ''"
414
+ placeholder="例:!has(node.disabled) || !node.disabled"
415
+ result-type="bool"
416
+ :extra-vars="ROW_NODE_VARS"
417
+ class="min-h-10"
418
+ @update:model-value="(v) => setOptionalExpression('nodeSelectable', v)"
419
+ />
420
+ </Field>
421
+
422
+ <Field orientation="vertical">
423
+ <FieldLabel class="text-xs text-zinc-500">
424
+ <template
425
+ v-if="fieldDescription('cascade')"
426
+ #tooltip
427
+ >
428
+ <Markdown
429
+ :source="fieldDescription('cascade')"
430
+ block
431
+ class="prose prose-sm prose-zinc"
432
+ />
433
+ </template>
434
+ {{ fieldTitle("cascade") }}
435
+ </FieldLabel>
436
+ <Select
437
+ v-model:open="cascadeOpen"
438
+ :model-value="value.cascade ?? 'independent'"
439
+ @update:model-value="(v) => value = { ...value, cascade: v }"
440
+ >
441
+ <SelectTrigger class="w-full">
442
+ <SelectValue />
443
+ </SelectTrigger>
444
+ <SelectContent>
445
+ <SelectItem
446
+ v-for="opt in CASCADE_OPTIONS"
447
+ :key="opt.value"
448
+ :value="opt.value"
449
+ @mouseenter="hoveredCascade = opt.value"
450
+ @focus="hoveredCascade = opt.value"
451
+ >
452
+ {{ opt.label }}
453
+ </SelectItem>
454
+ <div
455
+ v-if="hoveredCascadeDescription"
456
+ data-slot="cascade-description"
457
+ class="mt-1 border-t border-zinc-200 px-2 py-1.5 text-xs text-zinc-500"
458
+ >
459
+ {{ hoveredCascadeDescription }}
460
+ </div>
461
+ </SelectContent>
462
+ </Select>
463
+ </Field>
464
+
465
+ <Field orientation="vertical">
466
+ <FieldLabel class="text-xs text-zinc-500">
467
+ <template
468
+ v-if="fieldDescription('expandAll')"
469
+ #tooltip
470
+ >
471
+ <Markdown
472
+ :source="fieldDescription('expandAll')"
473
+ block
474
+ class="prose prose-sm prose-zinc"
475
+ />
476
+ </template>
477
+ {{ fieldTitle("expandAll") }}
478
+ </FieldLabel>
479
+ <div>
480
+ <Switch
481
+ :model-value="value.expandAll ?? false"
482
+ @update:model-value="(v) => value = { ...value, expandAll: v }"
483
+ />
484
+ </div>
485
+ </Field>
486
+ </div>
487
+
488
+ <!-- 通用: 隐藏 / 禁用 / 只读 + 派生值 -->
489
+ <div class="grid grid-cols-2 gap-x-6 gap-y-4">
490
+ <Field orientation="vertical">
491
+ <FieldLabel class="text-xs text-zinc-500">
492
+ <template
493
+ v-if="fieldDescription('hidden')"
494
+ #tooltip
495
+ >
496
+ <Markdown
497
+ :source="fieldDescription('hidden')"
498
+ block
499
+ class="prose prose-sm prose-zinc"
500
+ />
501
+ </template>
502
+ {{ fieldTitle("hidden") }}
503
+ </FieldLabel>
504
+ <ExpressionEditor
505
+ :model-value="value.hidden ?? ''"
506
+ placeholder="例:row.archived"
507
+ result-type="bool"
508
+ :extra-vars="ROW_VARS"
509
+ @update:model-value="(v) => setOptionalExpression('hidden', v)"
510
+ />
511
+ </Field>
512
+ <Field orientation="vertical">
513
+ <FieldLabel class="text-xs text-zinc-500">
514
+ <template
515
+ v-if="fieldDescription('disabled')"
516
+ #tooltip
517
+ >
518
+ <Markdown
519
+ :source="fieldDescription('disabled')"
520
+ block
521
+ class="prose prose-sm prose-zinc"
522
+ />
523
+ </template>
524
+ {{ fieldTitle("disabled") }}
525
+ </FieldLabel>
526
+ <ExpressionEditor
527
+ :model-value="value.disabled ?? ''"
528
+ placeholder="例:row.locked"
529
+ result-type="bool"
530
+ :extra-vars="ROW_VARS"
531
+ @update:model-value="(v) => setOptionalExpression('disabled', v)"
532
+ />
533
+ </Field>
534
+ <Field orientation="vertical">
535
+ <FieldLabel class="text-xs text-zinc-500">
536
+ <template
537
+ v-if="fieldDescription('readonly')"
538
+ #tooltip
539
+ >
540
+ <Markdown
541
+ :source="fieldDescription('readonly')"
542
+ block
543
+ class="prose prose-sm prose-zinc"
544
+ />
545
+ </template>
546
+ {{ fieldTitle("readonly") }}
547
+ </FieldLabel>
548
+ <ExpressionEditor
549
+ :model-value="value.readonly ?? ''"
550
+ placeholder="例:row.id != null"
551
+ result-type="bool"
552
+ :extra-vars="ROW_VARS"
553
+ @update:model-value="(v) => setOptionalExpression('readonly', v)"
554
+ />
555
+ </Field>
556
+ <Field
557
+ orientation="vertical"
558
+ class="col-span-2"
559
+ >
560
+ <FieldLabel class="text-xs text-zinc-500">
561
+ <template
562
+ v-if="fieldDescription('derived')"
563
+ #tooltip
564
+ >
565
+ <Markdown
566
+ :source="fieldDescription('derived')"
567
+ block
568
+ class="prose prose-sm prose-zinc"
569
+ />
570
+ </template>
571
+ {{ fieldTitle("derived") }}
572
+ </FieldLabel>
573
+ <DerivedValueEditor
574
+ v-model="derivedModel"
575
+ result-type="list"
576
+ placeholder="例:row.defaultIds"
577
+ />
578
+ </Field>
579
+ </div>
580
+
581
+ <Separator />
582
+ <div class="flex flex-wrap gap-x-8 gap-y-3">
583
+ <Field
584
+ orientation="horizontal"
585
+ class="w-auto gap-2"
586
+ >
587
+ <Switch
588
+ :model-value="value.enableSorting ?? false"
589
+ @update:model-value="(v) => value = { ...value, enableSorting: v }"
590
+ />
591
+ <FieldLabel class="text-sm text-zinc-600">
592
+ <template
593
+ v-if="fieldDescription('enableSorting')"
594
+ #tooltip
595
+ >
596
+ <Markdown
597
+ :source="fieldDescription('enableSorting')"
598
+ block
599
+ class="prose prose-sm prose-zinc"
600
+ />
601
+ </template>
602
+ {{ fieldTitle("enableSorting") }}
603
+ </FieldLabel>
604
+ </Field>
605
+ </div>
606
+ </div>
607
+ </template>