feat(admin): add Tripo3D config in local AI settings
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-04 22:37:08 +08:00
parent cd09eb9004
commit 4349c1cd5f

View File

@ -778,6 +778,14 @@ export function AdminSettingsClient() {
modelId: "", // 首选生图模型ID(多样性模式下优先尝试)
});
const [tripo3dConfig, setTripo3dConfig] = useState({
providerId: "",
name: "Tripo3D",
baseUrl: getProviderDefaultBaseUrl("tripo-3d"),
apiKey: "",
isEnabled: true,
});
// 加载抠图API配置
const { data: rmbgConfigData } = useSWR("/api/admin/settings?key=rmbg_api_config", fetcher);
useEffect(() => {
@ -969,6 +977,30 @@ export function AdminSettingsClient() {
}
}, [sceneFusionConfigData]);
useEffect(() => {
const tripoProvider = (providersData?.providers || []).find(
(provider) => provider.type === "tripo-3d"
);
if (tripoProvider) {
setTripo3dConfig({
providerId: tripoProvider.id,
name: tripoProvider.name || "Tripo3D",
baseUrl: tripoProvider.baseUrl || getProviderDefaultBaseUrl("tripo-3d"),
apiKey: "",
isEnabled: tripoProvider.isEnabled,
});
return;
}
setTripo3dConfig({
providerId: "",
name: "Tripo3D",
baseUrl: getProviderDefaultBaseUrl("tripo-3d"),
apiKey: "",
isEnabled: true,
});
}, [providersData?.providers]);
// 导航链接状态
const [navLinkForm, setNavLinkForm] = useState({
id: "",
@ -2209,6 +2241,56 @@ export function AdminSettingsClient() {
}
};
const handleSaveTripo3dConfig = async () => {
try {
const trimmedName = tripo3dConfig.name.trim() || "Tripo3D";
const trimmedBaseUrl =
tripo3dConfig.baseUrl.trim() || getProviderDefaultBaseUrl("tripo-3d");
const hasProvider = Boolean(tripo3dConfig.providerId);
if (!hasProvider && !tripo3dConfig.apiKey.trim()) {
toast.error("请填写 Tripo3D API Key");
return;
}
const requestData: Record<string, any> = hasProvider
? {
id: tripo3dConfig.providerId,
name: trimmedName,
type: "tripo-3d",
baseUrl: trimmedBaseUrl,
isEnabled: tripo3dConfig.isEnabled,
}
: {
name: trimmedName,
type: "tripo-3d",
baseUrl: trimmedBaseUrl,
apiKey: tripo3dConfig.apiKey.trim(),
isEnabled: tripo3dConfig.isEnabled,
};
if (hasProvider && tripo3dConfig.apiKey.trim()) {
requestData.apiKey = tripo3dConfig.apiKey.trim();
}
const response = await fetch("/api/admin/ai-providers", {
method: hasProvider ? "PUT" : "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(requestData),
});
if (!response.ok) {
throw new Error("保存失败");
}
toast.success("Tripo3D 配置保存成功");
setTripo3dConfig((prev) => ({ ...prev, apiKey: "" }));
mutateProviders();
} catch (error) {
toast.error("保存 Tripo3D 配置失败");
}
};
// 快速添加火山引擎视频预设模型
const handleQuickAddVolcanoModels = async (providerId: string) => {
if (!confirm("将为此服务商添加4个预设模型:\n- Seedance Pro (全功能)\n- Seedance Pro Fast (快速)\n- Seedance Lite I2V (图生视频)\n- Seedance Lite T2V (文生视频)\n\n继续吗?")) {
@ -7225,6 +7307,80 @@ export function AdminSettingsClient() {
{/* 本地AI设置 */}
<TabsContent value="rmbg" className="mt-6 space-y-6">
<Card>
<CardHeader>
<CardTitle className="text-xl">Tripo3D API 配置</CardTitle>
<CardDescription>
配置无限画布 3D 生成功能使用的 Tripo3D 接口,保存后写入数据库 AI 提供商配置。
</CardDescription>
</CardHeader>
<CardContent className="space-y-6 pt-6">
<div className="space-y-2">
<Label htmlFor="tripo3dName">提供商名称</Label>
<Input
id="tripo3dName"
value={tripo3dConfig.name}
onChange={(e) =>
setTripo3dConfig({ ...tripo3dConfig, name: e.target.value })
}
placeholder="Tripo3D"
/>
</div>
<div className="space-y-2">
<Label htmlFor="tripo3dBaseUrl">API 地址</Label>
<Input
id="tripo3dBaseUrl"
value={tripo3dConfig.baseUrl}
onChange={(e) =>
setTripo3dConfig({ ...tripo3dConfig, baseUrl: e.target.value })
}
placeholder={getProviderDefaultBaseUrl("tripo-3d")}
/>
<div className="text-xs text-muted-foreground">
默认:{getProviderDefaultBaseUrl("tripo-3d")}
</div>
</div>
<div className="space-y-2">
<Label htmlFor="tripo3dApiKey">
API Key {tripo3dConfig.providerId ? "(留空则不修改)" : "*"}
</Label>
<Input
id="tripo3dApiKey"
type="password"
value={tripo3dConfig.apiKey}
onChange={(e) =>
setTripo3dConfig({ ...tripo3dConfig, apiKey: e.target.value })
}
placeholder={
tripo3dConfig.providerId ? "留空则不修改当前 Key" : "请输入 Tripo3D API Key"
}
/>
</div>
<div className="flex items-center justify-between rounded-lg border p-3">
<div className="space-y-0.5">
<Label className="text-sm">启用 Tripo3D</Label>
<div className="text-xs text-muted-foreground">
关闭后 3D 生成接口将不可用
</div>
</div>
<div className="flex items-center gap-2">
<Switch
checked={tripo3dConfig.isEnabled}
onCheckedChange={(checked) =>
setTripo3dConfig({ ...tripo3dConfig, isEnabled: checked })
}
/>
<span className="text-sm font-medium text-muted-foreground min-w-[3rem]">
{tripo3dConfig.isEnabled ? "已开启" : "已关闭"}
</span>
</div>
</div>
<Button onClick={handleSaveTripo3dConfig}>
<Save className="mr-2 h-4 w-4" /> 保存 Tripo3D 配置
</Button>
</CardContent>
</Card>
{/* 抠图API配置 */}
<Card>
<CardHeader>