import { app, BrowserWindow, ipcMain, shell, dialog } from 'electron'; import * as path from 'path'; import * as fs from 'fs'; import express from 'express'; import { GrpcClient } from './modules/grpc-client'; import { SecureStorage } from './modules/storage'; // 内置 HTTP 服务器端口 const HTTP_PORT = 3456; let mainWindow: BrowserWindow | null = null; let grpcClient: GrpcClient | null = null; let storage: SecureStorage | null = null; let httpServer: ReturnType | null = null; // 创建主窗口 function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, minWidth: 800, minHeight: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true, nodeIntegration: false, }, titleBarStyle: 'hiddenInset', show: false, }); // 开发模式下加载 Vite 开发服务器 if (process.env.NODE_ENV === 'development') { mainWindow.loadURL('http://localhost:5173'); mainWindow.webContents.openDevTools(); } else { // 生产模式下加载打包后的文件 mainWindow.loadFile(path.join(__dirname, '../dist/index.html')); } mainWindow.once('ready-to-show', () => { mainWindow?.show(); }); mainWindow.on('closed', () => { mainWindow = null; }); // 处理外部链接 mainWindow.webContents.setWindowOpenHandler(({ url }) => { shell.openExternal(url); return { action: 'deny' }; }); } // 启动内置 HTTP 服务器 function startHttpServer() { const expressApp = express(); expressApp.use(express.json()); expressApp.use(express.static(path.join(__dirname, '../dist'))); // API 路由 expressApp.get('/api/status', (_req, res) => { res.json({ connected: grpcClient?.isConnected() ?? false, partyId: grpcClient?.getPartyId() ?? null, }); }); // 所有其他路由返回 index.html (SPA) expressApp.get('*', (_req, res) => { res.sendFile(path.join(__dirname, '../dist/index.html')); }); httpServer = expressApp.listen(HTTP_PORT, '127.0.0.1', () => { console.log(`HTTP server running at http://127.0.0.1:${HTTP_PORT}`); }); } // 初始化服务 async function initServices() { // 初始化 gRPC 客户端 grpcClient = new GrpcClient(); // 初始化安全存储 storage = new SecureStorage(); // 设置 IPC 处理器 setupIpcHandlers(); } // 设置 IPC 通信处理器 function setupIpcHandlers() { // gRPC 连接 ipcMain.handle('grpc:connect', async (_event, { host, port }) => { try { await grpcClient?.connect(host, port); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 注册为参与方 ipcMain.handle('grpc:register', async (_event, { partyId, role }) => { try { await grpcClient?.registerParty(partyId, role); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 加入会话 ipcMain.handle('grpc:joinSession', async (_event, { sessionId, partyId, joinToken }) => { try { const result = await grpcClient?.joinSession(sessionId, partyId, joinToken); return { success: true, data: result }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 存储 - 保存 share ipcMain.handle('storage:saveShare', async (_event, { share, password }) => { try { storage?.saveShare(share, password); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 存储 - 获取 share 列表 ipcMain.handle('storage:listShares', async () => { try { const shares = storage?.listShares() ?? []; return { success: true, data: shares }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 存储 - 导出 share ipcMain.handle('storage:exportShare', async (_event, { id, password }) => { try { const data = storage?.exportShare(id, password); return { success: true, data }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 存储 - 导入 share (从文件路径) ipcMain.handle('storage:importShare', async (_event, { filePath, password }) => { try { const data = fs.readFileSync(filePath); const share = storage?.importShare(data, password); return { success: true, share }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 存储 - 获取单个 share ipcMain.handle('storage:getShare', async (_event, { id, password }) => { try { const share = storage?.getShare(id, password); return share; } catch (error) { return null; } }); // 存储 - 删除 share ipcMain.handle('storage:deleteShare', async (_event, { id }) => { try { storage?.deleteShare(id); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // 存储 - 获取设置 ipcMain.handle('storage:getSettings', async () => { try { return storage?.getSettings() ?? null; } catch (error) { return null; } }); // 存储 - 保存设置 ipcMain.handle('storage:saveSettings', async (_event, { settings }) => { try { storage?.saveSettings(settings); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // gRPC - 创建会话 ipcMain.handle('grpc:createSession', async (_event, params) => { // TODO: 实现创建会话逻辑 return { success: false, error: '功能尚未实现 - 需要连接到 Session Coordinator' }; }); // gRPC - 验证邀请码 ipcMain.handle('grpc:validateInviteCode', async (_event, { code }) => { // TODO: 实现验证邀请码逻辑 return { success: false, error: '功能尚未实现 - 需要连接到 Session Coordinator' }; }); // gRPC - 获取会话状态 ipcMain.handle('grpc:getSessionStatus', async (_event, { sessionId }) => { // TODO: 实现获取会话状态逻辑 return { success: false, error: '功能尚未实现' }; }); // gRPC - 测试连接 ipcMain.handle('grpc:testConnection', async (_event, { url }) => { try { // 地址格式: host:port (例如 mpc-grpc.szaiai.com:443) await grpcClient?.connect(url); return { success: true }; } catch (error) { return { success: false, error: (error as Error).message }; } }); // gRPC - 验证签名会话 ipcMain.handle('grpc:validateSigningSession', async (_event, { code }) => { // TODO: 实现验证签名会话逻辑 return { success: false, error: '功能尚未实现 - 需要连接到 Session Coordinator' }; }); // gRPC - 加入签名会话 ipcMain.handle('grpc:joinSigningSession', async (_event, params) => { // TODO: 实现加入签名会话逻辑 return { success: false, error: '功能尚未实现' }; }); // 对话框 - 选择目录 ipcMain.handle('dialog:selectDirectory', async () => { const result = await dialog.showOpenDialog(mainWindow!, { properties: ['openDirectory'], }); return result.canceled ? null : result.filePaths[0]; }); // 对话框 - 选择文件 ipcMain.handle('dialog:selectFile', async (_event, { filters }) => { const result = await dialog.showOpenDialog(mainWindow!, { properties: ['openFile'], filters: filters || [], }); return result.canceled ? null : result.filePaths[0]; }); // 对话框 - 保存文件 ipcMain.handle('dialog:saveFile', async (_event, { defaultPath, filters }) => { const result = await dialog.showSaveDialog(mainWindow!, { defaultPath, filters: filters || [], }); return result.canceled ? null : result.filePath; }); } // 应用生命周期 app.whenReady().then(async () => { await initServices(); // HTTP 服务器仅在开发模式下启动 if (process.env.NODE_ENV === 'development') { startHttpServer(); } createWindow(); app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } }); }); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit(); } }); app.on('before-quit', () => { // 清理资源 grpcClient?.disconnect(); httpServer?.close(); });