2053 lines
70 KiB
TypeScript
2053 lines
70 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
||
import { z } from "zod";
|
||
import { db } from "@/lib/db";
|
||
import { siteSettings, systemSettings } from "@/lib/db/schema";
|
||
import { eq } from "drizzle-orm";
|
||
import { auth } from "@/app/(auth)/auth";
|
||
import { isAgentWorkflowAdminType, isSiteAdminType } from "@/lib/middleware/admin";
|
||
import {
|
||
defaultMembershipConfig,
|
||
defaultMembershipUserOverrides,
|
||
normalizeMembershipConfig,
|
||
normalizeMembershipUserOverrides,
|
||
} from "@/lib/membership/config";
|
||
import {
|
||
defaultPointsPackages,
|
||
defaultPointsSystemConfig,
|
||
normalizePointsPackages,
|
||
normalizePointsSystemConfig,
|
||
POINTS_PACKAGES_KEY,
|
||
POINTS_SYSTEM_CONFIG_KEY,
|
||
} from "@/lib/points/config";
|
||
import {
|
||
defaultDulupayConfig,
|
||
DULUPAY_CONFIG_KEY,
|
||
normalizeDulupayConfig,
|
||
normalizeDulupayForPublic,
|
||
} from "@/lib/payment/dulupay-config";
|
||
import {
|
||
AGENT_SECONDARY_TYPE_CONFIG_KEY,
|
||
defaultAgentSecondaryTypeConfig,
|
||
normalizeAgentSecondaryTypeConfig,
|
||
} from "@/lib/agents/secondary-type-config";
|
||
import {
|
||
AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||
defaultAgentWorkflowUiConfig,
|
||
normalizeAgentWorkflowUiConfig,
|
||
} from "@/lib/agents/workflow-ui-config";
|
||
import {
|
||
AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY,
|
||
defaultAgentWorkflowBrandModelConfig,
|
||
normalizeAgentWorkflowBrandModelConfig,
|
||
} from "@/lib/agents/workflow-brand-model-config";
|
||
import {
|
||
AGENT_WORKFLOW_MATERIAL_API_CONFIG_KEY,
|
||
defaultAgentWorkflowMaterialApiConfig,
|
||
normalizeAgentWorkflowMaterialApiConfig,
|
||
normalizeAgentWorkflowMaterialApiConfigForPublic,
|
||
} from "@/lib/agents/workflow-material-config";
|
||
import {
|
||
AGENT_WORKFLOW_GOODS_INFO_API_CONFIG_KEY,
|
||
defaultAgentWorkflowGoodsInfoApiConfig,
|
||
normalizeAgentWorkflowGoodsInfoApiConfig,
|
||
normalizeAgentWorkflowGoodsInfoApiConfigForPublic,
|
||
} from "@/lib/agents/workflow-goods-info-config";
|
||
import {
|
||
AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY,
|
||
defaultAgentWorkflowShowcaseConfig,
|
||
normalizeAgentWorkflowShowcaseConfig,
|
||
} from "@/lib/agents/workflow-showcase-config";
|
||
import {
|
||
AGENT_PRESET_LIBRARY_CONFIG_KEY,
|
||
defaultAgentPresetLibraryConfig,
|
||
normalizeAgentPresetLibraryConfig,
|
||
} from "@/lib/agents/preset-library-config";
|
||
import {
|
||
defaultOssImageMigrationConfig,
|
||
normalizeOssImageMigrationConfig,
|
||
OSS_MIGRATION_CONFIG_KEY,
|
||
} from "@/lib/storage/migration-config";
|
||
import type { AgentCategoryTreeConfig } from "@/types/agent";
|
||
|
||
const HOME_VARIANT_KEY = "home_variant";
|
||
// Historically stored as "home_surprise_categories" but used for the featured gallery categories.
|
||
const HOME_SURPRISE_CATEGORIES_KEY = "home_surprise_categories";
|
||
const AI_DETAIL_GENERATOR_ENABLED_KEY = "ai_detail_generator_enabled";
|
||
const LOVART_COMPOSER_PREVIEW_TEXTS_KEY = "lovart_composer_preview_texts";
|
||
const LOVART_COMPOSER_PREFIX_KEY = "lovart_composer_prefix";
|
||
const LOVART_PROMPT_TAG_VISIBILITY_KEY = "lovart_prompt_tag_visibility";
|
||
const CONTACT_CONFIG_KEY = "contact_config";
|
||
const MEMBERSHIP_CONFIG_KEY = "membership_config";
|
||
const MEMBERSHIP_USER_OVERRIDES_KEY = "membership_user_plan_overrides";
|
||
const STORAGE_FAILOVER_CONFIG_KEY = "storage_failover_config";
|
||
const REALTIME_CANVAS_CONFIG_KEY = "realtime_canvas_config";
|
||
const AGENT_CATEGORY_TREE_CONFIG_KEY = "agent_category_tree_config";
|
||
const CANVAS_AGENT_MODE_ENABLED_KEY = "canvas_agent_mode_enabled";
|
||
|
||
function normalizeHomeVariant(value: unknown): "classic" | "lovart" {
|
||
return value === "lovart" ? "lovart" : "classic";
|
||
}
|
||
|
||
function normalizeSurpriseCategories(value: unknown): string[] {
|
||
if (!Array.isArray(value)) {
|
||
return ["全部", "精选"];
|
||
}
|
||
|
||
const normalized = value
|
||
.map((item) => String(item || "").trim())
|
||
.filter(Boolean)
|
||
// legacy typo compatibility: treat "惊喜" as "精选"
|
||
.map((item) => (item === "惊喜" ? "精选" : item))
|
||
.slice(0, 12);
|
||
|
||
if (normalized.length === 0) {
|
||
return ["全部", "精选"];
|
||
}
|
||
|
||
const unique = Array.from(new Set(normalized));
|
||
if (!unique.includes("全部")) {
|
||
unique.unshift("全部");
|
||
}
|
||
|
||
return unique;
|
||
}
|
||
|
||
function normalizeLovartComposerPreviewTexts(value: unknown): string[] {
|
||
const defaults = [
|
||
"打造引人注目的社交媒体视觉",
|
||
"帮我把这张产品图做成高级电商海报",
|
||
"基于参考图延展 3 套同风格方案",
|
||
];
|
||
|
||
if (!Array.isArray(value)) {
|
||
return defaults;
|
||
}
|
||
|
||
const normalized = value
|
||
.map((item) => String(item || "").trim())
|
||
.filter(Boolean)
|
||
.slice(0, 20);
|
||
|
||
return normalized.length > 0 ? normalized : defaults;
|
||
}
|
||
|
||
function normalizeLovartComposerPrefix(value: unknown): string {
|
||
const normalized = String(value || "").trim();
|
||
if (!normalized) {
|
||
return "让Buyi-ai";
|
||
}
|
||
return normalized.slice(0, 40);
|
||
}
|
||
|
||
function normalizeLovartPromptTagVisibility(value: unknown): {
|
||
nanoBananaPro: boolean;
|
||
design: boolean;
|
||
branding: boolean;
|
||
illustration: boolean;
|
||
ecommerce: boolean;
|
||
video: boolean;
|
||
} {
|
||
const raw =
|
||
value && typeof value === "object" && !Array.isArray(value)
|
||
? (value as Record<string, unknown>)
|
||
: {};
|
||
|
||
return {
|
||
nanoBananaPro: raw.nanoBananaPro !== false,
|
||
design: raw.design !== false,
|
||
branding: raw.branding !== false,
|
||
illustration: raw.illustration !== false,
|
||
ecommerce: raw.ecommerce !== false,
|
||
video: raw.video !== false,
|
||
};
|
||
}
|
||
|
||
function normalizeContactConfig(value: unknown): {
|
||
phone: string;
|
||
wechatQrUrl: string;
|
||
} {
|
||
const raw =
|
||
value && typeof value === "object" && !Array.isArray(value)
|
||
? (value as Record<string, unknown>)
|
||
: {};
|
||
|
||
const phone = String(raw.phone || "").trim().slice(0, 64);
|
||
const wechatQrUrl = String(raw.wechatQrUrl || "").trim().slice(0, 1000);
|
||
|
||
return {
|
||
phone,
|
||
wechatQrUrl,
|
||
};
|
||
}
|
||
|
||
function normalizeStorageFailoverConfig(value: unknown): {
|
||
enabled: boolean;
|
||
backupStorageConfigId: string;
|
||
} {
|
||
const raw =
|
||
value && typeof value === "object" && !Array.isArray(value)
|
||
? (value as Record<string, unknown>)
|
||
: {};
|
||
|
||
const backupStorageConfigId = String(raw.backupStorageConfigId || "").trim();
|
||
|
||
return {
|
||
enabled: raw.enabled === true,
|
||
backupStorageConfigId,
|
||
};
|
||
}
|
||
|
||
function normalizeCanvasAgentModeEnabled(value: unknown): boolean {
|
||
return value !== false;
|
||
}
|
||
|
||
function normalizeAgentCategoryTreeConfig(value: unknown): AgentCategoryTreeConfig {
|
||
const raw =
|
||
value && typeof value === "object" && !Array.isArray(value)
|
||
? (value as Record<string, unknown>)
|
||
: {};
|
||
|
||
const normalizeList = (input: unknown) => {
|
||
if (!Array.isArray(input)) return [] as string[];
|
||
return Array.from(
|
||
new Set(
|
||
input
|
||
.map((item) => String(item || "").trim())
|
||
.filter(Boolean)
|
||
.slice(0, 200)
|
||
)
|
||
);
|
||
};
|
||
|
||
return {
|
||
productCategories: normalizeList(raw.productCategories),
|
||
audienceTags: normalizeList(raw.audienceTags),
|
||
usageScenarios: normalizeList(raw.usageScenarios),
|
||
brands: normalizeList(raw.brands),
|
||
};
|
||
}
|
||
|
||
// GET /api/site-settings - 获取网站设置 (公开)
|
||
export async function GET() {
|
||
try {
|
||
const session = await auth().catch(() => null);
|
||
const isAdmin = isSiteAdminType(session?.user?.type);
|
||
const canManageAgentWorkflow = isAgentWorkflowAdminType(session?.user?.type);
|
||
const [
|
||
settings,
|
||
notificationSetting,
|
||
homeVariantSetting,
|
||
surpriseCategoriesSetting,
|
||
aiDetailGeneratorEnabledSetting,
|
||
lovartComposerPreviewTextsSetting,
|
||
lovartComposerPrefixSetting,
|
||
lovartPromptTagVisibilitySetting,
|
||
contactConfigSetting,
|
||
membershipConfigSetting,
|
||
membershipOverridesSetting,
|
||
pointsSystemConfigSetting,
|
||
pointsPackagesSetting,
|
||
dulupayConfigSetting,
|
||
realtimeCanvasConfigSetting,
|
||
canvasAgentModeEnabledSetting,
|
||
storageFailoverConfigSetting,
|
||
ossImageMigrationConfigSetting,
|
||
agentPresetLibraryConfigSetting,
|
||
agentCategoryTreeConfigSetting,
|
||
agentSecondaryTypeConfigSetting,
|
||
agentWorkflowUiConfigSetting,
|
||
agentWorkflowMaterialApiConfigSetting,
|
||
agentWorkflowGoodsInfoApiConfigSetting,
|
||
agentWorkflowBrandModelConfigSetting,
|
||
agentWorkflowShowcaseConfigSetting,
|
||
] = await Promise.all([
|
||
db.select().from(siteSettings).limit(1).then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, "login_notification"))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, HOME_VARIANT_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, HOME_SURPRISE_CATEGORIES_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AI_DETAIL_GENERATOR_ENABLED_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, LOVART_COMPOSER_PREVIEW_TEXTS_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, LOVART_COMPOSER_PREFIX_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, LOVART_PROMPT_TAG_VISIBILITY_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, CONTACT_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, MEMBERSHIP_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, MEMBERSHIP_USER_OVERRIDES_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, POINTS_SYSTEM_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, POINTS_PACKAGES_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, DULUPAY_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, REALTIME_CANVAS_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, CANVAS_AGENT_MODE_ENABLED_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, STORAGE_FAILOVER_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, OSS_MIGRATION_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_PRESET_LIBRARY_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_CATEGORY_TREE_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_SECONDARY_TYPE_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_WORKFLOW_UI_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_WORKFLOW_MATERIAL_API_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_WORKFLOW_GOODS_INFO_API_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
db
|
||
.select()
|
||
.from(systemSettings)
|
||
.where(eq(systemSettings.key, AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY))
|
||
.limit(1)
|
||
.then(rows => rows[0]),
|
||
]);
|
||
|
||
const notification = notificationSetting?.value || { enabled: false, title: "", content: "" };
|
||
const homeVariant = normalizeHomeVariant(homeVariantSetting?.value);
|
||
const surpriseCategories = normalizeSurpriseCategories(surpriseCategoriesSetting?.value);
|
||
const aiDetailGenerationEnabled = Boolean(aiDetailGeneratorEnabledSetting?.value);
|
||
const lovartComposerPreviewTexts = normalizeLovartComposerPreviewTexts(
|
||
lovartComposerPreviewTextsSetting?.value
|
||
);
|
||
const lovartComposerPrefix = normalizeLovartComposerPrefix(
|
||
lovartComposerPrefixSetting?.value
|
||
);
|
||
const lovartPromptTagVisibility = normalizeLovartPromptTagVisibility(
|
||
lovartPromptTagVisibilitySetting?.value
|
||
);
|
||
const contactConfig = normalizeContactConfig(contactConfigSetting?.value);
|
||
const membershipConfig = normalizeMembershipConfig(membershipConfigSetting?.value);
|
||
const membershipUserOverrides = normalizeMembershipUserOverrides(
|
||
membershipOverridesSetting?.value
|
||
);
|
||
const pointsSystemConfig = normalizePointsSystemConfig(
|
||
pointsSystemConfigSetting?.value
|
||
);
|
||
const pointsPackages = normalizePointsPackages(pointsPackagesSetting?.value);
|
||
const dulupayConfig = isAdmin
|
||
? normalizeDulupayConfig(dulupayConfigSetting?.value)
|
||
: normalizeDulupayForPublic(dulupayConfigSetting?.value);
|
||
const realtimeCanvasServiceEnabled =
|
||
(realtimeCanvasConfigSetting?.value as { enabled?: boolean } | undefined)?.enabled !== false;
|
||
const canvasAgentModeEnabled = normalizeCanvasAgentModeEnabled(
|
||
canvasAgentModeEnabledSetting?.value
|
||
);
|
||
const storageFailoverConfig = normalizeStorageFailoverConfig(
|
||
storageFailoverConfigSetting?.value
|
||
);
|
||
const ossImageMigrationConfig = normalizeOssImageMigrationConfig(
|
||
ossImageMigrationConfigSetting?.value
|
||
);
|
||
const agentPresetLibraryConfig = normalizeAgentPresetLibraryConfig(
|
||
agentPresetLibraryConfigSetting?.value
|
||
);
|
||
const agentCategoryTreeConfig = normalizeAgentCategoryTreeConfig(
|
||
agentCategoryTreeConfigSetting?.value
|
||
);
|
||
const agentSecondaryTypeConfig = normalizeAgentSecondaryTypeConfig(
|
||
agentSecondaryTypeConfigSetting?.value
|
||
);
|
||
const agentWorkflowUiConfig = normalizeAgentWorkflowUiConfig(
|
||
agentWorkflowUiConfigSetting?.value
|
||
);
|
||
const agentWorkflowMaterialApiConfig = canManageAgentWorkflow
|
||
? normalizeAgentWorkflowMaterialApiConfig(agentWorkflowMaterialApiConfigSetting?.value)
|
||
: normalizeAgentWorkflowMaterialApiConfigForPublic(
|
||
agentWorkflowMaterialApiConfigSetting?.value
|
||
);
|
||
const agentWorkflowGoodsInfoApiConfig = canManageAgentWorkflow
|
||
? normalizeAgentWorkflowGoodsInfoApiConfig(agentWorkflowGoodsInfoApiConfigSetting?.value)
|
||
: normalizeAgentWorkflowGoodsInfoApiConfigForPublic(
|
||
agentWorkflowGoodsInfoApiConfigSetting?.value
|
||
);
|
||
const agentWorkflowBrandModelConfig = normalizeAgentWorkflowBrandModelConfig(
|
||
agentWorkflowBrandModelConfigSetting?.value
|
||
);
|
||
const agentWorkflowShowcaseConfig = normalizeAgentWorkflowShowcaseConfig(
|
||
agentWorkflowShowcaseConfigSetting?.value
|
||
);
|
||
|
||
// 如果没有设置记录,返回默认值
|
||
const baseSettings = settings || {
|
||
siteName: "AI Chatbot",
|
||
siteLogo: null,
|
||
siteLogoDark: null,
|
||
favicon: null,
|
||
showAutoModel: true,
|
||
defaultTheme: "system",
|
||
usageTimeEnabled: false,
|
||
usageTimeStart: "08:00",
|
||
usageTimeEnd: "20:00",
|
||
usageTimeMessage: "由壹点累了也是需要休息的",
|
||
bannerEnabled: true,
|
||
bannerText: "升级会员, Nano Banana Pro 免费365天!",
|
||
bannerLink: null,
|
||
toolbox1Name: "工具箱",
|
||
toolbox1Enabled: true,
|
||
toolbox2Name: "工具箱2",
|
||
toolbox2Enabled: false,
|
||
tutorialVideoUrl: null,
|
||
tutorialEnabled: false,
|
||
rankingEnabled: true,
|
||
canvasEnabled: true,
|
||
agentEnabled: true,
|
||
canvasAgentModeEnabled: true,
|
||
agentPresetLibraryConfig: defaultAgentPresetLibraryConfig,
|
||
agentCategoryTreeConfig: normalizeAgentCategoryTreeConfig(undefined),
|
||
agentSecondaryTypeConfig: defaultAgentSecondaryTypeConfig,
|
||
agentWorkflowUiConfig: defaultAgentWorkflowUiConfig,
|
||
agentWorkflowMaterialApiConfig: defaultAgentWorkflowMaterialApiConfig,
|
||
agentWorkflowGoodsInfoApiConfig: defaultAgentWorkflowGoodsInfoApiConfig,
|
||
agentWorkflowBrandModelConfig: defaultAgentWorkflowBrandModelConfig,
|
||
agentWorkflowShowcaseConfig: defaultAgentWorkflowShowcaseConfig,
|
||
realtimeCanvasEnabled: true,
|
||
realtimeCanvasServiceEnabled: true,
|
||
storageFailoverConfig,
|
||
ossImageMigrationConfig,
|
||
canvasDefaultModelId: null,
|
||
canvasAutoModeDefaultModelId: null,
|
||
canvasDetailDefaultModelId: null,
|
||
canvasDetailAgentModelId: null,
|
||
lovartPromoText: "现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
|
||
lovartPromoActionText: "立即升级",
|
||
lovartHeroTitle: "由壹点AI 让设计更简单",
|
||
lovartHeroSubtitle: "懂你的设计代理,帮你搞定一切",
|
||
homeVariant,
|
||
surpriseCategories,
|
||
aiDetailGenerationEnabled,
|
||
lovartComposerPrefix,
|
||
lovartComposerPreviewTexts,
|
||
lovartPromptTagVisibility,
|
||
contactConfig,
|
||
membershipConfig,
|
||
membershipUserOverrides,
|
||
pointsSystemConfig,
|
||
pointsPackages,
|
||
dulupayConfig,
|
||
};
|
||
|
||
const response = NextResponse.json({
|
||
...baseSettings,
|
||
lovartPromoText:
|
||
baseSettings.lovartPromoText ||
|
||
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
|
||
lovartPromoActionText: baseSettings.lovartPromoActionText || "立即升级",
|
||
lovartHeroTitle: baseSettings.lovartHeroTitle || "由壹点AI 让设计更简单",
|
||
lovartHeroSubtitle: baseSettings.lovartHeroSubtitle || "懂你的设计代理,帮你搞定一切",
|
||
notification,
|
||
homeVariant,
|
||
surpriseCategories,
|
||
aiDetailGenerationEnabled,
|
||
lovartComposerPrefix,
|
||
lovartComposerPreviewTexts,
|
||
lovartPromptTagVisibility,
|
||
contactConfig,
|
||
agentPresetLibraryConfig,
|
||
agentCategoryTreeConfig,
|
||
agentSecondaryTypeConfig,
|
||
agentWorkflowUiConfig,
|
||
agentWorkflowMaterialApiConfig,
|
||
agentWorkflowGoodsInfoApiConfig,
|
||
agentWorkflowBrandModelConfig,
|
||
agentWorkflowShowcaseConfig,
|
||
membershipConfig,
|
||
membershipUserOverrides,
|
||
pointsSystemConfig,
|
||
pointsPackages,
|
||
dulupayConfig,
|
||
realtimeCanvasServiceEnabled,
|
||
canvasAgentModeEnabled,
|
||
storageFailoverConfig,
|
||
ossImageMigrationConfig,
|
||
});
|
||
|
||
// 禁用缓存,确保总是获取最新设置
|
||
response.headers.set("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
|
||
response.headers.set("Pragma", "no-cache");
|
||
response.headers.set("Expires", "0");
|
||
|
||
return response;
|
||
} catch (error) {
|
||
console.error("[Site Settings API] Get error:", error);
|
||
return NextResponse.json(
|
||
{ error: "Failed to fetch site settings" },
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|
||
|
||
const updateSchema = z.object({
|
||
siteName: z.string().min(1).max(128).optional(),
|
||
siteLogo: z.string().nullable().optional(),
|
||
siteLogoDark: z.string().nullable().optional(),
|
||
favicon: z.string().nullable().optional(),
|
||
showAutoModel: z.boolean().optional(),
|
||
defaultTheme: z.enum(["system", "light", "dark"]).optional(),
|
||
usageTimeEnabled: z.boolean().optional(),
|
||
usageTimeStart: z.string().length(5).optional(),
|
||
usageTimeEnd: z.string().length(5).optional(),
|
||
usageTimeMessage: z.string().optional(),
|
||
bannerEnabled: z.boolean().optional(),
|
||
bannerText: z.string().optional(),
|
||
bannerLink: z.string().nullable().optional(),
|
||
toolbox1Name: z.string().max(64).optional(),
|
||
toolbox1Enabled: z.boolean().optional(),
|
||
toolbox2Name: z.string().max(64).optional(),
|
||
toolbox2Enabled: z.boolean().optional(),
|
||
tutorialVideoUrl: z.string().nullable().optional(),
|
||
tutorialEnabled: z.boolean().optional(),
|
||
rankingEnabled: z.boolean().optional(),
|
||
canvasEnabled: z.boolean().optional(),
|
||
agentEnabled: z.boolean().optional(),
|
||
canvasAgentModeEnabled: z.boolean().optional(),
|
||
agentPresetLibraryConfig: z
|
||
.object({
|
||
sections: z
|
||
.array(
|
||
z.object({
|
||
id: z.string().trim().min(1).max(64).optional(),
|
||
label: z.string().trim().min(1).max(64),
|
||
description: z.string().trim().max(200).nullable().optional(),
|
||
enabled: z.boolean().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
categories: z
|
||
.array(
|
||
z.lazy(() =>
|
||
z.object({
|
||
id: z.string().trim().min(1).max(64).optional(),
|
||
name: z.string().trim().min(1).max(64),
|
||
enabled: z.boolean().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
children: z
|
||
.array(
|
||
z.lazy(() =>
|
||
z.object({
|
||
id: z.string().trim().min(1).max(64).optional(),
|
||
name: z.string().trim().min(1).max(64),
|
||
enabled: z.boolean().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
children: z
|
||
.array(
|
||
z.object({
|
||
id: z.string().trim().min(1).max(64).optional(),
|
||
name: z.string().trim().min(1).max(64),
|
||
enabled: z.boolean().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
children: z.array(z.any()).optional(),
|
||
})
|
||
)
|
||
.max(100)
|
||
.optional(),
|
||
})
|
||
)
|
||
)
|
||
.max(100)
|
||
.optional(),
|
||
})
|
||
)
|
||
)
|
||
.max(100)
|
||
.optional(),
|
||
})
|
||
)
|
||
.max(30),
|
||
})
|
||
.optional(),
|
||
agentCategoryTreeConfig: z
|
||
.object({
|
||
productCategories: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
audienceTags: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
usageScenarios: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
brands: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
})
|
||
.optional(),
|
||
agentSecondaryTypeConfig: z
|
||
.object({
|
||
image: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
video: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
text: z.array(z.string().trim().min(1).max(64)).max(200).optional(),
|
||
})
|
||
.optional(),
|
||
agentWorkflowUiConfig: z
|
||
.object({
|
||
inputOptions: z
|
||
.object({
|
||
brands: z.array(z.string().trim().min(1).max(64)).max(300).optional(),
|
||
stores: z.array(z.string().trim().min(1).max(64)).max(300).optional(),
|
||
priceBands: z.array(z.string().trim().min(1).max(64)).max(300).optional(),
|
||
brandStoreEntries: z
|
||
.array(
|
||
z.object({
|
||
brandName: z.string().trim().min(1).max(64),
|
||
stores: z.array(z.string().trim().min(1).max(64)).max(300).optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
})
|
||
)
|
||
.max(300)
|
||
.optional(),
|
||
})
|
||
.optional(),
|
||
steps: z
|
||
.array(
|
||
z.object({
|
||
key: z.string().trim().min(1).max(64),
|
||
title: z.string().trim().min(1).max(64),
|
||
description: z.string().trim().max(300).nullable().optional(),
|
||
enabled: z.boolean().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
options: z
|
||
.array(
|
||
z.lazy(() =>
|
||
z.object({
|
||
key: z.string().trim().min(1).max(64),
|
||
buttonName: z.string().trim().min(1).max(64),
|
||
description: z.string().trim().max(300).nullable().optional(),
|
||
previewImageUrl: z.string().trim().max(1000).nullable().optional(),
|
||
enabled: z.boolean().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
promptFragment: z.string().trim().max(1000).nullable().optional(),
|
||
children: z.array(z.any()).max(100).optional(),
|
||
})
|
||
)
|
||
)
|
||
.max(100),
|
||
})
|
||
)
|
||
.max(20),
|
||
})
|
||
.optional(),
|
||
agentWorkflowMaterialApiConfig: z
|
||
.object({
|
||
enabled: z.boolean().optional(),
|
||
baseUrl: z.string().trim().max(255).optional(),
|
||
apiKey: z.string().trim().max(500).optional(),
|
||
})
|
||
.optional(),
|
||
agentWorkflowGoodsInfoApiConfig: z
|
||
.object({
|
||
enabled: z.boolean().optional(),
|
||
baseUrl: z.string().trim().max(255).optional(),
|
||
clientKey: z.string().trim().max(255).optional(),
|
||
secret: z.string().trim().max(255).optional(),
|
||
})
|
||
.optional(),
|
||
agentWorkflowBrandModelConfig: z
|
||
.object({
|
||
entries: z
|
||
.array(
|
||
z.object({
|
||
brandName: z.string().trim().min(1).max(64),
|
||
images: z
|
||
.array(
|
||
z.object({
|
||
id: z.string().trim().min(1).max(128).optional(),
|
||
assetId: z.string().trim().max(128).nullable().optional(),
|
||
imageUrl: z.string().trim().min(1).max(2000),
|
||
displayName: z.string().trim().max(255).nullable().optional(),
|
||
mimeType: z.string().trim().max(128).nullable().optional(),
|
||
sortOrder: z.number().min(0).max(999).optional(),
|
||
})
|
||
)
|
||
.max(100),
|
||
})
|
||
)
|
||
.max(300),
|
||
})
|
||
.optional(),
|
||
agentWorkflowShowcaseConfig: z
|
||
.object({
|
||
enabled: z.boolean().optional(),
|
||
title: z.string().max(200).optional(),
|
||
subtitle: z.string().max(300).optional(),
|
||
actionText: z.string().max(48).optional(),
|
||
videoUrl: z.string().max(2000).optional(),
|
||
posterUrl: z.string().max(2000).nullable().optional(),
|
||
overlayText: z.string().max(200).optional(),
|
||
footerText: z.string().max(64).optional(),
|
||
})
|
||
.optional(),
|
||
realtimeCanvasEnabled: z.boolean().optional(),
|
||
aiDetailGenerationEnabled: z.boolean().optional(),
|
||
canvasDefaultModelId: z.string().nullable().optional(),
|
||
canvasAutoModeDefaultModelId: z.string().nullable().optional(),
|
||
canvasDetailDefaultModelId: z.string().nullable().optional(),
|
||
canvasDetailAgentModelId: z.string().nullable().optional(),
|
||
lovartPromoText: z.string().max(300).optional(),
|
||
lovartPromoActionText: z.string().max(32).optional(),
|
||
lovartHeroTitle: z.string().max(300).optional(),
|
||
lovartHeroSubtitle: z.string().max(300).optional(),
|
||
homeVariant: z.enum(["classic", "lovart"]).optional(),
|
||
surpriseCategories: z.array(z.string().trim().min(1).max(20)).max(12).optional(),
|
||
lovartComposerPrefix: z.string().trim().min(1).max(40).optional(),
|
||
lovartComposerPreviewTexts: z.array(z.string().trim().min(1).max(120)).max(20).optional(),
|
||
lovartPromptTagVisibility: z
|
||
.object({
|
||
nanoBananaPro: z.boolean().optional(),
|
||
design: z.boolean().optional(),
|
||
branding: z.boolean().optional(),
|
||
illustration: z.boolean().optional(),
|
||
ecommerce: z.boolean().optional(),
|
||
video: z.boolean().optional(),
|
||
})
|
||
.optional(),
|
||
contactConfig: z
|
||
.object({
|
||
phone: z.string().max(64).optional(),
|
||
wechatQrUrl: z.string().max(1000).optional(),
|
||
})
|
||
.optional(),
|
||
membershipConfig: z.unknown().optional(),
|
||
membershipUserOverrides: z.unknown().optional(),
|
||
pointsSystemConfig: z.unknown().optional(),
|
||
pointsPackages: z.unknown().optional(),
|
||
dulupayConfig: z.unknown().optional(),
|
||
storageFailoverConfig: z
|
||
.object({
|
||
enabled: z.boolean().optional(),
|
||
backupStorageConfigId: z.string().max(128).optional(),
|
||
})
|
||
.optional(),
|
||
ossImageMigrationConfig: z
|
||
.object({
|
||
enabled: z.boolean().optional(),
|
||
preferAliyunForUploads: z.boolean().optional(),
|
||
sourceStorageConfigId: z.string().max(128).optional(),
|
||
targetStorageConfigId: z.string().max(128).optional(),
|
||
migrateAfterHours: z.number().min(1).max(720).optional(),
|
||
cleanupAfterHours: z.number().min(1).max(1440).optional(),
|
||
batchSize: z.number().min(1).max(100).optional(),
|
||
})
|
||
.optional(),
|
||
});
|
||
|
||
// PUT /api/site-settings - 更新网站设置(管理员 / 智能体管理员)
|
||
export async function PUT(request: NextRequest) {
|
||
try {
|
||
const session = await auth();
|
||
|
||
if (!session?.user) {
|
||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||
}
|
||
|
||
const isAdmin = isSiteAdminType(session.user.type);
|
||
const canManageAgentWorkflow = isAgentWorkflowAdminType(session.user.type);
|
||
|
||
if (!canManageAgentWorkflow) {
|
||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||
}
|
||
|
||
const body = await request.json();
|
||
if (!isAdmin) {
|
||
const allowedKeys = new Set([
|
||
"agentPresetLibraryConfig",
|
||
"agentWorkflowUiConfig",
|
||
"agentWorkflowMaterialApiConfig",
|
||
"agentWorkflowGoodsInfoApiConfig",
|
||
"agentWorkflowBrandModelConfig",
|
||
"agentWorkflowShowcaseConfig",
|
||
]);
|
||
const hasRestrictedKeys = Object.keys(body || {}).some((key) => !allowedKeys.has(key));
|
||
if (hasRestrictedKeys) {
|
||
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
||
}
|
||
}
|
||
const data = updateSchema.parse(body);
|
||
const {
|
||
homeVariant,
|
||
surpriseCategories,
|
||
aiDetailGenerationEnabled,
|
||
lovartComposerPrefix,
|
||
lovartComposerPreviewTexts,
|
||
lovartPromptTagVisibility,
|
||
contactConfig,
|
||
agentPresetLibraryConfig,
|
||
agentCategoryTreeConfig,
|
||
agentSecondaryTypeConfig,
|
||
agentWorkflowUiConfig,
|
||
agentWorkflowMaterialApiConfig,
|
||
agentWorkflowGoodsInfoApiConfig,
|
||
agentWorkflowBrandModelConfig,
|
||
agentWorkflowShowcaseConfig,
|
||
membershipConfig,
|
||
membershipUserOverrides,
|
||
pointsSystemConfig,
|
||
pointsPackages,
|
||
dulupayConfig,
|
||
storageFailoverConfig,
|
||
ossImageMigrationConfig,
|
||
canvasAgentModeEnabled,
|
||
...siteSettingsPayload
|
||
} = data;
|
||
|
||
// 查找现有设置
|
||
const [existing] = await db.select().from(siteSettings).limit(1);
|
||
|
||
if (existing) {
|
||
// 更新现有设置
|
||
const [updated] = await db
|
||
.update(siteSettings)
|
||
.set({
|
||
...siteSettingsPayload,
|
||
agentEnabled: siteSettingsPayload.agentEnabled ?? existing.agentEnabled ?? true,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.where(eq(siteSettings.id, existing.id))
|
||
.returning();
|
||
|
||
if (homeVariant !== undefined) {
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: HOME_VARIANT_KEY,
|
||
value: homeVariant,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: homeVariant,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (surpriseCategories !== undefined) {
|
||
const normalized = normalizeSurpriseCategories(surpriseCategories);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: HOME_SURPRISE_CATEGORIES_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (aiDetailGenerationEnabled !== undefined) {
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AI_DETAIL_GENERATOR_ENABLED_KEY,
|
||
value: Boolean(aiDetailGenerationEnabled),
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: Boolean(aiDetailGenerationEnabled),
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (lovartComposerPreviewTexts !== undefined) {
|
||
const normalized = normalizeLovartComposerPreviewTexts(lovartComposerPreviewTexts);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: LOVART_COMPOSER_PREVIEW_TEXTS_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (lovartComposerPrefix !== undefined) {
|
||
const normalized = normalizeLovartComposerPrefix(lovartComposerPrefix);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: LOVART_COMPOSER_PREFIX_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (lovartPromptTagVisibility !== undefined) {
|
||
const normalized = normalizeLovartPromptTagVisibility(lovartPromptTagVisibility);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: LOVART_PROMPT_TAG_VISIBILITY_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (contactConfig !== undefined) {
|
||
const normalized = normalizeContactConfig(contactConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: CONTACT_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (canvasAgentModeEnabled !== undefined) {
|
||
const normalized = normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: CANVAS_AGENT_MODE_ENABLED_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentPresetLibraryConfig !== undefined) {
|
||
const normalized = normalizeAgentPresetLibraryConfig(agentPresetLibraryConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_PRESET_LIBRARY_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentCategoryTreeConfig !== undefined) {
|
||
const normalized = normalizeAgentCategoryTreeConfig(agentCategoryTreeConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_CATEGORY_TREE_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentSecondaryTypeConfig !== undefined) {
|
||
const normalized = normalizeAgentSecondaryTypeConfig(agentSecondaryTypeConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_SECONDARY_TYPE_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowUiConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowUiConfig(agentWorkflowUiConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowMaterialApiConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowMaterialApiConfig(
|
||
agentWorkflowMaterialApiConfig
|
||
);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_MATERIAL_API_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowGoodsInfoApiConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowGoodsInfoApiConfig(
|
||
agentWorkflowGoodsInfoApiConfig
|
||
);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_GOODS_INFO_API_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowBrandModelConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowBrandModelConfig(
|
||
agentWorkflowBrandModelConfig
|
||
);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowShowcaseConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowShowcaseConfig(agentWorkflowShowcaseConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (membershipConfig !== undefined) {
|
||
const normalized = normalizeMembershipConfig(membershipConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: MEMBERSHIP_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (membershipUserOverrides !== undefined) {
|
||
const normalized = normalizeMembershipUserOverrides(membershipUserOverrides);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: MEMBERSHIP_USER_OVERRIDES_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (pointsSystemConfig !== undefined) {
|
||
const normalized = normalizePointsSystemConfig(pointsSystemConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: POINTS_SYSTEM_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (pointsPackages !== undefined) {
|
||
const normalized = normalizePointsPackages(pointsPackages);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: POINTS_PACKAGES_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (dulupayConfig !== undefined) {
|
||
const normalized = normalizeDulupayConfig(dulupayConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: DULUPAY_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (storageFailoverConfig !== undefined) {
|
||
const normalized = normalizeStorageFailoverConfig(storageFailoverConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: STORAGE_FAILOVER_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (ossImageMigrationConfig !== undefined) {
|
||
const normalized = normalizeOssImageMigrationConfig(ossImageMigrationConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: OSS_MIGRATION_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
return NextResponse.json({
|
||
...updated,
|
||
homeVariant: homeVariant ?? normalizeHomeVariant(undefined),
|
||
surpriseCategories:
|
||
surpriseCategories !== undefined
|
||
? normalizeSurpriseCategories(surpriseCategories)
|
||
: normalizeSurpriseCategories(undefined),
|
||
aiDetailGenerationEnabled: aiDetailGenerationEnabled ?? false,
|
||
lovartComposerPrefix:
|
||
lovartComposerPrefix !== undefined
|
||
? normalizeLovartComposerPrefix(lovartComposerPrefix)
|
||
: normalizeLovartComposerPrefix(undefined),
|
||
lovartComposerPreviewTexts:
|
||
lovartComposerPreviewTexts !== undefined
|
||
? normalizeLovartComposerPreviewTexts(lovartComposerPreviewTexts)
|
||
: normalizeLovartComposerPreviewTexts(undefined),
|
||
lovartPromptTagVisibility:
|
||
lovartPromptTagVisibility !== undefined
|
||
? normalizeLovartPromptTagVisibility(lovartPromptTagVisibility)
|
||
: normalizeLovartPromptTagVisibility(undefined),
|
||
contactConfig:
|
||
contactConfig !== undefined
|
||
? normalizeContactConfig(contactConfig)
|
||
: normalizeContactConfig(undefined),
|
||
agentPresetLibraryConfig:
|
||
agentPresetLibraryConfig !== undefined
|
||
? normalizeAgentPresetLibraryConfig(agentPresetLibraryConfig)
|
||
: defaultAgentPresetLibraryConfig,
|
||
agentCategoryTreeConfig:
|
||
agentCategoryTreeConfig !== undefined
|
||
? normalizeAgentCategoryTreeConfig(agentCategoryTreeConfig)
|
||
: normalizeAgentCategoryTreeConfig(undefined),
|
||
agentSecondaryTypeConfig:
|
||
agentSecondaryTypeConfig !== undefined
|
||
? normalizeAgentSecondaryTypeConfig(agentSecondaryTypeConfig)
|
||
: defaultAgentSecondaryTypeConfig,
|
||
agentWorkflowUiConfig:
|
||
agentWorkflowUiConfig !== undefined
|
||
? normalizeAgentWorkflowUiConfig(agentWorkflowUiConfig)
|
||
: defaultAgentWorkflowUiConfig,
|
||
agentWorkflowMaterialApiConfig:
|
||
agentWorkflowMaterialApiConfig !== undefined
|
||
? normalizeAgentWorkflowMaterialApiConfig(agentWorkflowMaterialApiConfig)
|
||
: defaultAgentWorkflowMaterialApiConfig,
|
||
agentWorkflowGoodsInfoApiConfig:
|
||
agentWorkflowGoodsInfoApiConfig !== undefined
|
||
? normalizeAgentWorkflowGoodsInfoApiConfig(agentWorkflowGoodsInfoApiConfig)
|
||
: defaultAgentWorkflowGoodsInfoApiConfig,
|
||
agentWorkflowBrandModelConfig:
|
||
agentWorkflowBrandModelConfig !== undefined
|
||
? normalizeAgentWorkflowBrandModelConfig(agentWorkflowBrandModelConfig)
|
||
: defaultAgentWorkflowBrandModelConfig,
|
||
agentWorkflowShowcaseConfig:
|
||
agentWorkflowShowcaseConfig !== undefined
|
||
? normalizeAgentWorkflowShowcaseConfig(agentWorkflowShowcaseConfig)
|
||
: defaultAgentWorkflowShowcaseConfig,
|
||
membershipConfig:
|
||
membershipConfig !== undefined
|
||
? normalizeMembershipConfig(membershipConfig)
|
||
: defaultMembershipConfig,
|
||
membershipUserOverrides:
|
||
membershipUserOverrides !== undefined
|
||
? normalizeMembershipUserOverrides(membershipUserOverrides)
|
||
: defaultMembershipUserOverrides,
|
||
pointsSystemConfig:
|
||
pointsSystemConfig !== undefined
|
||
? normalizePointsSystemConfig(pointsSystemConfig)
|
||
: defaultPointsSystemConfig,
|
||
pointsPackages:
|
||
pointsPackages !== undefined
|
||
? normalizePointsPackages(pointsPackages)
|
||
: defaultPointsPackages,
|
||
dulupayConfig:
|
||
dulupayConfig !== undefined
|
||
? normalizeDulupayConfig(dulupayConfig)
|
||
: defaultDulupayConfig,
|
||
storageFailoverConfig:
|
||
storageFailoverConfig !== undefined
|
||
? normalizeStorageFailoverConfig(storageFailoverConfig)
|
||
: normalizeStorageFailoverConfig(undefined),
|
||
ossImageMigrationConfig:
|
||
ossImageMigrationConfig !== undefined
|
||
? normalizeOssImageMigrationConfig(ossImageMigrationConfig)
|
||
: defaultOssImageMigrationConfig,
|
||
canvasAgentModeEnabled:
|
||
canvasAgentModeEnabled !== undefined
|
||
? normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled)
|
||
: normalizeCanvasAgentModeEnabled(undefined),
|
||
});
|
||
} else {
|
||
// 创建新设置
|
||
const [created] = await db
|
||
.insert(siteSettings)
|
||
.values({
|
||
siteName: siteSettingsPayload.siteName || "AI Chatbot",
|
||
siteLogo: siteSettingsPayload.siteLogo,
|
||
siteLogoDark: siteSettingsPayload.siteLogoDark,
|
||
favicon: siteSettingsPayload.favicon,
|
||
showAutoModel: siteSettingsPayload.showAutoModel ?? true,
|
||
defaultTheme: siteSettingsPayload.defaultTheme ?? "system",
|
||
usageTimeEnabled: siteSettingsPayload.usageTimeEnabled ?? false,
|
||
usageTimeStart: siteSettingsPayload.usageTimeStart ?? "08:00",
|
||
usageTimeEnd: siteSettingsPayload.usageTimeEnd ?? "20:00",
|
||
usageTimeMessage: siteSettingsPayload.usageTimeMessage ?? "由壹点累了也是需要休息的",
|
||
bannerEnabled: siteSettingsPayload.bannerEnabled ?? true,
|
||
bannerText: siteSettingsPayload.bannerText ?? "升级会员, Nano Banana Pro 免费365天!",
|
||
bannerLink: siteSettingsPayload.bannerLink,
|
||
toolbox1Name: siteSettingsPayload.toolbox1Name ?? "工具箱",
|
||
toolbox1Enabled: siteSettingsPayload.toolbox1Enabled ?? true,
|
||
toolbox2Name: siteSettingsPayload.toolbox2Name ?? "工具箱2",
|
||
toolbox2Enabled: siteSettingsPayload.toolbox2Enabled ?? false,
|
||
tutorialVideoUrl: siteSettingsPayload.tutorialVideoUrl,
|
||
tutorialEnabled: siteSettingsPayload.tutorialEnabled ?? false,
|
||
rankingEnabled: siteSettingsPayload.rankingEnabled ?? true,
|
||
canvasEnabled: siteSettingsPayload.canvasEnabled ?? true,
|
||
agentEnabled: siteSettingsPayload.agentEnabled ?? true,
|
||
realtimeCanvasEnabled: siteSettingsPayload.realtimeCanvasEnabled ?? true,
|
||
canvasDefaultModelId: siteSettingsPayload.canvasDefaultModelId,
|
||
canvasAutoModeDefaultModelId: siteSettingsPayload.canvasAutoModeDefaultModelId,
|
||
canvasDetailDefaultModelId: siteSettingsPayload.canvasDetailDefaultModelId,
|
||
canvasDetailAgentModelId: siteSettingsPayload.canvasDetailAgentModelId,
|
||
lovartPromoText:
|
||
siteSettingsPayload.lovartPromoText ??
|
||
"现在升级,立享 Kling 3.0 与 Nano Banana Pro,最高 5 折优惠",
|
||
lovartPromoActionText: siteSettingsPayload.lovartPromoActionText ?? "立即升级",
|
||
lovartHeroTitle: siteSettingsPayload.lovartHeroTitle ?? "由壹点AI 让设计更简单",
|
||
lovartHeroSubtitle: siteSettingsPayload.lovartHeroSubtitle ?? "懂你的设计代理,帮你搞定一切",
|
||
updatedBy: session.user.id,
|
||
})
|
||
.returning();
|
||
|
||
if (homeVariant !== undefined) {
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: HOME_VARIANT_KEY,
|
||
value: homeVariant,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: homeVariant,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (surpriseCategories !== undefined) {
|
||
const normalized = normalizeSurpriseCategories(surpriseCategories);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: HOME_SURPRISE_CATEGORIES_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (aiDetailGenerationEnabled !== undefined) {
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AI_DETAIL_GENERATOR_ENABLED_KEY,
|
||
value: Boolean(aiDetailGenerationEnabled),
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: Boolean(aiDetailGenerationEnabled),
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (lovartComposerPreviewTexts !== undefined) {
|
||
const normalized = normalizeLovartComposerPreviewTexts(lovartComposerPreviewTexts);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: LOVART_COMPOSER_PREVIEW_TEXTS_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (lovartComposerPrefix !== undefined) {
|
||
const normalized = normalizeLovartComposerPrefix(lovartComposerPrefix);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: LOVART_COMPOSER_PREFIX_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (lovartPromptTagVisibility !== undefined) {
|
||
const normalized = normalizeLovartPromptTagVisibility(lovartPromptTagVisibility);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: LOVART_PROMPT_TAG_VISIBILITY_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (contactConfig !== undefined) {
|
||
const normalized = normalizeContactConfig(contactConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: CONTACT_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (canvasAgentModeEnabled !== undefined) {
|
||
const normalized = normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: CANVAS_AGENT_MODE_ENABLED_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentPresetLibraryConfig !== undefined) {
|
||
const normalized = normalizeAgentPresetLibraryConfig(agentPresetLibraryConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_PRESET_LIBRARY_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentCategoryTreeConfig !== undefined) {
|
||
const normalized = normalizeAgentCategoryTreeConfig(agentCategoryTreeConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_CATEGORY_TREE_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentSecondaryTypeConfig !== undefined) {
|
||
const normalized = normalizeAgentSecondaryTypeConfig(agentSecondaryTypeConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_SECONDARY_TYPE_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowUiConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowUiConfig(agentWorkflowUiConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_UI_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowMaterialApiConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowMaterialApiConfig(
|
||
agentWorkflowMaterialApiConfig
|
||
);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_MATERIAL_API_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowBrandModelConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowBrandModelConfig(
|
||
agentWorkflowBrandModelConfig
|
||
);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_BRAND_MODEL_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (agentWorkflowShowcaseConfig !== undefined) {
|
||
const normalized = normalizeAgentWorkflowShowcaseConfig(agentWorkflowShowcaseConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: AGENT_WORKFLOW_SHOWCASE_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (membershipConfig !== undefined) {
|
||
const normalized = normalizeMembershipConfig(membershipConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: MEMBERSHIP_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (membershipUserOverrides !== undefined) {
|
||
const normalized = normalizeMembershipUserOverrides(membershipUserOverrides);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: MEMBERSHIP_USER_OVERRIDES_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (pointsSystemConfig !== undefined) {
|
||
const normalized = normalizePointsSystemConfig(pointsSystemConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: POINTS_SYSTEM_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (pointsPackages !== undefined) {
|
||
const normalized = normalizePointsPackages(pointsPackages);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: POINTS_PACKAGES_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (dulupayConfig !== undefined) {
|
||
const normalized = normalizeDulupayConfig(dulupayConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: DULUPAY_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (storageFailoverConfig !== undefined) {
|
||
const normalized = normalizeStorageFailoverConfig(storageFailoverConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: STORAGE_FAILOVER_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
if (ossImageMigrationConfig !== undefined) {
|
||
const normalized = normalizeOssImageMigrationConfig(ossImageMigrationConfig);
|
||
await db
|
||
.insert(systemSettings)
|
||
.values({
|
||
key: OSS_MIGRATION_CONFIG_KEY,
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
})
|
||
.onConflictDoUpdate({
|
||
target: systemSettings.key,
|
||
set: {
|
||
value: normalized,
|
||
updatedAt: new Date(),
|
||
updatedBy: session.user.id,
|
||
},
|
||
});
|
||
}
|
||
|
||
return NextResponse.json({
|
||
...created,
|
||
homeVariant: homeVariant ?? normalizeHomeVariant(undefined),
|
||
surpriseCategories:
|
||
surpriseCategories !== undefined
|
||
? normalizeSurpriseCategories(surpriseCategories)
|
||
: normalizeSurpriseCategories(undefined),
|
||
aiDetailGenerationEnabled: aiDetailGenerationEnabled ?? false,
|
||
lovartComposerPrefix:
|
||
lovartComposerPrefix !== undefined
|
||
? normalizeLovartComposerPrefix(lovartComposerPrefix)
|
||
: normalizeLovartComposerPrefix(undefined),
|
||
lovartComposerPreviewTexts:
|
||
lovartComposerPreviewTexts !== undefined
|
||
? normalizeLovartComposerPreviewTexts(lovartComposerPreviewTexts)
|
||
: normalizeLovartComposerPreviewTexts(undefined),
|
||
lovartPromptTagVisibility:
|
||
lovartPromptTagVisibility !== undefined
|
||
? normalizeLovartPromptTagVisibility(lovartPromptTagVisibility)
|
||
: normalizeLovartPromptTagVisibility(undefined),
|
||
contactConfig:
|
||
contactConfig !== undefined
|
||
? normalizeContactConfig(contactConfig)
|
||
: normalizeContactConfig(undefined),
|
||
agentPresetLibraryConfig:
|
||
agentPresetLibraryConfig !== undefined
|
||
? normalizeAgentPresetLibraryConfig(agentPresetLibraryConfig)
|
||
: defaultAgentPresetLibraryConfig,
|
||
agentCategoryTreeConfig:
|
||
agentCategoryTreeConfig !== undefined
|
||
? normalizeAgentCategoryTreeConfig(agentCategoryTreeConfig)
|
||
: normalizeAgentCategoryTreeConfig(undefined),
|
||
agentSecondaryTypeConfig:
|
||
agentSecondaryTypeConfig !== undefined
|
||
? normalizeAgentSecondaryTypeConfig(agentSecondaryTypeConfig)
|
||
: defaultAgentSecondaryTypeConfig,
|
||
agentWorkflowUiConfig:
|
||
agentWorkflowUiConfig !== undefined
|
||
? normalizeAgentWorkflowUiConfig(agentWorkflowUiConfig)
|
||
: defaultAgentWorkflowUiConfig,
|
||
agentWorkflowMaterialApiConfig:
|
||
agentWorkflowMaterialApiConfig !== undefined
|
||
? normalizeAgentWorkflowMaterialApiConfig(agentWorkflowMaterialApiConfig)
|
||
: defaultAgentWorkflowMaterialApiConfig,
|
||
agentWorkflowGoodsInfoApiConfig:
|
||
agentWorkflowGoodsInfoApiConfig !== undefined
|
||
? normalizeAgentWorkflowGoodsInfoApiConfig(agentWorkflowGoodsInfoApiConfig)
|
||
: defaultAgentWorkflowGoodsInfoApiConfig,
|
||
agentWorkflowBrandModelConfig:
|
||
agentWorkflowBrandModelConfig !== undefined
|
||
? normalizeAgentWorkflowBrandModelConfig(agentWorkflowBrandModelConfig)
|
||
: defaultAgentWorkflowBrandModelConfig,
|
||
agentWorkflowShowcaseConfig:
|
||
agentWorkflowShowcaseConfig !== undefined
|
||
? normalizeAgentWorkflowShowcaseConfig(agentWorkflowShowcaseConfig)
|
||
: defaultAgentWorkflowShowcaseConfig,
|
||
membershipConfig:
|
||
membershipConfig !== undefined
|
||
? normalizeMembershipConfig(membershipConfig)
|
||
: defaultMembershipConfig,
|
||
membershipUserOverrides:
|
||
membershipUserOverrides !== undefined
|
||
? normalizeMembershipUserOverrides(membershipUserOverrides)
|
||
: defaultMembershipUserOverrides,
|
||
pointsSystemConfig:
|
||
pointsSystemConfig !== undefined
|
||
? normalizePointsSystemConfig(pointsSystemConfig)
|
||
: defaultPointsSystemConfig,
|
||
pointsPackages:
|
||
pointsPackages !== undefined
|
||
? normalizePointsPackages(pointsPackages)
|
||
: defaultPointsPackages,
|
||
dulupayConfig:
|
||
dulupayConfig !== undefined
|
||
? normalizeDulupayConfig(dulupayConfig)
|
||
: defaultDulupayConfig,
|
||
storageFailoverConfig:
|
||
storageFailoverConfig !== undefined
|
||
? normalizeStorageFailoverConfig(storageFailoverConfig)
|
||
: normalizeStorageFailoverConfig(undefined),
|
||
ossImageMigrationConfig:
|
||
ossImageMigrationConfig !== undefined
|
||
? normalizeOssImageMigrationConfig(ossImageMigrationConfig)
|
||
: defaultOssImageMigrationConfig,
|
||
canvasAgentModeEnabled:
|
||
canvasAgentModeEnabled !== undefined
|
||
? normalizeCanvasAgentModeEnabled(canvasAgentModeEnabled)
|
||
: normalizeCanvasAgentModeEnabled(undefined),
|
||
});
|
||
}
|
||
} catch (error) {
|
||
console.error("[Site Settings API] Update error:", error);
|
||
|
||
if (error instanceof z.ZodError) {
|
||
return NextResponse.json(
|
||
{ error: "Invalid request data", details: error.errors },
|
||
{ status: 400 }
|
||
);
|
||
}
|
||
|
||
return NextResponse.json(
|
||
{ error: "Failed to update site settings" },
|
||
{ status: 500 }
|
||
);
|
||
}
|
||
}
|