123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // main.js (ESM 版本)
- import { app, BrowserWindow, Menu, ipcMain, shell } from 'electron';
- import { fileURLToPath } from 'url';
- import { dirname, join } from 'path';
- import { exec } from 'child_process';
- import { promisify } from 'util';
- import { writeLog } from './src/log/log-writer.js';
- // -------------- 构造 ESM 版 __dirname --------------
- const __filename = fileURLToPath(import.meta.url);
- const __dirname = dirname(__filename);
- const execAsync = promisify(exec);
- // -------------- 创建窗口 --------------
- function createWindow() {
- const isMac = process.platform === 'darwin';
- const win = new BrowserWindow({
- show: false,
- frame: false,
- titleBarStyle: 'hidden',
- webPreferences: {
- nodeIntegration: false,
- contextIsolation: true,
- preload: join(__dirname, 'preload.js'),
- },
- });
- // 去掉应用菜单栏
- Menu.setApplicationMenu(null);
- if (!isMac) win.removeMenu();
- win.maximize();
- // 加载外置 H5 页面
- win.loadFile(join(process.cwd(), 'h5/index.html'));
- win.once('ready-to-show', () => win.show());
- //渲染进程死了,纪录日志
- win.webContents.on('render-process-gone', (event, details) => {
- writeLog('error',`渲染进程崩溃 ${details}`);
- // writeLog('error', JSON.stringify(details));
- });
- }
- // -------------- 应用生命周期 --------------
- app.whenReady().then(createWindow);
- app.on('window-all-closed', () => {
- if (process.platform !== 'darwin') app.quit();
- });
- app.on('activate', () => {
- if (BrowserWindow.getAllWindows().length === 0) createWindow();
- });
- // -------------- 系统操作函数 --------------
- const getSystemCommands = () => {
- const platform = process.platform;
-
- switch (platform) {
- case 'win32': // Windows
- return {
- shutdown: 'shutdown /s /t 0'
- };
- case 'darwin': // macOS
- return {
- shutdown: 'sudo shutdown -h now'
- };
- case 'linux': // Linux
- return {
- shutdown: 'systemctl poweroff'
- };
- default:
- return {
- shutdown: null
- };
- }
- };
- const executeSystemCommand = async (command, requiresAdmin = false) => {
- try {
- if (!command) {
- throw new Error('当前平台不支持该操作');
- }
-
- // Windows平台的权限检查
- if (process.platform === 'win32' && requiresAdmin) {
- // 检查是否以管理员身份运行
- try {
- await execAsync('net session', { timeout: 5000 });
- } catch (adminCheckError) {
- writeLog('warn', '操作可能需要管理员权限');
- return {
- success: false,
- error: '该操作需要管理员权限,请以管理员身份运行程序后重试',
- requiresAdmin: true
- };
- }
- }
-
- const { stdout, stderr } = await execAsync(command, { timeout: 10000 });
- writeLog('info', `系统命令执行成功: ${command}`);
-
- if (stderr && stderr.trim()) {
- writeLog('warn', `系统命令有警告信息: ${stderr}`);
- }
-
- return { success: true, stdout, stderr };
- } catch (error) {
- let errorMessage = error.message;
-
- // 特定错误类型的处理
- if (error.code === 'EACCES') {
- errorMessage = '权限不足,请以管理员身份运行程序';
- } else if (error.code === 'ENOENT') {
- errorMessage = '系统命令不存在或路径错误';
- } else if (error.code === 'ETIMEDOUT') {
- errorMessage = '操作超时,请重试';
- }
-
- writeLog('error', `系统命令执行失败: ${command}, 错误: ${errorMessage}`);
- return { success: false, error: errorMessage };
- }
- };
- // -------------- IPC --------------
- ipcMain.handle('write-log', async (_, level, msg) => {
- writeLog(level, msg);
- });
- // 退出应用
- ipcMain.handle('exit-close', async () => {
- writeLog('info', '用户选择关闭应用程序');
- app.quit();
- return { success: true };
- });
- // 关机
- ipcMain.handle('exit-shutdown', async () => {
- writeLog('info', '用户选择关机');
- const commands = getSystemCommands();
- // 关机通常需要管理员权限
- const requiresAdmin = true;
- return await executeSystemCommand(commands.shutdown, requiresAdmin);
- });
|