BodyBalanceEvaluation/frontend/src/renderer/main/main.js

237 lines
6.6 KiB
JavaScript
Raw Normal View History

2025-08-15 10:12:38 +08:00
const { app, BrowserWindow } = require('electron');
const path = require('path');
const http = require('http');
const fs = require('fs');
const url = require('url');
const { spawn } = require('child_process');
let mainWindow;
let localServer;
let backendProcess;
function startBackendService() {
// 在打包后的应用中使用process.resourcesPath获取resources目录
const resourcesPath = process.resourcesPath || path.join(__dirname, '../..');
const backendPath = path.join(resourcesPath, 'backend/BodyBalanceBackend.exe');
const backendDir = path.join(resourcesPath, 'backend/');
console.log('Resources path:', resourcesPath);
console.log('Backend path:', backendPath);
console.log('Backend directory:', backendDir);
// 检查后端可执行文件是否存在
if (!fs.existsSync(backendPath)) {
console.error('Backend executable not found:', backendPath);
// 尝试备用路径
const fallbackPath = path.join(__dirname, 'resources/backend/BodyBalanceBackend.exe');
console.log('Trying fallback path:', fallbackPath);
if (!fs.existsSync(fallbackPath)) {
console.error('Fallback backend executable not found:', fallbackPath);
return;
}
// 使用备用路径
const fallbackDir = path.join(__dirname, 'resources/backend/');
backendProcess = spawn(fallbackPath, [], {
cwd: fallbackDir,
stdio: ['ignore', 'pipe', 'pipe']
});
console.log('Starting backend service with fallback path:', fallbackPath);
} else {
console.log('Starting backend service:', backendPath);
// 启动后端进程
backendProcess = spawn(backendPath, [], {
cwd: backendDir,
stdio: ['ignore', 'pipe', 'pipe']
});
}
backendProcess.stdout.on('data', (data) => {
console.log('Backend stdout:', data.toString());
});
backendProcess.stderr.on('data', (data) => {
console.error('Backend stderr:', data.toString());
});
backendProcess.on('close', (code) => {
console.log('Backend process exited with code:', code);
backendProcess = null;
});
backendProcess.on('error', (err) => {
console.error('Failed to start backend process:', err);
backendProcess = null;
});
}
function stopBackendService() {
if (backendProcess) {
console.log('Stopping backend service...');
backendProcess.kill('SIGTERM');
backendProcess = null;
}
// 强制杀死所有BodyBalanceBackend.exe进程
try {
const { exec } = require('child_process');
exec('taskkill /f /im BodyBalanceBackend.exe', (error, stdout, stderr) => {
if (error) {
// 如果没有找到进程taskkill会返回错误这是正常的
if (!error.message.includes('not found')) {
console.error('Error killing BodyBalanceBackend processes:', error.message);
}
} else {
console.log('Successfully killed all BodyBalanceBackend processes:', stdout);
}
});
} catch (err) {
console.error('Failed to execute taskkill command:', err);
}
}
function createWindow() {
mainWindow = new BrowserWindow({
width: 1920,
height: 1080,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
preload: path.join(__dirname, 'preload.js')
},
icon: path.join(__dirname, '../../assets/icon.ico'),
show: false,
fullscreen: false,
frame: true,
autoHideMenuBar: true,
backgroundColor: '#000000'
});
// 开发环境加载本地服务器,生产环境加载打包后的文件
const isDev = process.env.NODE_ENV === 'development';
if (isDev) {
mainWindow.loadURL('http://localhost:3000');
// mainWindow.webContents.openDevTools(); // 如需调试,请手动打开或在 did-finish-load 之后打开
} else {
// 启动后端服务
startBackendService();
// 延迟1秒后启动本地HTTP服务器
setTimeout(() => {
startLocalServer(() => {
mainWindow.loadURL('http://localhost:3000');
});
}, 1000);
}
// 窗口就绪后再显示,避免白屏/闪烁
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
// 监听页面加载完成事件
mainWindow.webContents.once('did-finish-load', () => {
console.log('Page loaded completely');
});
// 添加加载失败的处理
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL) => {
console.log('Failed to load:', errorDescription, 'URL:', validatedURL);
mainWindow.show(); // 即使加载失败也显示窗口
});
mainWindow.on('closed', () => {
mainWindow = null;
if (localServer) {
localServer.close();
}
// 关闭后端服务
stopBackendService();
});
}
function startLocalServer(callback) {
const staticPath = path.join(__dirname, '../dist/');
localServer = http.createServer((req, res) => {
const parsedUrl = url.parse(req.url);
let pathname = parsedUrl.pathname;
// 默认加载index.html
if (pathname === '/') {
pathname = '/index.html';
}
const filePath = path.join(staticPath, pathname);
fs.readFile(filePath, (err, data) => {
if (err) {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('File not found');
return;
}
// 设置正确的Content-Type
const ext = path.extname(filePath);
let contentType = 'text/html';
switch (ext) {
case '.js':
contentType = 'application/javascript';
break;
case '.css':
contentType = 'text/css';
break;
case '.json':
contentType = 'application/json';
break;
case '.png':
contentType = 'image/png';
break;
case '.jpg':
case '.jpeg':
contentType = 'image/jpeg';
break;
case '.svg':
contentType = 'image/svg+xml';
break;
}
res.writeHead(200, { 'Content-Type': contentType });
res.end(data);
});
});
localServer.listen(3000, 'localhost', () => {
console.log('Local server started on http://localhost:3000');
callback();
});
}
// 应用事件处理
// 关闭硬件加速以规避 GPU 进程异常导致的闪烁
app.disableHardwareAcceleration();
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
if (localServer) {
localServer.close();
}
// 关闭后端服务
stopBackendService();
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
// 应用退出前清理资源
app.on('before-quit', () => {
stopBackendService();
});