From 654a4745d5ef08f32674a89973fc5d5d0eca49b2 Mon Sep 17 00:00:00 2001 From: farion1231 Date: Thu, 21 Aug 2025 22:20:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20API=20Key=20?= =?UTF-8?q?=E5=BF=AB=E9=80=9F=E8=BE=93=E5=85=A5=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 选择预设模板后自动显示 API Key 输入框 - 输入 API Key 后自动更新 JSON 配置 - 简化用户配置流程,无需手动编辑 JSON - 优化交互体验,API Key 输入框位于供应商名称下方 --- src/renderer/components/ProviderForm.tsx | 195 +++++++++++++++-------- 1 file changed, 126 insertions(+), 69 deletions(-) diff --git a/src/renderer/components/ProviderForm.tsx b/src/renderer/components/ProviderForm.tsx index c2e7367..0c74c28 100644 --- a/src/renderer/components/ProviderForm.tsx +++ b/src/renderer/components/ProviderForm.tsx @@ -1,16 +1,20 @@ -import React, { useState, useEffect } from 'react' -import { Provider } from '../../shared/types' -import { updateCoAuthoredSetting, checkCoAuthoredSetting, extractWebsiteUrl } from '../utils/providerConfigUtils' -import { providerPresets } from '../config/providerPresets' -import './AddProviderModal.css' +import React, { useState, useEffect } from "react"; +import { Provider } from "../../shared/types"; +import { + updateCoAuthoredSetting, + checkCoAuthoredSetting, + extractWebsiteUrl, +} 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 + title: string; + submitText: string; + initialData?: Provider; + showPresets?: boolean; + onSubmit: (data: Omit) => void; + onClose: () => void; } const ProviderForm: React.FC = ({ @@ -19,111 +23,148 @@ const ProviderForm: React.FC = ({ initialData, showPresets = false, onSubmit, - onClose + 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) + 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) + const configString = JSON.stringify(initialData.settingsConfig, null, 2); + const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); + setDisableCoAuthored(hasCoAuthoredDisabled); } - }, [initialData]) + }, [initialData]); const handleSubmit = (e: React.FormEvent) => { - e.preventDefault() - setError('') + e.preventDefault(); + setError(""); if (!formData.name) { - setError('请填写供应商名称') - return + setError("请填写供应商名称"); + return; } if (!formData.settingsConfig.trim()) { - setError('请填写配置内容') - return + setError("请填写配置内容"); + return; } - let settingsConfig: Record - + let settingsConfig: Record; + try { - settingsConfig = JSON.parse(formData.settingsConfig) + settingsConfig = JSON.parse(formData.settingsConfig); } catch (err) { - setError('配置JSON格式错误,请检查语法') - return + setError("配置JSON格式错误,请检查语法"); + return; } onSubmit({ name: formData.name, websiteUrl: formData.websiteUrl, - settingsConfig - }) - } + settingsConfig, + }); + }; const handleChange = ( e: React.ChangeEvent ) => { - const { name, value } = e.target - - if (name === 'settingsConfig') { + const { name, value } = e.target; + + if (name === "settingsConfig") { // 当用户修改配置时,尝试自动提取官网地址 - const extractedWebsiteUrl = extractWebsiteUrl(value) - + const extractedWebsiteUrl = extractWebsiteUrl(value); + // 同时检查并同步选择框状态 - const hasCoAuthoredDisabled = checkCoAuthoredSetting(value) - setDisableCoAuthored(hasCoAuthoredDisabled) - + const hasCoAuthoredDisabled = checkCoAuthoredSetting(value); + setDisableCoAuthored(hasCoAuthoredDisabled); + setFormData({ ...formData, [name]: value, // 只有在官网地址为空时才自动填入 websiteUrl: formData.websiteUrl || extractedWebsiteUrl, - }) + }); } else { setFormData({ ...formData, [name]: value, - }) + }); } - } + }; // 处理选择框变化 const handleCoAuthoredToggle = (checked: boolean) => { - setDisableCoAuthored(checked) - + setDisableCoAuthored(checked); + // 更新JSON配置 - const updatedConfig = updateCoAuthoredSetting(formData.settingsConfig, checked) + 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); - 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 - }) - + settingsConfig: configString, + }); + // 设置选中的预设 - setSelectedPreset(index) - + setSelectedPreset(index); + + // 清空 API Key 输入框,让用户重新输入 + setApiKey(""); + // 同步选择框状态 - const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString) - setDisableCoAuthored(hasCoAuthoredDisabled) - } + const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); + setDisableCoAuthored(hasCoAuthoredDisabled); + }; + + // 处理 API Key 输入并自动更新配置 + const handleApiKeyChange = (key: string) => { + setApiKey(key); + + if (selectedPreset !== null && key.trim()) { + // 获取当前选中的预设配置 + const preset = providerPresets[selectedPreset]; + const updatedConfig = JSON.parse(JSON.stringify(preset.settingsConfig)); + + // 替换配置中的 API Key + if (updatedConfig.env && updatedConfig.env.ANTHROPIC_AUTH_TOKEN) { + updatedConfig.env.ANTHROPIC_AUTH_TOKEN = key.trim(); + } + + const configString = JSON.stringify(updatedConfig, null, 2); + + // 更新表单配置 + setFormData((prev) => ({ + ...prev, + settingsConfig: configString, + })); + + // 同步选择框状态 + const hasCoAuthoredDisabled = checkCoAuthoredSetting(configString); + setDisableCoAuthored(hasCoAuthoredDisabled); + } + }; return (
@@ -140,7 +181,9 @@ const ProviderForm: React.FC = ({
+ {selectedPreset !== null && ( +
+ + handleApiKeyChange(e.target.value)} + placeholder="只需要填这里,下方配置会自动填充" + autoComplete="off" + /> +
+ )} +
= ({ } }`} rows={12} - style={{fontFamily: 'monospace', fontSize: '14px'}} + style={{ fontFamily: "monospace", fontSize: "14px" }} required /> @@ -221,7 +278,7 @@ const ProviderForm: React.FC = ({
- ) -} + ); +}; -export default ProviderForm \ No newline at end of file +export default ProviderForm;