diff --git a/src/renderer/components/AddProviderModal.css b/src/renderer/components/AddProviderModal.css index f1bb6c4..22ee112 100644 --- a/src/renderer/components/AddProviderModal.css +++ b/src/renderer/components/AddProviderModal.css @@ -167,4 +167,12 @@ .password-toggle:focus { outline: none; +} + +.field-hint { + display: block; + margin-top: 0.25rem; + color: #7f8c8d; + font-size: 0.8rem; + line-height: 1.3; } \ No newline at end of file diff --git a/src/renderer/components/AddProviderModal.tsx b/src/renderer/components/AddProviderModal.tsx index 6d79af3..9d6a161 100644 --- a/src/renderer/components/AddProviderModal.tsx +++ b/src/renderer/components/AddProviderModal.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react' import { Provider } from '../../shared/types' +import { inferWebsiteUrl } from '../../shared/utils' import './AddProviderModal.css' interface AddProviderModalProps { @@ -11,7 +12,8 @@ const AddProviderModal: React.FC = ({ onAdd, onClose }) = const [formData, setFormData] = useState({ name: '', apiUrl: '', - apiKey: '' + apiKey: '', + websiteUrl: '' }) const [showPassword, setShowPassword] = useState(false) @@ -27,10 +29,18 @@ const AddProviderModal: React.FC = ({ onAdd, onClose }) = } const handleChange = (e: React.ChangeEvent) => { - setFormData({ + const { name, value } = e.target + const newFormData = { ...formData, - [e.target.name]: e.target.value - }) + [name]: value + } + + // 如果修改的是API地址,自动推测网站地址 + if (name === 'apiUrl') { + newFormData.websiteUrl = inferWebsiteUrl(value) + } + + setFormData(newFormData) } // 预设的供应商配置 @@ -46,11 +56,14 @@ const AddProviderModal: React.FC = ({ onAdd, onClose }) = ] const applyPreset = (preset: typeof presets[0]) => { - setFormData({ + const newFormData = { ...formData, name: preset.name, apiUrl: preset.apiUrl - }) + } + // 应用预设时也自动推测网站地址 + newFormData.websiteUrl = inferWebsiteUrl(preset.apiUrl) + setFormData(newFormData) } return ( @@ -101,6 +114,19 @@ const AddProviderModal: React.FC = ({ onAdd, onClose }) = /> +
+ + + 用于在面板中显示可访问的网站链接,留空则显示API地址 +
+
diff --git a/src/renderer/components/EditProviderModal.tsx b/src/renderer/components/EditProviderModal.tsx index 6ef0a9f..1e14cd9 100644 --- a/src/renderer/components/EditProviderModal.tsx +++ b/src/renderer/components/EditProviderModal.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react' import { Provider } from '../../shared/types' +import { inferWebsiteUrl } from '../../shared/utils' import './AddProviderModal.css' interface EditProviderModalProps { @@ -12,7 +13,8 @@ const EditProviderModal: React.FC = ({ provider, onSave, const [formData, setFormData] = useState({ name: provider.name, apiUrl: provider.apiUrl, - apiKey: provider.apiKey + apiKey: provider.apiKey, + websiteUrl: provider.websiteUrl || '' }) const [showPassword, setShowPassword] = useState(false) @@ -20,7 +22,8 @@ const EditProviderModal: React.FC = ({ provider, onSave, setFormData({ name: provider.name, apiUrl: provider.apiUrl, - apiKey: provider.apiKey + apiKey: provider.apiKey, + websiteUrl: provider.websiteUrl || '' }) }, [provider]) @@ -40,10 +43,17 @@ const EditProviderModal: React.FC = ({ provider, onSave, const handleChange = (e: React.ChangeEvent) => { const { name, value } = e.target - setFormData(prev => ({ - ...prev, + const newFormData = { + ...formData, [name]: value - })) + } + + // 如果修改的是API地址,自动推测网站地址 + if (name === 'apiUrl') { + newFormData.websiteUrl = inferWebsiteUrl(value) + } + + setFormData(newFormData) } return ( @@ -80,6 +90,20 @@ const EditProviderModal: React.FC = ({ provider, onSave, />
+
+ + + 用于在面板中显示可访问的网站链接,留空则显示API地址 +
+
diff --git a/src/renderer/components/ProviderList.css b/src/renderer/components/ProviderList.css index d3b059d..35e4b1c 100644 --- a/src/renderer/components/ProviderList.css +++ b/src/renderer/components/ProviderList.css @@ -90,6 +90,10 @@ text-decoration: underline; } +.api-url { + color: #7f8c8d; +} + .provider-status { display: flex; align-items: center; diff --git a/src/renderer/components/ProviderList.tsx b/src/renderer/components/ProviderList.tsx index da46724..373caa3 100644 --- a/src/renderer/components/ProviderList.tsx +++ b/src/renderer/components/ProviderList.tsx @@ -54,16 +54,23 @@ const ProviderList: React.FC = ({ {isCurrent && 当前使用}
diff --git a/src/shared/types.ts b/src/shared/types.ts index b5385d4..7f896b6 100644 --- a/src/shared/types.ts +++ b/src/shared/types.ts @@ -4,6 +4,7 @@ export interface Provider { apiUrl: string apiKey: string model?: string + websiteUrl?: string } export interface AppConfig { diff --git a/src/shared/utils.ts b/src/shared/utils.ts new file mode 100644 index 0000000..97c9086 --- /dev/null +++ b/src/shared/utils.ts @@ -0,0 +1,35 @@ +/** + * 从API地址推测对应的网站地址 + * @param apiUrl API地址 + * @returns 推测的网站地址,如果无法推测则返回空字符串 + */ +export function inferWebsiteUrl(apiUrl: string): string { + if (!apiUrl || !apiUrl.trim()) { + return '' + } + + try { + const url = new URL(apiUrl.trim()) + + // 如果是localhost或IP地址,去掉路径部分 + if (url.hostname === 'localhost' || /^\d+\.\d+\.\d+\.\d+$/.test(url.hostname)) { + return `${url.protocol}//${url.host}` + } + + // 处理域名,去掉api前缀 + let hostname = url.hostname + + // 去掉 api. 前缀 + if (hostname.startsWith('api.')) { + hostname = hostname.substring(4) + } + + // 构建推测的网站地址 + const port = url.port ? `:${url.port}` : '' + return `${url.protocol}//${hostname}${port}` + + } catch (error) { + // URL解析失败,返回空字符串 + return '' + } +} \ No newline at end of file