fix: portable 版 3D 拓扑设备位置 fallback 到主进程 JSON
Some checks failed
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled

renderer 原来只读 localStorage 的 monitoring-topology-positions,
portable 版 userData 是全新空目录,Local Storage 里没有这个 key,
导致设备布局 fallback 到大圆圈自动布局。

加主进程 inspection-data.json 的同步 fallback:
- preload/api.cjs 新增 getTopologyPositionsSync(ipcRenderer.sendSync)
- index.cjs 新增 ipcMain.on 同步 handler(与 handle 并存)
- MonitoringTopologyView.tsx localStorage 找不到时 fallback 读主进程 JSON
This commit is contained in:
2026-10-21 17:35:19 +08:00
committed by trae-solo-agent
parent 1c3c8c4b20
commit 4d343d5de3
3 changed files with 25 additions and 4 deletions

View File

@@ -1,4 +1,4 @@
/**
/**
* 运行监控 - 3D 拓扑大屏
*
* 移植自 ITYUNWEI TopologyView.vue
@@ -2306,10 +2306,20 @@ export function MonitoringTopologyView({ hosts, keys }: Props) {
}
} catch { /* ignore */ }
}
// 本地 Electron:从 localStorage 读
// 本地 Electron:从 localStorage 读,找不到则从主进程 inspection-data.json 读
try {
const saved = localStorage.getItem('monitoring-topology-positions');
return saved ? JSON.parse(saved) : null;
let saved = localStorage.getItem('monitoring-topology-positions');
if (saved) return JSON.parse(saved);
// portable 版 localStorage 为空 → fallback 主进程 JSON(sendSync 同步)
try {
const nc = (window as any).netcatty;
const fromMain = nc?.inspection?.getTopologyPositionsSync?.();
if (fromMain && typeof fromMain === 'object' && Object.keys(fromMain).length > 0) {
console.info('[Monitoring] localStorage 无位置,从主进程 inspection-data.json 加载');
return fromMain;
}
} catch { /* ignore */ }
return null;
} catch { return null; }
})();

View File

@@ -1544,6 +1544,13 @@ function registerInspectionHandlers(ipcMain, options) {
} catch { return {}; }
});
// sendSync 同步版本 — renderer 3D 布局 fallback 读取用
ipcMain.on("inspection:getTopologyPositions", (event) => {
try {
event.returnValue = readStorage("_topology_positions") || {};
} catch { event.returnValue = {}; }
});
// 监控大屏标题同步(Electron localStorage → 远程浏览器可读)
ipcMain.handle("inspection:saveDashboardTitle", (_e, title) => {
if (!title || typeof title !== "string") return { ok: false };

View File

@@ -2122,6 +2122,10 @@ function createPreloadApi(ctx) {
// 拓扑位置持久化(供远程浏览器同步读取)
saveTopologyPositions: (positions) => ipcRenderer.invoke("inspection:saveTopologyPositions", positions),
getTopologyPositions: () => ipcRenderer.invoke("inspection:getTopologyPositions"),
// 同步版本 — renderer 3D 布局同步加载位置时用(portable 版 localStorage 为空时 fallback 读主进程 JSON)
getTopologyPositionsSync: () => {
try { return ipcRenderer.sendSync("inspection:getTopologyPositions"); } catch { return null; }
},
// 监控大屏标题同步
saveDashboardTitle: (title) => ipcRenderer.invoke("inspection:saveDashboardTitle", title),
getDashboardTitle: () => ipcRenderer.invoke("inspection:getDashboardTitle"),