@arronqzy/react-view 1.0.36 → 1.0.38
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 +5 -5
- package/readme.md +10 -1
- package/src/index.ts +34 -0
- package/src/panel/ReactViewPanel.tsx +6 -0
- package/src/panel/hooks/useWorkspaceProjects.ts +19 -2
- package/src/panel/library/abuilder-storage.ts +70 -0
- package/src/panel/library/blueprint-library-sync.ts +22 -0
- package/src/panel/library/event-subscription.ts +9 -0
- 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 +51 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arronqzy/react-view",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.38",
|
|
4
4
|
"files": [
|
|
5
5
|
"src",
|
|
6
6
|
"dist",
|
|
@@ -33,11 +33,11 @@
|
|
|
33
33
|
"@arronqzy/blueprint-dsl": "1.0.17",
|
|
34
34
|
"@arronqzy/ui": "1.0.10",
|
|
35
35
|
"@arronqzy/i18n": "0.1.17",
|
|
36
|
-
"@arronqzy/react-blueprint": "1.0.
|
|
36
|
+
"@arronqzy/react-blueprint": "1.0.23",
|
|
37
37
|
"@arronqzy/rx-store": "1.0.8",
|
|
38
38
|
"@arronqzy/view-scene3d": "0.1.5",
|
|
39
|
-
"@arronqzy/
|
|
40
|
-
"@arronqzy/
|
|
39
|
+
"@arronqzy/webllm-assistant": "0.1.16",
|
|
40
|
+
"@arronqzy/view-table": "0.1.8"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/react": "^19.0.1",
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"@types/use-sync-external-store": "^1.5.0",
|
|
46
46
|
"eslint": "^8.57.0",
|
|
47
47
|
"typescript": "^5.5.4",
|
|
48
|
-
"@arronqzy/typescript-config": "1.0.0",
|
|
49
48
|
"@arronqzy/eslint-config": "0.0.0",
|
|
49
|
+
"@arronqzy/typescript-config": "1.0.0",
|
|
50
50
|
"@arronqzy/tailwind": "1.0.2"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
package/readme.md
CHANGED
|
@@ -112,8 +112,9 @@ syncSub.unsubscribe();
|
|
|
112
112
|
|------|------|----------|
|
|
113
113
|
| `workspace:add` | `AbuilderEvents.workspaceAdd` | 创建成功 |
|
|
114
114
|
| `workspace:sync` | `AbuilderEvents.workspaceSync` | 同步成功 |
|
|
115
|
+
| `workspace:delete` | `AbuilderEvents.workspaceDelete` | 删除工作区,参数 `{ ids, nameSpace }` |
|
|
115
116
|
|
|
116
|
-
|
|
117
|
+
`workspace:add` / `workspace:sync` 的参数字段:`id`、`name`、`createdAt`、`updatedAt`、`panelState`、`blueprintDocument`、`blueprintMeta`、`productName`、`titleIconDataUrl`。
|
|
117
118
|
|
|
118
119
|
校验:
|
|
119
120
|
|
|
@@ -154,6 +155,14 @@ const dataUrl = await getPreviewSnapshot({
|
|
|
154
155
|
| `addEventSubscription` / `AbuilderEvents` | 工作区事件 |
|
|
155
156
|
| `getPreviewSnapshot` | 预览截图 data URL |
|
|
156
157
|
| `parseWorkspaceData` 等 | 校验 / 解析 / 空工作区 |
|
|
158
|
+
| `listWorkspaceProjects` / `getWorkspaceProject` / `deleteWorkspaceProject` / `clearWorkspaceProjects` | 浏览器 IndexedDB 中保存的工作区 |
|
|
159
|
+
| `listBlueprintLibrary` / `getBlueprintLibraryRecord` / `deleteBlueprintLibraryRecord` / `clearBlueprintLibrary` | 蓝图库;删除后已挂载的面板自动刷新 |
|
|
160
|
+
| `listExecutionRunRecords` / `getExecutionRunRecord` / `deleteExecutionRunRecord` / `clearAllExecutionRunRecords` / `purgeExecutionRunsOlderThan` / `trimExecutionRunRecordsToMax` | 蓝图执行日志 |
|
|
161
|
+
| `readExecutionLogSettings` / `writeExecutionLogSettings` | 执行日志保留策略 |
|
|
162
|
+
| `listApiCollectionRecords` / `deleteApiCollection` / `clearApiCollections` | 接口集合 |
|
|
163
|
+
| `clearAbuilderStorage` | 一次清空以上四类数据,返回各自删除数量;不动偏好设置 |
|
|
164
|
+
|
|
165
|
+
本地数据函数的最后一个参数都是 `nameSpace`,要和面板的 `nameSpace` 一致。
|
|
157
166
|
| `createView` / `createAction` | 视图 DSL 扩展点(`src/core`) |
|
|
158
167
|
|
|
159
168
|
## 样式
|
package/src/index.ts
CHANGED
|
@@ -14,10 +14,44 @@ export type {
|
|
|
14
14
|
AbuilderEventPayloadMap,
|
|
15
15
|
WorkspaceAddEventPayload,
|
|
16
16
|
WorkspaceSyncEventPayload,
|
|
17
|
+
WorkspaceDeleteEventPayload,
|
|
17
18
|
ApiCollectionUploadStartEventPayload,
|
|
18
19
|
ApiCollectionUploadSuccessEventPayload,
|
|
19
20
|
WorkspaceData,
|
|
20
21
|
} from "./panel/library/event-subscription";
|
|
21
22
|
export type { WorkspaceProjectRecord } from "./panel/library/workspace-project-db";
|
|
23
|
+
export {
|
|
24
|
+
listWorkspaceProjects,
|
|
25
|
+
getWorkspaceProject,
|
|
26
|
+
deleteWorkspaceProject,
|
|
27
|
+
clearWorkspaceProjects,
|
|
28
|
+
} from "./panel/library/workspace-storage";
|
|
29
|
+
export type { WorkspaceProjectListItem } from "./panel/library/workspace-storage";
|
|
30
|
+
export {
|
|
31
|
+
listBlueprintLibrary,
|
|
32
|
+
getBlueprintLibraryRecord,
|
|
33
|
+
deleteBlueprintLibraryRecord,
|
|
34
|
+
clearBlueprintLibrary,
|
|
35
|
+
listExecutionRunRecords,
|
|
36
|
+
getExecutionRunRecord,
|
|
37
|
+
deleteExecutionRunRecord,
|
|
38
|
+
clearAllExecutionRunRecords,
|
|
39
|
+
purgeExecutionRunsOlderThan,
|
|
40
|
+
trimExecutionRunRecordsToMax,
|
|
41
|
+
readExecutionLogSettings,
|
|
42
|
+
writeExecutionLogSettings,
|
|
43
|
+
listApiCollectionRecords,
|
|
44
|
+
deleteApiCollection,
|
|
45
|
+
clearApiCollections,
|
|
46
|
+
clearAbuilderStorage,
|
|
47
|
+
} from "./panel/library/abuilder-storage";
|
|
48
|
+
export type {
|
|
49
|
+
AbuilderStorageClearResult,
|
|
50
|
+
BlueprintLibraryListItem,
|
|
51
|
+
BlueprintLibraryRecord,
|
|
52
|
+
ExecutionRunRecord,
|
|
53
|
+
ExecutionLogSettings,
|
|
54
|
+
ApiCollectionRecord,
|
|
55
|
+
} from "./panel/library/abuilder-storage";
|
|
22
56
|
export { getPreviewSnapshot } from "./panel/library/preview-snapshot";
|
|
23
57
|
export type { GetPreviewSnapshotOptions } from "./panel/library/preview-snapshot";
|
|
@@ -7,6 +7,7 @@ import type { PanelElement } from "./types";
|
|
|
7
7
|
import { usePanelElements } from "./hooks/usePanelElements";
|
|
8
8
|
import { useWorkspaceProjects } from "./hooks/useWorkspaceProjects";
|
|
9
9
|
import type { WorkspaceProjectRecord } from "./library/workspace-project-db";
|
|
10
|
+
import { subscribeBlueprintLibraryChanged } from "./library/blueprint-library-sync";
|
|
10
11
|
import { WorkspaceProjectNav } from "./components/WorkspaceProjectNav";
|
|
11
12
|
import { BusyOverlay } from "./components/BusyOverlay";
|
|
12
13
|
import { PanelCanvas } from "./components/PanelCanvas";
|
|
@@ -803,6 +804,11 @@ function ReactViewPanelInner({
|
|
|
803
804
|
void refreshBlueprintLibrary();
|
|
804
805
|
}, [refreshBlueprintLibrary]);
|
|
805
806
|
|
|
807
|
+
useEffect(
|
|
808
|
+
() => subscribeBlueprintLibraryChanged(() => void refreshBlueprintLibrary(), nameSpace),
|
|
809
|
+
[nameSpace, refreshBlueprintLibrary]
|
|
810
|
+
);
|
|
811
|
+
|
|
806
812
|
const loadBlueprintFromLibrary = useCallback(
|
|
807
813
|
async (id: string) => {
|
|
808
814
|
const record = await getBlueprintLibraryRecord(id, nameSpace);
|
|
@@ -5,14 +5,17 @@ import type { BlueprintDocument, BlueprintMetaDraft } from "@arronqzy/react-blue
|
|
|
5
5
|
import type { State } from "@arronqzy/rx-store";
|
|
6
6
|
import {
|
|
7
7
|
createWorkspaceProjectId,
|
|
8
|
-
deleteWorkspaceProject,
|
|
9
8
|
getWorkspaceProject,
|
|
10
9
|
listWorkspaceProjects,
|
|
11
10
|
putWorkspaceProject,
|
|
12
11
|
type WorkspaceProjectListItem,
|
|
13
12
|
type WorkspaceProjectRecord,
|
|
14
13
|
} from "../library/workspace-project-db";
|
|
15
|
-
import {
|
|
14
|
+
import { deleteWorkspaceProject } from "../library/workspace-storage";
|
|
15
|
+
import {
|
|
16
|
+
broadcastWorkspaceProjectUpdate,
|
|
17
|
+
subscribeWorkspaceProjectsChanged,
|
|
18
|
+
} from "../library/workspace-project-sync";
|
|
16
19
|
import { writeWorkspacePreviewCache, readWorkspacePreviewCache } from "../library/workspace-project-cache";
|
|
17
20
|
import {
|
|
18
21
|
cloneWorkspaceSnapshot,
|
|
@@ -159,6 +162,20 @@ export function useWorkspaceProjects({
|
|
|
159
162
|
void refreshProjects();
|
|
160
163
|
}, [refreshProjects]);
|
|
161
164
|
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
return subscribeWorkspaceProjectsChanged((message) => {
|
|
167
|
+
const removedActive =
|
|
168
|
+
message.type === "cleared" ||
|
|
169
|
+
(activeProjectId !== null && message.projectIds.includes(activeProjectId));
|
|
170
|
+
if (removedActive) {
|
|
171
|
+
setActiveProjectId(null);
|
|
172
|
+
setActiveProjectName(null);
|
|
173
|
+
syncedSnapshotRef.current = null;
|
|
174
|
+
}
|
|
175
|
+
void refreshProjects();
|
|
176
|
+
}, nameSpace);
|
|
177
|
+
}, [activeProjectId, nameSpace, refreshProjects]);
|
|
178
|
+
|
|
162
179
|
useEffect(() => {
|
|
163
180
|
if (!pendingRevisionSyncRef.current) return;
|
|
164
181
|
syncedPanelRevisionRef.current = panelRevision;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearAllExecutionRunRecords,
|
|
3
|
+
clearApiCollections,
|
|
4
|
+
clearBlueprintLibrary as clearBlueprintLibraryRecords,
|
|
5
|
+
deleteBlueprintLibraryRecord as deleteBlueprintLibraryRecordRaw,
|
|
6
|
+
} from "@arronqzy/react-blueprint";
|
|
7
|
+
import { broadcastBlueprintLibraryChanged } from "./blueprint-library-sync";
|
|
8
|
+
import { clearWorkspaceProjects } from "./workspace-storage";
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
listBlueprintLibrary,
|
|
12
|
+
getBlueprintLibraryRecord,
|
|
13
|
+
listExecutionRunRecords,
|
|
14
|
+
getExecutionRunRecord,
|
|
15
|
+
deleteExecutionRunRecord,
|
|
16
|
+
clearAllExecutionRunRecords,
|
|
17
|
+
purgeExecutionRunsOlderThan,
|
|
18
|
+
trimExecutionRunRecordsToMax,
|
|
19
|
+
readExecutionLogSettings,
|
|
20
|
+
writeExecutionLogSettings,
|
|
21
|
+
listApiCollectionRecords,
|
|
22
|
+
deleteApiCollection,
|
|
23
|
+
clearApiCollections,
|
|
24
|
+
} from "@arronqzy/react-blueprint";
|
|
25
|
+
export type {
|
|
26
|
+
BlueprintLibraryListItem,
|
|
27
|
+
BlueprintLibraryRecord,
|
|
28
|
+
ExecutionRunRecord,
|
|
29
|
+
ExecutionLogSettings,
|
|
30
|
+
} from "@arronqzy/react-blueprint";
|
|
31
|
+
export type { ApiCollectionRecord } from "@arronqzy/blueprint-dsl";
|
|
32
|
+
|
|
33
|
+
/** 删除蓝图库中的一条蓝图;已挂载的编辑器会刷新蓝图库列表 */
|
|
34
|
+
export async function deleteBlueprintLibraryRecord(
|
|
35
|
+
id: string,
|
|
36
|
+
nameSpace?: string | null
|
|
37
|
+
): Promise<void> {
|
|
38
|
+
await deleteBlueprintLibraryRecordRaw(id, nameSpace);
|
|
39
|
+
broadcastBlueprintLibraryChanged(nameSpace);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** 清空该 nameSpace 下的蓝图库,返回删除数量;已挂载的编辑器会刷新蓝图库列表 */
|
|
43
|
+
export async function clearBlueprintLibrary(nameSpace?: string | null): Promise<number> {
|
|
44
|
+
const count = await clearBlueprintLibraryRecords(nameSpace);
|
|
45
|
+
broadcastBlueprintLibraryChanged(nameSpace);
|
|
46
|
+
return count;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type AbuilderStorageClearResult = {
|
|
50
|
+
workspaces: number;
|
|
51
|
+
blueprints: number;
|
|
52
|
+
executionRuns: number;
|
|
53
|
+
apiCollections: number;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* 清空该 nameSpace 下编辑器写入浏览器的全部数据:工作区、蓝图库、执行日志、接口集合。
|
|
58
|
+
* 主题、字号、日志保留设置等偏好不受影响。
|
|
59
|
+
*/
|
|
60
|
+
export async function clearAbuilderStorage(
|
|
61
|
+
nameSpace?: string | null
|
|
62
|
+
): Promise<AbuilderStorageClearResult> {
|
|
63
|
+
const [workspaces, blueprints, executionRuns, apiCollections] = await Promise.all([
|
|
64
|
+
clearWorkspaceProjects(nameSpace),
|
|
65
|
+
clearBlueprintLibrary(nameSpace),
|
|
66
|
+
clearAllExecutionRunRecords(nameSpace),
|
|
67
|
+
clearApiCollections(nameSpace),
|
|
68
|
+
]);
|
|
69
|
+
return { workspaces, blueprints, executionRuns, apiCollections };
|
|
70
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { appStorageKey } from "@arronqzy/blueprint-dsl";
|
|
2
|
+
|
|
3
|
+
const CHANNEL = "arronqzy-blueprint-library-changed";
|
|
4
|
+
|
|
5
|
+
export function broadcastBlueprintLibraryChanged(nameSpace?: string | null): void {
|
|
6
|
+
if (typeof BroadcastChannel === "undefined") return;
|
|
7
|
+
const channel = new BroadcastChannel(appStorageKey(CHANNEL, nameSpace));
|
|
8
|
+
channel.postMessage({ type: "changed" });
|
|
9
|
+
channel.close();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function subscribeBlueprintLibraryChanged(
|
|
13
|
+
onChange: () => void,
|
|
14
|
+
nameSpace?: string | null
|
|
15
|
+
): () => void {
|
|
16
|
+
if (typeof BroadcastChannel === "undefined") {
|
|
17
|
+
return () => {};
|
|
18
|
+
}
|
|
19
|
+
const channel = new BroadcastChannel(appStorageKey(CHANNEL, nameSpace));
|
|
20
|
+
channel.onmessage = () => onChange();
|
|
21
|
+
return () => channel.close();
|
|
22
|
+
}
|
|
@@ -5,6 +5,8 @@ export const AbuilderEvents = {
|
|
|
5
5
|
workspaceAdd: "workspace:add",
|
|
6
6
|
/** 同步工作区 */
|
|
7
7
|
workspaceSync: "workspace:sync",
|
|
8
|
+
/** 删除工作区(界面删除,或调用 deleteWorkspaceProject / clearWorkspaceProjects) */
|
|
9
|
+
workspaceDelete: "workspace:delete",
|
|
8
10
|
/** 开始上传接口集合 */
|
|
9
11
|
apiCollectionUploadStart: "api-collection:upload-start",
|
|
10
12
|
/** 上传接口集合成功 */
|
|
@@ -18,6 +20,12 @@ export type WorkspaceData = WorkspaceProjectRecord;
|
|
|
18
20
|
|
|
19
21
|
export type WorkspaceAddEventPayload = WorkspaceData;
|
|
20
22
|
export type WorkspaceSyncEventPayload = WorkspaceData;
|
|
23
|
+
export type WorkspaceDeleteEventPayload = {
|
|
24
|
+
/** 被删除的工作区 id */
|
|
25
|
+
ids: string[];
|
|
26
|
+
/** 所属 nameSpace,默认库为 null */
|
|
27
|
+
nameSpace: string | null;
|
|
28
|
+
};
|
|
21
29
|
|
|
22
30
|
export type ApiCollectionUploadStartEventPayload = {
|
|
23
31
|
fileNames: string[];
|
|
@@ -36,6 +44,7 @@ export type ApiCollectionUploadSuccessEventPayload = {
|
|
|
36
44
|
export type AbuilderEventPayloadMap = {
|
|
37
45
|
[AbuilderEvents.workspaceAdd]: WorkspaceAddEventPayload;
|
|
38
46
|
[AbuilderEvents.workspaceSync]: WorkspaceSyncEventPayload;
|
|
47
|
+
[AbuilderEvents.workspaceDelete]: WorkspaceDeleteEventPayload;
|
|
39
48
|
[AbuilderEvents.apiCollectionUploadStart]: ApiCollectionUploadStartEventPayload;
|
|
40
49
|
[AbuilderEvents.apiCollectionUploadSuccess]: ApiCollectionUploadSuccessEventPayload;
|
|
41
50
|
};
|
|
@@ -36,3 +36,30 @@ export function readWorkspacePreviewCache(
|
|
|
36
36
|
return null;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
export function removeWorkspacePreviewCache(
|
|
41
|
+
projectId: string,
|
|
42
|
+
nameSpace?: string | null
|
|
43
|
+
): void {
|
|
44
|
+
try {
|
|
45
|
+
localStorage.removeItem(previewCacheKey(projectId, nameSpace));
|
|
46
|
+
} catch {
|
|
47
|
+
// ignore private mode
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function clearWorkspacePreviewCaches(nameSpace?: string | null): void {
|
|
52
|
+
try {
|
|
53
|
+
const suffix = appStorageKey("", nameSpace);
|
|
54
|
+
const keys: string[] = [];
|
|
55
|
+
for (let i = 0; i < localStorage.length; i += 1) {
|
|
56
|
+
const key = localStorage.key(i);
|
|
57
|
+
if (!key || !key.startsWith(CACHE_PREFIX)) continue;
|
|
58
|
+
// 无 nameSpace 时 key 不带 "__<ns>" 后缀,避免误删其他 nameSpace 的标记
|
|
59
|
+
if (suffix ? key.endsWith(suffix) : !key.includes("__")) keys.push(key);
|
|
60
|
+
}
|
|
61
|
+
keys.forEach((key) => localStorage.removeItem(key));
|
|
62
|
+
} catch {
|
|
63
|
+
// ignore private mode
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -286,3 +286,7 @@ export async function deleteWorkspaceProject(
|
|
|
286
286
|
): Promise<void> {
|
|
287
287
|
await runTransaction<undefined>("readwrite", (store) => store.delete(id), nameSpace);
|
|
288
288
|
}
|
|
289
|
+
|
|
290
|
+
export async function clearWorkspaceProjectStore(nameSpace?: string | null): Promise<void> {
|
|
291
|
+
await runTransaction<undefined>("readwrite", (store) => store.clear(), nameSpace);
|
|
292
|
+
}
|
|
@@ -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,51 @@
|
|
|
1
|
+
import { normalizeAppNameSpace } from "@arronqzy/blueprint-dsl";
|
|
2
|
+
import {
|
|
3
|
+
clearWorkspaceProjectStore,
|
|
4
|
+
deleteWorkspaceProject as deleteWorkspaceProjectRecord,
|
|
5
|
+
getWorkspaceProject,
|
|
6
|
+
listWorkspaceProjects,
|
|
7
|
+
} from "./workspace-project-db";
|
|
8
|
+
import {
|
|
9
|
+
clearWorkspacePreviewCaches,
|
|
10
|
+
removeWorkspacePreviewCache,
|
|
11
|
+
} from "./workspace-project-cache";
|
|
12
|
+
import { broadcastWorkspaceProjectsChanged } from "./workspace-project-sync";
|
|
13
|
+
import { AbuilderEvents, emitAbuilderEvent } from "./event-subscription";
|
|
14
|
+
|
|
15
|
+
export { listWorkspaceProjects, getWorkspaceProject };
|
|
16
|
+
export type { WorkspaceProjectListItem } from "./workspace-project-db";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 删除 IndexedDB 中保存的单个工作区(及其 localStorage 预览标记)。
|
|
20
|
+
* `nameSpace` 需与 `ReactViewPanel` 的 `nameSpace` 一致;已挂载的面板会自动刷新工作区列表。
|
|
21
|
+
*/
|
|
22
|
+
export async function deleteWorkspaceProject(
|
|
23
|
+
id: string,
|
|
24
|
+
nameSpace?: string | null
|
|
25
|
+
): Promise<void> {
|
|
26
|
+
await deleteWorkspaceProjectRecord(id, nameSpace);
|
|
27
|
+
removeWorkspacePreviewCache(id, nameSpace);
|
|
28
|
+
broadcastWorkspaceProjectsChanged({ type: "deleted", projectIds: [id] }, nameSpace);
|
|
29
|
+
emitAbuilderEvent(AbuilderEvents.workspaceDelete, {
|
|
30
|
+
ids: [id],
|
|
31
|
+
nameSpace: normalizeAppNameSpace(nameSpace) || null,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* 清空该 `nameSpace` 下保存的全部工作区,返回删除的数量。
|
|
37
|
+
* 不影响蓝图库、执行日志、接口集合等其他存储。
|
|
38
|
+
*/
|
|
39
|
+
export async function clearWorkspaceProjects(nameSpace?: string | null): Promise<number> {
|
|
40
|
+
const items = await listWorkspaceProjects(nameSpace);
|
|
41
|
+
await clearWorkspaceProjectStore(nameSpace);
|
|
42
|
+
clearWorkspacePreviewCaches(nameSpace);
|
|
43
|
+
broadcastWorkspaceProjectsChanged({ type: "cleared" }, nameSpace);
|
|
44
|
+
if (items.length > 0) {
|
|
45
|
+
emitAbuilderEvent(AbuilderEvents.workspaceDelete, {
|
|
46
|
+
ids: items.map((item) => item.id),
|
|
47
|
+
nameSpace: normalizeAppNameSpace(nameSpace) || null,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return items.length;
|
|
51
|
+
}
|