"use strict"; const { app, BrowserWindow, ipcMain, shell, session, Menu, Tray, nativeImage, webContents } = require("electron"); const { join } = require("path"); require("fs"); let mainWindow = null; let tray = null; let isQuitting = false; const VITE_DEV_SERVER_URL = process.env.VITE_DEV_SERVER_URL; function getIconPath() { return VITE_DEV_SERVER_URL ? join(__dirname, "../public/icons/icon-256.png") : join(__dirname, "../dist/icons/icon-256.png"); } function getTrayIconPath() { return VITE_DEV_SERVER_URL ? join(__dirname, "../public/icons/tray-icon.png") : join(__dirname, "../dist/icons/tray-icon.png"); } function createTrayIcon() { const trayIconPath = getTrayIconPath(); return nativeImage.createFromPath(trayIconPath); } function createTray() { const trayIcon = createTrayIcon(); tray = new Tray(trayIcon); const contextMenu = Menu.buildFromTemplate([ { label: "显示主窗口", click: () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } } }, { label: "最小化到托盘", click: () => { mainWindow == null ? void 0 : mainWindow.hide(); } }, { type: "separator" }, { label: "退出", click: () => { isQuitting = true; app.quit(); } } ]); tray.setToolTip("多平台媒体管理系统"); tray.setContextMenu(contextMenu); tray.on("click", () => { if (mainWindow) { if (mainWindow.isVisible()) { mainWindow.focus(); } else { mainWindow.show(); mainWindow.focus(); } } }); tray.on("double-click", () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); } }); } function createWindow() { Menu.setApplicationMenu(null); const iconPath = getIconPath(); mainWindow = new BrowserWindow({ width: 1400, height: 900, minWidth: 1200, minHeight: 700, icon: iconPath, webPreferences: { preload: join(__dirname, "preload.js"), nodeIntegration: false, contextIsolation: true, webviewTag: true // 启用 webview 标签 }, frame: false, // 无边框窗口,自定义标题栏 transparent: false, backgroundColor: "#f0f2f5", show: false }); mainWindow.once("ready-to-show", () => { mainWindow == null ? void 0 : mainWindow.show(); setupWindowEvents(); }); if (VITE_DEV_SERVER_URL) { mainWindow.loadURL(VITE_DEV_SERVER_URL); mainWindow.webContents.openDevTools(); } else { mainWindow.loadFile(join(__dirname, "../dist/index.html")); } mainWindow.webContents.setWindowOpenHandler(({ url }) => { shell.openExternal(url); return { action: "deny" }; }); mainWindow.on("close", (event) => { if (!isQuitting) { event.preventDefault(); mainWindow == null ? void 0 : mainWindow.hide(); if (tray && !app.isPackaged) ; } }); mainWindow.on("closed", () => { mainWindow = null; }); } const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { app.quit(); } else { app.on("second-instance", () => { if (mainWindow) { mainWindow.show(); if (mainWindow.isMinimized()) mainWindow.restore(); mainWindow.focus(); } }); app.whenReady().then(() => { createTray(); createWindow(); setupWebviewSessions(); app.on("activate", () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow(); } else if (mainWindow) { mainWindow.show(); } }); }); } function setupWebviewSessions() { app.on("web-contents-created", (_event, contents) => { if (contents.getType() === "webview") { contents.setUserAgent( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" ); contents.session.setPermissionRequestHandler((_webContents, permission, callback) => { callback(true); }); contents.session.webRequest.onBeforeSendHeaders((details, callback) => { delete details.requestHeaders["X-DevTools-Emulate-Network-Conditions-Client-Id"]; if (!details.requestHeaders["Origin"] && !details.requestHeaders["origin"]) ; callback({ requestHeaders: details.requestHeaders }); }); } }); } app.on("window-all-closed", () => { }); app.on("before-quit", () => { isQuitting = true; }); app.on("quit", () => { if (tray) { tray.destroy(); tray = null; } }); ipcMain.handle("get-app-version", () => { return app.getVersion(); }); ipcMain.handle("get-platform", () => { return process.platform; }); ipcMain.on("window-minimize", () => { mainWindow == null ? void 0 : mainWindow.minimize(); }); ipcMain.on("window-maximize", () => { if (mainWindow == null ? void 0 : mainWindow.isMaximized()) { mainWindow.unmaximize(); } else { mainWindow == null ? void 0 : mainWindow.maximize(); } }); ipcMain.on("window-close", () => { mainWindow == null ? void 0 : mainWindow.hide(); }); ipcMain.on("app-quit", () => { isQuitting = true; app.quit(); }); ipcMain.handle("window-is-maximized", () => { return (mainWindow == null ? void 0 : mainWindow.isMaximized()) || false; }); function setupWindowEvents() { mainWindow == null ? void 0 : mainWindow.on("maximize", () => { mainWindow == null ? void 0 : mainWindow.webContents.send("window-maximized", true); }); mainWindow == null ? void 0 : mainWindow.on("unmaximize", () => { mainWindow == null ? void 0 : mainWindow.webContents.send("window-maximized", false); }); } ipcMain.handle("get-webview-cookies", async (_event, partition, url) => { try { const ses = session.fromPartition(partition); const cookies = await ses.cookies.get({ url }); return cookies; } catch (error) { console.error("获取 cookies 失败:", error); return []; } }); ipcMain.handle("clear-webview-cookies", async (_event, partition) => { try { const ses = session.fromPartition(partition); await ses.clearStorageData({ storages: ["cookies"] }); return true; } catch (error) { console.error("清除 cookies 失败:", error); return false; } }); ipcMain.handle("set-webview-cookies", async (_event, partition, cookies) => { try { const ses = session.fromPartition(partition); for (const cookie of cookies) { await ses.cookies.set(cookie); } return true; } catch (error) { console.error("设置 cookies 失败:", error); return false; } }); ipcMain.handle("capture-webview-page", async (_event, webContentsId) => { try { const wc = webContents.fromId(webContentsId); if (!wc) { console.error("找不到 webContents:", webContentsId); return null; } const image = await wc.capturePage(); if (!image || image.isEmpty()) { console.warn("截图为空"); return null; } const buffer = image.toJPEG(80); return buffer.toString("base64"); } catch (error) { console.error("截图失败:", error); return null; } }); ipcMain.handle("webview-send-mouse-click", async (_event, webContentsId, x, y) => { try { const wc = webContents.fromId(webContentsId); if (!wc) { console.error("找不到 webContents:", webContentsId); return false; } wc.sendInputEvent({ type: "mouseMove", x: Math.round(x), y: Math.round(y) }); await new Promise((resolve) => setTimeout(resolve, 50)); wc.sendInputEvent({ type: "mouseDown", x: Math.round(x), y: Math.round(y), button: "left", clickCount: 1 }); await new Promise((resolve) => setTimeout(resolve, 50)); wc.sendInputEvent({ type: "mouseUp", x: Math.round(x), y: Math.round(y), button: "left", clickCount: 1 }); console.log(`[webview-send-mouse-click] Clicked at (${x}, ${y})`); return true; } catch (error) { console.error("发送点击事件失败:", error); return false; } }); ipcMain.handle("webview-send-text-input", async (_event, webContentsId, text) => { try { const wc = webContents.fromId(webContentsId); if (!wc) { console.error("找不到 webContents:", webContentsId); return false; } for (const char of text) { wc.sendInputEvent({ type: "char", keyCode: char }); await new Promise((resolve) => setTimeout(resolve, 30)); } console.log(`[webview-send-text-input] Typed: ${text}`); return true; } catch (error) { console.error("发送输入事件失败:", error); return false; } }); ipcMain.handle("webview-get-element-position", async (_event, webContentsId, selector) => { try { const wc = webContents.fromId(webContentsId); if (!wc) { console.error("找不到 webContents:", webContentsId); return null; } const result = await wc.executeJavaScript(` (function() { const el = document.querySelector('${selector.replace(/'/g, "\\'")}'); if (!el) return null; const rect = el.getBoundingClientRect(); return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2, width: rect.width, height: rect.height }; })() `); return result; } catch (error) { console.error("获取元素位置失败:", error); return null; } }); ipcMain.handle("webview-click-by-text", async (_event, webContentsId, text) => { try { const wc = webContents.fromId(webContentsId); if (!wc) { console.error("找不到 webContents:", webContentsId); return false; } const position = await wc.executeJavaScript(` (function() { const searchText = '${text.replace(/'/g, "\\'")}'; // 查找可点击元素 const clickables = document.querySelectorAll('a, button, [role="button"], [onclick], input[type="submit"], input[type="button"]'); for (const el of clickables) { if (el.textContent?.includes(searchText) || el.getAttribute('aria-label')?.includes(searchText) || el.getAttribute('title')?.includes(searchText)) { const rect = el.getBoundingClientRect(); if (rect.width > 0 && rect.height > 0) { return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }; } } } // 查找所有包含文本的元素 const allElements = document.querySelectorAll('*'); for (const el of allElements) { const text = el.innerText?.trim(); if (text && text.length < 100 && text.includes(searchText)) { const rect = el.getBoundingClientRect(); if (rect.width > 0 && rect.height > 0 && rect.width < 500) { return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }; } } } return null; })() `); if (!position) { console.warn(`[webview-click-by-text] 未找到包含 "${text}" 的元素`); return false; } wc.sendInputEvent({ type: "mouseMove", x: Math.round(position.x), y: Math.round(position.y) }); await new Promise((resolve) => setTimeout(resolve, 50)); wc.sendInputEvent({ type: "mouseDown", x: Math.round(position.x), y: Math.round(position.y), button: "left", clickCount: 1 }); await new Promise((resolve) => setTimeout(resolve, 50)); wc.sendInputEvent({ type: "mouseUp", x: Math.round(position.x), y: Math.round(position.y), button: "left", clickCount: 1 }); console.log(`[webview-click-by-text] Clicked "${text}" at (${position.x}, ${position.y})`); return true; } catch (error) { console.error("通过文本点击失败:", error); return false; } }); //# sourceMappingURL=main.js.map