重启之后清除登录信息

This commit is contained in:
2025-07-15 19:55:59 +08:00
parent 4caff7542e
commit 0b2974e2c9
18 changed files with 1873 additions and 86 deletions

View File

@@ -3,28 +3,46 @@ import { electronApp, optimizer } from '@electron-toolkit/utils'
import Store from 'electron-store'
import { createWindow, createDrageWindow, unregisterAllShortcuts } from './window.js'
import { setupIPC } from './ipc.js'
import { createTray, destroyTray } from './tray.js'
import { getStoreValue } from './store.js'
import { createTray, destroyTray,clearBrowserCache } from './tray.js'
import XEUtils from 'xe-utils'
import fs from 'fs'
import path from 'path'
import dayjs from 'dayjs'
import logger from './utils/logger'
import { clearAllSessionData } from './utils/cacheUtils.js'
import SingleInstanceManager from './utils/singleInstance.js'
import { setStoreValue, getStoreValue ,deleteStore} from './store.js'
import AutoLaunch from 'auto-launch'
import WebSocketClient from './utils/WebSocketClient';
let wsClient=null
wsClient=new WebSocketClient({
autoReconnect: true,
autoReconnectAttempts: 9999,
autoReconnectInterval: 5000,
timeout: 30000,
})
// 延迟创建WebSocket连接等待应用完全启动后再连接
function createWebSocketClient() {
try {
wsClient = new WebSocketClient({
autoReconnect: true,
autoReconnectAttempts: 9999,
autoReconnectInterval: 5000,
timeout: 30000,
});
wsClient.on('open', () => {
logger.info('WebSocket连接已打开')
});
wsClient.on('open', () => {
logger.info('WebSocket连接已打开')
});
wsClient.on('error', (error) => {
logger.error('WebSocket连接错误:', error)
});
wsClient.on('close', (data) => {
logger.info('WebSocket连接已关闭:', data)
});
} catch (error) {
logger.error('创建WebSocket客户端失败:', error)
}
}
var minecraftAutoLauncher = new AutoLaunch({
@@ -53,40 +71,132 @@ if(!XEUtils.isEmpty(difySite)){
logger.info(`当前运行平台: ${process.platform}`)
if (process.platform === 'win32') {
logger.info('Windows 系统,设置控制台编码为 UTF-8')
require('child_process').execSync('chcp 65001', { stdio: 'ignore' })
try {
require('child_process').execSync('chcp 65001', { stdio: 'ignore' })
} catch (error) {
logger.error('设置控制台编码失败:', error)
}
} else {
logger.info('非 Windows 系统,使用默认编码')
}
logger.info('%cRed text. %cGreen text', 'color: red', 'color: green')
const store = new Store()
try {
const store = new Store()
logger.info('Store 初始化成功')
} catch (error) {
logger.error('Store 初始化失败:', error)
}
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors')
app.commandLine.appendSwitch('ignore-certificate-errors')
app.disableHardwareAcceleration()
// 添加缓存相关配置,避免缓存错误
app.commandLine.appendSwitch('disable-http-cache')
app.commandLine.appendSwitch('disable-background-timer-throttling')
app.commandLine.appendSwitch('disable-renderer-backgrounding')
try {
app.disableHardwareAcceleration()
logger.info('硬件加速已禁用')
} catch (error) {
logger.error('禁用硬件加速失败:', error)
}
logger.info(app.getPath('userData'))
logger.info('应用启动,日志文件路径:', logger.getLogPath())
// 添加更多启动信息
logger.info('开始检查单实例锁...')
// 创建单实例管理器
const singleInstanceManager = new SingleInstanceManager()
// 清理缓存目录
function cleanupCacheDirectories() {
try {
const userDataPath = app.getPath('userData')
const cachePaths = [
path.join(userDataPath, 'Cache'),
path.join(userDataPath, 'Code Cache'),
path.join(userDataPath, 'GPUCache'),
path.join(userDataPath, 'Service Worker'),
path.join(userDataPath, 'Session Storage')
]
for (const cachePath of cachePaths) {
if (fs.existsSync(cachePath)) {
logger.info(`清理缓存目录: ${cachePath}`)
try {
// 递归删除目录
const deleteRecursive = (dirPath) => {
if (fs.existsSync(dirPath)) {
const files = fs.readdirSync(dirPath)
for (const file of files) {
const curPath = path.join(dirPath, file)
if (fs.lstatSync(curPath).isDirectory()) {
deleteRecursive(curPath)
} else {
try {
fs.unlinkSync(curPath)
} catch (error) {
logger.warn(`无法删除缓存文件: ${curPath}`, error.message)
}
}
}
try {
fs.rmdirSync(dirPath)
} catch (error) {
logger.warn(`无法删除缓存目录: ${dirPath}`, error.message)
}
}
}
deleteRecursive(cachePath)
logger.info(`缓存目录清理完成: ${cachePath}`)
} catch (error) {
logger.error(`清理缓存目录失败: ${cachePath}`, error)
}
}
}
} catch (error) {
logger.error('清理缓存目录失败:', error)
}
}
// 检查是否为第一个实例
const gotTheLock = app.requestSingleInstanceLock()
const isFirstInstance = singleInstanceManager.checkSingleInstance()
if (!gotTheLock) {
// 如果不是第一个实例,尝试激活第一个实例的窗口
const windows = BrowserWindow.getAllWindows()
if (windows.length > 0) {
const mainWindow = windows[0]
if (mainWindow.isMinimized()) {
mainWindow.restore()
if (!isFirstInstance) {
logger.info('检测到已有实例运行,尝试激活现有实例')
// 尝试激活第一个实例的窗口
try {
const windows = BrowserWindow.getAllWindows()
if (windows.length > 0) {
const mainWindow = windows[0]
if (mainWindow.isMinimized()) {
mainWindow.restore()
}
mainWindow.show()
mainWindow.focus()
logger.info('成功激活现有实例窗口')
app.quit() // 退出当前实例
} else {
logger.warn('未找到现有实例窗口,可能是锁未正确释放')
logger.info('尝试强制启动新实例...')
// 继续启动
}
mainWindow.show()
mainWindow.focus()
} catch (error) {
logger.error('激活现有实例失败:', error)
logger.info('尝试强制启动新实例...')
// 继续启动
}
app.quit() // 退出当前实例
} else {
logger.info('这是第一个实例,继续启动')
// 这是第一个实例
// 监听第二个实例的启动
@@ -104,6 +214,10 @@ if (!gotTheLock) {
})
app.whenReady().then(() => {
logger.info('应用已准备就绪,开始初始化...');
// 清理缓存目录
cleanupCacheDirectories()
// 获取默认会话并全局设置允许第三方 Cookie
const defaultSession = session.defaultSession;
@@ -134,6 +248,13 @@ if (!gotTheLock) {
createTray()
setupIPC()
// exe退出三秒之后即认为关闭过exe程序退出登录
checkIsKeepAlive()
// 延迟创建WebSocket连接
setTimeout(() => {
createWebSocketClient()
}, 2000); // 延迟2秒创建WebSocket连接
minecraftAutoLauncher.isEnabled()
.then(function(isEnabled){
@@ -151,26 +272,134 @@ if (!gotTheLock) {
app.on('activate', function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
logger.info('应用初始化完成');
})
// 修改窗口关闭行为
app.on('window-all-closed', () => {
app.on('window-all-closed', async (event) => {
if (process.platform !== 'darwin') {
event.preventDefault();
if (!app.isQuiting) {
// 如果不是主动退出,则隐藏所有窗口
BrowserWindow.getAllWindows().forEach(window => {
window.hide()
})
// 清除所有会话数据
try {
await clearAllSessionData('window-all-closed');
} catch (error) {
logger.error('窗口关闭时清理缓存失败:', error);
}
// 清理完成后退出应用
app.quit();
} else {
// 如果是主动退出,则销毁托盘并退出应用
destroyTray()
app.quit()
}
}
})
app.on('before-quit', async (event) => {
// 在应用程序即将退出时执行操作,例如保存数据
event.preventDefault();
// 清除所有会话数据
try {
await clearAllSessionData('before-quit');
} catch (error) {
logger.error('应用退出时清理缓存失败:', error);
}
// 清理完成后退出应用
app.quit();
});
// 在应用退出时注销所有快捷键
app.on('will-quit', () => {
app.on('will-quit', async (event) => {
event.preventDefault();
// 清除所有会话数据
try {
await clearAllSessionData('will-quit');
} catch (error) {
logger.error('应用退出时清理缓存失败:', error);
}
unregisterAllShortcuts()
// 清理完成后退出应用
app.quit();
})
// 监听进程退出信号,确保在系统强制关闭时也能清理缓存
process.on('SIGTERM', async () => {
logger.info('收到 SIGTERM 信号,开始清理缓存');
try {
await clearAllSessionData('SIGTERM');
} catch (error) {
logger.error('SIGTERM 时清理缓存失败:', error);
}
process.exit(0);
});
process.on('SIGINT', async () => {
logger.info('收到 SIGINT 信号,开始清理缓存');
try {
await clearAllSessionData('SIGINT');
} catch (error) {
logger.error('SIGINT 时清理缓存失败:', error);
}
process.exit(0);
});
// 监听未捕获的异常,确保应用崩溃时也能记录日志
process.on('uncaughtException', (error) => {
logger.error('未捕获的异常:', error);
// 不要立即退出,给应用一个恢复的机会
logger.error('应用遇到未捕获的异常,但将继续运行');
});
process.on('unhandledRejection', (reason, promise) => {
logger.error('未处理的 Promise 拒绝:', reason);
// 不要立即退出,给应用一个恢复的机会
logger.error('应用遇到未处理的 Promise 拒绝,但将继续运行');
});
}
export function checkIsKeepAlive(){
const checkIsKeepAliveTimer=setInterval(async () => {
const lastAliveTime = getStoreValue("lastAliveTime")||null
if (lastAliveTime!=null){
const nowTime=dayjs();
const lastTime=dayjs(lastAliveTime);
const diff=nowTime.diff(lastTime, 'second')
// 上次在线事件在三秒之前则认为关闭过exe程序
if (diff>5){
logger.info('上次在线事件在三秒之前则认为关闭过exe程序')
await clearAllSessionData('超时5秒');
deleteStore("lastAliveTime")
}else{
setStoreValue("lastAliveTime",dayjs())
}
}
}, 1000 * 2)
}