Your Name 24af251fd3 feat: 系统设置增加默认主题模式配置
- 管理员可以设置网站默认使用深色/浅色/跟随系统模式
- 新增 defaultTheme 字段到 SiteSettings 表
- 前端 ThemeProvider 从数据库读取默认主题设置
2026-01-18 15:21:17 +08:00

138 lines
4.2 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";
// GET /api/site-settings - 获取网站设置 (公开)
export async function GET() {
try {
const [settings] = await db.select().from(siteSettings).limit(1);
// 获取系统通知
const [notificationSetting] = await db
.select()
.from(systemSettings)
.where(eq(systemSettings.key, "login_notification"))
.limit(1);
const notification = notificationSetting?.value || { enabled: false, title: "", content: "" };
// 如果没有设置记录,返回默认值
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: "由壹点累了也是需要休息的",
};
const response = NextResponse.json({
...baseSettings,
notification,
});
// 禁用缓存,确保总是获取最新设置
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(),
});
// 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 });
}
if (session.user.type !== "admin") {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const body = await request.json();
const data = updateSchema.parse(body);
// 查找现有设置
const [existing] = await db.select().from(siteSettings).limit(1);
if (existing) {
// 更新现有设置
const [updated] = await db
.update(siteSettings)
.set({
...data,
updatedAt: new Date(),
updatedBy: session.user.id,
})
.where(eq(siteSettings.id, existing.id))
.returning();
return NextResponse.json(updated);
} else {
// 创建新设置
const [created] = await db
.insert(siteSettings)
.values({
siteName: data.siteName || "AI Chatbot",
siteLogo: data.siteLogo,
siteLogoDark: data.siteLogoDark,
favicon: data.favicon,
showAutoModel: data.showAutoModel ?? true,
defaultTheme: data.defaultTheme ?? "system",
usageTimeEnabled: data.usageTimeEnabled ?? false,
usageTimeStart: data.usageTimeStart ?? "08:00",
usageTimeEnd: data.usageTimeEnd ?? "20:00",
usageTimeMessage: data.usageTimeMessage ?? "由壹点累了也是需要休息的",
updatedBy: session.user.id,
})
.returning();
return NextResponse.json(created);
}
} 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 }
);
}
}