@arronqzy/vue-view 0.1.22 → 0.1.23
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/README.md +1 -1
- package/package.json +5 -5
- package/src/index.ts +6 -0
- package/src/panel/hooks/useWorkspaceProjects.ts +25 -2
- package/src/panel/library/workspace-project-cache.ts +27 -0
- package/src/panel/library/workspace-project-db.ts +4 -0
- package/src/panel/library/workspace-project-sync.ts +31 -0
- package/src/panel/library/workspace-storage.ts +38 -0
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
|
|
52
52
|
创建 / 同步发出 `workspace:add` / `workspace:sync`。`parseWorkspaceData` 的 `value` 可作 `initialWorkspace`。
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
本地保存的工作区可用 `listWorkspaceProjects` / `deleteWorkspaceProject` / `clearWorkspaceProjects`(参数为 `nameSpace`)列出和清理。其余 IndexedDB 读写与 `getPreviewSnapshot` **不导出**,缩略图只在 React 包实现。
|
|
55
55
|
|
|
56
56
|
## 和 React 版的差别
|
|
57
57
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arronqzy/vue-view",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.23",
|
|
4
4
|
"description": "Vue 3 visual view editor for Abuilder (Ant Design Vue)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"selecto": "^1.26.3",
|
|
24
24
|
"uuid": "^13.0.0",
|
|
25
25
|
"vue": "^3.5.13",
|
|
26
|
-
"@arronqzy/blueprint-dsl": "1.0.17",
|
|
27
26
|
"@arronqzy/i18n": "0.1.17",
|
|
28
|
-
"@arronqzy/
|
|
27
|
+
"@arronqzy/blueprint-dsl": "1.0.17",
|
|
29
28
|
"@arronqzy/rx-store": "1.0.8",
|
|
30
|
-
"@arronqzy/
|
|
29
|
+
"@arronqzy/view-scene3d": "0.1.5",
|
|
30
|
+
"@arronqzy/view-table": "0.1.8",
|
|
31
31
|
"@arronqzy/vue-rx-store": "0.1.6",
|
|
32
|
-
"@arronqzy/
|
|
32
|
+
"@arronqzy/vue-blueprint": "0.1.17"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"vue": "^3.4.0"
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,12 @@ export {
|
|
|
13
13
|
createEmptyWorkspace,
|
|
14
14
|
} from "./panel/library/parse-workspace-data";
|
|
15
15
|
export { createWorkspaceProjectId } from "./panel/library/workspace-project-db";
|
|
16
|
+
export {
|
|
17
|
+
listWorkspaceProjects,
|
|
18
|
+
deleteWorkspaceProject,
|
|
19
|
+
clearWorkspaceProjects,
|
|
20
|
+
} from "./panel/library/workspace-storage";
|
|
21
|
+
export type { WorkspaceProjectListItem } from "./panel/library/workspace-storage";
|
|
16
22
|
export {
|
|
17
23
|
addEventSubscription,
|
|
18
24
|
AbuilderEvents,
|
|
@@ -9,14 +9,17 @@ import type { State } from "@arronqzy/rx-store";
|
|
|
9
9
|
import { useI18nOptional } from "@arronqzy/i18n/vue";
|
|
10
10
|
import {
|
|
11
11
|
createWorkspaceProjectId,
|
|
12
|
-
deleteWorkspaceProject,
|
|
13
12
|
getWorkspaceProject,
|
|
14
13
|
listWorkspaceProjects,
|
|
15
14
|
putWorkspaceProject,
|
|
16
15
|
type WorkspaceProjectListItem,
|
|
17
16
|
type WorkspaceProjectRecord,
|
|
18
17
|
} from "../library/workspace-project-db";
|
|
19
|
-
import {
|
|
18
|
+
import { deleteWorkspaceProject } from "../library/workspace-storage";
|
|
19
|
+
import {
|
|
20
|
+
broadcastWorkspaceProjectUpdate,
|
|
21
|
+
subscribeWorkspaceProjectsChanged,
|
|
22
|
+
} from "../library/workspace-project-sync";
|
|
20
23
|
import { writeWorkspacePreviewCache, readWorkspacePreviewCache } from "../library/workspace-project-cache";
|
|
21
24
|
import {
|
|
22
25
|
cloneWorkspaceSnapshot,
|
|
@@ -140,6 +143,26 @@ export function useWorkspaceProjects(options: UseWorkspaceProjectsOptions) {
|
|
|
140
143
|
}
|
|
141
144
|
);
|
|
142
145
|
|
|
146
|
+
watch(
|
|
147
|
+
() => nameSpace(),
|
|
148
|
+
(ns, _prev, onCleanup) => {
|
|
149
|
+
const unsubscribe = subscribeWorkspaceProjectsChanged((message) => {
|
|
150
|
+
const active = activeProjectId.value;
|
|
151
|
+
const removedActive =
|
|
152
|
+
message.type === "cleared" ||
|
|
153
|
+
(active !== null && message.projectIds.includes(active));
|
|
154
|
+
if (removedActive) {
|
|
155
|
+
activeProjectId.value = null;
|
|
156
|
+
activeProjectName.value = null;
|
|
157
|
+
syncedSnapshotRef.value = null;
|
|
158
|
+
}
|
|
159
|
+
void refreshProjects();
|
|
160
|
+
}, ns);
|
|
161
|
+
onCleanup(unsubscribe);
|
|
162
|
+
},
|
|
163
|
+
{ immediate: true }
|
|
164
|
+
);
|
|
165
|
+
|
|
143
166
|
onUnmounted(() => {
|
|
144
167
|
if (previewPollTimer !== undefined) window.clearInterval(previewPollTimer);
|
|
145
168
|
});
|
|
@@ -35,3 +35,30 @@ export function readWorkspacePreviewCache(
|
|
|
35
35
|
return null;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
|
|
39
|
+
export function removeWorkspacePreviewCache(
|
|
40
|
+
projectId: string,
|
|
41
|
+
nameSpace?: string | null
|
|
42
|
+
): void {
|
|
43
|
+
try {
|
|
44
|
+
localStorage.removeItem(previewCacheKey(projectId, nameSpace));
|
|
45
|
+
} catch {
|
|
46
|
+
// ignore private mode
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function clearWorkspacePreviewCaches(nameSpace?: string | null): void {
|
|
51
|
+
try {
|
|
52
|
+
const suffix = appStorageKey("", nameSpace);
|
|
53
|
+
const keys: string[] = [];
|
|
54
|
+
for (let i = 0; i < localStorage.length; i += 1) {
|
|
55
|
+
const key = localStorage.key(i);
|
|
56
|
+
if (!key || !key.startsWith(CACHE_PREFIX)) continue;
|
|
57
|
+
// 无 nameSpace 时 key 不带 "__<ns>" 后缀,避免误删其他 nameSpace 的标记
|
|
58
|
+
if (suffix ? key.endsWith(suffix) : !key.includes("__")) keys.push(key);
|
|
59
|
+
}
|
|
60
|
+
keys.forEach((key) => localStorage.removeItem(key));
|
|
61
|
+
} catch {
|
|
62
|
+
// ignore private mode
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -283,3 +283,7 @@ export async function deleteWorkspaceProject(
|
|
|
283
283
|
): Promise<void> {
|
|
284
284
|
await runTransaction<undefined>("readwrite", (store) => store.delete(id), nameSpace);
|
|
285
285
|
}
|
|
286
|
+
|
|
287
|
+
export async function clearWorkspaceProjectStore(nameSpace?: string | null): Promise<void> {
|
|
288
|
+
await runTransaction<undefined>("readwrite", (store) => store.clear(), nameSpace);
|
|
289
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { appStorageKey } from "@arronqzy/blueprint-dsl";
|
|
2
2
|
|
|
3
3
|
const CHANNEL_PREFIX = "arronqzy-workspace-project";
|
|
4
|
+
const LIST_CHANNEL = "arronqzy-workspace-projects-changed";
|
|
4
5
|
|
|
5
6
|
export type WorkspaceProjectSyncMessage = {
|
|
6
7
|
type: "updated";
|
|
@@ -8,6 +9,36 @@ export type WorkspaceProjectSyncMessage = {
|
|
|
8
9
|
updatedAt: number;
|
|
9
10
|
};
|
|
10
11
|
|
|
12
|
+
export type WorkspaceProjectsChangedMessage =
|
|
13
|
+
| { type: "deleted"; projectIds: string[] }
|
|
14
|
+
| { type: "cleared" };
|
|
15
|
+
|
|
16
|
+
export function broadcastWorkspaceProjectsChanged(
|
|
17
|
+
message: WorkspaceProjectsChangedMessage,
|
|
18
|
+
nameSpace?: string | null
|
|
19
|
+
): void {
|
|
20
|
+
if (typeof BroadcastChannel === "undefined") return;
|
|
21
|
+
const channel = new BroadcastChannel(appStorageKey(LIST_CHANNEL, nameSpace));
|
|
22
|
+
channel.postMessage(message);
|
|
23
|
+
channel.close();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function subscribeWorkspaceProjectsChanged(
|
|
27
|
+
onChange: (message: WorkspaceProjectsChangedMessage) => void,
|
|
28
|
+
nameSpace?: string | null
|
|
29
|
+
): () => void {
|
|
30
|
+
if (typeof BroadcastChannel === "undefined") {
|
|
31
|
+
return () => {};
|
|
32
|
+
}
|
|
33
|
+
const channel = new BroadcastChannel(appStorageKey(LIST_CHANNEL, nameSpace));
|
|
34
|
+
channel.onmessage = (event: MessageEvent<WorkspaceProjectsChangedMessage>) => {
|
|
35
|
+
const data = event.data;
|
|
36
|
+
if (!data || (data.type !== "deleted" && data.type !== "cleared")) return;
|
|
37
|
+
onChange(data);
|
|
38
|
+
};
|
|
39
|
+
return () => channel.close();
|
|
40
|
+
}
|
|
41
|
+
|
|
11
42
|
export function getWorkspaceProjectChannelName(
|
|
12
43
|
projectId: string,
|
|
13
44
|
nameSpace?: string | null
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearWorkspaceProjectStore,
|
|
3
|
+
deleteWorkspaceProject as deleteWorkspaceProjectRecord,
|
|
4
|
+
listWorkspaceProjects,
|
|
5
|
+
} from "./workspace-project-db";
|
|
6
|
+
import {
|
|
7
|
+
clearWorkspacePreviewCaches,
|
|
8
|
+
removeWorkspacePreviewCache,
|
|
9
|
+
} from "./workspace-project-cache";
|
|
10
|
+
import { broadcastWorkspaceProjectsChanged } from "./workspace-project-sync";
|
|
11
|
+
|
|
12
|
+
export { listWorkspaceProjects };
|
|
13
|
+
export type { WorkspaceProjectListItem } from "./workspace-project-db";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 删除 IndexedDB 中保存的单个工作区(及其 localStorage 预览标记)。
|
|
17
|
+
* `nameSpace` 需与 `VueViewPanel` 的 `nameSpace` 一致;已挂载的面板会自动刷新工作区列表。
|
|
18
|
+
*/
|
|
19
|
+
export async function deleteWorkspaceProject(
|
|
20
|
+
id: string,
|
|
21
|
+
nameSpace?: string | null
|
|
22
|
+
): Promise<void> {
|
|
23
|
+
await deleteWorkspaceProjectRecord(id, nameSpace);
|
|
24
|
+
removeWorkspacePreviewCache(id, nameSpace);
|
|
25
|
+
broadcastWorkspaceProjectsChanged({ type: "deleted", projectIds: [id] }, nameSpace);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 清空该 `nameSpace` 下保存的全部工作区,返回删除的数量。
|
|
30
|
+
* 不影响蓝图库、执行日志、接口集合等其他存储。
|
|
31
|
+
*/
|
|
32
|
+
export async function clearWorkspaceProjects(nameSpace?: string | null): Promise<number> {
|
|
33
|
+
const items = await listWorkspaceProjects(nameSpace);
|
|
34
|
+
await clearWorkspaceProjectStore(nameSpace);
|
|
35
|
+
clearWorkspacePreviewCaches(nameSpace);
|
|
36
|
+
broadcastWorkspaceProjectsChanged({ type: "cleared" }, nameSpace);
|
|
37
|
+
return items.length;
|
|
38
|
+
}
|