import React, { useState, useEffect } from "react"; import { Provider } from "../types"; import { updateCoAuthoredSetting, checkCoAuthoredSetting, extractWebsiteUrl, getApiKeyFromConfig, hasApiKeyField, setApiKeyInConfig, } from "../utils/providerConfigUtils"; import { providerPresets } from "../config/providerPresets"; import "./AddProviderModal.css"; interface ProviderFormProps { title: string; submitText: string; initialData?: Provider; showPresets?: boolean; onSubmit: (data: Omit) => void; onClose: () => void; } const ProviderForm: React.FC = ({ title, submitText, initialData, showPresets = false, onSubmit, onClose, }) => { const [formData, setFormData] = useState({ name: initialData?.name || "", websiteUrl: initialData?.websiteUrl || "", settingsConfig: initialData ? JSON.stringify(initialData.settingsConfig, null, 2) : "", }); const [error, setError] = useState(""); const [disableCoAuthored, setDisableCoAuthored] = useState(false); const [selectedPreset, setSelectedPreset] = useState(null); const [apiKey, setApiKey] = useState(""); // 初始化时检查禁用签名状态 useEffect(() => { if (initialData) { const configString = JSON.stringify(initialData.settingsConfig, null, 2); const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); setDisableCoAuthored(hasCoAuthoredDisabled); } }, [initialData]); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); setError(""); if (!formData.name) { setError("请填写供应商名称"); return; } if (!formData.settingsConfig.trim()) { setError("请填写配置内容"); return; } let settingsConfig: Record; try { settingsConfig = JSON.parse(formData.settingsConfig); } catch (err) { setError("配置JSON格式错误,请检查语法"); return; } onSubmit({ name: formData.name, websiteUrl: formData.websiteUrl, settingsConfig, }); }; const handleChange = ( e: React.ChangeEvent ) => { const { name, value } = e.target; if (name === "settingsConfig") { // 当用户修改配置时,尝试自动提取官网地址 const extractedWebsiteUrl = extractWebsiteUrl(value); // 同时检查并同步选择框状态 const hasCoAuthoredDisabled = checkCoAuthoredSetting(value); setDisableCoAuthored(hasCoAuthoredDisabled); // 同步 API Key 输入框显示与值 const parsedKey = getApiKeyFromConfig(value); setApiKey(parsedKey); setFormData({ ...formData, [name]: value, // 只有在官网地址为空时才自动填入 websiteUrl: formData.websiteUrl || extractedWebsiteUrl, }); } else { setFormData({ ...formData, [name]: value, }); } }; // 处理选择框变化 const handleCoAuthoredToggle = (checked: boolean) => { setDisableCoAuthored(checked); // 更新JSON配置 const updatedConfig = updateCoAuthoredSetting( formData.settingsConfig, checked ); setFormData({ ...formData, settingsConfig: updatedConfig, }); }; const applyPreset = (preset: (typeof providerPresets)[0], index: number) => { const configString = JSON.stringify(preset.settingsConfig, null, 2); setFormData({ name: preset.name, websiteUrl: preset.websiteUrl, settingsConfig: configString, }); // 设置选中的预设 setSelectedPreset(index); // 清空 API Key 输入框,让用户重新输入 setApiKey(""); // 同步选择框状态 const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); setDisableCoAuthored(hasCoAuthoredDisabled); }; // 处理 API Key 输入并自动更新配置 const handleApiKeyChange = (key: string) => { setApiKey(key); const configString = setApiKeyInConfig( formData.settingsConfig, key.trim(), { createIfMissing: selectedPreset !== null } ); // 更新表单配置 setFormData((prev) => ({ ...prev, settingsConfig: configString, })); // 同步选择框状态 const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); setDisableCoAuthored(hasCoAuthoredDisabled); }; // 根据当前配置决定是否展示 API Key 输入框 const showApiKey = selectedPreset !== null || hasApiKeyField(formData.settingsConfig); // 初始时从配置中同步 API Key(编辑模式) useEffect(() => { if (initialData) { const parsedKey = getApiKeyFromConfig( JSON.stringify(initialData.settingsConfig) ); if (parsedKey) setApiKey(parsedKey); } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // 支持按下 ESC 关闭弹窗 useEffect(() => { const onKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") { e.preventDefault(); onClose(); } }; window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, [onClose]); return (
{ if (e.target === e.currentTarget) onClose(); }} >
{title}
{error &&
{error}
} {showPresets && (
{providerPresets.map((preset, index) => ( ))}
)}
handleApiKeyChange(e.target.value)} placeholder="只需要填这里,下方配置会自动填充" autoComplete="off" />