Files
CC-Switch/src/renderer/components/AddProviderModal.tsx
T
farion1231 b0d4537398 改进添加供应商界面:实现自动提取官网地址功能
- 新增 extractWebsiteUrl 函数,从 JSON 配置中自动解析 ANTHROPIC_BASE_URL
- 智能处理 URL 前缀,自动去掉 "api." 前缀生成官网地址
- 优化用户体验:仅在官网地址为空时自动填入,不覆盖用户手动输入
- 支持实时解析,用户输入 JSON 配置时立即更新官网地址字段
2025-08-07 22:20:03 +08:00

218 lines
5.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from "react";
import { Provider } from "../../shared/types";
import "./AddProviderModal.css";
interface AddProviderModalProps {
onAdd: (provider: Omit<Provider, "id">) => void;
onClose: () => void;
}
const AddProviderModal: React.FC<AddProviderModalProps> = ({
onAdd,
onClose,
}) => {
const [formData, setFormData] = useState({
name: "",
websiteUrl: "",
settingsConfig: ""
});
const [error, setError] = useState("");
// 预设的供应商配置模板
const presets = [
{
name: "Anthropic 官方",
websiteUrl: "https://console.anthropic.com",
settingsConfig: {
"env": {
"ANTHROPIC_BASE_URL": "https://api.anthropic.com",
"ANTHROPIC_AUTH_TOKEN": "sk-your-api-key-here"
}
}
},
{
name: "PackyCode",
websiteUrl: "https://www.packycode.com",
settingsConfig: {
"env": {
"ANTHROPIC_BASE_URL": "https://api.packycode.com",
"ANTHROPIC_AUTH_TOKEN": "sk-your-api-key-here"
}
}
},
{
name: "YesCode",
websiteUrl: "https://yes.vg",
settingsConfig: {
"env": {
"ANTHROPIC_BASE_URL": "https://co.yes.vg",
"ANTHROPIC_AUTH_TOKEN": "cr-your-api-key-here"
}
}
}
];
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
setError("");
if (!formData.name) {
setError("请填写供应商名称");
return;
}
if (!formData.settingsConfig.trim()) {
setError("请填写配置内容");
return;
}
let settingsConfig: object;
try {
settingsConfig = JSON.parse(formData.settingsConfig);
} catch (err) {
setError("配置JSON格式错误,请检查语法");
return;
}
onAdd({
name: formData.name,
websiteUrl: formData.websiteUrl,
settingsConfig
});
};
// 从JSON配置中提取并处理官网地址
const extractWebsiteUrl = (jsonString: string): string => {
try {
const config = JSON.parse(jsonString);
const baseUrl = config?.env?.ANTHROPIC_BASE_URL;
if (baseUrl && typeof baseUrl === 'string') {
// 去掉 "api." 前缀
return baseUrl.replace(/^https?:\/\/api\./, 'https://');
}
} catch (err) {
// 忽略JSON解析错误
}
return '';
};
const handleChange = (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
) => {
const { name, value } = e.target;
if (name === 'settingsConfig') {
// 当用户修改配置时,尝试自动提取官网地址
const extractedWebsiteUrl = extractWebsiteUrl(value);
setFormData({
...formData,
[name]: value,
// 只有在官网地址为空时才自动填入
websiteUrl: formData.websiteUrl || extractedWebsiteUrl,
});
} else {
setFormData({
...formData,
[name]: value,
});
}
};
const applyPreset = (preset: typeof presets[0]) => {
setFormData({
name: preset.name,
websiteUrl: preset.websiteUrl,
settingsConfig: JSON.stringify(preset.settingsConfig, null, 2)
});
};
return (
<div className="modal-overlay">
<div className="modal-content">
<h2></h2>
{error && <div className="error-message">{error}</div>}
<div className="presets">
<label></label>
<div className="preset-buttons">
{presets.map((preset, index) => (
<button
key={index}
type="button"
className="preset-btn"
onClick={() => applyPreset(preset)}
>
{preset.name}
</button>
))}
</div>
</div>
<form onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="name"> *</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
placeholder="例如:Anthropic 官方"
required
/>
</div>
<div className="form-group">
<label htmlFor="websiteUrl"></label>
<input
type="url"
id="websiteUrl"
name="websiteUrl"
value={formData.websiteUrl}
onChange={handleChange}
placeholder="https://example.com(可选)"
/>
</div>
<div className="form-group">
<label htmlFor="settingsConfig">Claude Code (JSON) *</label>
<textarea
id="settingsConfig"
name="settingsConfig"
value={formData.settingsConfig}
onChange={handleChange}
placeholder={`{
"env": {
"ANTHROPIC_BASE_URL": "https://api.anthropic.com",
"ANTHROPIC_AUTH_TOKEN": "sk-your-api-key-here"
}
}`}
rows={12}
style={{fontFamily: 'monospace', fontSize: '14px'}}
required
/>
<small className="field-hint">
Claude Code settings.json
</small>
</div>
<div className="form-actions">
<button type="button" className="cancel-btn" onClick={onClose}>
</button>
<button type="submit" className="submit-btn">
</button>
</div>
</form>
</div>
</div>
);
};
export default AddProviderModal;