feat: add Base URL input and endpoint speed test to ProviderForm

- Integrate useBaseUrlState hook for managing Base URL
- Add Base URL input field for third-party and custom providers
- Add endpoint speed test modal with management button
- Show Base URL section only for non-official providers
- Add Zap icon button to open endpoint speed test modal
- Pass baseUrl to EndpointSpeedTest component
- Add helper text explaining API endpoint usage

All TypeScript type checks pass.
This commit is contained in:
Jason
2025-10-16 17:44:23 +08:00
parent 98c35c7c62
commit 3b22bcc134

View File

@@ -24,7 +24,9 @@ import {
} from "@/config/codexProviderPresets"; } from "@/config/codexProviderPresets";
import { applyTemplateValues } from "@/utils/providerConfigUtils"; import { applyTemplateValues } from "@/utils/providerConfigUtils";
import ApiKeyInput from "@/components/ProviderForm/ApiKeyInput"; import ApiKeyInput from "@/components/ProviderForm/ApiKeyInput";
import { useProviderCategory, useApiKeyState } from "./hooks"; import EndpointSpeedTest from "@/components/ProviderForm/EndpointSpeedTest";
import { Zap } from "lucide-react";
import { useProviderCategory, useApiKeyState, useBaseUrlState } from "./hooks";
const CLAUDE_DEFAULT_CONFIG = JSON.stringify({ env: {}, config: {} }, null, 2); const CLAUDE_DEFAULT_CONFIG = JSON.stringify({ env: {}, config: {} }, null, 2);
const CODEX_DEFAULT_CONFIG = JSON.stringify({ auth: {}, config: "" }, null, 2); const CODEX_DEFAULT_CONFIG = JSON.stringify({ auth: {}, config: "" }, null, 2);
@@ -64,6 +66,7 @@ export function ProviderForm({
id: string; id: string;
category?: ProviderCategory; category?: ProviderCategory;
} | null>(null); } | null>(null);
const [isEndpointModalOpen, setIsEndpointModalOpen] = useState(false);
// 使用 category hook // 使用 category hook
const { category } = useProviderCategory({ const { category } = useProviderCategory({
@@ -103,6 +106,23 @@ export function ProviderForm({
selectedPresetId, selectedPresetId,
}); });
// 使用 Base URL hook
const {
baseUrl,
// codexBaseUrl, // TODO: 等 Codex 支持时使用
handleClaudeBaseUrlChange,
// handleCodexBaseUrlChange, // TODO: 等 Codex 支持时使用
} = useBaseUrlState({
appType,
category,
settingsConfig: form.watch("settingsConfig"),
codexConfig: "", // TODO: 从 settingsConfig 中提取 codex config
onSettingsConfigChange: (config) => form.setValue("settingsConfig", config),
onCodexConfigChange: () => {
// TODO: 更新 codex config
},
});
useEffect(() => { useEffect(() => {
form.reset(defaultValues); form.reset(defaultValues);
}, [defaultValues, form]); }, [defaultValues, form]);
@@ -181,6 +201,10 @@ export function ProviderForm({
); );
}, [groupedPresets]); }, [groupedPresets]);
// 判断是否显示端点测速(仅第三方和自定义类别)
const shouldShowSpeedTest =
category === "third_party" || category === "custom";
const handlePresetChange = (value: string) => { const handlePresetChange = (value: string) => {
setSelectedPresetId(value); setSelectedPresetId(value);
if (value === "custom") { if (value === "custom") {
@@ -338,6 +362,50 @@ export function ProviderForm({
</div> </div>
)} )}
{/* Base URL 输入框(仅 Claude 第三方/自定义显示) */}
{appType === "claude" && shouldShowSpeedTest && (
<div className="space-y-2">
<div className="flex items-center justify-between">
<FormLabel htmlFor="baseUrl">
{t("providerForm.apiEndpoint", { defaultValue: "API 端点" })}
</FormLabel>
<button
type="button"
onClick={() => setIsEndpointModalOpen(true)}
className="flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 transition-colors"
>
<Zap className="h-3.5 w-3.5" />
{t("providerForm.manageAndTest", { defaultValue: "管理和测速" })}
</button>
</div>
<Input
id="baseUrl"
type="url"
value={baseUrl}
onChange={(e) => handleClaudeBaseUrlChange(e.target.value)}
placeholder={t("providerForm.apiEndpointPlaceholder", { defaultValue: "https://api.example.com" })}
autoComplete="off"
/>
<div className="p-3 bg-amber-50 dark:bg-amber-900/20 border border-amber-200 dark:border-amber-700 rounded-lg">
<p className="text-xs text-amber-600 dark:text-amber-400">
{t("providerForm.apiHint", { defaultValue: "API 端点地址用于连接服务器" })}
</p>
</div>
</div>
)}
{/* 端点测速弹窗 - Claude */}
{appType === "claude" && shouldShowSpeedTest && isEndpointModalOpen && (
<EndpointSpeedTest
appType={appType}
value={baseUrl}
onChange={handleClaudeBaseUrlChange}
initialEndpoints={[{ url: baseUrl }]}
visible={isEndpointModalOpen}
onClose={() => setIsEndpointModalOpen(false)}
/>
)}
<FormField <FormField
control={form.control} control={form.control}
name="settingsConfig" name="settingsConfig"