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