const { BrowserWindow } = require('electron'); const path = require('path'); const fs = require('fs'); /** * 日志窗口管理器 * 显示 MySQL 和 Spring Boot 的实时日志 */ class LogWindowManager { constructor() { this.logWindow = null; this.logs = []; this.maxLogs = 1000; // 最多保留1000条日志 // 初始化日志文件路径 this.initLogFile(); } /** * 初始化日志文件路径(按天滚动) */ initLogFile() { // 开发环境:项目根目录的 logs 文件夹 // 打包后:应用根目录的 logs 文件夹 const isDev = !process.resourcesPath; const baseDir = isDev ? path.join(__dirname, '..') : path.dirname(process.resourcesPath); this.logsDir = path.join(baseDir, 'logs'); // 确保 logs 目录存在 if (!fs.existsSync(this.logsDir)) { fs.mkdirSync(this.logsDir, { recursive: true }); } // 生成当天的日志文件名:startup-YYYYMMDD.log const today = new Date(); const dateStr = today.getFullYear() + String(today.getMonth() + 1).padStart(2, '0') + String(today.getDate()).padStart(2, '0'); this.logFilePath = path.join(this.logsDir, `startup-${dateStr}.log`); console.log('[LogWindowManager] Log file:', this.logFilePath); // 写入启动标记 this.writeToFile(new Date().toISOString().replace('T', ' ').substring(0, 19), 'SYSTEM', '=' .repeat(80)); this.writeToFile(new Date().toISOString().replace('T', ' ').substring(0, 19), 'SYSTEM', 'NPQS9100 应用启动'); this.writeToFile(new Date().toISOString().replace('T', ' ').substring(0, 19), 'SYSTEM', '=' .repeat(80)); // 清理超过30天的旧日志 this.cleanOldLogs(30); } /** * 清理旧日志文件 * @param {number} days - 保留天数 */ cleanOldLogs(days) { try { const now = Date.now(); const maxAge = days * 24 * 60 * 60 * 1000; // 转换为毫秒 const files = fs.readdirSync(this.logsDir); let deletedCount = 0; files.forEach(file => { if (file.startsWith('startup-') && file.endsWith('.log')) { const filePath = path.join(this.logsDir, file); const stats = fs.statSync(filePath); const age = now - stats.mtimeMs; if (age > maxAge) { fs.unlinkSync(filePath); deletedCount++; console.log(`[LogWindowManager] Deleted old log: ${file}`); } } }); if (deletedCount > 0) { console.log(`[LogWindowManager] Cleaned up ${deletedCount} old log file(s)`); } } catch (error) { console.error('[LogWindowManager] Failed to clean old logs:', error); } } /** * 写入日志到文件 */ writeToFile(timestamp, type, message) { try { const logLine = `[${timestamp}] [${type.toUpperCase()}] ${message}\n`; fs.appendFileSync(this.logFilePath, logLine, 'utf-8'); } catch (error) { console.error('[LogWindowManager] Failed to write log to file:', error); } } /** * 创建日志窗口 */ createLogWindow() { const isDev = !process.resourcesPath; const iconPath = isDev ? path.join(__dirname, '..', 'public', 'images', 'icon.png') : path.join(process.resourcesPath, 'app.asar.unpacked', 'public', 'images', 'icon.png'); this.logWindow = new BrowserWindow({ width: 900, height: 600, title: 'NPQS9100 - 服务日志', backgroundColor: '#1e1e1e', icon: iconPath, webPreferences: { nodeIntegration: true, contextIsolation: false } }); // 加载日志页面 const logHtml = this.generateLogHTML(); this.logWindow.loadURL(`data:text/html;charset=utf-8,${encodeURIComponent(logHtml)}`); // 窗口关闭事件 - 只清理引用,不退出应用 this.logWindow.on('closed', () => { console.log('[LogWindow] Log window closed by user'); this.logWindow = null; }); // 防止日志窗口关闭时退出应用(但允许隐藏) this.closeHandler = (event) => { // 只是隐藏窗口,不是真正关闭 // 这样可以随时再打开 event.preventDefault(); this.logWindow.hide(); console.log('[LogWindow] Log window hidden'); }; this.logWindow.on('close', this.closeHandler); return this.logWindow; } /** * 生成日志HTML页面 */ generateLogHTML() { return `