diff --git a/src/components/ProviderForm.tsx b/src/components/ProviderForm.tsx index 189f64c..d957bed 100644 --- a/src/components/ProviderForm.tsx +++ b/src/components/ProviderForm.tsx @@ -54,6 +54,7 @@ const ProviderForm: React.FC = ({ // Claude 模型配置状态 const [claudeModel, setClaudeModel] = useState(""); const [claudeSmallFastModel, setClaudeSmallFastModel] = useState(""); + const [baseUrl, setBaseUrl] = useState(""); // 新增:基础 URL 状态 // Codex 特有的状态 const [codexAuth, setCodexAuth] = useState(""); @@ -136,6 +137,7 @@ const ProviderForm: React.FC = ({ if (config.env) { setClaudeModel(config.env.ANTHROPIC_MODEL || ""); setClaudeSmallFastModel(config.env.ANTHROPIC_SMALL_FAST_MODEL || ""); + setBaseUrl(config.env.ANTHROPIC_BASE_URL || ""); // 初始化基础 URL // 初始化 Kimi 模型选择 setKimiAnthropicModel(config.env.ANTHROPIC_MODEL || ""); @@ -293,6 +295,7 @@ const ProviderForm: React.FC = ({ // 清空 API Key 输入框,让用户重新输入 setApiKey(""); + setBaseUrl(""); // 清空基础 URL // 同步选择框状态 const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); @@ -338,6 +341,7 @@ const ProviderForm: React.FC = ({ settingsConfig: JSON.stringify(customTemplate, null, 2), }); setApiKey(""); + setBaseUrl("https://your-api-endpoint.com"); // 设置默认的基础 URL setDisableCoAuthored(false); setClaudeModel(""); setClaudeSmallFastModel(""); @@ -403,6 +407,26 @@ const ProviderForm: React.FC = ({ setDisableCoAuthored(hasCoAuthoredDisabled); }; + // 处理基础 URL 变化 + const handleBaseUrlChange = (url: string) => { + setBaseUrl(url); + + try { + const config = JSON.parse(formData.settingsConfig || "{}"); + if (!config.env) { + config.env = {}; + } + config.env.ANTHROPIC_BASE_URL = url.trim(); + + setFormData(prev => ({ + ...prev, + settingsConfig: JSON.stringify(config, null, 2) + })); + } catch { + // ignore + } + }; + // Codex: 处理 API Key 输入并写回 auth.json const handleCodexApiKeyChange = (key: string) => { setCodexApiKey(key); @@ -446,6 +470,32 @@ const ProviderForm: React.FC = ({ // 综合判断是否应该显示 Kimi 模型选择器 const shouldShowKimiSelector = isKimiPreset || isEditingKimi; + // 判断是否显示基础 URL 输入框(仅自定义模式显示) + const showBaseUrlInput = selectedPreset === -1 && !isCodex; + + // 判断是否显示"获取 API Key"链接(国产官方和聚合站显示) + const shouldShowApiKeyLink = !isCodex && !isOfficialPreset && + (category === "cn_official" || category === "aggregator" || + (selectedPreset !== null && selectedPreset >= 0 && + (providerPresets[selectedPreset]?.category === "cn_official" || + providerPresets[selectedPreset]?.category === "aggregator"))); + + // 获取当前供应商的网址 + const getCurrentWebsiteUrl = () => { + if (selectedPreset !== null && selectedPreset >= 0) { + return providerPresets[selectedPreset]?.websiteUrl || ""; + } + return formData.websiteUrl || ""; + }; + + // 获取 Codex 当前供应商的网址 + const getCurrentCodexWebsiteUrl = () => { + if (selectedCodexPreset !== null && selectedCodexPreset >= 0) { + return codexProviderPresets[selectedCodexPreset]?.websiteUrl || ""; + } + return formData.websiteUrl || ""; + }; + // Codex: 控制显示 API Key 与官方标记 const getCodexAuthApiKey = (authString: string): string => { try { @@ -470,6 +520,14 @@ const ProviderForm: React.FC = ({ codexProviderPresets[selectedCodexPreset]?.category === "official")) || category === "official"; + // 判断是否显示 Codex 的"获取 API Key"链接 + const shouldShowCodexApiKeyLink = isCodex && !isCodexOfficialPreset && + (category === "cn_official" || category === "aggregator" || category === "third_party" || + (selectedCodexPreset !== null && selectedCodexPreset >= 0 && + (codexProviderPresets[selectedCodexPreset]?.category === "cn_official" || + codexProviderPresets[selectedCodexPreset]?.category === "aggregator" || + codexProviderPresets[selectedCodexPreset]?.category === "third_party"))); + // 处理模型输入变化,自动更新 JSON 配置 const handleModelChange = (field: 'ANTHROPIC_MODEL' | 'ANTHROPIC_SMALL_FAST_MODEL', value: string) => { if (field === 'ANTHROPIC_MODEL') { @@ -649,22 +707,62 @@ const ProviderForm: React.FC = ({ {!isCodex && showApiKey && ( - +
+ + {shouldShowApiKeyLink && getCurrentWebsiteUrl() && ( + + )} +
)} - {!isCodex && shouldShowKimiSelector && apiKey.trim() && ( + {/* 基础 URL 输入框 - 仅在自定义模式下显示 */} + {!isCodex && showBaseUrlInput && ( +
+ + handleBaseUrlChange(e.target.value)} + placeholder="https://your-api-endpoint.com" + autoComplete="off" + className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + /> +
+

+ 💡 填写兼容 Claude API 的服务端点地址 +

+
+
+ )} + + {!isCodex && shouldShowKimiSelector && ( = ({ )} {isCodex && showCodexApiKey && ( - = 0 && - !isCodexOfficialPreset - } - /> +
+ = 0 && + !isCodexOfficialPreset + } + /> + {shouldShowCodexApiKeyLink && getCurrentCodexWebsiteUrl() && ( + + )} +
)} {/* Claude 或 Codex 的配置部分 */} @@ -716,43 +828,51 @@ const ProviderForm: React.FC = ({ /> ) : ( <> - {/* 可选的模型配置输入框 - 简化为一行 */} - {!isOfficialPreset && ( -
-
- - handleModelChange('ANTHROPIC_MODEL', e.target.value)} - placeholder="例如: deepseek-chat" - autoComplete="off" - className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" - /> + {/* 可选的模型配置输入框 - 仅在非官方且非 Kimi 时显示 */} + {!isOfficialPreset && !shouldShowKimiSelector && ( +
+
+
+ + handleModelChange('ANTHROPIC_MODEL', e.target.value)} + placeholder="例如: GLM-4.5" + autoComplete="off" + className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + /> +
+ +
+ + handleModelChange('ANTHROPIC_SMALL_FAST_MODEL', e.target.value)} + placeholder="例如: GLM-4.5-Air" + autoComplete="off" + className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" + /> +
-
- - handleModelChange('ANTHROPIC_SMALL_FAST_MODEL', e.target.value)} - placeholder="例如: glm-4-flash" - autoComplete="off" - className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500/20 focus:border-blue-500 transition-colors" - /> +
+

+ 💡 留空将使用供应商的默认模型 +

)} diff --git a/src/components/ProviderForm/KimiModelSelector.tsx b/src/components/ProviderForm/KimiModelSelector.tsx index aab8e9e..18a0942 100644 --- a/src/components/ProviderForm/KimiModelSelector.tsx +++ b/src/components/ProviderForm/KimiModelSelector.tsx @@ -172,9 +172,9 @@ const KimiModelSelector: React.FC = ({
{!apiKey.trim() && ( -
-

- 📝 请先填写 API Key(格式:sk-xxx-api-key-here)以获取可用模型列表 +

+

+ 💡 填写 API Key 后将自动获取可用模型列表

)} diff --git a/src/config/providerPresets.ts b/src/config/providerPresets.ts index 11a59c7..cb1c3cd 100644 --- a/src/config/providerPresets.ts +++ b/src/config/providerPresets.ts @@ -13,7 +13,7 @@ export interface ProviderPreset { export const providerPresets: ProviderPreset[] = [ { - name: "Claude官方登录", + name: "Claude官方", websiteUrl: "https://www.anthropic.com/claude-code", settingsConfig: { env: {}, @@ -22,7 +22,7 @@ export const providerPresets: ProviderPreset[] = [ category: "official", }, { - name: "DeepSeek v3.1", + name: "DeepSeek", websiteUrl: "https://platform.deepseek.com", settingsConfig: { env: { @@ -41,21 +41,21 @@ export const providerPresets: ProviderPreset[] = [ env: { ANTHROPIC_BASE_URL: "https://open.bigmodel.cn/api/anthropic", ANTHROPIC_AUTH_TOKEN: "", - ANTHROPIC_MODEL: "glm-4-plus", - ANTHROPIC_SMALL_FAST_MODEL: "glm-4-flash", + ANTHROPIC_MODEL: "GLM-4.5", + ANTHROPIC_SMALL_FAST_MODEL: "GLM-4.5-Air", }, }, category: "cn_official", }, { - name: "千问Qwen-Coder", + name: "Qwen-Coder", websiteUrl: "https://bailian.console.aliyun.com", settingsConfig: { env: { ANTHROPIC_BASE_URL: "https://dashscope.aliyuncs.com/api/v2/apps/claude-code-proxy", ANTHROPIC_AUTH_TOKEN: "", - ANTHROPIC_MODEL: "qwen-coder-turbo", - ANTHROPIC_SMALL_FAST_MODEL: "qwen-coder-turbo", + ANTHROPIC_MODEL: "qwen3-coder-plus", + ANTHROPIC_SMALL_FAST_MODEL: "qwen3-coder-plus", }, }, category: "cn_official",