feat(electron):优化应用启动和健康检查逻辑

- 修改 Spring Boot 配置启用懒加载初始化
- 优化主进程窗口打开逻辑,增加销毁状态检查
- 简化数据迁移函数中的条件判断
- 添加 JVM 参数 UseSerialGC优化内存使用- 移除 Spring 进程的标准输出和错误流监听- 改进健康检查机制,使用版本接口确认服务就绪
- 调整启动超时时间并优化重试间隔
- 延迟更新检查时机以提升启动速度
This commit is contained in:
2025-10-28 11:05:53 +08:00
parent 1aceceb38f
commit 6443cdc8d0
3 changed files with 57 additions and 70 deletions

View File

@@ -20,9 +20,12 @@ let downloadedJarPath: string | null = null;
let isQuitting = false;
let currentDownloadAbortController: AbortController | null = null;
function openAppIfNotOpened() {
if (appOpened) return;
if (appOpened || !mainWindow || mainWindow.isDestroyed()) {
!appOpened && setTimeout(openAppIfNotOpened, 50);
return;
}
appOpened = true;
if (mainWindow && !mainWindow.isDestroyed()) {
isDev
? mainWindow.loadURL(`http://localhost:${process.argv[2] || 8083}`)
: mainWindow.loadFile(join(__dirname, '../renderer/index.html'));
@@ -30,8 +33,7 @@ function openAppIfNotOpened() {
mainWindow.webContents.once('did-finish-load', () => {
setTimeout(() => {
if (mainWindow && !mainWindow.isDestroyed()) {
const config = loadConfig();
const shouldMinimize = config.launchMinimized || false;
const shouldMinimize = loadConfig().launchMinimized || false;
if (!shouldMinimize) {
mainWindow.show();
mainWindow.focus();
@@ -42,9 +44,8 @@ function openAppIfNotOpened() {
splashWindow.close();
splashWindow = null;
}
}, 500);
}, 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;
}
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, 200);
});
}).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);
});
}

View File

@@ -64,7 +64,6 @@
<scope>provided</scope>
</dependency>
<!-- 拆分 hutool-all 为按需依赖,减少 JAR 包体积 -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>

View File

@@ -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