Files
Termix/electron/main-simple.cjs
2025-09-07 21:30:46 -05:00

178 lines
4.6 KiB
JavaScript

const { app, BrowserWindow, Menu, shell, ipcMain } = require('electron');
const path = require('path');
const { spawn } = require('child_process');
// 全局变量
let mainWindow = null;
let backendProcess = null;
// 开发环境检测
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;
// 启动后端服务
function startBackendServer() {
if (backendProcess) {
console.log('Backend server already running');
return;
}
const backendPath = path.join(__dirname, '../dist/backend/starter.js');
console.log('Starting backend server from:', backendPath);
backendProcess = spawn('node', [backendPath], {
stdio: ['ignore', 'pipe', 'pipe'],
detached: false,
cwd: path.join(__dirname, '..') // Set working directory to app root
});
backendProcess.stdout.on('data', (data) => {
console.log('Backend:', data.toString());
});
backendProcess.stderr.on('data', (data) => {
console.error('Backend Error:', data.toString());
});
backendProcess.on('close', (code) => {
console.log(`Backend process exited with code ${code}`);
backendProcess = null;
});
}
// 停止后端服务
function stopBackendServer() {
if (backendProcess) {
console.log('Stopping backend server...');
backendProcess.kill();
backendProcess = null;
}
}
// 防止多开
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
app.quit();
} else {
app.on('second-instance', () => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
});
}
// 创建主窗口
function createWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
title: 'Termix',
icon: path.join(__dirname, '..', 'public', 'icon.png'),
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload-simple.cjs'),
webSecurity: !isDev
},
show: false,
});
// 创建应用菜单(包含开发者工具快捷键)
const template = [
{
label: 'View',
submenu: [
{
label: 'Toggle Developer Tools',
accelerator: process.platform === 'darwin' ? 'Alt+Command+I' : 'Ctrl+Shift+I',
click: () => {
mainWindow.webContents.toggleDevTools();
}
},
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: () => {
mainWindow.webContents.reload();
}
}
]
}
];
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
// 加载应用
if (isDev) {
// 开发环境:连接到 Vite 开发服务器
mainWindow.loadURL('http://localhost:5173');
mainWindow.webContents.openDevTools();
} else {
// 生产环境:加载构建后的文件
mainWindow.loadFile(path.join(__dirname, '..', 'dist', 'index.html'));
// 生产环境也启用开发者工具以便调试
mainWindow.webContents.openDevTools();
}
// 窗口准备好后显示
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
// 处理窗口关闭事件
mainWindow.on('closed', () => {
mainWindow = null;
});
// 处理外部链接
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: 'deny' };
});
}
// IPC 通信处理
ipcMain.handle('get-app-version', () => {
return app.getVersion();
});
ipcMain.handle('get-platform', () => {
return process.platform;
});
// 应用事件处理
app.whenReady().then(() => {
// 在生产环境启动后端服务
if (!isDev) {
startBackendServer();
}
createWindow();
});
app.on('window-all-closed', () => {
stopBackendServer();
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
} else if (mainWindow) {
mainWindow.show();
}
});
// 处理未捕获的异常
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error);
});
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});