AssetPro/electron/main.ts

170 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Electron 主进程入口文件
* 负责创建窗口、管理应用生命周期
*/
import { app, BrowserWindow } from 'electron'
import path from 'path'
import { setupIpcHandlers } from './ipc'
import { initStore, getWindowBounds, saveWindowBounds } from './store'
// 开发环境下的 Vite 开发服务器地址
const VITE_DEV_SERVER_URL = process.env['VITE_DEV_SERVER_URL']
// 主窗口引用
let mainWindow: BrowserWindow | null = null
/**
* 创建主窗口
*/
function createWindow() {
// 获取保存的窗口尺寸
const bounds = getWindowBounds()
// 构建窗口配置
const windowOptions: Electron.BrowserWindowConstructorOptions = {
width: bounds.width,
height: bounds.height,
webPreferences: {
// 安全配置:启用上下文隔离
contextIsolation: true,
// 安全配置:禁用 Node.js 集成
nodeIntegration: false,
// 预加载脚本路径
preload: path.join(__dirname, 'preload.js'),
// 启用沙盒模式
sandbox: false // 需要设为 false 才能使用 preload
},
// 窗口样式
title: 'AssetPro',
show: false, // 先隐藏,等准备好再显示
backgroundColor: '#ffffff',
// 无边框窗口
frame: false
}
// 如果有保存的位置,使用保存的位置;否则居中显示
if (bounds.x !== undefined && bounds.y !== undefined) {
windowOptions.x = bounds.x
windowOptions.y = bounds.y
} else {
windowOptions.center = true // 居中显示
}
mainWindow = new BrowserWindow(windowOptions)
// 窗口准备好后显示
mainWindow.once('ready-to-show', () => {
mainWindow?.show()
})
// 如果 3 秒后还没显示,强制显示窗口(防止页面加载失败导致窗口不显示)
setTimeout(() => {
if (mainWindow && !mainWindow.isVisible()) {
console.log('超时后强制显示窗口')
mainWindow.show()
}
}, 3000)
// 监听窗口关闭事件,保存窗口位置和大小
mainWindow.on('close', () => {
if (mainWindow) {
const bounds = mainWindow.getBounds()
saveWindowBounds(bounds)
}
})
// 加载页面
if (VITE_DEV_SERVER_URL) {
// 开发环境:加载 Vite 开发服务器
mainWindow.loadURL(VITE_DEV_SERVER_URL)
// 开发者工具默认关闭,可按 F12 手动打开
} else {
// 生产环境:加载打包后的文件
const fs = require('fs')
// dist-renderer 被打包到 asar 中,从 asar 内部加载
const possiblePaths = [
path.join(app.getAppPath(), 'dist-renderer', 'index.html'), // asar 内部(主要路径)
path.join(process.resourcesPath, 'dist-renderer', 'index.html'), // resources/dist-renderer如果 extraResources 存在)
path.join(process.resourcesPath, 'dist', 'index.html'), // resources/dist备用
]
console.log('尝试加载页面,检查以下路径:')
possiblePaths.forEach(p => {
const exists = fs.existsSync(p)
console.log(` ${exists ? '✓' : '✗'} ${p}`)
})
console.log('process.resourcesPath:', process.resourcesPath)
console.log('app.getAppPath():', app.getAppPath())
let indexPath: string | null = null
for (const testPath of possiblePaths) {
if (fs.existsSync(testPath)) {
indexPath = testPath
console.log('找到页面文件:', indexPath)
break
}
}
if (!indexPath) {
console.error('无法找到 index.html 文件!')
// 显示一个错误页面
mainWindow.loadURL('data:text/html,<h1>无法找到页面文件</h1><p>请检查控制台输出</p>')
return
}
// 使用 loadFile 加载文件
mainWindow.loadFile(indexPath).catch((error) => {
console.error('loadFile 失败:', error)
// 如果 loadFile 失败,尝试使用 loadURL
// Windows 路径需要特殊处理
let fileUrl = indexPath.replace(/\\/g, '/')
if (fileUrl.match(/^[A-Z]:/)) {
fileUrl = `file:///${fileUrl}`
} else {
fileUrl = `file://${fileUrl}`
}
console.log('尝试使用 loadURL:', fileUrl)
mainWindow.loadURL(fileUrl).catch((urlError) => {
console.error('loadURL 也失败:', urlError)
// 显示错误页面
mainWindow.loadURL('data:text/html,<h1>页面加载失败</h1><p>请查看控制台错误信息</p>')
})
})
}
// 监听页面加载错误
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('页面加载失败:', errorCode, errorDescription)
// 开发者工具默认关闭,可按 F12 手动打开
})
}
/**
* 应用初始化
*/
app.whenReady().then(() => {
// 初始化 electron-store
initStore()
// 设置 IPC 处理器
setupIpcHandlers()
// 创建窗口
createWindow()
// macOS 特殊处理:点击 dock 图标时重新创建窗口
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
// 所有窗口关闭时退出应用macOS 除外)
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})