feat(electron):优化应用启动和健康检查逻辑
- 修改 Spring Boot 配置启用懒加载初始化 - 优化主进程窗口打开逻辑,增加销毁状态检查 - 简化数据迁移函数中的条件判断 - 添加 JVM 参数 UseSerialGC优化内存使用- 移除 Spring 进程的标准输出和错误流监听- 改进健康检查机制,使用版本接口确认服务就绪 - 调整启动超时时间并优化重试间隔 - 延迟更新检查时机以提升启动速度
This commit is contained in:
@@ -20,31 +20,32 @@ let downloadedJarPath: string | null = null;
|
||||
let isQuitting = false;
|
||||
let currentDownloadAbortController: AbortController | null = null;
|
||||
function openAppIfNotOpened() {
|
||||
if (appOpened) return;
|
||||
appOpened = true;
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
isDev
|
||||
? mainWindow.loadURL(`http://localhost:${process.argv[2] || 8083}`)
|
||||
: mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
|
||||
|
||||
mainWindow.webContents.once('did-finish-load', () => {
|
||||
setTimeout(() => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
const config = loadConfig();
|
||||
const shouldMinimize = config.launchMinimized || false;
|
||||
if (!shouldMinimize) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
if (isDev) mainWindow.webContents.openDevTools();
|
||||
}
|
||||
if (splashWindow && !splashWindow.isDestroyed()) {
|
||||
splashWindow.close();
|
||||
splashWindow = null;
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
if (appOpened || !mainWindow || mainWindow.isDestroyed()) {
|
||||
!appOpened && setTimeout(openAppIfNotOpened, 50);
|
||||
return;
|
||||
}
|
||||
|
||||
appOpened = true;
|
||||
isDev
|
||||
? mainWindow.loadURL(`http://localhost:${process.argv[2] || 8083}`)
|
||||
: mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
|
||||
|
||||
mainWindow.webContents.once('did-finish-load', () => {
|
||||
setTimeout(() => {
|
||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||
const shouldMinimize = loadConfig().launchMinimized || false;
|
||||
if (!shouldMinimize) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
if (isDev) mainWindow.webContents.openDevTools();
|
||||
}
|
||||
if (splashWindow && !splashWindow.isDestroyed()) {
|
||||
splashWindow.close();
|
||||
splashWindow = null;
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// 通用资源路径获取函数
|
||||
@@ -127,21 +128,15 @@ function saveConfig(config: AppConfig) {
|
||||
|
||||
function migrateDataFromPublic(): void {
|
||||
if (!isDev) return;
|
||||
|
||||
const oldDataPath = join(__dirname, '../../public/data');
|
||||
if (!existsSync(oldDataPath)) return;
|
||||
|
||||
const newDataPath = getDataDirectoryPath();
|
||||
try {
|
||||
readdirSync(oldDataPath).forEach(file => {
|
||||
const destFile = join(newDataPath, file);
|
||||
if (!existsSync(destFile)) {
|
||||
copyFileSync(join(oldDataPath, file), destFile);
|
||||
}
|
||||
!existsSync(destFile) && copyFileSync(join(oldDataPath, file), destFile);
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('数据迁移失败,使用默认配置');
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
||||
@@ -160,6 +155,7 @@ function startSpringBoot() {
|
||||
|
||||
try {
|
||||
const springArgs = [
|
||||
'-XX:+UseSerialGC',
|
||||
'-jar', jarPath,
|
||||
`--spring.datasource.url=jdbc:sqlite:${dataDir}/erp-cache.db`,
|
||||
`--server.port=8081`,
|
||||
@@ -169,54 +165,46 @@ function startSpringBoot() {
|
||||
springProcess = spawn(javaPath, springArgs, {
|
||||
cwd: dataDir,
|
||||
detached: false,
|
||||
stdio: ['ignore', 'pipe', 'pipe']
|
||||
stdio: 'ignore'
|
||||
});
|
||||
|
||||
let startupCompleted = false;
|
||||
|
||||
springProcess.stdout?.on('data', (data) => {
|
||||
console.log('[Spring Boot]', data.toString().trim());
|
||||
});
|
||||
|
||||
springProcess.stderr?.on('data', (data) => {
|
||||
console.log('[Spring Boot]', data.toString().trim());
|
||||
});
|
||||
|
||||
springProcess.on('close', (code) => {
|
||||
mainWindow ? mainWindow.close() : app.quit();
|
||||
});
|
||||
|
||||
springProcess.on('close', () => mainWindow ? mainWindow.close() : app.quit());
|
||||
springProcess.on('error', (error) => {
|
||||
let errorMessage = '启动 Java 应用失败';
|
||||
if (error.message.includes('ENOENT')) {
|
||||
errorMessage = '找不到 Java 运行环境\n请确保应用包含 JRE 或系统已安装 Java';
|
||||
}
|
||||
dialog.showErrorBox('启动失败', errorMessage);
|
||||
dialog.showErrorBox('启动失败', error.message.includes('ENOENT')
|
||||
? '找不到 Java 运行环境'
|
||||
: '启动 Java 应用失败');
|
||||
app.quit();
|
||||
});
|
||||
|
||||
const checkHealth = () => {
|
||||
if (startupCompleted) return;
|
||||
|
||||
http.get('http://127.0.0.1:8081', (res) => {
|
||||
if (!startupCompleted) {
|
||||
startupCompleted = true;
|
||||
console.log('[Spring Boot] 服务已就绪');
|
||||
openAppIfNotOpened();
|
||||
http.get('http://127.0.0.1:8081/api/system/version', (res) => {
|
||||
if (res.statusCode !== 200) {
|
||||
setTimeout(checkHealth, 100);
|
||||
return;
|
||||
}
|
||||
}).on('error', () => {
|
||||
setTimeout(checkHealth, 200);
|
||||
});
|
||||
let data = '';
|
||||
res.on('data', chunk => data += chunk);
|
||||
res.on('end', () => {
|
||||
try {
|
||||
const json = JSON.parse(data);
|
||||
if (json.success && json.currentVersion) {
|
||||
startupCompleted = true;
|
||||
openAppIfNotOpened();
|
||||
} else {
|
||||
setTimeout(checkHealth, 100);
|
||||
}
|
||||
} catch {
|
||||
setTimeout(checkHealth, 100);
|
||||
}
|
||||
});
|
||||
}).on('error', () => setTimeout(checkHealth, 100));
|
||||
};
|
||||
|
||||
setTimeout(checkHealth, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
if (!startupCompleted) {
|
||||
console.log('[Spring Boot] 启动超时,强制打开窗口');
|
||||
openAppIfNotOpened();
|
||||
}
|
||||
}, 15000);
|
||||
setTimeout(checkHealth, 100);
|
||||
setTimeout(() => !startupCompleted && openAppIfNotOpened(), 60000);
|
||||
} catch (error) {
|
||||
dialog.showErrorBox('启动异常', `无法启动应用: ${error}`);
|
||||
app.quit();
|
||||
@@ -296,7 +284,7 @@ function createWindow() {
|
||||
});
|
||||
|
||||
mainWindow.webContents.once('did-finish-load', () => {
|
||||
setTimeout(() => checkPendingUpdate(), 500);
|
||||
setTimeout(checkPendingUpdate, 100);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- 拆分 hutool-all 为按需依赖,减少 JAR 包体积 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
|
||||
@@ -9,7 +9,7 @@ javafx:
|
||||
|
||||
spring:
|
||||
main:
|
||||
lazy-initialization: false
|
||||
lazy-initialization: true
|
||||
datasource:
|
||||
url: jdbc:sqlite:./data/erp-cache.db?journal_mode=WAL&synchronous=NORMAL&cache_size=10000&temp_store=memory&busy_timeout=30000
|
||||
driver-class-name: org.sqlite.JDBC
|
||||
|
||||
Reference in New Issue
Block a user