import { BrowserWindow } from 'electron'; import type { WebContents } from 'electron'; import { logger } from 'ee-core/log'; import { closeSmartWindow, focusMainWindow, isSmartWindow, isSmartWindowOpen, openSmartWindow, } from '../service/window/smartWindow'; /** 主进程 → 渲染进程的跨窗口状态事件通道 */ export const SYNC_EVENT_CHANNEL = 'app:state'; interface IpcEventLike { sender?: WebContents; } interface OpenSmartWindowParams { fullPath?: string; reloadIfOpen?: boolean; navigateIfOpen?: boolean; } interface SyncStateParams { event?: { type?: string; payload?: Record; }; } function toMessage(error: unknown): string { return error instanceof Error ? error.message : String(error); } /** * 窗口管理 IPC:通道名 controller/windowCtl/<方法>(ee-core 按文件名自动注册)。 * * 统一返回 { success, data|message },失败不抛到 Electron 层。 */ class WindowCtl { /** 打开/聚焦智能工作台窗口;params { fullPath?, reloadIfOpen? } */ async openSmartWindow(params: OpenSmartWindowParams = {}) { try { openSmartWindow({ fullPath: params?.fullPath, reloadIfOpen: params?.reloadIfOpen === true, navigateIfOpen: params?.navigateIfOpen === true, }); return { success: true, data: { open: true } }; } catch (e) { const message = toMessage(e); logger.error('[windowCtl] openSmartWindow failed:', message); return { success: false, message }; } } /** 关闭智能工作台窗口(已关闭时是 no-op) */ async closeSmartWindow() { try { closeSmartWindow(); return { success: true }; } catch (e) { const message = toMessage(e); logger.error('[windowCtl] closeSmartWindow failed:', message); return { success: false, message }; } } async isSmartWindowOpen() { return { success: true, data: { open: isSmartWindowOpen() } }; } /** 智能窗口遇到登录失效时,把主窗口拉到前台负责提示 */ async focusMainWindow() { try { focusMainWindow(); return { success: true }; } catch (e) { const message = toMessage(e); logger.error('[windowCtl] focusMainWindow failed:', message); return { success: false, message }; } } /** * 渲染进程启动时问一次自己的角色。 * *

ee-core 的 IPC 注册是 fn.call(controller, params, event), * event.sender 就是发起调用的 webContents。 */ async getWindowRole(_params: unknown, event?: IpcEventLike) { const win = event?.sender ? BrowserWindow.fromWebContents(event.sender) : null; return { success: true, data: { role: isSmartWindow(win) ? 'smart' : 'main' } }; } /** * 跨窗口状态同步:把语义事件发给除发送者外的所有窗口。 * *

只做转发,不解释业务;接收方负责按事件类型重读事实源或关闭自己。 */ async syncState(params: SyncStateParams, event?: IpcEventLike) { const payload = params?.event; if (!payload?.type) { return { success: false, message: '同步事件缺少 type' }; } const senderId = event?.sender?.id; for (const win of BrowserWindow.getAllWindows()) { if (win.isDestroyed() || win.webContents.isDestroyed()) continue; if (senderId && win.webContents.id === senderId) continue; try { win.webContents.send(SYNC_EVENT_CHANNEL, payload); } catch (e) { logger.warn('[windowCtl] syncState send failed:', toMessage(e)); } } return { success: true }; } } WindowCtl.toString = () => 'WindowCtl'; export default WindowCtl;