import { prisma } from "@/lib/prisma"; import { NextResponse } from "next/server"; const DAYS = 90; export async function GET(_req: Request, { params }: { params: { id: string } }) { try { const userId = parseInt(params.id); if (isNaN(userId)) { return NextResponse.json({ error: "无效的用户ID" }, { status: 400 }); } const since = new Date(); since.setDate(since.getDate() - DAYS); since.setHours(0, 0, 0, 0); const [topics, posts, comments, checkIns] = await Promise.all([ prisma.forumTopic.findMany({ where: { userId, createdAt: { gte: since } }, select: { createdAt: true }, }), prisma.forumPost.findMany({ where: { userId, createdAt: { gte: since } }, select: { createdAt: true }, }), prisma.comment.findMany({ where: { userId, createdAt: { gte: since } }, select: { createdAt: true }, }), prisma.forumCheckIn.findMany({ where: { userId, checkInDate: { gte: since } }, select: { checkInDate: true, streak: true, pointsEarned: true }, }), ]); const all = new Map(); const bump = (d: Date, type: "topics" | "posts" | "comments") => { const k = d.toISOString().slice(0, 10); const cur = all.get(k) || { count: 0, topics: 0, posts: 0, comments: 0 }; cur.count += 1; cur[type] += 1; all.set(k, cur); }; topics.forEach(t => bump(t.createdAt, "topics")); posts.forEach(p => bump(p.createdAt, "posts")); comments.forEach(c => bump(c.createdAt, "comments")); const heatmap: Array<{ date: string; count: number; topics: number; posts: number; comments: number }> = []; for (let i = DAYS - 1; i >= 0; i--) { const d = new Date(); d.setDate(d.getDate() - i); const k = d.toISOString().slice(0, 10); const v = all.get(k); heatmap.push({ date: k, count: v?.count || 0, topics: v?.topics || 0, posts: v?.posts || 0, comments: v?.comments || 0, }); } const checkInList = checkIns .map(c => ({ date: c.checkInDate.toISOString().slice(0, 10), streak: c.streak, points: c.pointsEarned, })) .sort((a, b) => a.date.localeCompare(b.date)); const totalActiveDays = heatmap.filter(d => d.count > 0).length; const totalActions = topics.length + posts.length + comments.length; return NextResponse.json({ heatmap, checkIns: checkInList, summary: { totalDays: DAYS, activeDays: totalActiveDays, activeRate: Math.round((totalActiveDays / DAYS) * 100), totalActions, topicsCount: topics.length, postsCount: posts.length, commentsCount: comments.length, }, }); } catch (error: unknown) { const err = error as { message?: string }; return NextResponse.json({ error: err.message || "获取活跃度数据失败" }, { status: 500 }); } }