219 lines
5.8 KiB
JavaScript
219 lines
5.8 KiB
JavaScript
const { app, BrowserWindow, ipcMain } = require("electron");
|
||
const path = require("path");
|
||
const https = require("https");
|
||
const http = require("http");
|
||
|
||
let mainWindow = null;
|
||
const { Worker } = require("worker_threads");
|
||
const log = require("electron-log");
|
||
|
||
// 配置日志输出
|
||
log.transports.file.level = "info";
|
||
log.transports.file.resolvePath = () =>
|
||
path.join(path.dirname(app.getPath("exe")), "logs", "main.log");
|
||
log.info("App starting...");
|
||
|
||
// 监听渲染进程日志
|
||
ipcMain.on("log-message", (event, { level, message }) => {
|
||
if (log[level]) {
|
||
log[level](`[Renderer] ${message}`);
|
||
} else {
|
||
log.info(`[Renderer] ${message}`);
|
||
}
|
||
});
|
||
|
||
let idCardWorker = null;
|
||
|
||
function createIdCardWorker() {
|
||
if (idCardWorker) return;
|
||
|
||
log.info("Creating IDCard Worker...");
|
||
idCardWorker = new Worker(path.join(__dirname, "idcard-worker.js"));
|
||
|
||
idCardWorker.on("message", (msg) => {
|
||
if (!mainWindow) return;
|
||
|
||
if (msg.type === "data") {
|
||
log.info("IDCard data received");
|
||
mainWindow.webContents.send("idcard-data", { payload: msg.payload });
|
||
} else if (msg.type === "error") {
|
||
log.error("IDCard worker error message:", msg.payload);
|
||
mainWindow.webContents.send("idcard-error", { payload: msg.payload });
|
||
} else if (msg.type === "log") {
|
||
log.info("[Worker]", msg.payload);
|
||
}
|
||
});
|
||
|
||
idCardWorker.on("error", (err) => {
|
||
log.error("Worker thread error:", err);
|
||
});
|
||
|
||
idCardWorker.on("exit", (code) => {
|
||
if (code !== 0) log.error(`Worker stopped with exit code ${code}`);
|
||
else log.info("Worker stopped gracefully");
|
||
idCardWorker = null;
|
||
});
|
||
}
|
||
|
||
function createWindow() {
|
||
mainWindow = new BrowserWindow({
|
||
width: 1080,
|
||
height: 1920,
|
||
webPreferences: {
|
||
preload: path.join(__dirname, "preload.js"),
|
||
nodeIntegration: false,
|
||
contextIsolation: true,
|
||
},
|
||
});
|
||
|
||
mainWindow = win;
|
||
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC><EFBFBD> Vite <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
|
||
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD><C2BC>ش<EFBFBD><D8B4><EFBFBD><EFBFBD><EFBFBD> index.html
|
||
const isDev = !app.isPackaged;
|
||
|
||
if (isDev) {
|
||
win.loadURL("http://localhost:5173");
|
||
// <20><EFBFBD><F2BFAABF><EFBFBD><EFBFBD>߹<EFBFBD><DFB9><EFBFBD>
|
||
win.webContents.openDevTools();
|
||
mainWindow.loadURL("http://localhost:5173");
|
||
// 打开开发者工具
|
||
mainWindow.webContents.openDevTools();
|
||
} else {
|
||
mainWindow.loadFile(path.join(__dirname, "../dist/index.html"));
|
||
}
|
||
}
|
||
|
||
// 处理PDF获取请求(绕过CORS)
|
||
ipcMain.handle("fetch-pdf", async (event, pdfUrl) => {
|
||
return new Promise((resolve, reject) => {
|
||
const protocol = pdfUrl.startsWith("https") ? https : http;
|
||
|
||
protocol
|
||
.get(pdfUrl, (response) => {
|
||
// 处理重定向
|
||
if (response.statusCode === 301 || response.statusCode === 302) {
|
||
const redirectUrl = response.headers.location;
|
||
protocol
|
||
.get(redirectUrl, (redirectResponse) => {
|
||
const chunks = [];
|
||
redirectResponse.on("data", (chunk) => chunks.push(chunk));
|
||
redirectResponse.on("end", () => {
|
||
const buffer = Buffer.concat(chunks);
|
||
resolve({
|
||
success: true,
|
||
data: buffer.toString("base64"),
|
||
});
|
||
});
|
||
redirectResponse.on("error", (error) => {
|
||
reject({ success: false, error: error.message });
|
||
});
|
||
})
|
||
.on("error", (error) => {
|
||
reject({ success: false, error: error.message });
|
||
});
|
||
} else {
|
||
const chunks = [];
|
||
response.on("data", (chunk) => chunks.push(chunk));
|
||
response.on("end", () => {
|
||
const buffer = Buffer.concat(chunks);
|
||
resolve({
|
||
success: true,
|
||
data: buffer.toString("base64"),
|
||
});
|
||
});
|
||
response.on("error", (error) => {
|
||
reject({ success: false, error: error.message });
|
||
});
|
||
}
|
||
})
|
||
.on("error", (error) => {
|
||
reject({ success: false, error: error.message });
|
||
});
|
||
});
|
||
});
|
||
|
||
// 处理PDF打印请求
|
||
ipcMain.handle("print-pdf", async (event, pdfUrl) => {
|
||
try {
|
||
// 创建一个隐藏的窗口用于加载PDF
|
||
const printWindow = new BrowserWindow({
|
||
width: 800,
|
||
height: 600,
|
||
show: false,
|
||
webPreferences: {
|
||
nodeIntegration: false,
|
||
contextIsolation: true,
|
||
},
|
||
});
|
||
|
||
// 加载PDF
|
||
await printWindow.loadURL(pdfUrl);
|
||
|
||
// 等待页面加载完成
|
||
await new Promise((resolve) => {
|
||
printWindow.webContents.on("did-finish-load", resolve);
|
||
});
|
||
|
||
// 静默打印(直接调用系统打印对话框)
|
||
printWindow.webContents.print(
|
||
{
|
||
silent: false, // 显示打印对话框
|
||
printBackground: true,
|
||
margins: {
|
||
marginType: "none",
|
||
},
|
||
},
|
||
(success, errorType) => {
|
||
printWindow.close();
|
||
if (!success) {
|
||
console.error("Print failed:", errorType);
|
||
}
|
||
}
|
||
);
|
||
|
||
return { success: true };
|
||
} catch (error) {
|
||
console.error("Print error:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
});
|
||
|
||
app.whenReady().then(() => {
|
||
createWindow();
|
||
createIdCardWorker();
|
||
|
||
// IPC <20><><EFBFBD><EFBFBD>
|
||
ipcMain.handle("start_idcard_listen", () => {
|
||
if (idCardWorker) {
|
||
idCardWorker.postMessage("start");
|
||
} else {
|
||
createIdCardWorker();
|
||
idCardWorker.postMessage("start");
|
||
}
|
||
return "started";
|
||
});
|
||
|
||
ipcMain.handle("stop_idcard_listen", () => {
|
||
if (idCardWorker) {
|
||
idCardWorker.postMessage("stop");
|
||
}
|
||
return "stopped";
|
||
});
|
||
|
||
app.on("activate", () => {
|
||
if (BrowserWindow.getAllWindows().length === 0) {
|
||
createWindow();
|
||
}
|
||
});
|
||
});
|
||
|
||
app.on("window-all-closed", () => {
|
||
if (idCardWorker) {
|
||
idCardWorker.terminate();
|
||
}
|
||
if (process.platform !== "darwin") {
|
||
app.quit();
|
||
}
|
||
});
|