@arronqzy/vue-blueprint 0.1.18 → 0.1.20

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.18",
3
+ "version": "0.1.20",
4
4
  "description": "Vue 3 blueprint editor for Abuilder (Vue Flow + Ant Design Vue)",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,8 +20,8 @@
20
20
  "dayjs": "^1.11.13",
21
21
  "vue": "^3.5.13",
22
22
  "@arronqzy/blueprint-dsl": "1.0.17",
23
- "@arronqzy/i18n": "0.1.17",
24
- "@arronqzy/vue-rx-store": "0.1.6"
23
+ "@arronqzy/vue-rx-store": "0.1.6",
24
+ "@arronqzy/i18n": "0.1.17"
25
25
  },
26
26
  "peerDependencies": {
27
27
  "vue": "^3.4.0"
@@ -244,6 +244,7 @@ async function handleFiles(files: FileList | null) {
244
244
  :title="t('blueprint.apiCollection.managerTitle')"
245
245
  :footer="null"
246
246
  width="960px"
247
+ :mask-style="{ background: 'transparent' }"
247
248
  :body-style="{ maxHeight: '90vh', display: 'flex', flexDirection: 'column' }"
248
249
  @update:open="onOpenChange"
249
250
  >
@@ -350,47 +351,48 @@ async function handleFiles(files: FileList | null) {
350
351
  : t('blueprint.apiCollection.createTitle')
351
352
  "
352
353
  :footer="null"
353
- width="1100px"
354
+ width="620px"
354
355
  :style="{ top: '4vh' }"
356
+ :mask-style="{ background: 'transparent' }"
357
+ destroy-on-close
355
358
  @update:open="(v) => (editorOpen = v)"
356
359
  >
357
- <p class="mb-3 text-xs text-muted-foreground">
360
+ <p class="mb-2 text-xs text-muted-foreground">
358
361
  {{ t("blueprint.apiCollection.editorDescription") }}
359
362
  </p>
360
363
 
361
- <div class="space-y-2">
362
- <div class="flex items-center justify-between gap-2">
363
- <span class="text-xs">{{ t("blueprint.apiCollection.jsonEditor") }}</span>
364
- <label class="flex cursor-pointer items-center gap-2 text-[11px] text-muted-foreground">
365
- <Checkbox v-model:checked="editorPersistLocal" />
366
- {{ t("blueprint.apiCollection.persistLocal") }}
367
- </label>
368
- </div>
369
- <Input.TextArea
370
- v-model:value="editorJson"
371
- :rows="28"
372
- :spellcheck="false"
373
- class="!min-h-[62vh] font-mono text-[12px] leading-relaxed"
374
- :status="editorError ? 'error' : undefined"
375
- />
376
- <p v-if="editorError" class="text-[11px] text-destructive">{{ editorError }}</p>
377
- </div>
378
-
379
- <div class="mt-4 flex flex-wrap justify-end gap-2">
380
- <Button @click="downloadApiCollectionTemplate()">
364
+ <div class="mb-2 flex flex-wrap items-center gap-1.5 border-b border-border/60 pb-2">
365
+ <Button size="small" @click="downloadApiCollectionTemplate()">
381
366
  {{ t("blueprint.apiCollection.downloadTemplate") }}
382
367
  </Button>
383
368
  <Button
369
+ size="small"
384
370
  :disabled="busy || !onSyncCollection"
385
371
  :title="t('blueprint.apiCollection.syncHint')"
386
372
  @click="void handleSyncFromEditor()"
387
373
  >
388
374
  {{ t("blueprint.apiCollection.sync") }}
389
375
  </Button>
390
- <Button @click="editorOpen = false">{{ t("common.cancel") }}</Button>
391
- <Button type="primary" :disabled="busy" @click="void handleSaveEditor()">
376
+ <Button size="small" @click="editorOpen = false">{{ t("common.cancel") }}</Button>
377
+ <Button size="small" type="primary" :disabled="busy" @click="void handleSaveEditor()">
392
378
  {{ t("common.save") }}
393
379
  </Button>
380
+ <label class="ml-auto flex cursor-pointer items-center gap-1.5 text-[11px] text-muted-foreground">
381
+ <Checkbox v-model:checked="editorPersistLocal" />
382
+ {{ t("blueprint.apiCollection.persistLocal") }}
383
+ </label>
384
+ </div>
385
+
386
+ <div class="flex flex-col gap-2">
387
+ <span class="text-xs">{{ t("blueprint.apiCollection.jsonEditor") }}</span>
388
+ <Input.TextArea
389
+ v-model:value="editorJson"
390
+ :rows="16"
391
+ :spellcheck="false"
392
+ class="!h-[min(68vh,640px)] !min-h-[320px] font-mono text-[12px] leading-relaxed"
393
+ :status="editorError ? 'error' : undefined"
394
+ />
395
+ <p v-if="editorError" class="text-[11px] text-destructive">{{ editorError }}</p>
394
396
  </div>
395
397
  </Modal>
396
398
  </template>
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ export {
28
28
  getApiCollectionById,
29
29
  getApiCollectionListItems,
30
30
  upsertApiCollectionFromJson,
31
+ putApiCollection,
31
32
  removeApiCollection,
32
33
  deleteApiCollection,
33
34
  clearApiCollections,
@@ -70,18 +70,48 @@ export type UpsertApiCollectionInput = {
70
70
  persistLocal: boolean;
71
71
  /** 未写 document.name 时用文件名 */
72
72
  fallbackName?: string;
73
+ /** 省略时写入当前已 hydrate 的 nameSpace */
74
+ nameSpace?: string | null;
73
75
  };
74
76
 
75
77
  export type UpsertApiCollectionResult =
76
78
  | { ok: true; record: ApiCollectionRecord }
77
79
  | { ok: false; error: string };
78
80
 
81
+ function isCurrentNameSpace(nameSpace?: string | null): boolean {
82
+ return normalizeAppNameSpace(nameSpace) === normalizeAppNameSpace(nameSpaceRef);
83
+ }
84
+
85
+ /** 写入接口集合;persistLocal 时落 IndexedDB,同一 nameSpace 下刷新内存列表 */
86
+ export async function putApiCollection(
87
+ record: ApiCollectionRecord,
88
+ nameSpace?: string | null
89
+ ): Promise<ApiCollectionRecord> {
90
+ if (record.persistLocal) {
91
+ await putApiCollectionRecord(record, nameSpace);
92
+ } else if (isCurrentNameSpace(nameSpace)) {
93
+ const existing = records.find((item) => item.id === record.id);
94
+ if (existing?.persistLocal) {
95
+ await deleteApiCollectionRecord(record.id, nameSpace);
96
+ }
97
+ }
98
+ if (isCurrentNameSpace(nameSpace)) {
99
+ const next = records.filter((item) => item.id !== record.id);
100
+ next.push(record);
101
+ records = sortRecords(next);
102
+ emit();
103
+ }
104
+ return record;
105
+ }
106
+
79
107
  export async function upsertApiCollectionFromJson(
80
108
  input: UpsertApiCollectionInput
81
109
  ): Promise<UpsertApiCollectionResult> {
82
110
  const parsed = parseApiCollectionJson(input.rawJson);
83
111
  if (!parsed.ok) return parsed;
84
112
 
113
+ const targetNameSpace =
114
+ input.nameSpace !== undefined ? input.nameSpace : nameSpaceRef;
85
115
  const document: ApiCollectionDocument = {
86
116
  ...parsed.document,
87
117
  name:
@@ -90,11 +120,18 @@ export async function upsertApiCollectionFromJson(
90
120
  parsed.document.name,
91
121
  };
92
122
  const now = Date.now();
93
- const existing = input.id
123
+ const existingInMemory = input.id
94
124
  ? records.find((item) => item.id === input.id) ?? null
95
125
  : null;
126
+ const existingPersisted =
127
+ input.id && !isCurrentNameSpace(targetNameSpace)
128
+ ? await listApiCollectionRecords(targetNameSpace).then(
129
+ (list) => list.find((item) => item.id === input.id) ?? null
130
+ )
131
+ : null;
132
+ const existing = existingInMemory ?? existingPersisted;
96
133
  const record: ApiCollectionRecord = {
97
- id: existing?.id ?? createApiCollectionId(),
134
+ id: existing?.id ?? input.id ?? createApiCollectionId(),
98
135
  name: document.name,
99
136
  persistLocal: input.persistLocal,
100
137
  document,
@@ -103,16 +140,7 @@ export async function upsertApiCollectionFromJson(
103
140
  updatedAt: now,
104
141
  };
105
142
 
106
- if (record.persistLocal) {
107
- await putApiCollectionRecord(record, nameSpaceRef);
108
- } else if (existing?.persistLocal) {
109
- await deleteApiCollectionRecord(record.id, nameSpaceRef);
110
- }
111
-
112
- const next = records.filter((item) => item.id !== record.id);
113
- next.push(record);
114
- records = sortRecords(next);
115
- emit();
143
+ await putApiCollection(record, targetNameSpace);
116
144
  return { ok: true, record };
117
145
  }
118
146
 
@@ -129,10 +157,6 @@ export async function removeApiCollection(id: string): Promise<void> {
129
157
  emit();
130
158
  }
131
159
 
132
- function isCurrentNameSpace(nameSpace?: string | null): boolean {
133
- return normalizeAppNameSpace(nameSpace) === normalizeAppNameSpace(nameSpaceRef);
134
- }
135
-
136
160
  /** 按 nameSpace 删除接口集合;若该 nameSpace 正在被编辑器使用,内存列表同步移除 */
137
161
  export async function deleteApiCollection(
138
162
  id: string,