@arronqzy/vue-blueprint 0.1.16 → 0.1.17
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/package.json +6 -6
- package/src/BlueprintNodeConfigSidebar.vue +12 -8
- package/src/components/ApiCollectionManagerDialog.vue +4 -5
- package/src/components/BluePrintVueRoot.vue +3 -0
- package/src/components/ClockNodeConfigPanel.vue +5 -3
- package/src/components/ConfigHintIcon.vue +15 -2
- package/src/components/FetchNodeConfigPanel.vue +23 -19
- package/src/components/LogicNodeConfigPanel.vue +5 -4
- package/src/composables/useBlueprintDslLocaleSync.ts +12 -0
- package/src/graph/document.ts +12 -5
- package/src/index.ts +1 -0
- package/src/nodes/BlueprintNodeCard.vue +8 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arronqzy/vue-blueprint",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Vue 3 blueprint editor for Abuilder (Vue Flow + Ant Design Vue)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"ant-design-vue": "^4.2.6",
|
|
20
20
|
"dayjs": "^1.11.13",
|
|
21
21
|
"vue": "^3.5.13",
|
|
22
|
-
"@arronqzy/blueprint-dsl": "1.0.
|
|
23
|
-
"@arronqzy/
|
|
24
|
-
"@arronqzy/
|
|
22
|
+
"@arronqzy/blueprint-dsl": "1.0.17",
|
|
23
|
+
"@arronqzy/i18n": "0.1.17",
|
|
24
|
+
"@arronqzy/vue-rx-store": "0.1.6"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"vue": "^3.4.0"
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"eslint": "^8.57.0",
|
|
32
32
|
"typescript": "^5.5.4",
|
|
33
33
|
"vue-tsc": "^2.2.0",
|
|
34
|
-
"@arronqzy/
|
|
35
|
-
"@arronqzy/
|
|
34
|
+
"@arronqzy/typescript-config": "1.0.0",
|
|
35
|
+
"@arronqzy/eslint-config": "0.0.0"
|
|
36
36
|
},
|
|
37
37
|
"publishConfig": {
|
|
38
38
|
"access": "public"
|
|
@@ -281,15 +281,17 @@ function toggleEventType(eventType: ViewEventType, checked: boolean) {
|
|
|
281
281
|
<p v-if="!node.libraryBlueprintId" class="text-[11px] text-muted-foreground">
|
|
282
282
|
{{ t("blueprint.config.selectLibraryFirst") }}
|
|
283
283
|
</p>
|
|
284
|
-
<label class="flex items-
|
|
284
|
+
<label class="flex items-center gap-2 pt-1">
|
|
285
285
|
<Checkbox
|
|
286
286
|
:checked="allowFalseSignalPropagation"
|
|
287
|
-
class="mt-0.5"
|
|
288
287
|
@update:checked="(v) => onUpdateAllowFalseSignalPropagation?.(Boolean(v))"
|
|
289
288
|
/>
|
|
290
|
-
<span class="text-[11px]
|
|
291
|
-
{{ t("blueprint.config.
|
|
289
|
+
<span class="text-[11px] text-muted-foreground">
|
|
290
|
+
{{ t("blueprint.config.allowFalsePropagate") }}
|
|
292
291
|
</span>
|
|
292
|
+
<ConfigHintIcon :label="t('blueprint.config.allowFalsePropagate')">
|
|
293
|
+
{{ t("blueprint.config.allowFalsePropagateBlueprint") }}
|
|
294
|
+
</ConfigHintIcon>
|
|
293
295
|
</label>
|
|
294
296
|
</div>
|
|
295
297
|
|
|
@@ -426,15 +428,17 @@ function toggleEventType(eventType: ViewEventType, checked: boolean) {
|
|
|
426
428
|
class="space-y-2 rounded-md border border-border/70 bg-muted/20 p-2.5"
|
|
427
429
|
>
|
|
428
430
|
<div class="font-medium text-foreground">{{ t("blueprint.config.taskChain") }}</div>
|
|
429
|
-
<label class="flex items-
|
|
431
|
+
<label class="flex items-center gap-2">
|
|
430
432
|
<Checkbox
|
|
431
433
|
:checked="allowFalseSignalPropagation"
|
|
432
|
-
class="mt-0.5"
|
|
433
434
|
@update:checked="(v) => onUpdateAllowFalseSignalPropagation?.(Boolean(v))"
|
|
434
435
|
/>
|
|
435
|
-
<span class="text-[11px]
|
|
436
|
-
{{ t("blueprint.config.
|
|
436
|
+
<span class="text-[11px] text-muted-foreground">
|
|
437
|
+
{{ t("blueprint.config.allowFalsePropagate") }}
|
|
437
438
|
</span>
|
|
439
|
+
<ConfigHintIcon :label="t('blueprint.config.allowFalsePropagate')">
|
|
440
|
+
{{ t("blueprint.config.allowFalsePropagateDefault") }}
|
|
441
|
+
</ConfigHintIcon>
|
|
438
442
|
</label>
|
|
439
443
|
</div>
|
|
440
444
|
</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, ref, watch } from "vue";
|
|
3
|
+
import ConfigHintIcon from "./ConfigHintIcon.vue";
|
|
3
4
|
import { useI18n } from "@arronqzy/i18n/vue";
|
|
4
5
|
import { Button, Checkbox, Input, Modal } from "ant-design-vue";
|
|
5
6
|
import {
|
|
@@ -263,6 +264,9 @@ async function handleFiles(files: FileList | null) {
|
|
|
263
264
|
<label class="ml-auto flex cursor-pointer items-center gap-2 text-[11px] text-muted-foreground">
|
|
264
265
|
<Checkbox v-model:checked="persistLocalDefault" />
|
|
265
266
|
{{ t("blueprint.apiCollection.persistLocal") }}
|
|
267
|
+
<ConfigHintIcon :label="t('blueprint.apiCollection.persistLocal')">
|
|
268
|
+
{{ t("blueprint.apiCollection.persistLocalHint") }}
|
|
269
|
+
</ConfigHintIcon>
|
|
266
270
|
</label>
|
|
267
271
|
<input
|
|
268
272
|
ref="fileInputRef"
|
|
@@ -273,11 +277,6 @@ async function handleFiles(files: FileList | null) {
|
|
|
273
277
|
@change="(e) => void handleFiles((e.target as HTMLInputElement).files)"
|
|
274
278
|
/>
|
|
275
279
|
</div>
|
|
276
|
-
|
|
277
|
-
<p class="mb-2 text-[11px] text-muted-foreground">
|
|
278
|
-
{{ t("blueprint.apiCollection.persistLocalHint") }}
|
|
279
|
-
</p>
|
|
280
|
-
|
|
281
280
|
<pre
|
|
282
281
|
v-if="error"
|
|
283
282
|
class="mb-2 max-h-24 overflow-auto whitespace-pre-wrap rounded border border-destructive/40 bg-destructive/5 p-2 text-[11px] text-destructive"
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
import type { BlueprintGraph } from "../graph/blueprint-graph";
|
|
3
3
|
import type { BlueprintExecutionOverlay } from "../runtime/execution-overlay";
|
|
4
4
|
import BlueprintCanvas from "./BlueprintCanvas.vue";
|
|
5
|
+
import { useBlueprintDslLocaleSync } from "../composables/useBlueprintDslLocaleSync";
|
|
6
|
+
|
|
7
|
+
useBlueprintDslLocaleSync();
|
|
5
8
|
|
|
6
9
|
const props = withDefaults(
|
|
7
10
|
defineProps<{
|
|
@@ -102,15 +102,17 @@ function handleEmitImmediatelyChange(checked: boolean) {
|
|
|
102
102
|
/>
|
|
103
103
|
</label>
|
|
104
104
|
|
|
105
|
-
<label class="flex items-
|
|
105
|
+
<label class="flex items-center gap-2">
|
|
106
106
|
<Checkbox
|
|
107
107
|
:checked="clockConfig.emitImmediately"
|
|
108
|
-
class="mt-0.5"
|
|
109
108
|
@update:checked="handleEmitImmediatelyChange"
|
|
110
109
|
/>
|
|
111
|
-
<span class="text-[11px]
|
|
110
|
+
<span class="text-[11px] text-muted-foreground">
|
|
112
111
|
{{ t("blueprint.config.emitImmediately") }}
|
|
113
112
|
</span>
|
|
113
|
+
<ConfigHintIcon :label="t('blueprint.config.emitImmediately')">
|
|
114
|
+
{{ t("blueprint.config.emitImmediatelyHint") }}
|
|
115
|
+
</ConfigHintIcon>
|
|
114
116
|
</label>
|
|
115
117
|
|
|
116
118
|
<label class="block space-y-1">
|
|
@@ -28,11 +28,24 @@ const resolvedLabel = computed(() => props.label || t("common.hint"));
|
|
|
28
28
|
type="button"
|
|
29
29
|
:class="
|
|
30
30
|
buttonClass ??
|
|
31
|
-
'inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
31
|
+
'inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring'
|
|
32
32
|
"
|
|
33
33
|
:aria-label="t('common.hintAria', { label: resolvedLabel })"
|
|
34
34
|
>
|
|
35
|
-
|
|
35
|
+
<svg
|
|
36
|
+
viewBox="0 0 24 24"
|
|
37
|
+
fill="none"
|
|
38
|
+
stroke="currentColor"
|
|
39
|
+
stroke-width="2"
|
|
40
|
+
stroke-linecap="round"
|
|
41
|
+
stroke-linejoin="round"
|
|
42
|
+
class="h-3.5 w-3.5"
|
|
43
|
+
aria-hidden="true"
|
|
44
|
+
>
|
|
45
|
+
<circle cx="12" cy="12" r="10" />
|
|
46
|
+
<path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
|
|
47
|
+
<path d="M12 17h.01" />
|
|
48
|
+
</svg>
|
|
36
49
|
</button>
|
|
37
50
|
</Tooltip>
|
|
38
51
|
</template>
|
|
@@ -45,7 +45,7 @@ import ConfigHintIcon from "./ConfigHintIcon.vue";
|
|
|
45
45
|
import FetchUrlAutocomplete from "./FetchUrlAutocomplete.vue";
|
|
46
46
|
import ScopeTemplateAutocompleteHost from "./ScopeTemplateAutocompleteHost.vue";
|
|
47
47
|
|
|
48
|
-
const { t } = useI18n();
|
|
48
|
+
const { t, locale } = useI18n();
|
|
49
49
|
|
|
50
50
|
export type FetchNodeConfigPanelProps = {
|
|
51
51
|
node: BlueprintGraphNode;
|
|
@@ -113,12 +113,14 @@ const resolvedBodyPreview = computed(() => {
|
|
|
113
113
|
if (!usesScopeTemplate.value) return "";
|
|
114
114
|
return resolvedFetchConfig.value.body?.trim() ?? "";
|
|
115
115
|
});
|
|
116
|
-
const headersJsonError = computed(() =>
|
|
117
|
-
|
|
118
|
-
);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
const headersJsonError = computed(() => {
|
|
117
|
+
void locale.value;
|
|
118
|
+
return getFetchHeadersValidationError(fetchConfig.value, incomingScope.value);
|
|
119
|
+
});
|
|
120
|
+
const bodyJsonError = computed(() => {
|
|
121
|
+
void locale.value;
|
|
122
|
+
return getFetchBodyValidationError(fetchConfig.value.body, resolvedFetchConfig.value.body);
|
|
123
|
+
});
|
|
122
124
|
const incomingHasPendingValue = computed(() => {
|
|
123
125
|
const scope = incomingScope.value;
|
|
124
126
|
if (!scope || typeof scope !== "object") return false;
|
|
@@ -411,8 +413,15 @@ function handleHeadersInput(event: Event) {
|
|
|
411
413
|
</div>
|
|
412
414
|
|
|
413
415
|
<div class="space-y-1">
|
|
414
|
-
<span class="text-[11px] text-muted-foreground">
|
|
416
|
+
<span class="inline-flex items-center gap-1 text-[11px] text-muted-foreground">
|
|
415
417
|
{{ t("blueprint.config.fetchSourceMode") }}
|
|
418
|
+
<ConfigHintIcon :label="t('blueprint.config.fetchSourceMode')">
|
|
419
|
+
{{
|
|
420
|
+
usingCollection
|
|
421
|
+
? t("blueprint.config.fetchSourceCollectionHint")
|
|
422
|
+
: t("blueprint.config.fetchSourceDirectHint")
|
|
423
|
+
}}
|
|
424
|
+
</ConfigHintIcon>
|
|
416
425
|
</span>
|
|
417
426
|
<div class="flex rounded-md border border-border p-0.5">
|
|
418
427
|
<button
|
|
@@ -440,13 +449,6 @@ function handleHeadersInput(event: Event) {
|
|
|
440
449
|
{{ t("blueprint.config.fetchSourceCollection") }}
|
|
441
450
|
</button>
|
|
442
451
|
</div>
|
|
443
|
-
<p class="text-[10px] text-muted-foreground">
|
|
444
|
-
{{
|
|
445
|
-
usingCollection
|
|
446
|
-
? t("blueprint.config.fetchSourceCollectionHint")
|
|
447
|
-
: t("blueprint.config.fetchSourceDirectHint")
|
|
448
|
-
}}
|
|
449
|
-
</p>
|
|
450
452
|
</div>
|
|
451
453
|
|
|
452
454
|
<div class="space-y-1 rounded-md border border-gray-200/80 bg-white/80 p-2">
|
|
@@ -491,7 +493,12 @@ function handleHeadersInput(event: Event) {
|
|
|
491
493
|
</Select>
|
|
492
494
|
</label>
|
|
493
495
|
<label class="block space-y-1">
|
|
494
|
-
<span class="text-muted-foreground">
|
|
496
|
+
<span class="inline-flex items-center gap-1 text-muted-foreground">
|
|
497
|
+
{{ t("blueprint.config.apiCollectionEndpoint") }}
|
|
498
|
+
<ConfigHintIcon :label="t('blueprint.config.apiCollectionEndpoint')">
|
|
499
|
+
{{ t("blueprint.config.apiCollectionFilledHint") }}
|
|
500
|
+
</ConfigHintIcon>
|
|
501
|
+
</span>
|
|
495
502
|
<div class="flex gap-1.5">
|
|
496
503
|
<Tooltip
|
|
497
504
|
:title="selectedEndpointDescription || undefined"
|
|
@@ -544,9 +551,6 @@ function handleHeadersInput(event: Event) {
|
|
|
544
551
|
</Button>
|
|
545
552
|
</div>
|
|
546
553
|
</label>
|
|
547
|
-
<p v-if="selectedCollection" class="text-[10px] text-muted-foreground">
|
|
548
|
-
{{ t("blueprint.config.apiCollectionFilledHint") }}
|
|
549
|
-
</p>
|
|
550
554
|
<label class="block space-y-1">
|
|
551
555
|
<span class="text-muted-foreground">{{ t("blueprint.config.requestUrl") }}</span>
|
|
552
556
|
<Input
|
|
@@ -8,7 +8,7 @@ import ConfigHintIcon from "./ConfigHintIcon.vue";
|
|
|
8
8
|
import type { BlueprintGraphNode } from "../graph/document";
|
|
9
9
|
import { resolveNodeLogicConfig } from "../graph/document";
|
|
10
10
|
|
|
11
|
-
const { t } = useI18n();
|
|
11
|
+
const { t, locale } = useI18n();
|
|
12
12
|
|
|
13
13
|
export type LogicNodeConfigPanelProps = {
|
|
14
14
|
node: BlueprintGraphNode;
|
|
@@ -31,9 +31,10 @@ function patchLogicConfig(node: BlueprintGraphNode, patch: Partial<LogicNodeConf
|
|
|
31
31
|
|
|
32
32
|
const logicConfig = computed(() => resolveNodeLogicConfig(props.node));
|
|
33
33
|
|
|
34
|
-
const storedValidation = computed(() =>
|
|
35
|
-
|
|
36
|
-
);
|
|
34
|
+
const storedValidation = computed(() => {
|
|
35
|
+
void locale.value;
|
|
36
|
+
return validateLogicSourceCode(logicConfig.value.sourceCode);
|
|
37
|
+
});
|
|
37
38
|
|
|
38
39
|
const parseError = computed(
|
|
39
40
|
() => draftError.value ?? (storedValidation.value.ok ? null : storedValidation.value.error)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { setBlueprintDslLocale } from "@arronqzy/blueprint-dsl";
|
|
2
|
+
import { useI18nOptional } from "@arronqzy/i18n/vue";
|
|
3
|
+
import { watch } from "vue";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Keeps blueprint-dsl validation / runtime messages in the app locale. `flush: "sync"`
|
|
7
|
+
* updates it before computeds that track the locale are re-evaluated.
|
|
8
|
+
*/
|
|
9
|
+
export function useBlueprintDslLocaleSync(): void {
|
|
10
|
+
const { locale } = useI18nOptional();
|
|
11
|
+
watch(locale, (next) => setBlueprintDslLocale(next), { immediate: true, flush: "sync" });
|
|
12
|
+
}
|
package/src/graph/document.ts
CHANGED
|
@@ -207,7 +207,7 @@ export function resolveRunnableNodeType(
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
import type { TranslateFn } from "@arronqzy/i18n";
|
|
210
|
-
import { resolveLocale, tForLocale } from "@arronqzy/i18n";
|
|
210
|
+
import { matchMessageInAnyLocale, relocalizeMessage, resolveLocale, tForLocale } from "@arronqzy/i18n";
|
|
211
211
|
|
|
212
212
|
/** 画布节点顶部(拖拽区)配置类型对应的 i18n key */
|
|
213
213
|
export const BLUEPRINT_CONFIG_TYPE_LABEL_KEYS: Record<
|
|
@@ -289,16 +289,23 @@ export function defaultBlueprintNodeLabel(
|
|
|
289
289
|
return getBlueprintNodeTypeLabel(t, configSource);
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
-
|
|
292
|
+
const BLUEPRINT_TYPE_LABEL_KEY_LIST = Object.values(BLUEPRINT_CONFIG_TYPE_LABEL_KEYS);
|
|
293
|
+
|
|
294
|
+
/** 当前名称是否仍是「类型默认名」(空或等于任一语言下的任一类型文案) */
|
|
293
295
|
export function isDefaultBlueprintNodeLabel(
|
|
294
296
|
label: string | undefined | null,
|
|
295
297
|
t: TranslateFn = defaultTranslate()
|
|
296
298
|
): boolean {
|
|
297
299
|
const trimmed = (label ?? "").trim();
|
|
298
300
|
if (!trimmed) return true;
|
|
299
|
-
return (
|
|
300
|
-
|
|
301
|
-
)
|
|
301
|
+
return BLUEPRINT_TYPE_LABEL_KEY_LIST.some(
|
|
302
|
+
(key) => t(key) === trimmed || matchMessageInAnyLocale(trimmed, key) !== null
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/** 类型默认名按当前语言显示;用户自定义名称保持不变 */
|
|
307
|
+
export function localizeBlueprintNodeLabel(label: string, t: TranslateFn): string {
|
|
308
|
+
return relocalizeMessage(label, BLUEPRINT_TYPE_LABEL_KEY_LIST, t);
|
|
302
309
|
}
|
|
303
310
|
|
|
304
311
|
export function resolveNodeFetchConfig(
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ export { documentToRunnableGraph } from "./runtime/document-to-runnable-graph";
|
|
|
4
4
|
export type { BlueprintExecutionOverlay } from "./runtime/execution-overlay";
|
|
5
5
|
export type { BlueprintFlowNodeData } from "./types";
|
|
6
6
|
export { default as BluePrintVueRoot } from "./components/BluePrintVueRoot.vue";
|
|
7
|
+
export { useBlueprintDslLocaleSync } from "./composables/useBlueprintDslLocaleSync";
|
|
7
8
|
export { default as BlueprintCanvas } from "./components/BlueprintCanvas.vue";
|
|
8
9
|
export { default as BlueprintNodeConfigSidebar } from "./BlueprintNodeConfigSidebar.vue";
|
|
9
10
|
export type {
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { useI18n } from "@arronqzy/i18n/vue";
|
|
3
3
|
import { computed } from "vue";
|
|
4
4
|
import { cn } from "../utils/cn";
|
|
5
|
+
import { localizeBlueprintNodeLabel } from "../graph/document";
|
|
5
6
|
|
|
6
|
-
const { t } = useI18n();
|
|
7
|
+
const { t, locale } = useI18n();
|
|
7
8
|
|
|
8
9
|
export type BlueprintNodeCardProps = {
|
|
9
10
|
nodeId: string;
|
|
@@ -26,7 +27,11 @@ const emit = defineEmits<{
|
|
|
26
27
|
select: [nodeId: string];
|
|
27
28
|
}>();
|
|
28
29
|
|
|
29
|
-
const
|
|
30
|
+
const displayLabel = computed(() => {
|
|
31
|
+
void locale.value;
|
|
32
|
+
return localizeBlueprintNodeLabel(props.label, t);
|
|
33
|
+
});
|
|
34
|
+
const showMeta = computed(() => Boolean(props.meta && props.meta !== displayLabel.value));
|
|
30
35
|
</script>
|
|
31
36
|
|
|
32
37
|
<template>
|
|
@@ -108,7 +113,7 @@ const showMeta = computed(() => Boolean(props.meta && props.meta !== props.label
|
|
|
108
113
|
</span>
|
|
109
114
|
<div class="bp-node-card__content">
|
|
110
115
|
<div class="bp-node-card__title-row">
|
|
111
|
-
<div class="bp-node-card__title">{{
|
|
116
|
+
<div class="bp-node-card__title">{{ displayLabel }}</div>
|
|
112
117
|
<span
|
|
113
118
|
v-if="progressLabel"
|
|
114
119
|
:class="cn('bp-node-card__badge', `bp-node-card__badge--${variant}`)"
|