feat: add lemonapi gemini preset
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-03-08 21:52:52 +08:00
parent 1a80812c4f
commit a389d6b7dc
3 changed files with 124 additions and 10 deletions

View File

@ -479,6 +479,25 @@ const PROVIDER_DEFAULT_BASE_URL: Record<string, string> = {
"volcano-video": "https://ark.cn-beijing.volces.com/api/v3",
};
const LEMON_OPENAI_BASE_URL = "https://new.lemonapi.site/v1";
const LEMON_PROVIDER_PRESET = {
name: "LemonAPI Gemini",
type: "openai" as const,
baseUrl: LEMON_OPENAI_BASE_URL,
};
const LEMON_MODEL_PRESETS = [
{
modelId: "[L]gemini-3.1-pro-preview",
displayName: "Gemini-3.1-pro-preview",
supportsVision: true,
supportsImageGen: false,
isMultimodal: true,
description: "LemonAPI OpenAI兼容 Gemini 3.1 Pro 预设模型",
},
];
function getProviderDefaultBaseUrl(type?: string) {
if (!type) return "";
return PROVIDER_DEFAULT_BASE_URL[type] || "";
@ -488,6 +507,10 @@ function isHttpUrlLike(value: string) {
return /^https?:\/\//i.test(value.trim());
}
function isLemonApiBaseUrl(value?: string | null) {
return String(value || "").trim().replace(/\/+$/, "") === LEMON_OPENAI_BASE_URL;
}
export function AdminSettingsClient() {
const [activeTab, setActiveTab] = useState("users");
@ -2249,6 +2272,9 @@ export function AdminSettingsClient() {
const method = editingProvider ? "PUT" : "POST";
const isNewProvider = !editingProvider;
const isVolcanoVideo = providerForm.type === 'volcano-video';
const isLemonProvider =
providerForm.type === "openai" &&
isLemonApiBaseUrl(providerForm.baseUrl || getProviderDefaultBaseUrl(providerForm.type));
const defaultBaseUrl = getProviderDefaultBaseUrl(providerForm.type);
const normalizedBaseUrl = providerForm.baseUrl.trim();
@ -2306,6 +2332,15 @@ export function AdminSettingsClient() {
toast.warning('预设模型添加失败,请手动点击"快速添加预设模型"按钮');
}
}
if (isNewProvider && isLemonProvider && providerId) {
try {
await handleQuickAddLemonModels(providerId);
} catch (modelError) {
console.error("[Auto Add Lemon Models] Error:", modelError);
toast.warning('LemonAPI 预设模型添加失败,请手动点击"快速添加 Gemini 预设模型"按钮');
}
}
} catch (error) {
toast.error("保存提供商失败");
}
@ -2412,6 +2447,69 @@ export function AdminSettingsClient() {
}
};
const handleUseLemonProviderPreset = () => {
setProviderForm({
id: "",
name: LEMON_PROVIDER_PRESET.name,
type: LEMON_PROVIDER_PRESET.type,
baseUrl: LEMON_PROVIDER_PRESET.baseUrl,
apiKey: "",
isEnabled: true,
});
setEditingProvider(null);
setShowProviderDialog(true);
};
const handleQuickAddLemonModels = async (providerId: string) => {
try {
toast.info("正在添加 LemonAPI Gemini 预设模型...");
let addedCount = 0;
let duplicateCount = 0;
for (const preset of LEMON_MODEL_PRESETS) {
const response = await fetch("/api/admin/ai-models", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
providerId,
modelId: preset.modelId,
displayName: preset.displayName,
description: preset.description,
supportsVision: preset.supportsVision,
supportsImageGen: preset.supportsImageGen,
isEnabled: true,
isHidden: false,
isDefault: false,
isAgentModel: false,
agentCodingModelId: "",
isMultimodal: preset.isMultimodal,
sortOrder: 0,
}),
});
if (response.ok) {
addedCount += 1;
continue;
}
duplicateCount += 1;
}
if (addedCount > 0) {
toast.success(`成功添加 ${addedCount} 个 LemonAPI 预设模型`);
mutateModels();
}
if (addedCount === 0 && duplicateCount > 0) {
toast.warning("LemonAPI 预设模型可能已存在");
}
} catch (error) {
console.error("[Quick Add Lemon Models] Error:", error);
toast.error("添加 LemonAPI 预设模型失败");
}
};
// --- AI 模型逻辑 ---
const resetModelForm = () => {
setModelForm({
@ -6443,17 +6541,21 @@ export function AdminSettingsClient() {
<TabsContent value="ai" className="mt-6 space-y-6">
<Card>
<CardHeader className="flex flex-row items-center justify-between">
<div>
<div>
<CardTitle>AI 提供商</CardTitle>
<CardDescription>配置 AI 服务提供商</CardDescription>
</div>
<Dialog open={showProviderDialog} onOpenChange={setShowProviderDialog}>
<DialogTrigger asChild>
<Button onClick={() => { resetProviderForm(); setShowProviderDialog(true); }}>
<Plus className="mr-2 h-4 w-4" /> 添加提供商
<div className="flex items-center gap-2">
<Button variant="outline" onClick={handleUseLemonProviderPreset}>
<Sparkles className="mr-2 h-4 w-4" /> LemonAPI Gemini
</Button>
</DialogTrigger>
<DialogContent className="!bg-white !dark:bg-zinc-950">
<Dialog open={showProviderDialog} onOpenChange={setShowProviderDialog}>
<DialogTrigger asChild>
<Button onClick={() => { resetProviderForm(); setShowProviderDialog(true); }}>
<Plus className="mr-2 h-4 w-4" /> 添加提供商
</Button>
</DialogTrigger>
<DialogContent className="!bg-white !dark:bg-zinc-950">
<DialogHeader>
<DialogTitle>{editingProvider ? "编辑提供商" : "添加提供商"}</DialogTitle>
</DialogHeader>
@ -6544,8 +6646,9 @@ export function AdminSettingsClient() {
<Button variant="outline" onClick={() => setShowProviderDialog(false)}>取消</Button>
<Button onClick={handleSaveProvider}>保存</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</DialogContent>
</Dialog>
</div>
</CardHeader>
<CardContent>
<div className="space-y-4">
@ -6570,6 +6673,17 @@ export function AdminSettingsClient() {
快速添加预设模型
</Button>
)}
{provider.type === "openai" && isLemonApiBaseUrl(provider.baseUrl) && (
<Button
variant="secondary"
size="sm"
className="mt-2"
onClick={() => handleQuickAddLemonModels(provider.id)}
>
<Sparkles className="h-4 w-4 mr-1" />
快速添加 Gemini 预设模型
</Button>
)}
</div>
<div className="flex items-center gap-2">
<Button variant="outline" size="sm" onClick={() => {

Binary file not shown.

File diff suppressed because one or more lines are too long