diff --git a/src/index.ts b/src/index.ts index 91bf252..a3c4355 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,4 @@ -// Webview元素接口 -interface WebviewElement extends HTMLElement { - src: string; - addEventListener(event: string, listener: (event: any) => void): void; -} +import { WebviewTag } from "electron"; // 菜单项接口 interface MenuItem { @@ -78,9 +74,25 @@ function createMenuItem(item: MenuItem): HTMLLIElement { li.appendChild(span); if (item.Url) { - li.addEventListener('click', () => { - (document.querySelector("webview") as WebviewElement).src = item.Url; + li.addEventListener('click', async () => { //(document.querySelector("webview") as WebviewElement).src = "https://www.baidu.com"; + //(document.querySelector("webview") as WebviewTag).src = item.Url; + + // 需要明确url是否指定http协议或https协议,如果没有指定,则默认使用http协议。因为没有指定协议会导致webview无法加载。 + const url: string = item.Url.startsWith("http") ? item.Url : `http://${item.Url}`; + + /** + * 无法访问的错误有很多种,但总的来说可以分为两大类: + * 1. 网络错误:DNS解析错误、连接超时、SSL证书错误等。 + * 2. 服务器错误:服务器拒绝连接、服务器无响应、404、500等。 + */ + const result = await window.electronAPI.checkUrl(url); + if (result.ok && result.status >= 200 && result.status < 400) { + console.log('✅ URL 可访问:', result.status); + (document.querySelector("webview") as WebviewTag).src = url; + } else { + console.warn('❌ URL 不可访问:', result.error ?? `status ${result.status}`); + } }); } diff --git a/src/main.ts b/src/main.ts index fa6d0a1..9fd1c09 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,9 @@ import { app, BrowserWindow, globalShortcut, ipcMain, Menu, Tray } from 'electron'; import path from 'node:path'; import started from 'electron-squirrel-startup'; +import * as http from 'http'; +import * as https from 'https'; +import { URL } from 'url'; // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (started) { @@ -18,6 +21,42 @@ ipcMain.handle('set-cookie', async (event, cookie) => { } }); +ipcMain.handle('check-url', async (event, rawUrl: string) => { + try { + const url = new URL(rawUrl); + const lib = url.protocol === 'https:' ? https : http; + + return await new Promise((resolve) => { + const req = lib.request( + { + method: 'HEAD', + hostname: url.hostname, + port: url.port || undefined, + path: url.pathname + url.search, + timeout: 3000, + }, + (res) => { + resolve({ ok: true, status: res.statusCode }) + req.destroy() + } + ); + + req.on('error', (err) => { + resolve({ ok: false, error: err.message }) + }); + + req.on('timeout', () => { + req.destroy() + resolve({ ok: false, error: 'Timeout' }) + }); + + req.end(); + }) + } catch (e) { + return { ok: false, error: 'Invalid URL' }; + } +}); + const createWindow = () => { // Create the browser window. const win = new BrowserWindow({ diff --git a/src/preload.ts b/src/preload.ts index ba39303..3eec1af 100644 --- a/src/preload.ts +++ b/src/preload.ts @@ -33,5 +33,6 @@ contextBridge.exposeInMainWorld('electronAPI', { } } } - } + }, + checkUrl: (url: string) => ipcRenderer.invoke('check-url', url) }); diff --git a/src/types/electron.d.ts b/src/types/electron.d.ts index 2f6382a..79d2520 100644 --- a/src/types/electron.d.ts +++ b/src/types/electron.d.ts @@ -1,5 +1,6 @@ export interface ElectronAPI { setCookie: (cookieString: string) => Promise; + checkUrl: (url: string) => Promise<{ ok: boolean; status: number; error?: string }>; } declare global {