Your Name 53ddb7e585
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
Initial commit - clean repository
2025-12-17 20:15:18 +08:00

112 lines
3.4 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { db } from "@/lib/db";
import { generatedImage, user } from "@/lib/db/schema";
import { eq, desc, sql, and, gte, lte, like, or } from "drizzle-orm";
import { auth } from "@/app/(auth)/auth";
export async function GET(request: NextRequest) {
try {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// 检查是否为管理员
const currentUser = await db.query.user.findFirst({
where: eq(user.id, session.user.id),
});
if (currentUser?.role !== "admin") {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
// 获取查询参数
const searchParams = request.nextUrl.searchParams;
const page = Number.parseInt(searchParams.get("page") || "1");
const pageSize = Number.parseInt(searchParams.get("pageSize") || "200");
const offset = (page - 1) * pageSize;
const search = searchParams.get("search") || "";
const startDate = searchParams.get("startDate");
const endDate = searchParams.get("endDate");
// 构建查询条件
const conditions = [];
if (search) {
// 搜索用户名或邮箱
const matchingUsers = await db
.select({ id: user.id })
.from(user)
.where(or(
like(user.name, `%${search}%`),
like(user.email, `%${search}%`)
));
if (matchingUsers.length > 0) {
const userIds = matchingUsers.map(u => u.id);
conditions.push(sql`${generatedImage.userId} IN (${sql.join(userIds.map(id => sql`${id}`), sql`, `)})`);
} else {
// 没有匹配的用户,返回空结果
return NextResponse.json({
images: [],
pagination: { page, pageSize, total: 0, totalPages: 0 }
});
}
}
if (startDate) {
conditions.push(gte(generatedImage.createdAt, new Date(startDate)));
}
if (endDate) {
const end = new Date(endDate);
end.setHours(23, 59, 59, 999);
conditions.push(lte(generatedImage.createdAt, end));
}
const whereClause = conditions.length > 0 ? and(...conditions) : undefined;
// 查询总数
const countResult = await db
.select({ count: sql<number>`count(*)::int` })
.from(generatedImage)
.where(whereClause);
const total = countResult[0]?.count || 0;
// 查询图片列表(包含用户信息)
const images = await db
.select({
id: generatedImage.id,
userId: generatedImage.userId,
userName: user.name,
userEmail: user.email,
thumbnailUrl: generatedImage.thumbnailUrl,
originalUrl: generatedImage.originalUrl,
imageSize: generatedImage.imageSize,
prompt: generatedImage.prompt,
modelId: generatedImage.modelId,
createdAt: generatedImage.createdAt,
chatId: generatedImage.chatId,
})
.from(generatedImage)
.leftJoin(user, eq(generatedImage.userId, user.id))
.where(whereClause)
.orderBy(desc(generatedImage.createdAt))
.limit(pageSize)
.offset(offset);
const totalPages = Math.ceil(total / pageSize);
return NextResponse.json({
images,
pagination: { page, pageSize, total, totalPages }
});
} catch (error) {
console.error("[Admin Images API] Error:", error);
return NextResponse.json({ error: "Failed to fetch images" }, { status: 500 });
}
}