@shwfed/config 2.7.7 → 2.8.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.
- package/dist/mcp.mjs +128 -55
- package/dist/module.json +1 -1
- package/dist/preview/assets/{badge-B0tiCpa_.js → badge-BI1mdo92.js} +1 -1
- package/dist/preview/assets/{config-jDPbLgBr.js → config-BNF2r9jW.js} +1 -1
- package/dist/preview/assets/{config-CGvnv-5x.js → config-BxuGYvER.js} +1 -1
- package/dist/preview/assets/{config-GCvXe12z.js → config-Cy5w3JWQ.js} +1 -1
- package/dist/preview/assets/{config-BG9TRQcv.js → config-DqUnpWZk.js} +1 -1
- package/dist/preview/assets/{config-C-XJ-8Rs.js → config-Du5SuNSb.js} +1 -1
- package/dist/preview/assets/{config-Dafqx9xC.js → config-DuzQXHvg.js} +1 -1
- package/dist/preview/assets/{config-Bfb2sH6S.js → config-OrJljNWU.js} +1 -1
- package/dist/preview/assets/{config-DqMRy1WL.js → config-XgVqueyq.js} +1 -1
- package/dist/preview/assets/{config-DDPihojt.js → config-ggyCcWNZ.js} +1 -1
- package/dist/preview/assets/{definition.vue_vue_type_script_setup_true_lang-DBXfCj4Q.js → definition.vue_vue_type_script_setup_true_lang-lEhYVEcN.js} +1 -1
- package/dist/preview/assets/{index-D7jDE3kp.js → index-BvLLQuQr.js} +1 -1
- package/dist/preview/assets/{index-B0PL01fm.css → index-DsMR5NfK.css} +1 -1
- package/dist/preview/assets/{index-CHzOsSTW.js → index-Yv78vz4W.js} +168 -168
- package/dist/preview/assets/index-yrBKwEfk.js +1 -0
- package/dist/preview/assets/{item-DV-Garrg.js → item-DMtXi_cx.js} +1 -1
- package/dist/preview/assets/{runtime-DKtlQWwc.js → runtime-2S3Yr051.js} +1 -1
- package/dist/preview/assets/{runtime-UmLaEUGf.js → runtime-BUPuX-Gq.js} +1 -1
- package/dist/preview/assets/{runtime-BovPWken.js → runtime-C4jFTZ4Z.js} +1 -1
- package/dist/preview/assets/{runtime-DA77AmOP.js → runtime-CA58Mif7.js} +1 -1
- package/dist/preview/assets/{runtime-BxBBFFHA.js → runtime-CWqQzWuc.js} +1 -1
- package/dist/preview/assets/{runtime-D-LBi56N.js → runtime-CjJBU_e1.js} +1 -1
- package/dist/preview/assets/{runtime-DHTqFEQI.js → runtime-DeUmGsM_.js} +1 -1
- package/dist/preview/assets/{runtime-CwmJ9MLQ.js → runtime-DnXoWy2A.js} +1 -1
- package/dist/preview/assets/{runtime-Cyjx6haa.js → runtime-wVZ1xP8L.js} +1 -1
- package/dist/preview/index.html +2 -2
- package/dist/runtime/components/block-layout-editor/index.vue +1 -4
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.d.vue.ts +2 -0
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/config.vue.d.ts +2 -0
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.d.vue.ts +2 -0
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/runtime.vue.d.ts +2 -0
- package/dist/runtime/components/config/blocks/2026-05-06/com.shwfed.block.table/schema.d.ts +2 -0
- package/dist/runtime/components/config/blocks/2026-05-17/com.shwfed.block.chart.xy/config.vue +5 -0
- package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/config.vue +2 -0
- package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/schema.d.ts +5 -0
- package/dist/runtime/components/config/blocks/2026-06-02/com.shwfed.block.card/schema.js +8 -3
- package/dist/runtime/components/form/config.vue +24 -16
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/runtime.vue +12 -1
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/schema.d.ts +8 -2
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.markdown/schema.js +3 -3
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.d.vue.ts +2 -2
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue +15 -25
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/config.vue.d.ts +2 -2
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/runtime.vue +11 -2
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/schema.d.ts +1 -1
- package/dist/runtime/components/form/fields/2026-04-22/com.shwfed.form.field.textarea/schema.js +4 -4
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.d.vue.ts +2 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/config.vue.d.ts +2 -0
- package/dist/runtime/components/form/fields/2026-05-18/com.shwfed.form.field.table/schema.d.ts +2 -0
- package/dist/runtime/components/form/index.vue +5 -1
- package/dist/runtime/components/form/schema.d.ts +1 -1
- package/dist/runtime/components/form/schema.js +6 -1
- package/dist/runtime/components/form/utils/form-vars.js +2 -0
- package/dist/runtime/components/form/utils/schema-meta.d.ts +2 -0
- package/dist/runtime/components/form/utils/schema-meta.js +24 -0
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-24/com.shwfed.table.column.combobox-single.remote.options-static/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-25/com.shwfed.table.column.combobox-multi.remote.options-static/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-multi.remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-26/com.shwfed.table.column.combobox-single.remote/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-multi/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.d.vue.ts +2 -2
- package/dist/runtime/components/table/columns/2026-05-28/com.shwfed.table.column.combobox-single/config.vue.d.ts +2 -2
- package/dist/runtime/components/table/config.vue +30 -36
- package/dist/runtime/components/table/index.d.vue.ts +2 -0
- package/dist/runtime/components/table/index.vue +8 -0
- package/dist/runtime/components/table/index.vue.d.ts +2 -0
- package/dist/runtime/components/table/schema.d.ts +4 -0
- package/dist/runtime/components/table/schema.js +4 -0
- package/dist/runtime/components/ui/expression-editor/ExpressionEditor.d.vue.ts +4 -3
- package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue +135 -111
- package/dist/runtime/components/ui/expression-editor/ExpressionEditor.vue.d.ts +4 -3
- package/dist/runtime/share/expression.d.ts +23 -0
- package/dist/runtime/share/expression.js +37 -17
- package/dist/runtime/share/use-persisted-query.d.ts +21 -0
- package/dist/runtime/share/use-persisted-query.js +33 -0
- package/dist/runtime/vendor/cel-js/CLAUDE.md +2 -2
- package/dist/runtime/vendor/cel-js/PROMPT.md +15 -6
- package/dist/runtime/vendor/cel-js/lib/macros.js +66 -14
- package/package.json +1 -1
- package/dist/preview/assets/index-CSfKAdi7.js +0 -1
|
@@ -914,6 +914,16 @@ function setPaginationEnabled(enabled) {
|
|
|
914
914
|
const { pagination: _drop, ...rest } = cur;
|
|
915
915
|
config.value = rest;
|
|
916
916
|
}
|
|
917
|
+
function setPersistQueryEnabled(enabled) {
|
|
918
|
+
if (enabled) {
|
|
919
|
+
writeGeneralPatch({ persistQuery: true });
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
const cur = config.value;
|
|
923
|
+
if (!cur || cur.persistQuery === void 0) return;
|
|
924
|
+
const { persistQuery: _drop, ...rest } = cur;
|
|
925
|
+
config.value = rest;
|
|
926
|
+
}
|
|
917
927
|
function setPageSize(value) {
|
|
918
928
|
const cur = readGeneral();
|
|
919
929
|
if (!cur.pagination) return;
|
|
@@ -1249,12 +1259,6 @@ const tableQueryValue = computed({
|
|
|
1249
1259
|
@update:model-value="(v) => updateGeneralOptionalString('rowKey', v)"
|
|
1250
1260
|
/>
|
|
1251
1261
|
</RowKeyCELContext>
|
|
1252
|
-
<p
|
|
1253
|
-
v-if="getError('rowKey')"
|
|
1254
|
-
class="text-xs text-red-500"
|
|
1255
|
-
>
|
|
1256
|
-
{{ getError("rowKey") }}
|
|
1257
|
-
</p>
|
|
1258
1262
|
</Field>
|
|
1259
1263
|
|
|
1260
1264
|
<!-- Host slot inside the general grid: a wrapping editor (e.g. the
|
|
@@ -1297,12 +1301,6 @@ const tableQueryValue = computed({
|
|
|
1297
1301
|
@update:model-value="(v) => updateDataSourceOptional('request', v)"
|
|
1298
1302
|
/>
|
|
1299
1303
|
</RequestCELContext>
|
|
1300
|
-
<p
|
|
1301
|
-
v-if="getError('dataSource.request')"
|
|
1302
|
-
class="text-xs text-red-500"
|
|
1303
|
-
>
|
|
1304
|
-
{{ getError("dataSource.request") }}
|
|
1305
|
-
</p>
|
|
1306
1304
|
</Field>
|
|
1307
1305
|
|
|
1308
1306
|
<div class="grid grid-cols-2 gap-x-6 gap-y-4">
|
|
@@ -1328,12 +1326,6 @@ const tableQueryValue = computed({
|
|
|
1328
1326
|
@update:model-value="(v) => setDataSourceField('data', v)"
|
|
1329
1327
|
/>
|
|
1330
1328
|
</JsonCELContext>
|
|
1331
|
-
<p
|
|
1332
|
-
v-if="getError('dataSource.data')"
|
|
1333
|
-
class="text-xs text-red-500"
|
|
1334
|
-
>
|
|
1335
|
-
{{ getError("dataSource.data") }}
|
|
1336
|
-
</p>
|
|
1337
1329
|
</Field>
|
|
1338
1330
|
<Field orientation="vertical">
|
|
1339
1331
|
<FieldLabel class="text-xs text-zinc-500">
|
|
@@ -1357,12 +1349,6 @@ const tableQueryValue = computed({
|
|
|
1357
1349
|
@update:model-value="(v) => updateDataSourceOptional('total', v)"
|
|
1358
1350
|
/>
|
|
1359
1351
|
</JsonCELContext>
|
|
1360
|
-
<p
|
|
1361
|
-
v-if="getError('dataSource.total')"
|
|
1362
|
-
class="text-xs text-red-500"
|
|
1363
|
-
>
|
|
1364
|
-
{{ getError("dataSource.total") }}
|
|
1365
|
-
</p>
|
|
1366
1352
|
</Field>
|
|
1367
1353
|
</div>
|
|
1368
1354
|
</div>
|
|
@@ -1486,6 +1472,26 @@ const tableQueryValue = computed({
|
|
|
1486
1472
|
|
|
1487
1473
|
<Separator />
|
|
1488
1474
|
|
|
1475
|
+
<div class="flex items-center gap-2">
|
|
1476
|
+
<h3 class="text-xs font-medium text-zinc-500">
|
|
1477
|
+
{{ generalFieldTitle("persistQuery") }}
|
|
1478
|
+
</h3>
|
|
1479
|
+
<Switch
|
|
1480
|
+
size="sm"
|
|
1481
|
+
:model-value="editingGeneralConfig.persistQuery === true"
|
|
1482
|
+
aria-label="搜索条件持久化"
|
|
1483
|
+
@update:model-value="setPersistQueryEnabled"
|
|
1484
|
+
/>
|
|
1485
|
+
</div>
|
|
1486
|
+
<p
|
|
1487
|
+
v-if="generalFieldDescription('persistQuery')"
|
|
1488
|
+
class="text-xs text-zinc-400"
|
|
1489
|
+
>
|
|
1490
|
+
{{ generalFieldDescription("persistQuery") }}
|
|
1491
|
+
</p>
|
|
1492
|
+
|
|
1493
|
+
<Separator />
|
|
1494
|
+
|
|
1489
1495
|
<h3 class="text-xs font-medium text-zinc-500">
|
|
1490
1496
|
样式
|
|
1491
1497
|
</h3>
|
|
@@ -1515,12 +1521,6 @@ const tableQueryValue = computed({
|
|
|
1515
1521
|
@update:model-value="(v) => updateGeneralOptionalString('cellStyle', v)"
|
|
1516
1522
|
/>
|
|
1517
1523
|
</CellStyleCELContext>
|
|
1518
|
-
<p
|
|
1519
|
-
v-if="getError('cellStyle')"
|
|
1520
|
-
class="text-xs text-red-500"
|
|
1521
|
-
>
|
|
1522
|
-
{{ getError("cellStyle") }}
|
|
1523
|
-
</p>
|
|
1524
1524
|
</Field>
|
|
1525
1525
|
|
|
1526
1526
|
<Field orientation="vertical">
|
|
@@ -1543,12 +1543,6 @@ const tableQueryValue = computed({
|
|
|
1543
1543
|
class="min-h-20 font-mono text-xs"
|
|
1544
1544
|
@update:model-value="(v) => updateGeneralOptionalString('style', String(v))"
|
|
1545
1545
|
/>
|
|
1546
|
-
<p
|
|
1547
|
-
v-if="getError('style')"
|
|
1548
|
-
class="text-xs text-red-500"
|
|
1549
|
-
>
|
|
1550
|
-
{{ getError("style") }}
|
|
1551
|
-
</p>
|
|
1552
1546
|
</Field>
|
|
1553
1547
|
</div>
|
|
1554
1548
|
</div>
|
|
@@ -31,6 +31,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
31
31
|
cellStyle?: string;
|
|
32
32
|
style?: string;
|
|
33
33
|
pagination?: import("effect/Schema").Schema.Type<typeof import("./schema.js").Pagination>;
|
|
34
|
+
persistQuery?: boolean;
|
|
34
35
|
initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
|
|
35
36
|
columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
|
|
36
37
|
columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
|
|
@@ -76,6 +77,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
76
77
|
cellStyle?: string;
|
|
77
78
|
style?: string;
|
|
78
79
|
pagination?: import("effect/Schema").Schema.Type<typeof import("./schema.js").Pagination>;
|
|
80
|
+
persistQuery?: boolean;
|
|
79
81
|
initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
|
|
80
82
|
columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
|
|
81
83
|
columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
|
|
@@ -30,6 +30,7 @@ import { evaluateInitial } from "../form/utils/initial";
|
|
|
30
30
|
import { provideTableInstanceId } from "./utils/instance";
|
|
31
31
|
import { provideSharedFetchLayer } from "./utils/shared-fetch";
|
|
32
32
|
import { provideEventTarget } from "../../share/event-bus";
|
|
33
|
+
import { usePersistedQuery } from "../../share/use-persisted-query";
|
|
33
34
|
import { findColumn } from "./utils/resolve";
|
|
34
35
|
import { interpolateMarkdown } from "./utils/runtime";
|
|
35
36
|
import { carrySymbolId, createRowKeyResolver } from "./utils/row-key";
|
|
@@ -42,6 +43,11 @@ const rowData = defineModel("rows", { type: Array, ...{ default: () => [] } });
|
|
|
42
43
|
const serverTotal = ref(void 0);
|
|
43
44
|
const isFetching = ref(false);
|
|
44
45
|
const queryState = ref({});
|
|
46
|
+
const persistedQuery = usePersistedQuery(
|
|
47
|
+
config.value?.id,
|
|
48
|
+
queryState,
|
|
49
|
+
() => config.value?.persistQuery === true
|
|
50
|
+
);
|
|
45
51
|
const { t, locale } = useI18n({
|
|
46
52
|
inheritLocale: true,
|
|
47
53
|
messages: {
|
|
@@ -379,6 +385,7 @@ async function fetchDataSource() {
|
|
|
379
385
|
}
|
|
380
386
|
}
|
|
381
387
|
async function resetQuery() {
|
|
388
|
+
persistedQuery.clear();
|
|
382
389
|
const initial = config.value?.query?.initial;
|
|
383
390
|
if (!initial) {
|
|
384
391
|
queryState.value = {};
|
|
@@ -435,6 +442,7 @@ provideEventTarget(tableInstanceId, {
|
|
|
435
442
|
const queryRef = ref(null);
|
|
436
443
|
onMounted(async () => {
|
|
437
444
|
await queryRef.value?.seeded;
|
|
445
|
+
persistedQuery.restore();
|
|
438
446
|
await fetchDataSource();
|
|
439
447
|
});
|
|
440
448
|
watch(
|
|
@@ -31,6 +31,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
31
31
|
cellStyle?: string;
|
|
32
32
|
style?: string;
|
|
33
33
|
pagination?: import("effect/Schema").Schema.Type<typeof import("./schema.js").Pagination>;
|
|
34
|
+
persistQuery?: boolean;
|
|
34
35
|
initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
|
|
35
36
|
columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
|
|
36
37
|
columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
|
|
@@ -76,6 +77,7 @@ declare const __VLS_export: import("vue").DefineComponent<{
|
|
|
76
77
|
cellStyle?: string;
|
|
77
78
|
style?: string;
|
|
78
79
|
pagination?: import("effect/Schema").Schema.Type<typeof import("./schema.js").Pagination>;
|
|
80
|
+
persistQuery?: boolean;
|
|
79
81
|
initialState?: import("effect/Schema").Schema.Type<import("effect/Schema").Struct<{
|
|
80
82
|
columnVisibility: import("effect/Schema").optional<import("effect/Schema").Record$<typeof import("effect/Schema").String, typeof import("effect/Schema").Boolean>>;
|
|
81
83
|
columnOrder: import("effect/Schema").optional<import("effect/Schema").Array$<typeof import("effect/Schema").String>>;
|
|
@@ -255,6 +255,7 @@ export declare function TableConfig(configure: (env: Environment) => void): Sche
|
|
|
255
255
|
readonly pageSizes?: readonly number[] | undefined;
|
|
256
256
|
readonly pageIndex?: number | undefined;
|
|
257
257
|
} | undefined;
|
|
258
|
+
readonly persistQuery?: boolean | undefined;
|
|
258
259
|
readonly initialState?: {
|
|
259
260
|
readonly expanded?: boolean | {
|
|
260
261
|
readonly [x: string]: boolean;
|
|
@@ -536,6 +537,7 @@ export declare function TableConfig(configure: (env: Environment) => void): Sche
|
|
|
536
537
|
message: Schema.SchemaClass<string, string, never>;
|
|
537
538
|
}>]>>;
|
|
538
539
|
}>>;
|
|
540
|
+
persistQuery: Schema.optional<Schema.SchemaClass<boolean, boolean, never>>;
|
|
539
541
|
initialState: Schema.optional<Schema.Struct<{
|
|
540
542
|
columnVisibility: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Boolean>>;
|
|
541
543
|
columnOrder: Schema.optional<Schema.Array$<typeof Schema.String>>;
|
|
@@ -703,6 +705,7 @@ export declare function createTableConfig(body: Omit<Schema.Schema.Type<ReturnTy
|
|
|
703
705
|
readonly pageSizes?: readonly number[] | undefined;
|
|
704
706
|
readonly pageIndex?: number | undefined;
|
|
705
707
|
} | undefined;
|
|
708
|
+
persistQuery?: boolean | undefined;
|
|
706
709
|
initialState?: {
|
|
707
710
|
readonly expanded?: boolean | {
|
|
708
711
|
readonly [x: string]: boolean;
|
|
@@ -761,6 +764,7 @@ export type TableConfigValue = Readonly<{
|
|
|
761
764
|
cellStyle?: string;
|
|
762
765
|
style?: string;
|
|
763
766
|
pagination?: Schema.Schema.Type<typeof Pagination>;
|
|
767
|
+
persistQuery?: boolean;
|
|
764
768
|
initialState?: Schema.Schema.Type<typeof InitialState>;
|
|
765
769
|
}>;
|
|
766
770
|
export type PaginationValue = Schema.Schema.Type<typeof Pagination>;
|
|
@@ -328,6 +328,10 @@ export function TableConfig(configure) {
|
|
|
328
328
|
pagination: Schema.optional(Pagination).annotations({
|
|
329
329
|
title: "\u5206\u9875"
|
|
330
330
|
}),
|
|
331
|
+
persistQuery: Schema.optional(Schema.Boolean.annotations({
|
|
332
|
+
title: "\u641C\u7D22\u6761\u4EF6\u6301\u4E45\u5316",
|
|
333
|
+
description: "\u5F00\u542F\u540E\uFF0C\u641C\u7D22\u6761\u4EF6\u8868\u5355\u7684\u5F53\u524D\u503C\u4F1A\u5199\u5165\u6D4F\u89C8\u5668\u4F1A\u8BDD\u5B58\u50A8\uFF08sessionStorage\uFF09\uFF0C\u5237\u65B0\u9875\u9762\u540E\u81EA\u52A8\u6062\u590D\uFF0C\u76F4\u5230\u5173\u95ED\u6807\u7B7E\u9875\u6216\u79BB\u5F00\u7AD9\u70B9\u3002\u9700\u8981\u8868\u683C\u5DF2\u914D\u7F6E ID\u3002"
|
|
334
|
+
})),
|
|
331
335
|
initialState: Schema.optional(InitialState)
|
|
332
336
|
}).pipe(Schema.filter((cfg) => {
|
|
333
337
|
if (cfg.dataSource?.total !== void 0 && cfg.pagination === void 0) {
|
|
@@ -12,12 +12,13 @@ type __VLS_Props = {
|
|
|
12
12
|
placeholder?: string;
|
|
13
13
|
resultType?: string | string[];
|
|
14
14
|
extraVars?: Record<string, VarSpec>;
|
|
15
|
+
unlistedVarsAreDyn?: boolean;
|
|
15
16
|
};
|
|
16
|
-
declare var
|
|
17
|
+
declare var __VLS_13: {}, __VLS_129: {};
|
|
17
18
|
type __VLS_Slots = {} & {
|
|
18
|
-
leading?: (props: typeof
|
|
19
|
+
leading?: (props: typeof __VLS_13) => any;
|
|
19
20
|
} & {
|
|
20
|
-
trailing?: (props: typeof
|
|
21
|
+
trailing?: (props: typeof __VLS_129) => any;
|
|
21
22
|
};
|
|
22
23
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
23
24
|
"update:modelValue": (payload: string) => any;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { Icon } from "@iconify/vue";
|
|
3
3
|
import { computed, ref, useSlots, useTemplateRef, watch } from "vue";
|
|
4
|
+
import { buildCheckEnvironment, evaluateExpression } from "../../../share/expression";
|
|
4
5
|
import { injectCELContext, useScopeAncestry } from "../../../utils/cel-context";
|
|
5
6
|
import { Markdown } from "../markdown";
|
|
6
7
|
import CodeMirrorInput from "./CodeMirrorInput.vue";
|
|
@@ -17,7 +18,8 @@ const props = defineProps({
|
|
|
17
18
|
multiline: { type: Boolean, required: false },
|
|
18
19
|
placeholder: { type: String, required: false },
|
|
19
20
|
resultType: { type: [String, Array], required: false },
|
|
20
|
-
extraVars: { type: Object, required: false }
|
|
21
|
+
extraVars: { type: Object, required: false },
|
|
22
|
+
unlistedVarsAreDyn: { type: Boolean, required: false }
|
|
21
23
|
});
|
|
22
24
|
const emits = defineEmits(["update:modelValue"]);
|
|
23
25
|
const celContext = injectCELContext();
|
|
@@ -26,6 +28,20 @@ const varEntries = computed(() => buildVarEntries(celContext, props.extraVars));
|
|
|
26
28
|
const scopeEntries = computed(() => buildScopeEntries(scopeAncestry.value.slice(1)));
|
|
27
29
|
const scopeLookup = computed(() => buildScopeLookup(scopeAncestry.value));
|
|
28
30
|
const hasVars = computed(() => varEntries.value.length > 0 || scopeEntries.value.length > 0);
|
|
31
|
+
const checkEnvironment = computed(() => {
|
|
32
|
+
const vars = /* @__PURE__ */ new Map();
|
|
33
|
+
for (const [name, entry] of Object.entries(celContext)) vars.set(name, entry.type);
|
|
34
|
+
for (const [name, spec] of Object.entries(props.extraVars ?? {})) vars.set(name, spec.type);
|
|
35
|
+
return buildCheckEnvironment(
|
|
36
|
+
[...vars].map(([name, type]) => ({ name, type })),
|
|
37
|
+
{ unlistedVariablesAreDyn: props.unlistedVarsAreDyn }
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
const validationError = computed(() => {
|
|
41
|
+
const value = props.modelValue ?? props.defaultValue ?? "";
|
|
42
|
+
if (value.trim() === "") return null;
|
|
43
|
+
return evaluateExpression(checkEnvironment.value, value, props.resultType);
|
|
44
|
+
});
|
|
29
45
|
const open = ref(false);
|
|
30
46
|
const entries = ref([]);
|
|
31
47
|
const shownVars = computed(() => entries.value.filter((e) => e.group === "var"));
|
|
@@ -60,120 +76,128 @@ const addonAlign = computed(
|
|
|
60
76
|
</script>
|
|
61
77
|
|
|
62
78
|
<template>
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
<slot name="leading" />
|
|
69
|
-
</InputGroupAddon>
|
|
70
|
-
<CodeMirrorInput
|
|
71
|
-
ref="editor"
|
|
72
|
-
:model-value="props.modelValue"
|
|
73
|
-
:default-value="props.defaultValue"
|
|
74
|
-
:placeholder="props.placeholder"
|
|
75
|
-
:multiline="props.multiline"
|
|
76
|
-
:scope-lookup="scopeLookup"
|
|
77
|
-
:class="props.class"
|
|
78
|
-
@update:model-value="(v) => emits('update:modelValue', v)"
|
|
79
|
-
/>
|
|
80
|
-
<InputGroupAddon
|
|
81
|
-
v-if="showAddon"
|
|
82
|
-
:align="addonAlign"
|
|
83
|
-
class="justify-end gap-1.5"
|
|
84
|
-
>
|
|
85
|
-
<Popover
|
|
86
|
-
v-if="hasVars"
|
|
87
|
-
v-model:open="open"
|
|
79
|
+
<div class="flex flex-col gap-1.5">
|
|
80
|
+
<InputGroup>
|
|
81
|
+
<InputGroupAddon
|
|
82
|
+
v-if="$slots.leading"
|
|
83
|
+
align="inline-start"
|
|
88
84
|
>
|
|
89
|
-
<
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
<slot name="leading" />
|
|
86
|
+
</InputGroupAddon>
|
|
87
|
+
<CodeMirrorInput
|
|
88
|
+
ref="editor"
|
|
89
|
+
:model-value="props.modelValue"
|
|
90
|
+
:default-value="props.defaultValue"
|
|
91
|
+
:placeholder="props.placeholder"
|
|
92
|
+
:multiline="props.multiline"
|
|
93
|
+
:scope-lookup="scopeLookup"
|
|
94
|
+
:class="props.class"
|
|
95
|
+
@update:model-value="(v) => emits('update:modelValue', v)"
|
|
96
|
+
/>
|
|
97
|
+
<InputGroupAddon
|
|
98
|
+
v-if="showAddon"
|
|
99
|
+
:align="addonAlign"
|
|
100
|
+
class="justify-end gap-1.5"
|
|
101
|
+
>
|
|
102
|
+
<Popover
|
|
103
|
+
v-if="hasVars"
|
|
104
|
+
v-model:open="open"
|
|
101
105
|
>
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
106
|
+
<PopoverTrigger as-child>
|
|
107
|
+
<InputGroupButton
|
|
108
|
+
size="icon-xs"
|
|
109
|
+
aria-label="Inspect available variables"
|
|
110
|
+
>
|
|
111
|
+
<Icon icon="fluent:braces-variable-20-regular" />
|
|
112
|
+
</InputGroupButton>
|
|
113
|
+
</PopoverTrigger>
|
|
114
|
+
<PopoverContent
|
|
115
|
+
align="end"
|
|
116
|
+
:side-offset="6"
|
|
117
|
+
class="group/popover w-80 p-0 data-[side=top]:**:data-[slot=command-input-wrapper]:border-t data-[side=top]:**:data-[slot=command-input-wrapper]:border-b-0"
|
|
118
|
+
>
|
|
119
|
+
<Command class="rounded group-data-[side=top]/popover:flex-col-reverse">
|
|
120
|
+
<CommandInput placeholder="搜索可用变量" />
|
|
121
|
+
<CommandList class="max-h-48 overflow-y-auto">
|
|
122
|
+
<CommandEmpty>No variables.</CommandEmpty>
|
|
123
|
+
<CommandGroup>
|
|
124
|
+
<CommandItem
|
|
125
|
+
v-for="entry in shownVars"
|
|
126
|
+
:key="entry.id"
|
|
127
|
+
:value="entry.display"
|
|
128
|
+
class="cursor-pointer gap-2"
|
|
129
|
+
@select="insertVariable(entry.insert)"
|
|
130
|
+
@mouseenter="hoveredName = entry.id"
|
|
131
|
+
@focus="hoveredName = entry.id"
|
|
132
|
+
>
|
|
133
|
+
<Icon
|
|
134
|
+
icon="fluent:braces-variable-20-regular"
|
|
135
|
+
class="size-3.5 shrink-0 text-zinc-400"
|
|
136
|
+
/>
|
|
137
|
+
<span class="font-mono text-xs text-zinc-800">{{ entry.display }}</span>
|
|
138
|
+
<span class="flex-1 truncate text-xs text-zinc-500">{{ entry.label }}</span>
|
|
139
|
+
<span class="rounded bg-purple-100 px-1.5 py-0.5 font-mono text-[10px] leading-none text-purple-700 select-none">
|
|
140
|
+
{{ entry.type }}
|
|
141
|
+
</span>
|
|
142
|
+
</CommandItem>
|
|
143
|
+
</CommandGroup>
|
|
144
|
+
<CommandGroup
|
|
145
|
+
v-if="shownScopes.length > 0"
|
|
146
|
+
heading="跨层引用"
|
|
115
147
|
>
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
148
|
+
<CommandItem
|
|
149
|
+
v-for="entry in shownScopes"
|
|
150
|
+
:key="entry.id"
|
|
151
|
+
:value="`${entry.display} ${entry.id}`"
|
|
152
|
+
class="cursor-pointer gap-2"
|
|
153
|
+
@select="insertVariable(entry.insert)"
|
|
154
|
+
@mouseenter="hoveredName = entry.id"
|
|
155
|
+
@focus="hoveredName = entry.id"
|
|
156
|
+
>
|
|
157
|
+
<Icon
|
|
158
|
+
icon="fluent:link-20-regular"
|
|
159
|
+
class="size-3.5 shrink-0 text-zinc-400"
|
|
160
|
+
/>
|
|
161
|
+
<span class="flex-1 truncate text-xs text-zinc-700">{{ entry.display }}</span>
|
|
162
|
+
<span class="rounded bg-purple-100 px-1.5 py-0.5 font-mono text-[10px] leading-none text-purple-700 select-none">
|
|
163
|
+
{{ entry.type }}
|
|
164
|
+
</span>
|
|
165
|
+
</CommandItem>
|
|
166
|
+
</CommandGroup>
|
|
167
|
+
</CommandList>
|
|
168
|
+
<div
|
|
169
|
+
v-if="hoveredEntry"
|
|
170
|
+
class="border-t border-zinc-200 px-3 py-2 group-data-[side=top]/popover:border-t-0 group-data-[side=top]/popover:border-b"
|
|
130
171
|
>
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
class="cursor-pointer gap-2"
|
|
136
|
-
@select="insertVariable(entry.insert)"
|
|
137
|
-
@mouseenter="hoveredName = entry.id"
|
|
138
|
-
@focus="hoveredName = entry.id"
|
|
139
|
-
>
|
|
140
|
-
<Icon
|
|
141
|
-
icon="fluent:link-20-regular"
|
|
142
|
-
class="size-3.5 shrink-0 text-zinc-400"
|
|
143
|
-
/>
|
|
144
|
-
<span class="flex-1 truncate text-xs text-zinc-700">{{ entry.display }}</span>
|
|
145
|
-
<span class="rounded bg-purple-100 px-1.5 py-0.5 font-mono text-[10px] leading-none text-purple-700 select-none">
|
|
146
|
-
{{ entry.type }}
|
|
172
|
+
<div class="flex items-center gap-2">
|
|
173
|
+
<span class="text-xs font-medium text-zinc-700">{{ hoveredEntry.label }}</span>
|
|
174
|
+
<span class="ml-auto shrink-0 rounded bg-purple-100 px-1.5 py-0.5 font-mono text-[10px] leading-none text-purple-700 select-none">
|
|
175
|
+
{{ hoveredEntry.type }}
|
|
147
176
|
</span>
|
|
148
|
-
</
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
>
|
|
155
|
-
<div class="flex items-center gap-2">
|
|
156
|
-
<span class="text-xs font-medium text-zinc-700">{{ hoveredEntry.label }}</span>
|
|
157
|
-
<span class="ml-auto shrink-0 rounded bg-purple-100 px-1.5 py-0.5 font-mono text-[10px] leading-none text-purple-700 select-none">
|
|
158
|
-
{{ hoveredEntry.type }}
|
|
159
|
-
</span>
|
|
177
|
+
</div>
|
|
178
|
+
<Markdown
|
|
179
|
+
v-if="hoveredDescription"
|
|
180
|
+
:source="hoveredDescription"
|
|
181
|
+
class="prose prose-zinc prose-sm mt-1 text-xs"
|
|
182
|
+
/>
|
|
160
183
|
</div>
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
184
|
+
</Command>
|
|
185
|
+
</PopoverContent>
|
|
186
|
+
</Popover>
|
|
187
|
+
<span
|
|
188
|
+
v-if="resultTypeLabel"
|
|
189
|
+
class="rounded bg-purple-100 px-1.5 py-0.5 font-mono text-[10px] leading-none text-purple-700 select-none"
|
|
190
|
+
>
|
|
191
|
+
{{ resultTypeLabel }}
|
|
192
|
+
</span>
|
|
193
|
+
<slot name="trailing" />
|
|
194
|
+
</InputGroupAddon>
|
|
195
|
+
</InputGroup>
|
|
196
|
+
<p
|
|
197
|
+
v-if="validationError"
|
|
198
|
+
class="text-xs text-red-500"
|
|
199
|
+
>
|
|
200
|
+
{{ validationError }}
|
|
201
|
+
</p>
|
|
202
|
+
</div>
|
|
179
203
|
</template>
|
|
@@ -12,12 +12,13 @@ type __VLS_Props = {
|
|
|
12
12
|
placeholder?: string;
|
|
13
13
|
resultType?: string | string[];
|
|
14
14
|
extraVars?: Record<string, VarSpec>;
|
|
15
|
+
unlistedVarsAreDyn?: boolean;
|
|
15
16
|
};
|
|
16
|
-
declare var
|
|
17
|
+
declare var __VLS_13: {}, __VLS_129: {};
|
|
17
18
|
type __VLS_Slots = {} & {
|
|
18
|
-
leading?: (props: typeof
|
|
19
|
+
leading?: (props: typeof __VLS_13) => any;
|
|
19
20
|
} & {
|
|
20
|
-
trailing?: (props: typeof
|
|
21
|
+
trailing?: (props: typeof __VLS_129) => any;
|
|
21
22
|
};
|
|
22
23
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
23
24
|
"update:modelValue": (payload: string) => any;
|
|
@@ -15,6 +15,29 @@ export type ResultType = string | string[] | ((type: string) => boolean);
|
|
|
15
15
|
* type-checker infers as `optional<HttpRequest>`.
|
|
16
16
|
*/
|
|
17
17
|
export declare const HttpRequestResult: ResultType;
|
|
18
|
+
/**
|
|
19
|
+
* Type-check `expression` against `env` and, if `resultType` is given, verify the
|
|
20
|
+
* inferred type satisfies it. Returns a Chinese error message, or `null` when the
|
|
21
|
+
* expression is valid. This is the single chokepoint both the schema validator
|
|
22
|
+
* (`Expression`'s filter) and the live `ExpressionEditor` call, so an inline
|
|
23
|
+
* verdict can never disagree with the save-time decode.
|
|
24
|
+
*/
|
|
25
|
+
export declare function evaluateExpression(env: Environment, expression: string, resultType?: ResultType): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Build a checking `Environment` from a flat list of `{ name, type }` variable
|
|
28
|
+
* specs — the projection an `ExpressionEditor` already holds via its injected CEL
|
|
29
|
+
* context plus `extraVars`. Functions/operators come free from the cloned
|
|
30
|
+
* `globalRegistry`; only variables are host-scoped, so this is all the editor
|
|
31
|
+
* needs to reproduce the schema's validation env. `__scopes__` is registered
|
|
32
|
+
* canonically here (and skipped from `vars`) exactly as `Expression` does, so
|
|
33
|
+
* cross-layer addressing type-checks in the editor too.
|
|
34
|
+
*/
|
|
35
|
+
export declare function buildCheckEnvironment(vars: Iterable<{
|
|
36
|
+
name: string;
|
|
37
|
+
type: string;
|
|
38
|
+
}>, options?: {
|
|
39
|
+
unlistedVariablesAreDyn?: boolean;
|
|
40
|
+
}): Environment;
|
|
18
41
|
export declare function Expression(options: {
|
|
19
42
|
configure: (env: Environment) => void;
|
|
20
43
|
resultType?: ResultType;
|
|
@@ -3,9 +3,17 @@ import { Environment } from "../vendor/cel-js/lib/index.js";
|
|
|
3
3
|
import { CelError } from "../vendor/cel-js/lib/errors.js";
|
|
4
4
|
import { Locale } from "./locale.js";
|
|
5
5
|
export const HttpRequestResult = (t) => t === "HttpRequest" || t === "optional<HttpRequest>" || t === "optional<dyn>" || t === "dyn";
|
|
6
|
+
function matchesScalarType(actual, expected) {
|
|
7
|
+
if (expected === "dyn" || actual === "dyn") return true;
|
|
8
|
+
if (actual === expected) return true;
|
|
9
|
+
if (actual.startsWith(`${expected}<`)) return true;
|
|
10
|
+
if (actual === `optional<${expected}>` || actual === "optional<dyn>") return true;
|
|
11
|
+
if (actual.startsWith(`optional<${expected}<`)) return true;
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
6
14
|
function matchesResultType(actual, expected) {
|
|
7
|
-
if (typeof expected === "string") return
|
|
8
|
-
if (Array.isArray(expected)) return expected.
|
|
15
|
+
if (typeof expected === "string") return matchesScalarType(actual, expected);
|
|
16
|
+
if (Array.isArray(expected)) return expected.some((e) => matchesScalarType(actual, e));
|
|
9
17
|
return expected(actual);
|
|
10
18
|
}
|
|
11
19
|
function formatExpectedType(expected) {
|
|
@@ -19,6 +27,32 @@ function registerScopeAddressVar(env) {
|
|
|
19
27
|
description: "\u6309 UUID \u5BFB\u5740\u88AB\u906E\u853D\u7684\u7956\u5148\u4F5C\u7528\u57DF"
|
|
20
28
|
});
|
|
21
29
|
}
|
|
30
|
+
export function evaluateExpression(env, expression, resultType) {
|
|
31
|
+
const result = env.check(expression);
|
|
32
|
+
if (Either.isLeft(result)) {
|
|
33
|
+
const error = result.left;
|
|
34
|
+
const summary = error instanceof CelError ? error.summary : String(error);
|
|
35
|
+
return `\u8868\u8FBE\u5F0F\u65E0\u6548\uFF1A${summary}`;
|
|
36
|
+
}
|
|
37
|
+
if (resultType) {
|
|
38
|
+
const actualType = result.right;
|
|
39
|
+
if (!matchesResultType(actualType, resultType)) {
|
|
40
|
+
return `\u8868\u8FBE\u5F0F\u8FD4\u56DE\u7C7B\u578B\u4E0D\u5339\u914D\uFF0C\u671F\u671B ${formatExpectedType(resultType)}\uFF0C\u5B9E\u9645\u4E3A ${actualType}`;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
export function buildCheckEnvironment(vars, options) {
|
|
46
|
+
const env = new Environment({
|
|
47
|
+
unlistedVariablesAreDyn: options?.unlistedVariablesAreDyn ?? false
|
|
48
|
+
});
|
|
49
|
+
registerScopeAddressVar(env);
|
|
50
|
+
for (const { name, type } of vars) {
|
|
51
|
+
if (name === "__scopes__") continue;
|
|
52
|
+
env.registerVariable(name, type);
|
|
53
|
+
}
|
|
54
|
+
return env;
|
|
55
|
+
}
|
|
22
56
|
function buildDescription(baseline, env, resultType) {
|
|
23
57
|
const defs = env.getDefinitions();
|
|
24
58
|
const baselineVarNames = new Set(baseline.variables.map((v) => v.name));
|
|
@@ -52,21 +86,7 @@ export function Expression(options) {
|
|
|
52
86
|
const description = buildDescription(baseline, env, options.resultType);
|
|
53
87
|
return Schema.String.pipe(
|
|
54
88
|
Schema.filter(
|
|
55
|
-
(expression) =>
|
|
56
|
-
const result = env.check(expression);
|
|
57
|
-
if (Either.isLeft(result)) {
|
|
58
|
-
const error = result.left;
|
|
59
|
-
const summary = error instanceof CelError ? error.summary : String(error);
|
|
60
|
-
return `\u8868\u8FBE\u5F0F\u65E0\u6548\uFF1A${summary}`;
|
|
61
|
-
}
|
|
62
|
-
if (options.resultType) {
|
|
63
|
-
const actualType = result.right;
|
|
64
|
-
if (!matchesResultType(actualType, options.resultType)) {
|
|
65
|
-
return `\u8868\u8FBE\u5F0F\u8FD4\u56DE\u7C7B\u578B\u4E0D\u5339\u914D\uFF0C\u671F\u671B ${formatExpectedType(options.resultType)}\uFF0C\u5B9E\u9645\u4E3A ${actualType}`;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
return true;
|
|
69
|
-
},
|
|
89
|
+
(expression) => evaluateExpression(env, expression, options.resultType) ?? true,
|
|
70
90
|
{
|
|
71
91
|
title: "CEL Expression",
|
|
72
92
|
description
|