Selaa lähdekoodia

修改,总进球数结算问题

jax 5 kuukautta sitten
vanhempi
commit
22c96740f6

BIN
public/images/login_1919.webp


+ 71 - 0
src/app/api/cronTask/route.js

@@ -0,0 +1,71 @@
+// // src/app/api/cronTask/route.js
+// import { CronJob } from "cron";
+// import Match from "../../models/Match"; // 确保路径正确
+
+// const timezone = "Asia/Shanghai";
+// const now = moment.tz(timezone);
+// const currentDate = now.toDate();
+// const currentTimeString = now.format("HH:mm");
+
+// // 创建2小时前的时间点
+// const twoHoursAgo = moment(now).subtract(2, "hours");
+// const twoHoursAgoDate = twoHoursAgo.format("YYYY-MM-DD"); // 使用日期字符串
+// const twoHoursAgoTime = twoHoursAgo.format("HH:mm");
+// let job;
+
+// export async function GET(req) {
+//     if (!job) {
+//         // 设置定时任务,以下示例为每分钟执行一次
+//         job = new CronJob(
+//             "*/1 * * * *", // cron 表达式
+//             async () => {
+
+//                 // 更新所有开始超过2小时的比赛为已结束
+//                 Match.updateMany(
+//                     {
+//                         $or: [
+//                             // 早于今天的比赛
+//                             { date: { $lt: twoHoursAgoDate } },
+//                             // 今天的比赛且开始时间在2小时前
+//                             {
+//                                 date: twoHoursAgoDate,
+//                                 time: { $lte: twoHoursAgoTime },
+//                             },
+//                         ],
+//                         status: { $in: ["未开始", "进行中"] },
+//                         ...(type ? { type } : {}),
+//                     },
+//                     { $set: { status: "已结束" } }
+//                 ),
+
+//                     // 更新其他应该进行中的比赛
+//                     Match.updateMany(
+//                         {
+//                             date: { $lte: currentDate },
+//                             time: { $lte: currentTimeString },
+//                             status: "未开始",
+//                             // 排除已经过去2小时的比赛(因为上面的查询会处理)
+//                             $or: [
+//                                 { date: { $gt: twoHoursAgoDate } },
+//                                 {
+//                                     date: twoHoursAgoDate,
+//                                     time: { $gt: twoHoursAgoTime },
+//                                 },
+//                             ],
+//                             ...(type ? { type } : {}),
+//                         },
+//                         { $set: { status: "进行中" } }
+//                     )
+
+//             },
+//             null,
+//             true, // 设置自动启动任务
+//             "Asia/Shanghai" // 设置时区(可选)
+//         );
+//     }
+
+//     return new Response(JSON.stringify({ message: "定时任务已启动" }), {
+//         status: 200,
+//         headers: { "Content-Type": "application/json" },
+//     });
+// }

+ 42 - 40
src/app/api/match/route.js

@@ -1,16 +1,18 @@
+
+
 import dbConnect from "../../lib/dbConnect";
 import Match from "../../models/Match";
 import { NextResponse } from "next/server";
 import { setCORSHeaders, handleError } from "../../lib/apiUtils";
 import moment from "moment-timezone/moment-timezone-utils";
 import { withAuth } from "../../middleware/authMiddleware";
-
 // 假设你的服务器时区是 'Asia/Shanghai'
 const timezone = "Asia/Shanghai";
 
 export async function GET(request) {
   await dbConnect();
 
+
   try {
     const { searchParams } = new URL(request.url);
     const action = searchParams.get("action");
@@ -86,44 +88,44 @@ export async function GET(request) {
 
         console.log("Search Query:", searchQuery);
 
-        await Promise.all([
-          // 更新所有开始超过2小时的比赛为已结束
-          Match.updateMany(
-            {
-              $or: [
-                // 早于今天的比赛
-                { date: { $lt: twoHoursAgoDate } },
-                // 今天的比赛且开始时间在2小时前
-                {
-                  date: twoHoursAgoDate,
-                  time: { $lte: twoHoursAgoTime },
-                },
-              ],
-              status: { $in: ["未开始", "进行中"] },
-              ...(type ? { type } : {}),
-            },
-            { $set: { status: "已结束" } }
-          ),
-
-          // 更新其他应该进行中的比赛
-          Match.updateMany(
-            {
-              date: { $lte: currentDate },
-              time: { $lte: currentTimeString },
-              status: "未开始",
-              // 排除已经过去2小时的比赛(因为上面的查询会处理)
-              $or: [
-                { date: { $gt: twoHoursAgoDate } },
-                {
-                  date: twoHoursAgoDate,
-                  time: { $gt: twoHoursAgoTime },
-                },
-              ],
-              ...(type ? { type } : {}),
-            },
-            { $set: { status: "进行中" } }
-          ),
-        ]);
+        // await Promise.all([
+        //   // 更新所有开始超过2小时的比赛为已结束
+        //   Match.updateMany(
+        //     {
+        //       $or: [
+        //         // 早于今天的比赛
+        //         { date: { $lt: twoHoursAgoDate } },
+        //         // 今天的比赛且开始时间在2小时前
+        //         {
+        //           date: twoHoursAgoDate,
+        //           time: { $lte: twoHoursAgoTime },
+        //         },
+        //       ],
+        //       status: { $in: ["未开始", "进行中"] },
+        //       ...(type ? { type } : {}),
+        //     },
+        //     { $set: { status: "已结束" } }
+        //   ),
+
+        //   // 更新其他应该进行中的比赛
+        //   Match.updateMany(
+        //     {
+        //       date: { $lte: currentDate },
+        //       time: { $lte: currentTimeString },
+        //       status: "未开始",
+        //       // 排除已经过去2小时的比赛(因为上面的查询会处理)
+        //       $or: [
+        //         { date: { $gt: twoHoursAgoDate } },
+        //         {
+        //           date: twoHoursAgoDate,
+        //           time: { $gt: twoHoursAgoTime },
+        //         },
+        //       ],
+        //       ...(type ? { type } : {}),
+        //     },
+        //     { $set: { status: "进行中" } }
+        //   ),
+        // ]);
 
         const skip = (current - 1) * pageSize;
         const totalMatches = await Match.countDocuments(searchQuery);
@@ -198,7 +200,7 @@ export const POST = withAuth(async (request) => {
   try {
     const matchData = await request.json();
 
-    console.log(11, matchData);
+    // console.log(11, matchData);
 
     // 验证比赛类型
     if (

+ 14 - 26
src/app/api/updateForMatch/route.js

@@ -33,15 +33,13 @@ export const POST = withAuth(async (request) => {
     for (const history of previousPointHistories) {
       const user = await User.findById(history.user);
       if (user) {
-        user.points -= history.points;
-        await user.save();
+        await User.findByIdAndUpdate(user._id, { $inc: { points: -history.points } });
       }
       await PointHistory.deleteOne({ _id: history._id });
     }
 
     // 2. 查找所有相关预测
     const predictions = await Prediction.find({ match: matchId });
-
     // 3. 根据比赛类型处理预测结果和积分
     for (const prediction of predictions) {
       let pointsEarned = 0;
@@ -49,9 +47,7 @@ export const POST = withAuth(async (request) => {
 
       if (match.type === "football") {
         // 足球比赛预测处理
-        if (
-          prediction.football?.whoWillWin?.prediction ===
-          match.football.result.whoWillWin
+        if (prediction.football?.whoWillWin?.prediction == match.football.result.whoWillWin
         ) {
           prediction.football.whoWillWin.result = "correct";
           pointsEarned += match.football.pointRewards.whoWillWin;
@@ -60,20 +56,16 @@ export const POST = withAuth(async (request) => {
           prediction.football.whoWillWin.result = "incorrect";
         }
 
-        if (
-          prediction.football?.firstTeamToScore?.prediction ===
-          match.football.result.firstTeamToScore
-        ) {
+        if (prediction.football?.firstTeamToScore?.prediction == match.football.result.firstTeamToScore) {
           prediction.football.firstTeamToScore.result = "correct";
           pointsEarned += match.football.pointRewards.firstTeamToScore;
           reasons.push("正确预测首先得分球队");
         } else {
           prediction.football.firstTeamToScore.result = "incorrect";
         }
-
-        const actualTotalGoals =
-          match.football.homeTeamScore + match.football.awayTeamScore;
-        if (prediction.football?.totalGoals?.prediction === actualTotalGoals) {
+        //总进球
+        const actualTotalGoals = match.homeTeamScore + match.awayTeamScore;
+        if (prediction.football?.totalGoals?.prediction == actualTotalGoals) {
           prediction.football.totalGoals.result = "correct";
           pointsEarned += match.football.pointRewards.totalGoals;
           reasons.push("正确预测总进球数");
@@ -87,13 +79,11 @@ export const POST = withAuth(async (request) => {
         const awayScore = match.awayTeamScore;
         const winTeam = homeScore > awayScore ? "home" : "away";
 
-        if (prediction.basketball?.whoWillWin?.prediction === winTeam) {
+        if (prediction.basketball?.whoWillWin?.prediction == winTeam) {
           prediction.basketball.whoWillWin.result = "correct";
           pointsEarned += match.basketball.pointRewards.whoWillWin;
           reasons.push("正确预测比赛胜负");
         } else {
-          console.log(333);
-
           prediction.basketball.whoWillWin.result = "incorrect";
         }
 
@@ -108,7 +98,7 @@ export const POST = withAuth(async (request) => {
 
         const spreadResult = homeScoreWithSpread > awayScore ? "home" : "away";
 
-        if (prediction.basketball?.spread?.prediction === spreadResult) {
+        if (prediction.basketball?.spread?.prediction == spreadResult) {
           prediction.basketball.spread.result = "correct";
           pointsEarned += match.basketball.pointRewards.spread;
           reasons.push("正确预测让分");
@@ -122,9 +112,7 @@ export const POST = withAuth(async (request) => {
         const totalPointsResult =
           totalPoints > totalPointsLine ? "over" : "under";
 
-        if (
-          prediction.basketball?.totalPoints?.prediction === totalPointsResult
-        ) {
+        if (prediction.basketball?.totalPoints?.prediction == totalPointsResult) {
           prediction.basketball.totalPoints.result = "correct";
           pointsEarned += match.basketball.pointRewards.totalPoints;
           reasons.push("正确预测总分");
@@ -141,13 +129,13 @@ export const POST = withAuth(async (request) => {
       if (pointsEarned > 0) {
         const user = await User.findById(prediction.user);
         if (user) {
-          user.points += pointsEarned;
-          await user.save();
+          // user.points += pointsEarned;
+          // await user.save();
+          await User.findByIdAndUpdate(prediction.user, { $inc: { points: pointsEarned } });
 
           // 创建积分历史记录
-          const reason = `${match.homeTeam.name} vs ${match.awayTeam.name} ${
-            match.type === "football" ? "足球" : "篮球"
-          }比赛预测: ${reasons.join(", ")}`;
+          const reason = `${match.homeTeam.name} vs ${match.awayTeam.name} ${match.type === "football" ? "足球" : "篮球"
+            }比赛预测: ${reasons.join(", ")}`;
           const pointHistory = new PointHistory({
             user: user._id,
             points: pointsEarned,

+ 1 - 0
src/app/layout.js

@@ -1,4 +1,5 @@
 import "./globals.css";
+import "./utils/scheduler"; // 导入以启动任务
 
 export const metadata = {
   title: "比分预测",

+ 15 - 8
src/app/login/page.js

@@ -1,6 +1,7 @@
 "use client";
 import { useState } from "react";
 import Head from "next/head";
+
 import Alert from "../ui/components/Alert";
 import { useRouter } from "next/navigation";
 import Link from "next/link";
@@ -41,19 +42,23 @@ export default function LoginPage() {
   };
 
   return (
-    <div className="min-h-screen bg-gray-100 flex flex-col justify-center px-4 sm:px-6 lg:px-8">
+    <div className="min-h-screen bg-gray-100 flex flex-col justify-center px-4 sm:px-6 lg:px-8 relative">
       <Head>
         <title>登录</title>
       </Head>
 
-      {/* <div className="w-full max-w-md mx-auto">
-        <h2 className="text-center text-xl font-extrabold text-gray-900">
-          登录
-        </h2>
-      </div> */}
+      {/* 背景图片 */}
+      <div className="absolute inset-0 flex">
+        <img
+          src="https://007xagm5vezzk-fluid-aliyun.erzjzd.com/assets/bd7-bg_mobile@3x-0648c73a.png"
+          alt="背景图片"
+          className="object-cover"
+        />
+      </div>
 
-      <div className="mt-8 w-full max-w-md mx-auto">
-        <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
+      {/* 登录表单 */}
+      <div className="mt-80 relative w-full max-w-md mx-auto z-10 bg-opacity-80 bg-white rounded-lg shadow">
+        <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10 rounded-lg">
           <form className="space-y-6" onSubmit={handleSubmit}>
             <div>
               <label
@@ -124,6 +129,7 @@ export default function LoginPage() {
           </div>
         </div>
       </div>
+
       {alert && (
         <Alert
           message={alert.message}
@@ -132,5 +138,6 @@ export default function LoginPage() {
         />
       )}
     </div>
+
   );
 }

+ 2 - 2
src/app/middleware/authMiddleware.js

@@ -31,7 +31,7 @@ export function withAuth(handler) {
             NextResponse.json(
               {
                 success: false,
-                error: "token已过期",
+                error: "登录已过期",
                 code: "TOKEN_EXPIRED",
               },
               { status: 401 }
@@ -42,7 +42,7 @@ export function withAuth(handler) {
             NextResponse.json(
               {
                 success: false,
-                error: "token无效",
+                error: "登录已失效",
                 code: "TOKEN_INVALID",
               },
               { status: 401 }

+ 1 - 1
src/app/register/page.js

@@ -90,7 +90,7 @@ export default function RegisterPage() {
       </div> */}
 
       <div className="mt-8 w-full max-w-md mx-auto">
-        <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
+        <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10 rounded-lg">
           <form className="space-y-6" onSubmit={handleSubmit}>
             <div>
               <label className="block text-sm font-medium text-gray-700">

+ 1 - 1
src/app/reset-password/page.js

@@ -117,7 +117,7 @@ export default function ResetPasswordPage() {
       </div> */}
 
       <div className="mt-8 w-full max-w-md mx-auto">
-        <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
+        <div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10 rounded-lg">
           {step === 1 ? (
             <form className="space-y-6" onSubmit={handleVerification}>
               <div>

+ 1 - 1
src/app/ui/FootballMatch.jsx

@@ -58,7 +58,7 @@ const FootballMatch = ({ selectedDayMatches, currentUser }) => {
   // console.log("predictionMap", predictionMap);
 
   useEffect(() => {
-    console.log("currentUser", currentUser);
+    // console.log("currentUser", currentUser);
     const fetchPredictions = async () => {
       try {
         const res = await fetchApi(

+ 1 - 2
src/app/utils/fetch.js

@@ -15,6 +15,7 @@ const getToken = () => {
  * @param {Object} [options.extraHeaders={}] - 额外的 headers
  * @returns {Promise}
  */
+
 export const fetchApi = async (url, options = {}) => {
   const { extraHeaders = {}, ...fetchOptions } = options;
   const headers = {
@@ -36,8 +37,6 @@ export const fetchApi = async (url, options = {}) => {
       },
     });
 
-    console.log("response", response.ok);
-
     const data = await response.json();
 
     // 处理错误情况

+ 83 - 0
src/app/utils/scheduler.js

@@ -0,0 +1,83 @@
+// src/utils/scheduler.js
+import { CronJob } from "cron";
+import moment from "moment-timezone/moment-timezone-utils";
+import Match from "../models/Match";
+
+const timezone = "Asia/Shanghai";
+
+
+
+function startJob() {
+    const job = new CronJob(
+        "*/5 * * * *",
+        async () => {
+            const now = moment.tz(timezone);
+            const currentDate = now.toDate();
+            const currentTimeString = now.format("HH:mm");
+
+            // 创建2小时前的时间点
+            const twoHoursAgo = moment(now).subtract(2, "hours");
+            const twoHoursAgoDate = twoHoursAgo.format("YYYY-MM-DD"); // 使用日期字符串
+            const twoHoursAgoTime = twoHoursAgo.format("HH:mm");
+            // console.log("定时任务:每5分钟执行一次" + twoHoursAgoDate + ":" + twoHoursAgoTime);
+            try {
+                // 更新已结束的比赛
+                const updateResult1 = await Match.updateMany(
+                    {
+                        $or: [
+                            // 早于今天的比赛
+                            { date: { $lt: twoHoursAgoDate } },
+                            // 今天的比赛且开始时间在2小时前
+                            {
+                                date: twoHoursAgoDate,
+                                time: { $lte: twoHoursAgoTime },
+                            },
+                        ],
+                        status: { $in: ["未开始", "进行中"] },
+                        type: { $in: ["football", "basketball"] },
+                    },
+                    { $set: { status: "已结束" } } // 设置状态为已结束
+                );
+
+                // console.log(`已结束的比赛数量: ${updateResult1.modifiedCount}`);
+
+                // 更新进行中的比赛
+                const updateResult2 = await Match.updateMany(
+                    {
+                        date: { $lte: currentDate },
+                        time: { $lte: currentTimeString },
+                        status: "未开始",
+                        // 排除已经过去2小时的比赛(因为上面的查询会处理)
+                        $or: [
+                            { date: { $gt: twoHoursAgoDate } },
+                            {
+                                date: twoHoursAgoDate,
+                                time: { $gt: twoHoursAgoTime },
+                            },
+                        ],
+                        type: { $in: ["football", "basketball"] },
+                    },
+                    { $set: { status: "进行中" } } // 设置状态为进行中
+                );
+
+                // console.log(`进行中的比赛数量: ${updateResult2.modifiedCount}`);
+            } catch (error) {
+                console.error("更新比赛状态时出错:", error);
+            }
+        },
+        null,
+        true,
+        "Asia/Shanghai"
+    );
+    job.start();
+}
+
+// 使用 process.on 确保任务在服务器启动时执行
+process.on("SIGINT", () => {
+    console.log("服务器关闭,清理定时任务...");
+    // 在这里可以清理定时任务
+    process.exit();
+});
+
+// 立即启动定时任务
+startJob();