import React, { useState, useEffect, useRef } from "react"; import { X, Save } from "lucide-react"; import { isLinux } from "../../lib/platform"; import { generateThirdPartyAuth, generateThirdPartyConfig, } from "../../config/codexProviderPresets"; interface CodexConfigEditorProps { authValue: string; configValue: string; onAuthChange: (value: string) => void; onConfigChange: (value: string) => void; onAuthBlur?: () => void; useCommonConfig: boolean; onCommonConfigToggle: (checked: boolean) => void; commonConfigSnippet: string; onCommonConfigSnippetChange: (value: string) => void; commonConfigError: string; authError: string; isCustomMode?: boolean; // 新增:是否为自定义模式 onWebsiteUrlChange?: (url: string) => void; // 新增:更新网址回调 isTemplateModalOpen?: boolean; // 新增:模态框状态 setIsTemplateModalOpen?: (open: boolean) => void; // 新增:设置模态框状态 onNameChange?: (name: string) => void; // 新增:更新供应商名称回调 } const CodexConfigEditor: React.FC = ({ authValue, configValue, onAuthChange, onConfigChange, onAuthBlur, useCommonConfig, onCommonConfigToggle, commonConfigSnippet, onCommonConfigSnippetChange, commonConfigError, authError, onWebsiteUrlChange, onNameChange, isTemplateModalOpen: externalTemplateModalOpen, setIsTemplateModalOpen: externalSetTemplateModalOpen, }) => { const [isCommonConfigModalOpen, setIsCommonConfigModalOpen] = useState(false); // 使用内部状态或外部状态 const [internalTemplateModalOpen, setInternalTemplateModalOpen] = useState(false); const isTemplateModalOpen = externalTemplateModalOpen ?? internalTemplateModalOpen; const setIsTemplateModalOpen = externalSetTemplateModalOpen ?? setInternalTemplateModalOpen; const [templateApiKey, setTemplateApiKey] = useState(""); const [templateProviderName, setTemplateProviderName] = useState(""); const [templateBaseUrl, setTemplateBaseUrl] = useState(""); const [templateWebsiteUrl, setTemplateWebsiteUrl] = useState(""); const [templateModelName, setTemplateModelName] = useState("gpt-5-codex"); const apiKeyInputRef = useRef(null); const baseUrlInputRef = useRef(null); const modelNameInputRef = useRef(null); const displayNameInputRef = useRef(null); // 移除自动填充逻辑,因为现在在点击自定义按钮时就已经填充 const [templateDisplayName, setTemplateDisplayName] = useState(""); useEffect(() => { if (commonConfigError && !isCommonConfigModalOpen) { setIsCommonConfigModalOpen(true); } }, [commonConfigError, isCommonConfigModalOpen]); // 支持按下 ESC 关闭弹窗 useEffect(() => { if (!isCommonConfigModalOpen) return; const onKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") { e.preventDefault(); closeModal(); } }; window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, [isCommonConfigModalOpen]); const closeModal = () => { setIsCommonConfigModalOpen(false); }; const closeTemplateModal = () => { setIsTemplateModalOpen(false); }; const applyTemplate = () => { const requiredInputs = [ displayNameInputRef.current, apiKeyInputRef.current, baseUrlInputRef.current, modelNameInputRef.current, ]; for (const input of requiredInputs) { if (input && !input.checkValidity()) { input.reportValidity(); input.focus(); return; } } const trimmedKey = templateApiKey.trim(); const trimmedBaseUrl = templateBaseUrl.trim(); const trimmedModel = templateModelName.trim(); const auth = generateThirdPartyAuth(trimmedKey); const config = generateThirdPartyConfig( templateProviderName || "custom", trimmedBaseUrl, trimmedModel ); onAuthChange(JSON.stringify(auth, null, 2)); onConfigChange(config); if (onWebsiteUrlChange) { const trimmedWebsite = templateWebsiteUrl.trim(); if (trimmedWebsite) { onWebsiteUrlChange(trimmedWebsite); } } if (onNameChange) { const trimmedName = templateDisplayName.trim(); if (trimmedName) { onNameChange(trimmedName); } } setTemplateApiKey(""); setTemplateProviderName(""); setTemplateBaseUrl(""); setTemplateWebsiteUrl(""); setTemplateModelName("gpt-5-codex"); setTemplateDisplayName(""); closeTemplateModal(); }; const handleTemplateInputKeyDown = ( e: React.KeyboardEvent ) => { if (e.key === "Enter") { e.preventDefault(); e.stopPropagation(); applyTemplate(); } }; const handleAuthChange = (value: string) => { onAuthChange(value); }; const handleConfigChange = (value: string) => { onConfigChange(value); }; const handleCommonConfigSnippetChange = (value: string) => { onCommonConfigSnippetChange(value); }; return (