@arronqzy/vue-blueprint 0.1.0 → 0.1.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arronqzy/vue-blueprint",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Vue 3 blueprint editor for Abuilder (Vue Flow + Ant Design Vue)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -19,8 +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.3",
23
- "@arronqzy/vue-rx-store": "0.1.0"
22
+ "@arronqzy/i18n": "0.1.2",
23
+ "@arronqzy/vue-rx-store": "0.1.1",
24
+ "@arronqzy/blueprint-dsl": "1.0.4"
24
25
  },
25
26
  "peerDependencies": {
26
27
  "vue": "^3.4.0"
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
+ import { useI18n } from "@arronqzy/i18n/vue";
2
3
  import { computed, watch } from "vue";
3
4
  import { Checkbox, Input, Select } from "ant-design-vue";
4
5
  import {
5
6
  LIFECYCLE_NODE_TYPE,
6
- PAGE_LIFECYCLE_LABELS,
7
7
  PAGE_LIFECYCLE_PHASES,
8
8
  type PageLifecyclePhase,
9
9
  } from "@arronqzy/blueprint-dsl";
@@ -14,14 +14,18 @@ import JsonNodeConfigPanel from "./components/JsonNodeConfigPanel.vue";
14
14
  import LogicNodeConfigPanel from "./components/LogicNodeConfigPanel.vue";
15
15
  import ViewElementMultiSelect from "./components/ViewElementMultiSelect.vue";
16
16
  import {
17
+ getLifecyclePhaseLabel,
17
18
  patchNodeConfigSource,
18
19
  pruneViewElementIds,
19
20
  resolveBlueprintConfigSource,
20
21
  resolveViewElementIds,
21
22
  type BlueprintConfigSource,
22
23
  type BlueprintGraphNode,
24
+ type BlueprintNodeRole,
23
25
  } from "./graph/document";
24
26
 
27
+ const { t } = useI18n();
28
+
25
29
  export type BlueprintViewElementOption = {
26
30
  id: string;
27
31
  label: string;
@@ -76,15 +80,19 @@ const viewElementLabelById = computed(
76
80
  () => new Map(props.viewElementOptions.map((opt) => [opt.id, opt.label]))
77
81
  );
78
82
 
79
- const roleLabel = computed(() => {
80
- const role = props.node.role;
81
- if (role === "blueprint") return "蓝图节点";
82
- if (role === "lifecycle") return "生命周期节点";
83
- if (role === "and") return "并运算节点";
84
- if (role === "fetch") return "数据源节点";
85
- if (role === "json") return "JSON 节点";
86
- return "逻辑节点";
87
- });
83
+ const ROLE_LABEL_KEYS: Record<BlueprintNodeRole, string> = {
84
+ blueprint: "blueprint.config.roleBlueprint",
85
+ lifecycle: "blueprint.config.roleLifecycle",
86
+ and: "blueprint.config.roleAnd",
87
+ fetch: "blueprint.config.roleFetch",
88
+ json: "blueprint.config.roleJson",
89
+ logic: "blueprint.config.roleLogic",
90
+ clock: "blueprint.config.roleClock",
91
+ };
92
+
93
+ const roleLabel = computed(() =>
94
+ t(ROLE_LABEL_KEYS[props.node.role] ?? "blueprint.config.roleLogic")
95
+ );
88
96
 
89
97
  watch(
90
98
  [
@@ -130,14 +138,14 @@ function handleConfigSourceChange(value: string) {
130
138
  <template>
131
139
  <div class="flex h-full min-h-0 flex-col overflow-hidden bg-background text-foreground">
132
140
  <div class="shrink-0 border-b border-border px-3 py-2">
133
- <div class="text-xs font-semibold">蓝图节点配置</div>
141
+ <div class="text-xs font-semibold">{{ t("blueprint.config.title") }}</div>
134
142
  <div class="mt-0.5 text-[11px] text-muted-foreground">
135
143
  {{ roleLabel }} · {{ node.id }}
136
144
  </div>
137
145
  </div>
138
146
  <div class="min-h-0 flex-1 space-y-3 overflow-auto p-3 text-xs">
139
147
  <label class="block space-y-1">
140
- <span class="text-muted-foreground">节点名称</span>
148
+ <span class="text-muted-foreground">{{ t("blueprint.config.nodeName") }}</span>
141
149
  <Input
142
150
  size="small"
143
151
  :value="node.label"
@@ -146,30 +154,30 @@ function handleConfigSourceChange(value: string) {
146
154
  </label>
147
155
 
148
156
  <label class="block space-y-1">
149
- <span class="text-muted-foreground">配置类型</span>
157
+ <span class="text-muted-foreground">{{ t("blueprint.config.configType") }}</span>
150
158
  <Select
151
159
  size="small"
152
160
  class="w-full"
153
161
  :value="configSource"
154
162
  @change="(v) => handleConfigSourceChange(String(v))"
155
163
  >
156
- <Select.Option value="blueprint">蓝图配置</Select.Option>
157
- <Select.Option value="logic">逻辑配置</Select.Option>
158
- <Select.Option value="and">并运算</Select.Option>
159
- <Select.Option value="lifecycle">生命周期配置</Select.Option>
160
- <Select.Option value="fetch">数据源获取</Select.Option>
161
- <Select.Option value="json">JSON 节点</Select.Option>
162
- <Select.Option value="clock">时钟</Select.Option>
163
- <Select.Option value="view">视图节点配置</Select.Option>
164
+ <Select.Option value="blueprint">{{ t("blueprint.config.configBlueprint") }}</Select.Option>
165
+ <Select.Option value="logic">{{ t("blueprint.config.configLogic") }}</Select.Option>
166
+ <Select.Option value="and">{{ t("blueprint.config.configAnd") }}</Select.Option>
167
+ <Select.Option value="lifecycle">{{ t("blueprint.config.configLifecycle") }}</Select.Option>
168
+ <Select.Option value="fetch">{{ t("blueprint.config.configFetch") }}</Select.Option>
169
+ <Select.Option value="json">{{ t("blueprint.config.configJson") }}</Select.Option>
170
+ <Select.Option value="clock">{{ t("blueprint.config.configClock") }}</Select.Option>
171
+ <Select.Option value="view">{{ t("blueprint.config.configView") }}</Select.Option>
164
172
  </Select>
165
173
  </label>
166
174
 
167
175
  <div v-if="configSource === 'view'" class="block space-y-1">
168
- <span class="text-muted-foreground">关联视图节点</span>
176
+ <span class="text-muted-foreground">{{ t("blueprint.config.linkedViewNodes") }}</span>
169
177
  <ViewElementMultiSelect
170
178
  :options="viewElementOptions"
171
179
  :value="linkedViewElementIds"
172
- placeholder="选择视图节点"
180
+ :placeholder="t('blueprint.config.selectViewNode')"
173
181
  @change="
174
182
  (next) =>
175
183
  onUpdateNode(node.id, {
@@ -180,14 +188,17 @@ function handleConfigSourceChange(value: string) {
180
188
  "
181
189
  />
182
190
  <p v-if="linkedViewElementIds.length === 0" class="text-[11px] text-muted-foreground">
183
- 可多选视图画布节点;关联后仍在此配置蓝图节点,视图属性请在视图面板中编辑。
191
+ {{ t("blueprint.config.viewMultiHint") }}
184
192
  </p>
185
193
  <p v-else class="text-[11px] text-muted-foreground">
186
- 已关联 {{ linkedViewElementIds.length }} 个视图节点:{{
187
- linkedViewElementIds
188
- .map((id) => viewElementLabelById.get(id) ?? id)
189
- .join("、")
190
- }}。
194
+ {{
195
+ t("blueprint.config.linkedViewCount", {
196
+ count: linkedViewElementIds.length,
197
+ names: linkedViewElementIds
198
+ .map((id) => viewElementLabelById.get(id) ?? id)
199
+ .join("、"),
200
+ })
201
+ }}
191
202
  </p>
192
203
  </div>
193
204
 
@@ -195,15 +206,10 @@ function handleConfigSourceChange(value: string) {
195
206
  v-if="configSource === 'blueprint'"
196
207
  class="space-y-2 rounded-md border border-border/70 bg-muted/20 p-2.5"
197
208
  >
198
- <div class="font-medium text-foreground">蓝图属性</div>
199
- <p class="text-[11px] text-muted-foreground">
200
- 选中蓝图库中的蓝图后,当输入端收到<strong>真信号</strong>
201
- 时才会执行该蓝图;执行完成后从输出端发出
202
- <strong>真信号</strong>(含嵌套蓝图输出值与当前节点信息),执行失败则发出
203
- <strong>假信号</strong>。
204
- </p>
209
+ <div class="font-medium text-foreground">{{ t("blueprint.config.blueprintAttrs") }}</div>
210
+ <p class="text-[11px] text-muted-foreground">{{ t("blueprint.config.blueprintAttrsHint") }}</p>
205
211
  <label class="block space-y-1">
206
- <span class="text-muted-foreground">引用蓝图库</span>
212
+ <span class="text-muted-foreground">{{ t("blueprint.config.refLibrary") }}</span>
207
213
  <Select
208
214
  size="small"
209
215
  class="w-full"
@@ -217,7 +223,7 @@ function handleConfigSourceChange(value: string) {
217
223
  })
218
224
  "
219
225
  >
220
- <Select.Option value="__none__">未关联</Select.Option>
226
+ <Select.Option value="__none__">{{ t("blueprint.config.unlinked") }}</Select.Option>
221
227
  <Select.Option
222
228
  v-for="opt in blueprintLibraryOptions"
223
229
  :key="opt.id"
@@ -228,7 +234,7 @@ function handleConfigSourceChange(value: string) {
228
234
  </Select>
229
235
  </label>
230
236
  <p v-if="!node.libraryBlueprintId" class="text-[11px] text-muted-foreground">
231
- 请先从蓝图库选择要引用的蓝图。
237
+ {{ t("blueprint.config.selectLibraryFirst") }}
232
238
  </p>
233
239
  <label class="flex items-start gap-2 pt-1">
234
240
  <Checkbox
@@ -237,7 +243,7 @@ function handleConfigSourceChange(value: string) {
237
243
  @update:checked="(v) => onUpdateAllowFalseSignalPropagation?.(Boolean(v))"
238
244
  />
239
245
  <span class="text-[11px] leading-relaxed text-muted-foreground">
240
- 允许假信号传递:开启后,节点输出假信号时不会阻塞任务链,错误信息会继续向下游传递。
246
+ {{ t("blueprint.config.allowFalsePropagateBlueprint") }}
241
247
  </span>
242
248
  </label>
243
249
  </div>
@@ -246,17 +252,17 @@ function handleConfigSourceChange(value: string) {
246
252
  v-if="configSource === 'lifecycle'"
247
253
  class="space-y-2 rounded-md border border-border/70 bg-muted/20 p-2.5"
248
254
  >
249
- <div class="font-medium text-foreground">生命周期钩子</div>
255
+ <div class="font-medium text-foreground">{{ t("blueprint.config.lifecycleHook") }}</div>
250
256
  <p class="text-[11px] text-muted-foreground">
251
- 生命周期节点<strong>没有输入口</strong>,仅右侧输出口。
257
+ {{ t("blueprint.config.lifecycleNoInput") }}
252
258
  {{
253
259
  node.lifecyclePhase === "blueprintActivated"
254
- ? "当本蓝图被其他蓝图的蓝图配置节点引用且收到真信号时,自动向下游发出真信号,输出值为父级传入的输入数据。"
255
- : "当页面进入对应生命周期时,自动向下游发出真/假信号。"
260
+ ? t("blueprint.config.lifecycleBlueprintActivatedHint")
261
+ : t("blueprint.config.lifecyclePageHint")
256
262
  }}
257
263
  </p>
258
264
  <label class="block space-y-1">
259
- <span class="text-muted-foreground">监听阶段</span>
265
+ <span class="text-muted-foreground">{{ t("blueprint.config.listenPhase") }}</span>
260
266
  <Select
261
267
  size="small"
262
268
  class="w-full"
@@ -272,12 +278,12 @@ function handleConfigSourceChange(value: string) {
272
278
  "
273
279
  >
274
280
  <Select.Option v-for="phase in PAGE_LIFECYCLE_PHASES" :key="phase" :value="phase">
275
- {{ PAGE_LIFECYCLE_LABELS[phase] }}
281
+ {{ getLifecyclePhaseLabel(t, phase) }}
276
282
  </Select.Option>
277
283
  </Select>
278
284
  </label>
279
285
  <p v-if="node.parentId" class="text-[11px] text-muted-foreground">
280
- 所属蓝图节点:{{ node.parentId }}
286
+ {{ t("blueprint.config.parentBlueprintNode", { id: node.parentId }) }}
281
287
  </p>
282
288
  </div>
283
289
 
@@ -301,19 +307,14 @@ function handleConfigSourceChange(value: string) {
301
307
  v-if="configSource === 'and'"
302
308
  class="space-y-2 rounded-md border border-border/70 bg-muted/20 p-2.5"
303
309
  >
304
- <div class="font-medium text-foreground">并运算</div>
305
- <p class="text-[11px] text-muted-foreground">
306
- 左侧两个输入口 <strong>inA</strong>、<strong>inB</strong>。
307
- 每个输入口可连 n 条线,同端口任一为真则该端口视为真(或)。
308
- 仅当 <strong>inA 与 inB 均为真信号</strong> 时,从输出口发出真信号;
309
- 否则发出假信号。
310
- </p>
310
+ <div class="font-medium text-foreground">{{ t("blueprint.config.andTitle") }}</div>
311
+ <p class="text-[11px] text-muted-foreground">{{ t("blueprint.config.andHint") }}</p>
311
312
  </div>
312
313
 
313
314
  <template v-if="configSource === 'logic'">
314
315
  <LogicNodeConfigPanel :node="node" :on-update-node="onUpdateNode" />
315
316
  <p v-if="node.parentId" class="text-[11px] text-muted-foreground">
316
- 所属蓝图节点:{{ node.parentId }}
317
+ {{ t("blueprint.config.parentBlueprintNode", { id: node.parentId }) }}
317
318
  </p>
318
319
  </template>
319
320
 
@@ -321,7 +322,7 @@ function handleConfigSourceChange(value: string) {
321
322
  v-if="configSource !== 'blueprint' && configSource !== 'and'"
322
323
  class="space-y-2 rounded-md border border-border/70 bg-muted/20 p-2.5"
323
324
  >
324
- <div class="font-medium text-foreground">任务链执行</div>
325
+ <div class="font-medium text-foreground">{{ t("blueprint.config.taskChain") }}</div>
325
326
  <label class="flex items-start gap-2">
326
327
  <Checkbox
327
328
  :checked="allowFalseSignalPropagation"
@@ -329,7 +330,7 @@ function handleConfigSourceChange(value: string) {
329
330
  @update:checked="(v) => onUpdateAllowFalseSignalPropagation?.(Boolean(v))"
330
331
  />
331
332
  <span class="text-[11px] leading-relaxed text-muted-foreground">
332
- 允许假信号传递:默认假信号会阻塞任务链;开启后继续向下游传递假信号与错误信息。
333
+ {{ t("blueprint.config.allowFalsePropagateDefault") }}
333
334
  </span>
334
335
  </label>
335
336
  </div>
@@ -1,6 +1,8 @@
1
1
  <script setup lang="ts">
2
+ import { useI18n } from "@arronqzy/i18n/vue";
2
3
  import { onUnmounted, ref, watch } from "vue";
3
4
 
5
+ const { t } = useI18n();
4
6
  export type BlueprintContextMenuState =
5
7
  | {
6
8
  kind: "pane";
@@ -84,7 +86,7 @@ onUnmounted(() => {
84
86
  emit('close');
85
87
  "
86
88
  >
87
- 新增节点
89
+ {{ t("blueprint.toolbar.addNode") }}
88
90
  </button>
89
91
 
90
92
  <button
@@ -96,7 +98,7 @@ onUnmounted(() => {
96
98
  emit('close');
97
99
  "
98
100
  >
99
- 删除节点
101
+ {{ t("blueprint.toolbar.deleteNode") }}
100
102
  </button>
101
103
 
102
104
  <button
@@ -108,7 +110,7 @@ onUnmounted(() => {
108
110
  emit('close');
109
111
  "
110
112
  >
111
- 删除连线
113
+ {{ t("blueprint.toolbar.deleteEdge") }}
112
114
  </button>
113
115
  </div>
114
116
  </template>
@@ -1,15 +1,18 @@
1
1
  <script setup lang="ts">
2
+ import { useI18n } from "@arronqzy/i18n/vue";
2
3
  import { computed, nextTick, ref, watch } from "vue";
3
4
  import { Button, Checkbox, Input, Tooltip } from "ant-design-vue";
4
5
  import {
5
- PAGE_LIFECYCLE_LABELS,
6
6
  type ExecutionTraceEntry,
7
7
  type PageLifecyclePhase,
8
8
  } from "@arronqzy/blueprint-dsl";
9
+ import { getLifecyclePhaseLabel } from "../graph/document";
9
10
 
10
11
  import type { ExecutionLogSettings } from "../library/execution-log-settings";
11
12
  import { cn } from "../utils/cn";
12
13
 
14
+ const { t } = useI18n();
15
+
13
16
  export type BlueprintExecutionLogPanelProps = {
14
17
  entries: ExecutionTraceEntry[];
15
18
  settings: ExecutionLogSettings;
@@ -53,8 +56,7 @@ function formatJson(value: unknown) {
53
56
  const phaseLabel = computed(() => {
54
57
  if (!props.lifecyclePhase) return null;
55
58
  return (
56
- PAGE_LIFECYCLE_LABELS[props.lifecyclePhase as PageLifecyclePhase] ??
57
- props.lifecyclePhase
59
+ getLifecyclePhaseLabel(t, props.lifecyclePhase as PageLifecyclePhase)
58
60
  );
59
61
  });
60
62
 
@@ -111,31 +113,31 @@ watch(
111
113
  <div class="shrink-0 border-b border-border px-3 py-2">
112
114
  <div class="flex items-start justify-between gap-2">
113
115
  <div class="min-w-0">
114
- <div class="text-xs font-semibold">蓝图任务输出日志</div>
116
+ <div class="text-xs font-semibold">{{ t("blueprint.log.title") }}</div>
115
117
  <div class="mt-0.5 text-[11px] text-muted-foreground">
116
- {{ phaseLabel ? `模拟场景:${phaseLabel}` : "选择生命周期节点并开始调试" }}
118
+ {{ phaseLabel ? t("blueprint.log.simulateSceneWithPhase", { phaseLabel }) : t("blueprint.log.selectLifecycleToDebug") }}
117
119
  </div>
118
120
  </div>
119
121
  <div class="flex shrink-0 items-center gap-1">
120
122
  <Tooltip
121
123
  v-if="onClearAllSaved"
122
- title="立即清空 IndexedDB 中所有已保存的蓝图执行日志"
124
+ :title="t('blueprint.log.clearIdbTooltip')"
123
125
  >
124
126
  <Button
125
127
  size="small"
126
128
  class="h-7 w-7 shrink-0"
127
- aria-label="清空 IndexedDB 日志"
129
+ :aria-label="t('blueprint.log.clearIdbAria')"
128
130
  :disabled="!hasSavedRuns"
129
131
  @click="() => void onClearAllSaved?.()"
130
132
  >
131
133
  🗄✕
132
134
  </Button>
133
135
  </Tooltip>
134
- <Tooltip title="清空当前日志,并重置画布执行高亮">
136
+ <Tooltip :title="t('blueprint.log.clearCurrentTooltip')">
135
137
  <Button
136
138
  size="small"
137
139
  class="h-7 w-7 shrink-0"
138
- aria-label="清空日志"
140
+ :aria-label="t('blueprint.log.clearCurrentAria')"
139
141
  :disabled="entries.length === 0"
140
142
  @click="onClear"
141
143
  >
@@ -149,7 +151,7 @@ watch(
149
151
  <div class="relative min-h-0 flex-1">
150
152
  <div ref="scrollRef" class="h-full overflow-auto p-3" @scroll="handleScroll">
151
153
  <p v-if="entries.length === 0" class="text-[11px] text-muted-foreground">
152
- 暂无执行记录。使用工具栏「走完全流程」或「下一步」开始模拟。
154
+ {{ t("blueprint.log.emptyHint") }}
153
155
  </p>
154
156
  <div v-else class="space-y-0">
155
157
  <div v-for="(entry, index) in entries" :key="entry.id">
@@ -170,13 +172,13 @@ watch(
170
172
 
171
173
  <div class="mt-2 grid gap-2">
172
174
  <div>
173
- <div class="mb-1 text-[10px] font-medium text-muted-foreground">输入</div>
175
+ <div class="mb-1 text-[10px] font-medium text-muted-foreground">{{ t("blueprint.log.input") }}</div>
174
176
  <pre
175
177
  class="max-h-32 overflow-auto rounded border border-border/60 bg-background p-2 font-mono text-[10px] leading-relaxed text-foreground"
176
178
  >{{ formatJson(entry.inputs) }}</pre>
177
179
  </div>
178
180
  <div>
179
- <div class="mb-1 text-[10px] font-medium text-muted-foreground">输出</div>
181
+ <div class="mb-1 text-[10px] font-medium text-muted-foreground">{{ t("blueprint.log.output") }}</div>
180
182
  <pre
181
183
  class="max-h-32 overflow-auto rounded border p-2 font-mono text-[10px] leading-relaxed"
182
184
  :class="
@@ -211,7 +213,7 @@ watch(
211
213
  @click="() => void scrollToBottom('smooth')"
212
214
  >
213
215
  <span class="shrink-0">↓</span>
214
- <span class="truncate">有新日志</span>
216
+ <span class="truncate">{{ t("blueprint.log.hasNewLogs") }}</span>
215
217
  <span v-if="latestEntryPreview" class="truncate opacity-90">
216
218
  · {{ latestEntryPreview }}
217
219
  </span>
@@ -221,41 +223,41 @@ watch(
221
223
 
222
224
  <div class="shrink-0 space-y-2 border-t border-border p-3 text-xs">
223
225
  <div class="grid grid-cols-2 gap-2">
224
- <Tooltip title="将当前调试日志保存到 IndexedDB">
226
+ <Tooltip :title="t('blueprint.log.saveLogTooltip')">
225
227
  <Button size="small" block :disabled="entries.length === 0" @click="onSave">
226
- 保存日志
228
+ {{ t("blueprint.log.saveLog") }}
227
229
  </Button>
228
230
  </Tooltip>
229
- <Tooltip title="将当前调试日志导出为 JSON 文件">
231
+ <Tooltip :title="t('blueprint.log.exportJsonTooltip')">
230
232
  <Button size="small" block :disabled="entries.length === 0" @click="onExport">
231
- 导出 JSON
233
+ {{ t("blueprint.log.exportJson") }}
232
234
  </Button>
233
235
  </Tooltip>
234
236
  </div>
235
237
 
236
- <Tooltip title="调试运行完成后,自动将日志写入 IndexedDB">
238
+ <Tooltip :title="t('blueprint.log.autoSaveTooltip')">
237
239
  <label class="flex cursor-default items-center gap-2">
238
240
  <Checkbox
239
241
  :checked="settings.autoSave"
240
242
  @update:checked="(v) => onUpdateSettings({ autoSave: Boolean(v) })"
241
243
  />
242
244
  <span class="text-[11px] text-muted-foreground">
243
- 运行完成后自动保存到 IndexedDB
245
+ {{ t("blueprint.log.autoSaveAfterRun") }}
244
246
  </span>
245
247
  </label>
246
248
  </Tooltip>
247
249
 
248
250
  <div class="grid grid-cols-2 gap-2">
249
- <Tooltip title="IndexedDB 中最多保留的日志条数,超出后自动删除最旧记录">
251
+ <Tooltip :title="t('blueprint.log.maxSavedCountTooltip')">
250
252
  <div class="space-y-1">
251
- <span class="text-[11px] text-muted-foreground">最多保存条数</span>
253
+ <span class="text-[11px] text-muted-foreground">{{ t("blueprint.log.maxSavedCount") }}</span>
252
254
  <Input
253
255
  type="number"
254
256
  size="small"
255
257
  :min="1"
256
258
  :step="1"
257
259
  :value="settings.maxSavedRuns"
258
- aria-label="IndexedDB 最多保存日志条数"
260
+ :aria-label="t('blueprint.log.maxSavedCountAria')"
259
261
  @update:value="
260
262
  (v) =>
261
263
  onUpdateSettings({
@@ -265,16 +267,16 @@ watch(
265
267
  />
266
268
  </div>
267
269
  </Tooltip>
268
- <Tooltip title="超过保留天数的已保存日志将在清理时被删除">
270
+ <Tooltip :title="t('blueprint.log.retentionDaysTooltip')">
269
271
  <div class="space-y-1">
270
- <span class="text-[11px] text-muted-foreground">保留天数</span>
272
+ <span class="text-[11px] text-muted-foreground">{{ t("blueprint.log.retentionDays") }}</span>
271
273
  <Input
272
274
  type="number"
273
275
  size="small"
274
276
  :min="1"
275
277
  :step="1"
276
278
  :value="settings.retentionDays"
277
- aria-label="日志保留天数"
279
+ :aria-label="t('blueprint.log.retentionDaysAria')"
278
280
  @update:value="
279
281
  (v) =>
280
282
  onUpdateSettings({
@@ -286,8 +288,8 @@ watch(
286
288
  </Tooltip>
287
289
  </div>
288
290
 
289
- <Tooltip title="按保留天数与条数上限,清理 IndexedDB 中的日志记录">
290
- <Button size="small" block @click="onApplyRetention">清理过期与超额</Button>
291
+ <Tooltip :title="t('blueprint.log.cleanupTooltip')">
292
+ <Button size="small" block @click="onApplyRetention">{{ t("blueprint.log.cleanupExpired") }}</Button>
291
293
  </Tooltip>
292
294
  </div>
293
295
  </div>
@@ -1,9 +1,11 @@
1
1
  <script setup lang="ts">
2
+ import { useI18n } from "@arronqzy/i18n/vue";
2
3
  import { ref, watch } from "vue";
3
4
  import { Button, Input, Modal } from "ant-design-vue";
4
5
 
5
6
  import type { BlueprintMetaDraft } from "../library/types";
6
7
 
8
+ const { t } = useI18n();
7
9
  export type BlueprintMetaDialogProps = {
8
10
  open: boolean;
9
11
  mode: "export" | "save";
@@ -26,16 +28,20 @@ watch(
26
28
  }
27
29
  );
28
30
 
29
- const title = () => (props.mode === "export" ? "导出蓝图" : "保存蓝图");
31
+ const title = () =>
32
+ props.mode === "export"
33
+ ? t("blueprint.dialog.exportTitle")
34
+ : t("blueprint.dialog.saveTitle");
30
35
  const description = () =>
31
36
  props.mode === "export"
32
- ? "填写蓝图名称与备注,将当前蓝图导出为 JSON 文件。"
33
- : "填写蓝图名称与备注,将当前蓝图保存到本地蓝图库。";
34
- const confirmLabel = () => (props.mode === "export" ? "导出" : "保存");
37
+ ? t("blueprint.dialog.exportDescription")
38
+ : t("blueprint.dialog.saveDescription");
39
+ const confirmLabel = () =>
40
+ props.mode === "export" ? t("blueprint.dialog.export") : t("blueprint.dialog.save");
35
41
 
36
42
  function handleConfirm() {
37
43
  props.onConfirm({
38
- name: name.value.trim() || "未命名蓝图",
44
+ name: name.value.trim() || t("blueprint.dialog.unnamedBlueprint"),
39
45
  remark: remark.value.trim(),
40
46
  });
41
47
  props.onOpenChange(false);
@@ -47,33 +53,33 @@ function handleConfirm() {
47
53
  :open="open"
48
54
  :title="title()"
49
55
  :ok-text="confirmLabel()"
50
- cancel-text="取消"
56
+ :cancel-text="t('common.cancel')"
51
57
  @update:open="onOpenChange"
52
58
  @ok="handleConfirm"
53
59
  >
54
60
  <p class="mb-3 text-xs text-muted-foreground">{{ description() }}</p>
55
61
  <div class="space-y-3">
56
62
  <label class="block space-y-1">
57
- <span class="text-sm">蓝图名称</span>
63
+ <span class="text-sm">{{ t("blueprint.dialog.blueprintName") }}</span>
58
64
  <Input
59
65
  id="blueprint-meta-name"
60
66
  v-model:value="name"
61
- placeholder="例如:首页初始化流程"
67
+ :placeholder="t('blueprint.dialog.namePlaceholder')"
62
68
  autofocus
63
69
  />
64
70
  </label>
65
71
  <label class="block space-y-1">
66
- <span class="text-sm">蓝图备注</span>
72
+ <span class="text-sm">{{ t("blueprint.dialog.remark") }}</span>
67
73
  <Input.TextArea
68
74
  id="blueprint-meta-remark"
69
75
  v-model:value="remark"
70
- placeholder="可选:描述蓝图用途、触发条件等"
76
+ :placeholder="t('blueprint.dialog.remarkPlaceholder')"
71
77
  :rows="3"
72
78
  />
73
79
  </label>
74
80
  </div>
75
81
  <template #footer>
76
- <Button @click="onOpenChange(false)">取消</Button>
82
+ <Button @click="onOpenChange(false)">{{ t("common.cancel") }}</Button>
77
83
  <Button type="primary" @click="handleConfirm">{{ confirmLabel() }}</Button>
78
84
  </template>
79
85
  </Modal>
@@ -1,7 +1,9 @@
1
1
  <script setup lang="ts">
2
+ import { useI18n } from "@arronqzy/i18n/vue";
2
3
  import { computed } from "vue";
3
4
  import { Button, Modal } from "ant-design-vue";
4
5
 
6
+ const { t } = useI18n();
5
7
  export type BlueprintNodeSwitchTaskDialogProps = {
6
8
  open: boolean;
7
9
  fromNodeId: string;
@@ -14,28 +16,34 @@ export type BlueprintNodeSwitchTaskDialogProps = {
14
16
  const props = defineProps<BlueprintNodeSwitchTaskDialogProps>();
15
17
 
16
18
  const targetLabel = computed(() =>
17
- props.toNodeId === null ? "取消选中" : `节点 ${props.toNodeId}`
19
+ props.toNodeId === null
20
+ ? t("blueprint.dialog.cancelSelection")
21
+ : t("blueprint.dialog.nodeTarget", { id: props.toNodeId })
18
22
  );
19
23
  </script>
20
24
 
21
25
  <template>
22
26
  <Modal
23
27
  :open="open"
24
- title="节点正在执行任务"
28
+ :title="t('blueprint.dialog.taskRunningTitle')"
25
29
  :footer="null"
26
30
  @update:open="onOpenChange"
27
31
  >
28
32
  <p class="text-sm text-muted-foreground">
29
- 节点 <span class="font-mono text-foreground">{{ fromNodeId }}</span>
30
- 正在执行任务(Swagger 解析或请求调试)。是否切换到 {{ targetLabel }}?
33
+ {{
34
+ t("blueprint.dialog.taskRunningDescription", {
35
+ fromNodeId,
36
+ target: targetLabel,
37
+ })
38
+ }}
31
39
  </p>
32
40
  <p class="mt-2 text-xs text-muted-foreground">
33
- 选择「保留并切换」将在后台继续执行,回到该节点时仍能看到进度;选择「取消并切换」会中止当前任务。
41
+ {{ t("blueprint.dialog.taskSwitchHint") }}
34
42
  </p>
35
43
  <div class="mt-4 flex flex-wrap justify-end gap-2">
36
- <Button @click="onOpenChange(false)">留在此节点</Button>
37
- <Button @click="onCancelTaskAndSwitch">取消并切换</Button>
38
- <Button type="primary" @click="onKeepTaskAndSwitch">保留并切换</Button>
44
+ <Button @click="onOpenChange(false)">{{ t("blueprint.dialog.stayOnNode") }}</Button>
45
+ <Button @click="onCancelTaskAndSwitch">{{ t("blueprint.dialog.cancelAndSwitch") }}</Button>
46
+ <Button type="primary" @click="onKeepTaskAndSwitch">{{ t("blueprint.dialog.keepAndSwitch") }}</Button>
39
47
  </div>
40
48
  </Modal>
41
49
  </template>