2025-09-06 23:13:01 +08:00
|
|
|
import React from "react";
|
|
|
|
|
import { Zap } from "lucide-react";
|
2025-09-11 22:33:55 +08:00
|
|
|
import { ProviderCategory } from "../../types";
|
2025-09-13 17:04:46 +08:00
|
|
|
import { ClaudeIcon, CodexIcon } from "../BrandIcons";
|
2025-09-06 23:13:01 +08:00
|
|
|
|
|
|
|
|
interface Preset {
|
|
|
|
|
name: string;
|
|
|
|
|
isOfficial?: boolean;
|
2025-09-11 22:33:55 +08:00
|
|
|
category?: ProviderCategory;
|
2025-09-06 23:13:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface PresetSelectorProps {
|
|
|
|
|
title?: string;
|
|
|
|
|
presets: Preset[];
|
|
|
|
|
selectedIndex: number | null;
|
|
|
|
|
onSelectPreset: (index: number) => void;
|
|
|
|
|
onCustomClick: () => void;
|
|
|
|
|
customLabel?: string;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const PresetSelector: React.FC<PresetSelectorProps> = ({
|
|
|
|
|
title = "选择配置类型",
|
|
|
|
|
presets,
|
|
|
|
|
selectedIndex,
|
|
|
|
|
onSelectPreset,
|
|
|
|
|
onCustomClick,
|
|
|
|
|
customLabel = "自定义",
|
|
|
|
|
}) => {
|
2025-09-13 15:36:43 +08:00
|
|
|
const getButtonClass = (
|
|
|
|
|
index: number,
|
2025-09-13 17:04:46 +08:00
|
|
|
preset?: Preset,
|
2025-09-13 15:36:43 +08:00
|
|
|
) => {
|
2025-09-06 23:13:01 +08:00
|
|
|
const isSelected = selectedIndex === index;
|
|
|
|
|
const baseClass =
|
|
|
|
|
"inline-flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors";
|
|
|
|
|
|
|
|
|
|
if (isSelected) {
|
2025-09-13 17:04:46 +08:00
|
|
|
if (preset?.isOfficial || preset?.category === "official") {
|
|
|
|
|
// Codex 官方使用黑色背景
|
|
|
|
|
if (preset?.name.includes("Codex")) {
|
|
|
|
|
return `${baseClass} bg-gray-900 text-white`;
|
|
|
|
|
}
|
|
|
|
|
// Claude 官方使用品牌色背景
|
|
|
|
|
return `${baseClass} bg-[#D97757] text-white`;
|
|
|
|
|
}
|
|
|
|
|
return `${baseClass} bg-blue-500 text-white`;
|
2025-09-06 23:13:01 +08:00
|
|
|
}
|
|
|
|
|
|
2025-09-08 11:48:05 +08:00
|
|
|
return `${baseClass} bg-gray-100 text-gray-500 hover:bg-gray-200`;
|
2025-09-06 23:13:01 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getDescription = () => {
|
|
|
|
|
if (selectedIndex === -1) {
|
|
|
|
|
return "手动配置供应商,需要填写完整的配置信息";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selectedIndex !== null && selectedIndex >= 0) {
|
|
|
|
|
const preset = presets[selectedIndex];
|
2025-09-11 22:33:55 +08:00
|
|
|
return preset?.isOfficial || preset?.category === "official"
|
|
|
|
|
? "官方登录,不需要填写 API Key"
|
2025-09-06 23:13:01 +08:00
|
|
|
: "使用预设配置,只需填写 API Key";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="space-y-4">
|
|
|
|
|
<div>
|
2025-09-08 11:48:05 +08:00
|
|
|
<label className="block text-sm font-medium text-gray-900 mb-3">
|
2025-09-06 23:13:01 +08:00
|
|
|
{title}
|
|
|
|
|
</label>
|
|
|
|
|
<div className="flex flex-wrap gap-2">
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
2025-09-13 15:36:43 +08:00
|
|
|
className={`${getButtonClass(-1)} ${selectedIndex === -1 ? "" : ""}`}
|
2025-09-06 23:13:01 +08:00
|
|
|
onClick={onCustomClick}
|
|
|
|
|
>
|
|
|
|
|
{customLabel}
|
|
|
|
|
</button>
|
|
|
|
|
{presets.map((preset, index) => (
|
|
|
|
|
<button
|
|
|
|
|
key={index}
|
|
|
|
|
type="button"
|
2025-09-13 17:04:46 +08:00
|
|
|
className={getButtonClass(index, preset)}
|
2025-09-06 23:13:01 +08:00
|
|
|
onClick={() => onSelectPreset(index)}
|
|
|
|
|
>
|
2025-09-13 15:36:43 +08:00
|
|
|
{(preset.isOfficial || preset.category === "official") && (
|
2025-09-13 17:04:46 +08:00
|
|
|
<>
|
|
|
|
|
{preset.name.includes("Claude") ? (
|
|
|
|
|
<ClaudeIcon size={14} />
|
|
|
|
|
) : preset.name.includes("Codex") ? (
|
|
|
|
|
<CodexIcon size={14} />
|
|
|
|
|
) : (
|
|
|
|
|
<Zap size={14} />
|
|
|
|
|
)}
|
|
|
|
|
</>
|
2025-09-13 15:36:43 +08:00
|
|
|
)}
|
2025-09-06 23:13:01 +08:00
|
|
|
{preset.name}
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{getDescription() && (
|
2025-09-13 15:36:43 +08:00
|
|
|
<p className="text-sm text-gray-500">{getDescription()}</p>
|
2025-09-06 23:13:01 +08:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default PresetSelector;
|