- 新增 alibaba-image provider 支持 qwen-image-edit-plus 系列模型 - 支持 1-6 张图片输出、提示词优化、反向提示词等参数 - 扩展 ImageParamsBar 支持阿里模型专用参数 - 创建通用 ImageGenerationLoading 组件(可配置颜色主题) - 管理后台添加图片生成模型特性配置界面 - 数据库新增 imageGenConfig 字段存储生图特性 - 确保生成图片正确保存到相册和生图记录
168 lines
5.1 KiB
TypeScript
168 lines
5.1 KiB
TypeScript
import { z } from "zod";
|
|
import { requireAdmin } from "@/lib/middleware/admin";
|
|
import {
|
|
getAllAiModels,
|
|
getAiModelById,
|
|
getAiModelsByProviderId,
|
|
createAiModel,
|
|
updateAiModel,
|
|
deleteAiModel,
|
|
getAiProviderById,
|
|
} from "@/lib/db/queries";
|
|
import { ChatSDKError } from "@/lib/errors";
|
|
|
|
// 🆕 图片生成模型特性配置 Schema
|
|
const imageGenConfigSchema = z.object({
|
|
maxImages: z.number().min(1).max(10).optional(),
|
|
supportsSize: z.boolean().optional(),
|
|
supportsPromptExtend: z.boolean().optional(),
|
|
supportsNegativePrompt: z.boolean().optional(),
|
|
supportsWatermark: z.boolean().optional(),
|
|
supportsSeed: z.boolean().optional(),
|
|
enableLoadingPlaceholder: z.boolean().optional(),
|
|
loadingColor: z.string().optional(),
|
|
}).optional();
|
|
|
|
const createModelSchema = z.object({
|
|
providerId: z.string().uuid(),
|
|
modelId: z.string().min(1).max(128),
|
|
displayName: z.string().min(1).max(128),
|
|
description: z.string().optional(),
|
|
supportsVision: z.boolean().optional(),
|
|
supportsImageGen: z.boolean().optional(),
|
|
isEnabled: z.boolean().optional(),
|
|
isDefault: z.boolean().optional(),
|
|
sortOrder: z.number().optional(),
|
|
fallbackModelId1: z.string().max(128).optional(),
|
|
fallbackModelId2: z.string().max(128).optional(),
|
|
imageGenConfig: imageGenConfigSchema, // 🆕 图片生成特性配置
|
|
});
|
|
|
|
const updateModelSchema = z.object({
|
|
id: z.string().uuid(),
|
|
providerId: z.string().uuid().optional(),
|
|
modelId: z.string().min(1).max(128).optional(),
|
|
displayName: z.string().min(1).max(128).optional(),
|
|
description: z.string().optional(),
|
|
supportsVision: z.boolean().optional(),
|
|
supportsImageGen: z.boolean().optional(),
|
|
isEnabled: z.boolean().optional(),
|
|
isDefault: z.boolean().optional(),
|
|
sortOrder: z.number().optional(),
|
|
fallbackModelId1: z.string().max(128).optional(),
|
|
fallbackModelId2: z.string().max(128).optional(),
|
|
imageGenConfig: imageGenConfigSchema, // 🆕 图片生成特性配置
|
|
});
|
|
|
|
export async function GET(request: Request) {
|
|
try {
|
|
await requireAdmin();
|
|
|
|
const { searchParams } = new URL(request.url);
|
|
const id = searchParams.get("id");
|
|
const providerId = searchParams.get("providerId");
|
|
|
|
if (id) {
|
|
const model = await getAiModelById({ id });
|
|
if (!model) {
|
|
return new ChatSDKError("bad_request:api", "Model not found").toResponse();
|
|
}
|
|
return Response.json({ model });
|
|
}
|
|
|
|
if (providerId) {
|
|
const models = await getAiModelsByProviderId({ providerId });
|
|
return Response.json({ models });
|
|
}
|
|
|
|
const models = await getAllAiModels();
|
|
return Response.json({ models });
|
|
} catch (error) {
|
|
if (error instanceof ChatSDKError) {
|
|
return error.toResponse();
|
|
}
|
|
return new ChatSDKError("offline:admin").toResponse();
|
|
}
|
|
}
|
|
|
|
export async function POST(request: Request) {
|
|
try {
|
|
await requireAdmin();
|
|
|
|
const body = await request.json();
|
|
const data = createModelSchema.parse(body);
|
|
|
|
// 验证 provider 是否存在
|
|
const provider = await getAiProviderById({ id: data.providerId });
|
|
if (!provider) {
|
|
return new ChatSDKError("bad_request:api", "Provider not found").toResponse();
|
|
}
|
|
|
|
const model = await createAiModel(data);
|
|
|
|
return Response.json({ model: model[0] });
|
|
} catch (error) {
|
|
if (error instanceof ChatSDKError) {
|
|
return error.toResponse();
|
|
}
|
|
if (error instanceof z.ZodError) {
|
|
return new ChatSDKError("bad_request:api", error.message).toResponse();
|
|
}
|
|
return new ChatSDKError("offline:admin").toResponse();
|
|
}
|
|
}
|
|
|
|
export async function PUT(request: Request) {
|
|
try {
|
|
await requireAdmin();
|
|
|
|
const body = await request.json();
|
|
console.log("[Admin API] Update model request body:", JSON.stringify(body)); // Debug log
|
|
const data = updateModelSchema.parse(body);
|
|
console.log("[Admin API] Validation passed, updating model..."); // Debug log
|
|
|
|
const model = await updateAiModel(data);
|
|
|
|
if (model.length === 0) {
|
|
console.error("[Admin API] Model not found:", data.id); // Debug log
|
|
return new ChatSDKError("bad_request:api", "Model not found").toResponse();
|
|
}
|
|
|
|
console.log("[Admin API] Model updated successfully:", model[0].id); // Debug log
|
|
return Response.json({ model: model[0] });
|
|
} catch (error) {
|
|
console.error("[Admin API] Update model error:", error); // Debug log
|
|
if (error instanceof ChatSDKError) {
|
|
return error.toResponse();
|
|
}
|
|
if (error instanceof z.ZodError) {
|
|
console.error("[Admin API] Validation error details:", error.errors); // Debug log
|
|
return new ChatSDKError("bad_request:api", error.message).toResponse();
|
|
}
|
|
return new ChatSDKError("offline:admin").toResponse();
|
|
}
|
|
}
|
|
|
|
export async function DELETE(request: Request) {
|
|
try {
|
|
await requireAdmin();
|
|
|
|
const { searchParams } = new URL(request.url);
|
|
const id = searchParams.get("id");
|
|
|
|
if (!id) {
|
|
return new ChatSDKError("bad_request:api", "Model ID is required").toResponse();
|
|
}
|
|
|
|
await deleteAiModel({ id });
|
|
|
|
return Response.json({ success: true });
|
|
} catch (error) {
|
|
if (error instanceof ChatSDKError) {
|
|
return error.toResponse();
|
|
}
|
|
return new ChatSDKError("offline:admin").toResponse();
|
|
}
|
|
}
|
|
|