diff --git a/app/(admin)/settings/_lib/types.ts b/app/(admin)/settings/_lib/types.ts
index 82578cbf6..03db7244a 100644
--- a/app/(admin)/settings/_lib/types.ts
+++ b/app/(admin)/settings/_lib/types.ts
@@ -92,6 +92,7 @@ export type AdminAiProvider = {
| "bananaimage"
| "visionary"
| "atlascloud"
+ | "vip98k"
| "stepfun-image"
| "midjourney"
| "fal-video"
diff --git a/app/(admin)/settings/admin-settings-client.tsx b/app/(admin)/settings/admin-settings-client.tsx
index bab8ac724..dba9be50b 100644
--- a/app/(admin)/settings/admin-settings-client.tsx
+++ b/app/(admin)/settings/admin-settings-client.tsx
@@ -36,6 +36,7 @@ import {
ImagePlus,
Key,
Layers,
+ LayoutTemplate,
Loader2,
type LucideIcon,
Maximize2,
@@ -625,6 +626,7 @@ type AiProvider = {
| "bananaimage"
| "visionary"
| "atlascloud"
+ | "vip98k"
| "stepfun-image"
| "midjourney"
| "fal-video"
@@ -654,6 +656,9 @@ type ImageGenConfig = {
supportsSeed?: boolean; // 是否支持随机种子
supportedAspectRatios?: string[]; // 支持的图片比例
supportedImageSizes?: string[]; // 支持的分辨率/K 数
+ maxReferenceImages?: number; // 最大参考图数量
+ maxVideoReferences?: number; // 最大参考视频数量
+ supportsQuality?: boolean; // 是否支持质量档位
creditCostPerImage?: number; // 每张图片积分消耗
creditCostMultiplierBySize?: Record; // 各图片尺寸积分倍率
creditDiscountRate?: number; // 积分折扣,按“折”配置,如 5 = 5折
@@ -663,6 +668,7 @@ type ImageGenConfig = {
creditCostPerVideoByResolution?: Record; // 各分辨率积分
enableLoadingPlaceholder?: boolean; // 是否启用加载占位图
loadingColor?: string; // 占位图主题色,如 "purple", "blue", "green"
+ vip98k?: Record; // VIP98K 目录元数据
};
function createDefaultImageGenConfig(): ImageGenConfig {
@@ -1037,6 +1043,7 @@ const CANVAS_TOOLBAR_FALLBACK_ICONS: Record =
imageRemoveBackground: Scissors,
imageBoxCutout: Scan,
imageLocalEdit: Wand2,
+ imageLayoutReplace: LayoutTemplate,
imageRemoveWatermark: Eraser,
imageResize: Maximize2,
imageTextEdit: Type,
@@ -1585,6 +1592,7 @@ const PROVIDER_TYPES = [
{ value: "bananaimage", label: "BananaImage 生图" },
{ value: "visionary", label: "Visionary 生图" },
{ value: "atlascloud", label: "Atlas Cloud 图片 / 3D 模型" },
+ { value: "vip98k", label: "VIP98K 混合模型服务" },
{ value: "stepfun-image", label: "阶跃星辰 Step Image Edit" },
{ value: "bltcy-video", label: "柏拉图统一视频" },
{ value: "grsai-gpt-image", label: "Grsai GPT Image" },
@@ -1622,6 +1630,7 @@ const PROVIDER_DEFAULT_BASE_URL: Record = {
bananaimage: "https://bananaimage.aigenmedia.art",
visionary: "https://api.visionary.beer",
atlascloud: "https://api.atlascloud.ai",
+ vip98k: "https://api.vip98k.com",
"stepfun-image": "https://api.stepfun.com",
"bltcy-video": "https://api.bltcy.ai",
"grsai-gpt-image": "https://grsai.dakka.com.cn",
@@ -1629,7 +1638,7 @@ const PROVIDER_DEFAULT_BASE_URL: Record = {
midjourney: "https://your-midjourney-api.example.com",
"fal-video": "https://fal.run",
"tripo-3d": "https://api.tripo3d.ai/v2/openapi",
- "worldlabs-3d": "https://api.worldlabs.ai",
+ "worldlabs-3d": "https://api.vip98k.com",
"kittycad-cad": "https://api.zoo.dev",
runway: "https://api.dev.runwayml.com",
krea: "https://api.krea.ai",
@@ -4055,6 +4064,7 @@ export function AdminSettingsClient() {
| "bananaimage"
| "visionary"
| "atlascloud"
+ | "vip98k"
| "stepfun-image"
| "midjourney"
| "fal-video"
@@ -6329,6 +6339,7 @@ export function AdminSettingsClient() {
const isBananaImageProvider = providerForm.type === "bananaimage";
const isVisionaryProvider = providerForm.type === "visionary";
const isAtlasCloudProvider = providerForm.type === "atlascloud";
+ const isVip98kProvider = providerForm.type === "vip98k";
const isBltcyVideoProvider = providerForm.type === "bltcy-video";
const isLemonProvider =
providerForm.type === "openai" &&
@@ -6504,6 +6515,17 @@ export function AdminSettingsClient() {
}
}
+ if (isNewProvider && isVip98kProvider && providerId) {
+ try {
+ await handleQuickAddVip98kModels(providerId, { skipConfirm: true });
+ } catch (modelError) {
+ console.error("[Auto Sync VIP98K Models] Error:", modelError);
+ toast.warning(
+ 'VIP98K 模型同步失败,请手动点击"同步 VIP98K 全部模型"按钮'
+ );
+ }
+ }
+
if (isNewProvider && isBltcyVideoProvider && providerId) {
try {
await handleQuickAddBltcyVideoModels(providerId, {
@@ -7591,6 +7613,46 @@ export function AdminSettingsClient() {
}
};
+ const handleQuickAddVip98kModels = async (
+ providerId: string,
+ options?: { skipConfirm?: boolean }
+ ) => {
+ if (
+ !options?.skipConfirm &&
+ !confirm(
+ "将从 VIP98K 模型目录同步全部模型,并按图片、视频、3D 世界、文本、图片工具、OCR、音频工具分类。图片模型会配置比例、1K/2K/4K 和多参考图能力。\n\n继续吗?"
+ )
+ ) {
+ return;
+ }
+
+ try {
+ toast.info("正在读取 VIP98K 模型目录...");
+ const response = await fetch("/api/admin/vip98k-models", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify({ providerId }),
+ });
+ const data = await response.json();
+ if (!response.ok) throw new Error(data.error || "同步失败");
+
+ const totalSynced =
+ Number(data.addedCount || 0) + Number(data.updatedCount || 0);
+ const totalCatalog = Number(data.counts?.total || totalSynced);
+ toast.success(
+ `已同步 ${totalSynced} 个 VIP98K 模型(目录共 ${totalCatalog} 个)`
+ );
+ mutateModels();
+ if (data.errors?.length) {
+ toast.warning(`${data.errors.length} 个 VIP98K 模型同步失败`);
+ }
+ } catch (error: any) {
+ console.error("[Quick Add VIP98K Models] Error:", error);
+ toast.error(error.message || "同步 VIP98K 模型失败");
+ throw error;
+ }
+ };
+
const handleUseFalImageProviderPreset = () => {
setProviderForm({
id: "",
@@ -15800,6 +15862,13 @@ export function AdminSettingsClient() {
并按每个模型自己的 Schema 配置多图数量、比例及 1K/2K/4K 档位。
)}
+ {providerForm.type === "vip98k" && (
+
+ VIP98K 使用 Bearer API Key 认证,Base URL 只填写
+ https://api.vip98k.com。保存后会自动同步目录中的图片、视频、3D 世界、
+ 文本和工具模型;图片模型会配置比例、1K/2K/4K 与多参考图能力。
+
+ )}
{providerForm.type === "bfl-image" &&
isBltcyBflBaseUrl(providerForm.baseUrl) && (
@@ -15957,6 +16026,17 @@ export function AdminSettingsClient() {
同步 Atlas Cloud 图片 / 3D 模型
)}
+ {provider.type === "vip98k" && (
+
+ )}
{provider.type === "bltcy-video" && (
) : null}
+ {selectedImageLayoutReplaceEnabled && selectedImageNodes.length === 1 ? (
+
+ ) : null}