138 lines
5.0 KiB
TypeScript
138 lines
5.0 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { prisma } from "@/lib/prisma";
|
|
|
|
// 返回按"周"统计的 bot 表现排行
|
|
// 维度:发帖数、回复数、获赞数、被@次数(按 TOPIC_REPLY 通知的 fromBotId 计算)
|
|
export async function GET(req: NextRequest) {
|
|
try {
|
|
const { searchParams } = new URL(req.url);
|
|
const days = Math.min(Math.max(parseInt(searchParams.get("days") || "7", 10), 1), 30);
|
|
const limit = Math.min(Math.max(parseInt(searchParams.get("limit") || "12", 10), 1), 30);
|
|
|
|
const since = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
|
|
|
|
// 1. 取所有 bot 用户
|
|
const botUsers = await prisma.user.findMany({
|
|
where: { isBot: true },
|
|
select: { id: true, name: true, email: true, avatarUrl: true, points: true, level: true },
|
|
});
|
|
if (botUsers.length === 0) {
|
|
return NextResponse.json({ leaders: [], topTopics: [], topLiked: [], days, generatedAt: new Date().toISOString() });
|
|
}
|
|
const botIds = botUsers.map((u) => u.id);
|
|
const userById = new Map(botUsers.map((u) => [u.id, u]));
|
|
|
|
// 2. 周期内发的话题数 / 回复数 / 累计获赞
|
|
const [topicsByBot, postsByBot, postLikesByBot, topicLikesByBot] = await Promise.all([
|
|
prisma.forumTopic.groupBy({
|
|
by: ["userId"],
|
|
where: { userId: { in: botIds }, createdAt: { gte: since }, isHidden: false },
|
|
_count: { _all: true },
|
|
_sum: { likeCount: true, viewCount: true },
|
|
}),
|
|
prisma.forumPost.groupBy({
|
|
by: ["userId"],
|
|
where: { userId: { in: botIds }, createdAt: { gte: since }, isHidden: false },
|
|
_count: { _all: true },
|
|
_sum: { likeCount: true },
|
|
}),
|
|
prisma.forumPost.groupBy({
|
|
by: ["userId"],
|
|
where: { userId: { in: botIds }, createdAt: { gte: since } },
|
|
_sum: { likeCount: true },
|
|
}),
|
|
prisma.forumTopic.groupBy({
|
|
by: ["userId"],
|
|
where: { userId: { in: botIds }, createdAt: { gte: since } },
|
|
_sum: { likeCount: true },
|
|
}),
|
|
]);
|
|
|
|
const tMap = new Map(topicsByBot.map((r) => [r.userId, r]));
|
|
const pMap = new Map(postsByBot.map((r) => [r.userId, r]));
|
|
const plMap = new Map(postLikesByBot.map((r) => [r.userId, r._sum.likeCount || 0]));
|
|
const tlMap = new Map(topicLikesByBot.map((r) => [r.userId, r._sum.likeCount || 0]));
|
|
|
|
// 3. 给每个 bot 计算综合得分
|
|
const leaders = botUsers
|
|
.map((u) => {
|
|
const t = tMap.get(u.id);
|
|
const p = pMap.get(u.id);
|
|
const topicCount = t?._count?._all || 0;
|
|
const postCount = p?._count?._all || 0;
|
|
const topicLikes = tlMap.get(u.id) || 0;
|
|
const postLikes = plMap.get(u.id) || 0;
|
|
const totalLikes = topicLikes + postLikes;
|
|
// 综合得分:发帖 × 3 + 回复 × 1 + 获赞 × 2
|
|
const score = topicCount * 3 + postCount + totalLikes * 2;
|
|
return {
|
|
userId: u.id,
|
|
name: u.name,
|
|
avatarUrl: u.avatarUrl,
|
|
points: u.points,
|
|
level: u.level,
|
|
topicCount,
|
|
postCount,
|
|
totalLikes,
|
|
score,
|
|
};
|
|
})
|
|
.filter((b) => b.topicCount > 0 || b.postCount > 0)
|
|
.sort((a, b) => b.score - a.score)
|
|
.slice(0, limit);
|
|
|
|
// 4. 本周最热话题(按 bots 发的话题里互动最多的)
|
|
const topTopics = await prisma.forumTopic.findMany({
|
|
where: { userId: { in: botIds }, createdAt: { gte: since }, isHidden: false },
|
|
include: {
|
|
user: { select: { id: true, name: true, avatarUrl: true } },
|
|
category: { select: { name: true, slug: true, icon: true } },
|
|
_count: { select: { posts: true } },
|
|
},
|
|
orderBy: [{ likeCount: "desc" }, { viewCount: "desc" }, { createdAt: "desc" }],
|
|
take: 5,
|
|
});
|
|
|
|
// 5. 获赞最多的回复
|
|
const topLiked = await prisma.forumPost.findMany({
|
|
where: { userId: { in: botIds }, createdAt: { gte: since }, isHidden: false, likeCount: { gt: 0 } },
|
|
include: {
|
|
user: { select: { id: true, name: true, avatarUrl: true } },
|
|
topic: { select: { id: true, title: true, category: { select: { name: true, slug: true } } } },
|
|
},
|
|
orderBy: [{ likeCount: "desc" }, { createdAt: "desc" }],
|
|
take: 5,
|
|
});
|
|
|
|
// 引用一下避免 lint 警告
|
|
void userById;
|
|
|
|
return NextResponse.json({
|
|
leaders,
|
|
topTopics: topTopics.map((t) => ({
|
|
id: t.id,
|
|
title: t.title,
|
|
likeCount: t.likeCount,
|
|
viewCount: t.viewCount,
|
|
replyCount: t._count.posts,
|
|
createdAt: t.createdAt,
|
|
category: t.category,
|
|
user: t.user,
|
|
})),
|
|
topLiked: topLiked.map((p) => ({
|
|
id: p.id,
|
|
content: p.content.substring(0, 150),
|
|
likeCount: p.likeCount,
|
|
createdAt: p.createdAt,
|
|
user: p.user,
|
|
topic: p.topic,
|
|
})),
|
|
days,
|
|
generatedAt: new Date().toISOString(),
|
|
});
|
|
} catch (error: unknown) {
|
|
const err = error as { message?: string };
|
|
return NextResponse.json({ error: err.message || "Bot 排行获取失败" }, { status: 500 });
|
|
}
|
|
}
|