From 4540ad613f401a497b1af7af4fbbf57477fcf5f1 Mon Sep 17 00:00:00 2001 From: farion1231 Date: Wed, 6 Aug 2025 09:56:27 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BE=9B=E5=BA=94=E5=95=86UR?= =?UTF-8?q?L=E5=8F=AF=E7=82=B9=E5=87=BB=E5=8A=9F=E8=83=BD=EF=BC=9A?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8=E9=BB=98=E8=AE=A4=E6=B5=8F=E8=A7=88?= =?UTF-8?q?=E5=99=A8=E4=B8=AD=E6=89=93=E5=BC=80=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/index.ts | 12 +++++++++++- src/main/preload.ts | 3 ++- src/renderer/components/ProviderList.css | 12 ++++++++++++ src/renderer/components/ProviderList.tsx | 21 ++++++++++++++++++++- src/shared/types.ts | 2 ++ 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/src/main/index.ts b/src/main/index.ts index 8ee67d1..e0d27ba 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,4 +1,4 @@ -import { app, BrowserWindow, ipcMain, dialog } from 'electron' +import { app, BrowserWindow, ipcMain, dialog, shell } from 'electron' import path from 'path' import Store from 'electron-store' import { Provider, AppConfig } from '../shared/types' @@ -133,4 +133,14 @@ ipcMain.handle('checkStatus', async (_, provider: Provider) => { console.error('检查供应商状态失败:', error) return false } +}) + +ipcMain.handle('openExternal', async (_, url: string) => { + try { + await shell.openExternal(url) + return true + } catch (error) { + console.error('打开外部链接失败:', error) + return false + } }) \ No newline at end of file diff --git a/src/main/preload.ts b/src/main/preload.ts index 7b4b94f..ec3ab67 100644 --- a/src/main/preload.ts +++ b/src/main/preload.ts @@ -10,5 +10,6 @@ contextBridge.exposeInMainWorld('electronAPI', { checkStatus: (provider: Provider) => ipcRenderer.invoke('checkStatus', provider), switchProvider: (providerId: string) => ipcRenderer.invoke('switchProvider', providerId), getClaudeCodeConfigPath: () => ipcRenderer.invoke('getClaudeCodeConfigPath'), - selectConfigFile: () => ipcRenderer.invoke('selectConfigFile') + selectConfigFile: () => ipcRenderer.invoke('selectConfigFile'), + openExternal: (url: string) => ipcRenderer.invoke('openExternal', url) }) \ No newline at end of file diff --git a/src/renderer/components/ProviderList.css b/src/renderer/components/ProviderList.css index 1685faf..d3b059d 100644 --- a/src/renderer/components/ProviderList.css +++ b/src/renderer/components/ProviderList.css @@ -78,6 +78,18 @@ text-overflow: ellipsis; } +.url-link { + color: #3498db; + text-decoration: none; + cursor: pointer; + transition: color 0.2s; +} + +.url-link:hover { + color: #2980b9; + text-decoration: underline; +} + .provider-status { display: flex; align-items: center; diff --git a/src/renderer/components/ProviderList.tsx b/src/renderer/components/ProviderList.tsx index 89e42eb..da46724 100644 --- a/src/renderer/components/ProviderList.tsx +++ b/src/renderer/components/ProviderList.tsx @@ -17,6 +17,14 @@ const ProviderList: React.FC = ({ onDelete, onEdit }) => { + const handleUrlClick = async (url: string) => { + try { + await window.electronAPI.openExternal(url) + } catch (error) { + console.error('打开链接失败:', error) + } + } + return (
{Object.values(providers).length === 0 ? ( @@ -45,7 +53,18 @@ const ProviderList: React.FC = ({ {provider.name} {isCurrent && 当前使用}
-
{provider.apiUrl}
+
+ { + e.preventDefault() + handleUrlClick(provider.apiUrl) + }} + className="url-link" + > + {provider.apiUrl} + +
diff --git a/src/shared/types.ts b/src/shared/types.ts index 117e688..b5385d4 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -22,6 +22,8 @@ declare global { switchProvider: (providerId: string) => Promise getClaudeCodeConfigPath: () => Promise selectConfigFile: () => Promise + checkStatus: (provider: Provider) => Promise + openExternal: (url: string) => Promise } } } \ No newline at end of file