|
@@ -0,0 +1,220 @@
|
|
|
+import dbConnect from "../../lib/dbConnect";
|
|
|
+import PointHistory from "../../models/PointHistory";
|
|
|
+import User from "../../models/User";
|
|
|
+import { NextResponse } from "next/server";
|
|
|
+import { setCORSHeaders, handleError } from "../../lib/apiUtils";
|
|
|
+
|
|
|
+// 添加积分修改记录
|
|
|
+export async function POST(request) {
|
|
|
+ await dbConnect();
|
|
|
+
|
|
|
+ try {
|
|
|
+ const { userId, points, reason, matchId } = await request.json();
|
|
|
+
|
|
|
+ if (!userId || points === undefined || !reason) {
|
|
|
+ return NextResponse.json(
|
|
|
+ { success: false, error: "用户ID、积分变化和修改原因都是必填项" },
|
|
|
+ { status: 400 }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ const user = await User.findById(userId);
|
|
|
+ if (!user) {
|
|
|
+ return NextResponse.json(
|
|
|
+ { success: false, error: "未找到指定用户" },
|
|
|
+ { status: 404 }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ const pointHistory = new PointHistory({
|
|
|
+ user: userId,
|
|
|
+ points: points,
|
|
|
+ reason: reason,
|
|
|
+ match: matchId || null, // 如果提供了 matchId,则保存;否则为 null
|
|
|
+ });
|
|
|
+
|
|
|
+ await pointHistory.save();
|
|
|
+
|
|
|
+ // 更新用户总积分
|
|
|
+ user.points += points;
|
|
|
+ await user.save();
|
|
|
+
|
|
|
+ const response = NextResponse.json(
|
|
|
+ {
|
|
|
+ success: true,
|
|
|
+ message: "积分修改记录已添加",
|
|
|
+ data: {
|
|
|
+ userId: user._id,
|
|
|
+ pointChange: points,
|
|
|
+ reason: reason,
|
|
|
+ currentPoints: user.points, // 返回更新后的总积分
|
|
|
+ },
|
|
|
+ },
|
|
|
+ { status: 201 }
|
|
|
+ );
|
|
|
+
|
|
|
+ return setCORSHeaders(response);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("添加积分修改记录时出错:", error);
|
|
|
+ return handleError(error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 查询积分修改历史
|
|
|
+export async function GET(request) {
|
|
|
+ await dbConnect();
|
|
|
+
|
|
|
+ try {
|
|
|
+ const { searchParams } = new URL(request.url);
|
|
|
+
|
|
|
+ const current = parseInt(searchParams.get("current")) || 1;
|
|
|
+ const pageSize = parseInt(searchParams.get("pageSize")) || 10;
|
|
|
+
|
|
|
+ const searchQuery = {};
|
|
|
+
|
|
|
+ for (const [key, value] of searchParams.entries()) {
|
|
|
+ if (["current", "pageSize"].includes(key)) continue;
|
|
|
+
|
|
|
+ switch (key) {
|
|
|
+ case "user":
|
|
|
+ try {
|
|
|
+ const userObj = JSON.parse(value);
|
|
|
+ if (userObj.username) {
|
|
|
+ const users = await User.find({
|
|
|
+ username: { $regex: userObj.username, $options: "i" },
|
|
|
+ }).select("_id");
|
|
|
+ searchQuery.user = { $in: users.map((u) => u._id) };
|
|
|
+ } else if (userObj._id) {
|
|
|
+ searchQuery.user = userObj._id;
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error("解析用户参数时出错:", e);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case "username":
|
|
|
+ const users = await User.find({
|
|
|
+ username: { $regex: value, $options: "i" },
|
|
|
+ }).select("_id");
|
|
|
+ searchQuery.user = { $in: users.map((u) => u._id) };
|
|
|
+ break;
|
|
|
+ case "userId":
|
|
|
+ searchQuery.user = value;
|
|
|
+ break;
|
|
|
+ case "points":
|
|
|
+ const pointsRange = value.split(",");
|
|
|
+ if (pointsRange.length === 2) {
|
|
|
+ const [min, max] = pointsRange.map(Number);
|
|
|
+ searchQuery.points = { $gte: min, $lte: max };
|
|
|
+ } else {
|
|
|
+ searchQuery.points = Number(value);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case "reason":
|
|
|
+ searchQuery.reason = { $regex: value, $options: "i" };
|
|
|
+ break;
|
|
|
+ case "dateRange":
|
|
|
+ const [startDate, endDate] = value.split(",");
|
|
|
+ searchQuery.createdAt = {
|
|
|
+ $gte: new Date(startDate),
|
|
|
+ $lte: new Date(endDate),
|
|
|
+ };
|
|
|
+ break;
|
|
|
+ case "id":
|
|
|
+ searchQuery._id = value;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log("Search Query:", searchQuery);
|
|
|
+
|
|
|
+ const total = await PointHistory.countDocuments(searchQuery);
|
|
|
+ const history = await PointHistory.find(searchQuery)
|
|
|
+ .sort({ createdAt: -1 })
|
|
|
+ .skip((current - 1) * pageSize)
|
|
|
+ .limit(pageSize)
|
|
|
+ .select("-__v")
|
|
|
+ .populate("user", "username");
|
|
|
+
|
|
|
+ const response = NextResponse.json(
|
|
|
+ {
|
|
|
+ success: true,
|
|
|
+ total,
|
|
|
+ data: history,
|
|
|
+ },
|
|
|
+ { status: 200 }
|
|
|
+ );
|
|
|
+
|
|
|
+ return setCORSHeaders(response);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("查询积分修改历史时出错:", error);
|
|
|
+ return handleError(error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export async function DELETE(request) {
|
|
|
+ await dbConnect();
|
|
|
+
|
|
|
+ try {
|
|
|
+ const { searchParams } = new URL(request.url);
|
|
|
+ const id = searchParams.get("id");
|
|
|
+ const ids = searchParams.get("ids");
|
|
|
+
|
|
|
+ if (!id && !ids) {
|
|
|
+ return NextResponse.json(
|
|
|
+ { success: false, error: "需要提供id或ids参数" },
|
|
|
+ { status: 400 }
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ let deletedCount = 0;
|
|
|
+ let updatedUsers = new Set();
|
|
|
+
|
|
|
+ if (id) {
|
|
|
+ // 删除单个记录
|
|
|
+ const pointHistory = await PointHistory.findById(id);
|
|
|
+ if (pointHistory) {
|
|
|
+ updatedUsers.add(pointHistory.user.toString());
|
|
|
+ await PointHistory.findByIdAndDelete(id);
|
|
|
+ deletedCount = 1;
|
|
|
+ }
|
|
|
+ } else if (ids) {
|
|
|
+ // 批量删除记录
|
|
|
+ const idArray = ids.split(",");
|
|
|
+ const pointHistories = await PointHistory.find({ _id: { $in: idArray } });
|
|
|
+ pointHistories.forEach((ph) => updatedUsers.add(ph.user.toString()));
|
|
|
+ const result = await PointHistory.deleteMany({ _id: { $in: idArray } });
|
|
|
+ deletedCount = result.deletedCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新用户积分
|
|
|
+ for (let userId of updatedUsers) {
|
|
|
+ const user = await User.findById(userId);
|
|
|
+ if (user) {
|
|
|
+ const totalPoints = await PointHistory.aggregate([
|
|
|
+ { $match: { user: user._id } },
|
|
|
+ { $group: { _id: null, total: { $sum: "$points" } } },
|
|
|
+ ]);
|
|
|
+ user.points = totalPoints.length > 0 ? totalPoints[0].total : 0;
|
|
|
+ await user.save();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ const response = NextResponse.json(
|
|
|
+ {
|
|
|
+ success: true,
|
|
|
+ message: `成功删除 ${deletedCount} 条积分历史记录`,
|
|
|
+ },
|
|
|
+ { status: 200 }
|
|
|
+ );
|
|
|
+
|
|
|
+ return setCORSHeaders(response);
|
|
|
+ } catch (error) {
|
|
|
+ console.error("删除积分历史记录时出错:", error);
|
|
|
+ return handleError(error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+export async function OPTIONS() {
|
|
|
+ const response = new NextResponse(null, { status: 204 });
|
|
|
+ return setCORSHeaders(response);
|
|
|
+}
|