作弊&促销

Change-Id: Ibdee947370e11c3a98912569e1a290b5e0968fbe
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 64d19fc..f58e1e2 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -7,13 +7,12 @@
         <option value="$PROJECT_DIR$/pom.xml" />
       </list>
     </option>
-    <option name="workspaceImportForciblyTurnedOn" value="true" />
   </component>
   <component name="PWA">
     <option name="enabled" value="true" />
     <option name="wasEnabledAtLeastOnce" value="true" />
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
 </project>
\ No newline at end of file
diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 5e39899..d3c9b17 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,73 +5,14 @@
   </component>
   <component name="ChangeListManager">
     <list default="true" id="f008fe30-0711-42e2-bb33-17dcfdbad387" name="Changes" comment="pom">
-      <change beforePath="$PROJECT_DIR$/.idea/dataSources.local.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources.local.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/.idea/dataSources/6d2a7063-ae4c-471f-ae05-e32dede5d0ec.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources/6d2a7063-ae4c-471f-ae05-e32dede5d0ec.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/.idea/misc.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/pom.xml" beforeDir="false" afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/config/WebConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/config/WebConfig.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/DynamicController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/DynamicController.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/TorrentController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/TorrentController.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/UserController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/UserController.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/entity/User.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/entity/User.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/entity/Users.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/entity/Users.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/DynamicService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/DynamicService.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/PostService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/PostService.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/TorrentService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/TorrentService.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/UserService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/UserService.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/PromotionController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/controller/PromotionController.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/mapper/PromotionMapper.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/mapper/PromotionMapper.java" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/serviceImpl/PromotionServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/serviceImpl/PromotionServiceImpl.java" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/src/test/java/com/example/myproject/controller/DynamicControllerTest.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/test/java/com/example/myproject/controller/DynamicControllerTest.java" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/common/base/PageParam.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/common/base/PageParam.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/common/base/ResPage.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/common/base/ResPage.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/common/base/Result.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/common/base/Result.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/config/TrackerConfig.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/config/TrackerConfig.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/config/WebConfig.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/config/WebConfig.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/DynamicController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/DynamicController.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/GroupController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/GroupController.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/TorrentController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/TorrentController.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/TrackerController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/TrackerController.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/UserController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/controller/UserController.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/PromotionCreateDTO.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/PromotionCreateDTO.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/TorrentUpdateDTO.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/TorrentUpdateDTO.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/param/AnnounceRequest.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/param/AnnounceRequest.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/param/TorrentParam.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/param/TorrentParam.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/param/TorrentUploadParam.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/param/TorrentUploadParam.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/vo/TorrentVO.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/dto/vo/TorrentVO.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/EntityBase.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/EntityBase.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/FavoriteEntity.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/FavoriteEntity.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/Promotion.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/Promotion.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/TorrentEntity.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/TorrentEntity.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/User.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/User.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/VerificationToken.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/entity/VerificationToken.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/CommentService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/CommentService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/DynamicService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/DynamicService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/GroupService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/GroupService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/LevelService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/LevelService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/PostService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/PostService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/TorrentService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/TorrentService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/UserMessageService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/UserMessageService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/UserService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/UserService.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/EmailServiceImpl.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/EmailServiceImpl.class" afterDir="false" />
+      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/mapper/PromotionMapper.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/mapper/PromotionMapper.class" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/PromotionServiceImpl.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/PromotionServiceImpl.class" afterDir="false" />
       <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/utils/Result.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/utils/Result.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/com/example/myproject/utils/VerifyCode.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/example/myproject/utils/VerifyCode.class" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/files/files.torrent" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/classes/output/valid.torrent" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/CommentControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/DynamicControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/GroupControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/LevelControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/PostControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/TaskControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/UserControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/UserFollowControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/target/test-classes/com/example/myproject/controller/UserMessageControllerTest.class" beforeDir="false" />
-      <change beforePath="$PROJECT_DIR$/uploads/avatarUrl/1.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/uploads/avatarUrl/1.jpg" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/uploads/avatarUrl/2.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/uploads/avatarUrl/2.jpg" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/uploads/avatarUrl/3.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/uploads/avatarUrl/3.jpg" afterDir="false" />
-      <change beforePath="$PROJECT_DIR$/uploads/avatarUrl/4.jpg" beforeDir="false" afterPath="$PROJECT_DIR$/uploads/avatarUrl/4.jpg" afterDir="false" />
     </list>
     <option name="SHOW_DIALOG" value="false" />
     <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -110,38 +51,38 @@
     <option name="hideEmptyMiddlePackages" value="true" />
     <option name="showLibraryContents" value="true" />
   </component>
-  <component name="PropertiesComponent"><![CDATA[{
-  "keyToString": {
-    "ASKED_ADD_EXTERNAL_FILES": "true",
-    "JUnit.UserControllerTest.executor": "Run",
-    "JUnit.UserControllerTest.testUpdateUserAvatar.executor": "Run",
-    "JUnit.UserControllerTest.testUploadUserAvatar.executor": "Run",
-    "RequestMappingsPanelOrder0": "0",
-    "RequestMappingsPanelOrder1": "1",
-    "RequestMappingsPanelWidth0": "75",
-    "RequestMappingsPanelWidth1": "75",
-    "RunOnceActivity.OpenProjectViewOnStart": "true",
-    "RunOnceActivity.ShowReadmeOnStart": "true",
-    "RunOnceActivity.git.unshallow": "true",
-    "Spring Boot.MyProjectApplication.executor": "Run",
-    "git-widget-placeholder": "完成pt与bt交互、补充图片资源",
-    "ignore.virus.scanning.warn.message": "true",
-    "kotlin-language-version-configured": "true",
-    "last_opened_file_path": "D:/Desktop/echo后端/echo-backend/images",
-    "node.js.detected.package.eslint": "true",
-    "node.js.selected.package.eslint": "(autodetect)",
-    "node.js.selected.package.tslint": "(autodetect)",
-    "nodejs_package_manager_path": "npm",
-    "settings.editor.selected.configurable": "project.propVCSSupport.DirectoryMappings",
-    "vue.rearranger.settings.migration": "true",
-    "应用程序.MyProjectApplication.executor": "Run"
+  <component name="PropertiesComponent">{
+  &quot;keyToString&quot;: {
+    &quot;ASKED_ADD_EXTERNAL_FILES&quot;: &quot;true&quot;,
+    &quot;JUnit.UserControllerTest.executor&quot;: &quot;Run&quot;,
+    &quot;JUnit.UserControllerTest.testUpdateUserAvatar.executor&quot;: &quot;Run&quot;,
+    &quot;JUnit.UserControllerTest.testUploadUserAvatar.executor&quot;: &quot;Run&quot;,
+    &quot;RequestMappingsPanelOrder0&quot;: &quot;0&quot;,
+    &quot;RequestMappingsPanelOrder1&quot;: &quot;1&quot;,
+    &quot;RequestMappingsPanelWidth0&quot;: &quot;75&quot;,
+    &quot;RequestMappingsPanelWidth1&quot;: &quot;75&quot;,
+    &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
+    &quot;Spring Boot.MyProjectApplication.executor&quot;: &quot;Run&quot;,
+    &quot;git-widget-placeholder&quot;: &quot;完成pt与bt交互、补充图片资源&quot;,
+    &quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
+    &quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
+    &quot;last_opened_file_path&quot;: &quot;D:/Desktop/echo后端/echo-backend/images&quot;,
+    &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
+    &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
+    &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
+    &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
+    &quot;settings.editor.selected.configurable&quot;: &quot;project.propVCSSupport.DirectoryMappings&quot;,
+    &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;,
+    &quot;应用程序.MyProjectApplication.executor&quot;: &quot;Run&quot;
   },
-  "keyToStringList": {
-    "DatabaseDriversLRU": [
-      "mysql_aurora"
+  &quot;keyToStringList&quot;: {
+    &quot;DatabaseDriversLRU&quot;: [
+      &quot;mysql_aurora&quot;
     ]
   }
-}]]></component>
+}</component>
   <component name="RecentsManager">
     <key name="CopyFile.RECENT_KEYS">
       <recent name="D:\Desktop\echo后端\echo-backend\images" />
diff --git a/src/main/java/com/example/myproject/MyProjectApplication.java b/src/main/java/com/example/myproject/MyProjectApplication.java
index 49cd5f0..417fa6d 100644
--- a/src/main/java/com/example/myproject/MyProjectApplication.java
+++ b/src/main/java/com/example/myproject/MyProjectApplication.java
@@ -4,8 +4,11 @@
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 @SpringBootApplication
+@EnableScheduling
+
 @MapperScan("com.example.myproject.mapper")  // 扫描 Mapper 接口
 public class MyProjectApplication {
     public static void main(String[] args) {
diff --git a/src/main/java/com/example/myproject/controller/PromotionController.java b/src/main/java/com/example/myproject/controller/PromotionController.java
new file mode 100644
index 0000000..ab6efe7
--- /dev/null
+++ b/src/main/java/com/example/myproject/controller/PromotionController.java
@@ -0,0 +1,141 @@
+package com.example.myproject.controller;
+
+import cn.dev33.satoken.annotation.SaCheckLogin;
+import cn.dev33.satoken.stp.StpUtil;
+import com.example.myproject.common.base.Result;
+import com.example.myproject.dto.PromotionCreateDTO;
+import com.example.myproject.dto.TorrentUpdateDTO;
+import com.example.myproject.entity.Promotion;
+import com.example.myproject.service.PromotionService;
+import com.example.myproject.service.TorrentService;
+import com.example.myproject.service.UserService;
+import com.example.myproject.repository.UserRepository;
+import io.swagger.v3.oas.annotations.Operation;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+@RestController
+@RequestMapping("/seeds")
+@Slf4j
+@RequiredArgsConstructor
+public class PromotionController {
+    @Autowired
+    private TorrentService torrentService;
+    @Autowired
+    private UserRepository userRepository;
+
+
+    @Autowired
+    private PromotionService promotionService;
+
+    @Autowired
+    private UserService userService;
+    @SaCheckLogin
+    @Operation(summary = "删除种子")
+    @DeleteMapping("/{torrentId}")
+    public Result deleteTorrent(@PathVariable Long torrentId) {
+        try {
+            //  验证用户权限
+            Long userId = StpUtil.getLoginIdAsLong();
+            if (!torrentService.canUserDeleteTorrent(torrentId, userId)) {
+                return Result.error("没有权限删除此种子");
+            }
+
+            torrentService.deleteTorrent(torrentId);
+            return Result.ok();
+        } catch (Exception e) {
+            return Result.error("删除失败: " + e.getMessage());
+        }
+    }
+
+    @SaCheckLogin
+    @Operation(summary = "修改种子信息")
+    @PutMapping("/{torrentId}")
+    public Result updateTorrent(
+            @PathVariable Long torrentId,
+            @RequestBody @Validated TorrentUpdateDTO updateDTO) {
+        try {
+            // 验证用户权限
+            Long userId = StpUtil.getLoginIdAsLong();
+            if (!torrentService.canUserUpdateTorrent(torrentId, userId)) {
+                return Result.error("没有权限修改此种子");
+            }
+
+            torrentService.updateTorrent(torrentId, updateDTO);
+            return Result.ok();
+        } catch (Exception e) {
+            return Result.error("更新失败: " + e.getMessage());
+        }
+    }
+
+    @SaCheckLogin
+    @Operation(summary = "创建促销活动")
+    @PostMapping("/promotions")
+    public Result createPromotion(@RequestBody @Validated PromotionCreateDTO promotionDTO) {
+        try {
+            // 验证用户权限(只有管理员可以创建促销)
+//            if (!StpUtil.hasRole("admin")) {
+//                return Result.error("没有权限创建促销活动");
+//            }
+//
+            Promotion promotion = promotionService.createPromotion(promotionDTO);
+            return Result.ok(promotion);
+        } catch (Exception e) {
+            return Result.error("创建促销失败: " + e.getMessage());
+        }
+    }
+
+    @SaCheckLogin
+    @Operation(summary = "获取促销活动列表")
+    @GetMapping("/promotions")
+    public Result getPromotions() {
+        try {
+            List<Promotion> promotions = promotionService.getAllActivePromotions();
+            return Result.ok(promotions);
+        } catch (Exception e) {
+            return Result.error("获取促销列表失败: " + e.getMessage());
+        }
+    }
+
+    @SaCheckLogin
+    @Operation(summary = "获取促销详情")
+    @GetMapping("/promotions/{promotionId}")
+    public Result getPromotionDetails(@PathVariable Long promotionId) {
+        try {
+            Promotion promotion = promotionService.getPromotionById(promotionId);
+            if (promotion == null) {
+                return Result.error("促销活动不存在");
+            }
+            return Result.ok(promotion);
+        } catch (Exception e) {
+            return Result.error("获取促销详情失败: " + e.getMessage());
+        }
+    }
+
+    @SaCheckLogin
+    @Operation(summary = "删除促销活动")
+    @DeleteMapping("/promotions/{promotionId}")
+    public Result deletePromotion(@PathVariable Long promotionId) {
+        try {
+            // 验证用户权限(只有管理员可以删除促销)
+//            if (!StpUtil.hasRole("admin")) {
+//                return Result.error("没有权限删除促销活动");
+//            }
+            Long userId = StpUtil.getLoginIdAsLong();
+            // 查询用户
+            var userOpt = userRepository.findById(userId);
+            if (userOpt.isEmpty() || !"admin".equals(userOpt.get().getRole())) {
+                return Result.error("没有权限删除促销活动");
+            }
+
+            promotionService.deletePromotion(promotionId);
+            return Result.ok();
+        } catch (Exception e) {
+            return Result.error("删除促销失败: " + e.getMessage());
+        }
+    }
+}
diff --git a/src/main/java/com/example/myproject/controller/TorrentController.java b/src/main/java/com/example/myproject/controller/TorrentController.java
index aecfc64..846e5da 100644
--- a/src/main/java/com/example/myproject/controller/TorrentController.java
+++ b/src/main/java/com/example/myproject/controller/TorrentController.java
@@ -325,6 +325,7 @@
 import com.example.myproject.dto.TrackerProtocol;
 import com.example.myproject.entity.TorrentEntity;
 import com.example.myproject.entity.TorrentReport;
+import com.example.myproject.mapper.UserMapper;
 import com.example.myproject.repository.TorrentReportRepository;
 import com.example.myproject.service.TorrentService;
 import com.example.myproject.service.PromotionService;
@@ -335,6 +336,7 @@
 import com.example.myproject.dto.TorrentUpdateDTO;
 import com.example.myproject.dto.PromotionCreateDTO;
 import com.example.myproject.entity.Promotion;
+
 import com.example.myproject.service.UserService;
 
 import com.turn.ttorrent.bcodec.BEValue;
@@ -378,6 +380,9 @@
 
     @Autowired
     private PromotionService promotionService;
+    @Autowired
+    private UserMapper userMapper;
+
 
     @Autowired
     private UserService userService;
@@ -529,107 +534,23 @@
             return Result.error("失败: ");
         }
     }
-
-    @SaCheckLogin
-    @Operation(summary = "删除种子")
-    @DeleteMapping("/{torrentId}")
-    public Result deleteTorrent(@PathVariable Long torrentId) {
+    /**
+     * 查看个人收藏
+     */
+    @GetMapping("/my-favorite")
+    public Result getMyFavorite(
+            @RequestParam("user_id") Long  userId) {
         try {
-           //  验证用户权限
-            Long userId = StpUtil.getLoginIdAsLong();
-            if (!torrentService.canUserDeleteTorrent(torrentId, userId)) {
-                return Result.error("没有权限删除此种子");
-            }
-
-            torrentService.deleteTorrent(torrentId);
-            return Result.ok();
+            return  torrentService.getMyfavorite(userId);
         } catch (Exception e) {
-            return Result.error("删除失败: " + e.getMessage());
+            return Result.error("失败: ");
         }
     }
 
-    @SaCheckLogin
-    @Operation(summary = "修改种子信息")
-    @PutMapping("/{torrentId}")
-    public Result updateTorrent(
-            @PathVariable Long torrentId,
-            @RequestBody @Validated TorrentUpdateDTO updateDTO) {
-        try {
-            // 验证用户权限
-            Long userId = StpUtil.getLoginIdAsLong();
-            if (!torrentService.canUserUpdateTorrent(torrentId, userId)) {
-                return Result.error("没有权限修改此种子");
-            }
 
-            torrentService.updateTorrent(torrentId, updateDTO);
-            return Result.ok();
-        } catch (Exception e) {
-            return Result.error("更新失败: " + e.getMessage());
-        }
-    }
-
-    @SaCheckLogin
-    @Operation(summary = "创建促销活动")
-    @PostMapping("/promotions")
-    public Result createPromotion(@RequestBody @Validated PromotionCreateDTO promotionDTO) {
-        try {
-            // 验证用户权限(只有管理员可以创建促销)
-//            if (!StpUtil.hasRole("admin")) {
-//                return Result.error("没有权限创建促销活动");
-//            }
-//
-            Promotion promotion = promotionService.createPromotion(promotionDTO);
-            return Result.ok(promotion);
-        } catch (Exception e) {
-            return Result.error("创建促销失败: " + e.getMessage());
-        }
-    }
-
-    @SaCheckLogin
-    @Operation(summary = "获取促销活动列表")
-    @GetMapping("/promotions")
-    public Result getPromotions() {
-        try {
-            List<Promotion> promotions = promotionService.getAllActivePromotions();
-            return Result.ok(promotions);
-        } catch (Exception e) {
-            return Result.error("获取促销列表失败: " + e.getMessage());
-        }
-    }
-
-    @SaCheckLogin
-    @Operation(summary = "获取促销详情")
-    @GetMapping("/promotions/{promotionId}")
-    public Result getPromotionDetails(@PathVariable Long promotionId) {
-        try {
-            Promotion promotion = promotionService.getPromotionById(promotionId);
-            if (promotion == null) {
-                return Result.error("促销活动不存在");
-            }
-            return Result.ok(promotion);
-        } catch (Exception e) {
-            return Result.error("获取促销详情失败: " + e.getMessage());
-        }
-    }
-
-    @SaCheckLogin
-    @Operation(summary = "删除促销活动")
-    @DeleteMapping("/promotions/{promotionId}")
-    public Result deletePromotion(@PathVariable Long promotionId) {
-        try {
-            // 验证用户权限(只有管理员可以删除促销)
-            if (!StpUtil.hasRole("admin")) {
-                return Result.error("没有权限删除促销活动");
-            }
-
-            promotionService.deletePromotion(promotionId);
-            return Result.ok();
-        } catch (Exception e) {
-            return Result.error("删除促销失败: " + e.getMessage());
-        }
-    }
     @GetMapping("/announce")
     public ResponseEntity<byte[]> announce(TrackerProtocol trackerProtocol, HttpServletRequest request, @RequestParam(value = "info_hash") String encodedInfoHash){
+
         HashMap<String, BEValue> map = new HashMap<>();
         if (StrUtil.isBlank(trackerProtocol.getIp())) {
             trackerProtocol.setIp(request.getRemoteAddr());
@@ -641,13 +562,25 @@
 
             trackerProtocol.setInfo_hash(infoHash);
             TorrentEntity torrent = torrentService.selectByInfoHash(infoHash);
+            Long torrentId = torrent.getId();
+            String peerId = trackerProtocol.getPeer_id();
+
             if (torrent == null) {
                 throw new RuntimeException("种子不存在");
             }
             Integer userId = trackerProtocol.getUserId();
+            double uploaded = trackerProtocol.getUploaded();
+            double downloaded = trackerProtocol.getDownloaded();
+            /**
+             *更新种子上传量,下载量, 更新用户上传量下载量
+             * 为了总量检测作弊,种子的上传量和下载量是真实的
+             * 用户的上传下载量是“促销”后的
+             * 作弊检测——下载速度检测
+             */
+            torrentService.processUploadDownload(Long.valueOf(userId),peerId, infoHash,torrentId,uploaded,downloaded);
 
             TorrentReport report = TorrentReport.builder()
-                    .userId(userId )
+                    .userId(userId)
                     .torrentId(torrent.getId())
                     .peerId(trackerProtocol.getPeer_id())
                     .infoHash(infoHash)
diff --git a/src/main/java/com/example/myproject/entity/AuditRecord.java b/src/main/java/com/example/myproject/entity/AuditRecord.java
new file mode 100644
index 0000000..ed8b9de
--- /dev/null
+++ b/src/main/java/com/example/myproject/entity/AuditRecord.java
@@ -0,0 +1,20 @@
+package com.example.myproject.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+@TableName("audit_record")
+@ApiModel("种子实体类")
+public class AuditRecord {
+    private Integer id;
+    private Long torrentId;
+    private double upload;
+    private double download;
+    private LocalDateTime createTime;
+    public AuditRecord() {
+    }
+}
diff --git a/src/main/java/com/example/myproject/entity/BannedUser.java b/src/main/java/com/example/myproject/entity/BannedUser.java
new file mode 100644
index 0000000..a9aa2da
--- /dev/null
+++ b/src/main/java/com/example/myproject/entity/BannedUser.java
@@ -0,0 +1,27 @@
+package com.example.myproject.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+@Data
+@TableName("ba")
+public class BannedUser {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "用户ID", example = "1001")
+    @JsonProperty("userId")
+    @TableField("user_id")
+    private Long userId;
+
+    private String reason;
+    @JsonProperty("createTime")
+    @TableField("create_time")
+    private Date createTime;
+}
diff --git a/src/main/java/com/example/myproject/entity/SuspiciousUser.java b/src/main/java/com/example/myproject/entity/SuspiciousUser.java
new file mode 100644
index 0000000..8b15f08
--- /dev/null
+++ b/src/main/java/com/example/myproject/entity/SuspiciousUser.java
@@ -0,0 +1,35 @@
+package com.example.myproject.entity;
+
+
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+@TableName("suspicious_user")
+@ApiModel("列入怀疑用户")
+public class SuspiciousUser {
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "用户ID", example = "1001")
+    @JsonProperty("userId")
+    @TableField("user_id")
+    private Long userId;
+    @ApiModelProperty(value = "上传速度", example = "1001")
+    @TableField("peed_kbs")
+    private double speedKBs;
+
+    private String reason;
+    @JsonProperty("createTime")
+    @TableField("create_time")
+    private Date createTime;
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/entity/TorrentEntity.java b/src/main/java/com/example/myproject/entity/TorrentEntity.java
index f62fb76..b2b8192 100644
--- a/src/main/java/com/example/myproject/entity/TorrentEntity.java
+++ b/src/main/java/com/example/myproject/entity/TorrentEntity.java
@@ -93,6 +93,12 @@
     @JsonProperty("promotionUntil")
     @ApiModelProperty(value = "促销截止日期", example = "2024-12-31T23:59:59")
     private LocalDateTime promotionUntil;
+    @JsonProperty("upload_count")
+    @ApiModelProperty(value = "种子上传量", example = "false")
+    private double uploadCount;
+    @JsonProperty("down_count")
+    @ApiModelProperty(value = "种子下载量", example = "false")
+    private double downloadCount;
 
     
     @JsonProperty("torrentFile")
@@ -103,6 +109,7 @@
     @ApiModelProperty(value = "是否删除", example = "false")
     private Boolean isDeleted;
 
+
     public TorrentEntity() {
     }
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/entity/TorrentReport.java b/src/main/java/com/example/myproject/entity/TorrentReport.java
index a019f9e..0d6de00 100644
--- a/src/main/java/com/example/myproject/entity/TorrentReport.java
+++ b/src/main/java/com/example/myproject/entity/TorrentReport.java
@@ -1,5 +1,7 @@
 package com.example.myproject.entity;
 
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
 import lombok.Builder;
 import lombok.Data;
 
@@ -24,5 +26,12 @@
     private String event;
     private String  ip;
     private Integer port;
+
     private LocalDateTime reportTime;
+    @PrePersist
+    public void prePersist() {
+        this.reportTime = LocalDateTime.now();
+    }
+
+
 }
diff --git a/src/main/java/com/example/myproject/mapper/AuditRecordMapper.java b/src/main/java/com/example/myproject/mapper/AuditRecordMapper.java
new file mode 100644
index 0000000..2aae334
--- /dev/null
+++ b/src/main/java/com/example/myproject/mapper/AuditRecordMapper.java
@@ -0,0 +1,13 @@
+package com.example.myproject.mapper;
+
+import com.example.myproject.entity.AuditRecord;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AuditRecordMapper {
+
+    @Insert("INSERT INTO audit_record (torrent_id, upload, download, create_time) " +
+            "VALUES (#{torrentId}, #{upload}, #{download}, #{createTime})")
+    void insert(AuditRecord record);
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/mapper/BannedUserMapper.java b/src/main/java/com/example/myproject/mapper/BannedUserMapper.java
new file mode 100644
index 0000000..9b376e6
--- /dev/null
+++ b/src/main/java/com/example/myproject/mapper/BannedUserMapper.java
@@ -0,0 +1,15 @@
+package com.example.myproject.mapper;
+
+import com.example.myproject.entity.AuditRecord;
+import com.example.myproject.entity.BannedUser;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+
+
+@Mapper
+public interface BannedUserMapper {
+
+    @Insert("INSERT INTO banned_user (user_id, reason, create_time) " +
+            "VALUES (#{userId}, #{reason}, #{createTime})")
+    void insert(BannedUser bannedUser);
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/mapper/PromotionMapper.java b/src/main/java/com/example/myproject/mapper/PromotionMapper.java
index a478835..caf96ee 100644
--- a/src/main/java/com/example/myproject/mapper/PromotionMapper.java
+++ b/src/main/java/com/example/myproject/mapper/PromotionMapper.java
@@ -24,7 +24,8 @@
     @Select("SELECT p.* FROM promotion p " +
             "WHERE p.is_deleted = false " +
             "AND p.start_time <= #{now} AND p.end_time >= #{now} " +
-            "AND FIND_IN_SET(#{torrentId}, p.applicable_torrent_ids) > 0")
+//            "AND FIND_IN_SET(#{torrentId}, p.applicable_torrent_ids) > 0"
+             "AND JSON_CONTAINS(p.applicable_torrent_ids, CAST(#{torrentId} AS JSON))")
     List<Promotion> findActivePromotionsForTorrent(
             @Param("torrentId") Long torrentId,
             @Param("now") LocalDateTime now);
diff --git a/src/main/java/com/example/myproject/mapper/SuspiciousUserMapper.java b/src/main/java/com/example/myproject/mapper/SuspiciousUserMapper.java
new file mode 100644
index 0000000..533c597
--- /dev/null
+++ b/src/main/java/com/example/myproject/mapper/SuspiciousUserMapper.java
@@ -0,0 +1,12 @@
+package com.example.myproject.mapper;
+
+import com.example.myproject.entity.SuspiciousUser;
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SuspiciousUserMapper {
+    @Insert("INSERT INTO suspicious_user (user_id, reason, speed_kbs, create_time) " +
+            "VALUES (#{userId}, #{reason}, #{speedKBs}, #{createTime})")
+    void insert(SuspiciousUser user);
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/mapper/TorrentMapper.java b/src/main/java/com/example/myproject/mapper/TorrentMapper.java
index f9cdcdc..5e72bf2 100644
--- a/src/main/java/com/example/myproject/mapper/TorrentMapper.java
+++ b/src/main/java/com/example/myproject/mapper/TorrentMapper.java
@@ -15,18 +15,20 @@
 
     @Select("SELECT * FROM torrents WHERE info_hash = #{infoHash}")
     TorrentEntity selectByInfoHash(String infoHash);
-    
-    @Select("SELECT * FROM torrents WHERE seed_id = #{seedId}")
-    TorrentEntity selectBySeedId(Long seedId);
-    
+
     List<TorrentEntity> search(@Param("param") TorrentParam param);
-    
-    @Update("UPDATE torrent SET downloads = downloads + 1 WHERE id = #{torrentId}")
-    void increaseDownloads(@Param("torrentId") Long torrentId);
-    
+
     boolean checkFavorite(@Param("seedId") Long seedId, @Param("userId") Long userId);
     
     void addFavorite(@Param("seedId") Long seedId, @Param("userId") Long userId);
     
     void removeFavorite(@Param("seedId") Long seedId, @Param("userId") Long userId);
+    List<TorrentEntity> selectMyFavorite(@Param("userId") Long userId);
+    @Select("SELECT * FROM torrent")
+    List<TorrentEntity> findAllTorrents();
+    @Update("UPDATE torrent SET upload_count = upload_count + #{uploaded}, download_count = download_count + #{downloaded} WHERE id = #{torrentId}")
+    void updateTorrentUploadDownload(@Param("torrentId") Long torrentId,
+                                     @Param("uploaded") double uploaded,
+                                     @Param("downloaded") double downloaded);
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/mapper/UserMapper.java b/src/main/java/com/example/myproject/mapper/UserMapper.java
index 1752801..4a10a38 100644
--- a/src/main/java/com/example/myproject/mapper/UserMapper.java
+++ b/src/main/java/com/example/myproject/mapper/UserMapper.java
@@ -1,4 +1,5 @@
 package com.example.myproject.mapper;
+import com.example.myproject.entity.TorrentEntity;
 import com.example.myproject.entity.User;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
@@ -30,6 +31,14 @@
 
     @Select("SELECT * FROM user WHERE user_id = #{userId}")
     User selectByUserId(@Param("userId") Long userId);
+    @Update("UPDATE user SET upload_count = upload_count + #{bonusUploaded}, download_count = download_count + #{bonusDownloaded} WHERE user_id = #{userId}")
+    int updateUserUploadDownload(@Param("userId") Long userId,
+                                 @Param("bonusUploaded") double bonusUploaded,
+                                 @Param("bonusDownloaded") double bonusDownloaded);
+
+
+
+
 
 
 }
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/repository/TorrentReportRepository.java b/src/main/java/com/example/myproject/repository/TorrentReportRepository.java
index 9484d20..7b3e89c 100644
--- a/src/main/java/com/example/myproject/repository/TorrentReportRepository.java
+++ b/src/main/java/com/example/myproject/repository/TorrentReportRepository.java
@@ -2,6 +2,12 @@
 
 import com.example.myproject.entity.TorrentReport;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+
+import java.util.Optional;
 
 public interface TorrentReportRepository extends JpaRepository<TorrentReport, Integer> {
+    @Query(value = "SELECT * FROM TorrentReport WHERE peerId = :peerId AND infoHash = :infoHash ORDER BY id DESC LIMIT 1", nativeQuery = true)
+    Optional<TorrentReport> findLatestByPeerIdAndInfoHash(@Param("peerId") String peerId, @Param("infoHash") String infoHash);
 }
diff --git a/src/main/java/com/example/myproject/scheduler/TorrentAuditTask.java b/src/main/java/com/example/myproject/scheduler/TorrentAuditTask.java
new file mode 100644
index 0000000..bd985ad
--- /dev/null
+++ b/src/main/java/com/example/myproject/scheduler/TorrentAuditTask.java
@@ -0,0 +1,49 @@
+package com.example.myproject.scheduler;
+
+
+
+import com.example.myproject.entity.TorrentEntity;
+import com.example.myproject.mapper.TorrentMapper;
+import com.example.myproject.service.AuditService;
+import com.example.myproject.service.TorrentService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 作弊检测——总量核验
+ */
+@Slf4j
+@Component
+public class TorrentAuditTask {
+
+    private static final long THRESHOLD = 50 * 1024 * 1024; // 50MB
+
+    private final TorrentMapper torrentMapper;
+    private final AuditService auditService;
+
+    public TorrentAuditTask(TorrentMapper torrentMapper, AuditService auditService) {
+        this.torrentMapper = torrentMapper;
+        this.auditService = auditService;
+    }
+
+    @Scheduled(fixedRate = 3600000) // 每小时执行一次
+    public void checkTorrentUploadDownloadConsistency() {
+        List<TorrentEntity> torrents = torrentMapper.findAllTorrents();
+        for (TorrentEntity torrent : torrents) {
+            double upload = torrent.getUploadCount();
+            double download = torrent.getDownloadCount();
+            double delta = Math.abs(upload - download);
+
+            if (delta > THRESHOLD) {
+                log.warn("【总量核验】种子 {} 上传量={} 下载量={} 差值={},已触发人工审核",
+                        torrent.getInfoHash(), upload, download, delta);
+
+                auditService.flagTorrentForReview(torrent.getId(), upload, download);
+            }
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/service/AuditService.java b/src/main/java/com/example/myproject/service/AuditService.java
new file mode 100644
index 0000000..22d7124
--- /dev/null
+++ b/src/main/java/com/example/myproject/service/AuditService.java
@@ -0,0 +1,46 @@
+package com.example.myproject.service;
+
+import com.example.myproject.entity.AuditRecord;
+import com.example.myproject.entity.BannedUser;
+import com.example.myproject.entity.SuspiciousUser;
+import com.example.myproject.mapper.AuditRecordMapper;
+import com.example.myproject.mapper.BannedUserMapper;
+import com.example.myproject.mapper.SuspiciousUserMapper;
+import org.checkerframework.checker.units.qual.A;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDateTime;
+@Service
+public class AuditService {
+    @Autowired
+    AuditRecordMapper auditRecordMapper;
+    @Autowired
+    SuspiciousUserMapper suspiciousUserMapper;
+    @Autowired
+    BannedUserMapper bannedUserMapper;
+    public void flagTorrentForReview(Long torrentId, double upload, double download) {
+        AuditRecord record = new AuditRecord();
+        record.setTorrentId(torrentId);
+        record.setUpload(upload);
+        record.setDownload(download);
+        record.setCreateTime(LocalDateTime.now());
+
+        auditRecordMapper.insert(record);
+    }
+    public void addSuspiciousUser(Long userId, String reason, double speedKBs) {
+        SuspiciousUser user = new SuspiciousUser();
+        user.setUserId(userId);
+        user.setReason(reason);
+        user.setSpeedKBs(speedKBs);
+        suspiciousUserMapper.insert(user);
+    }
+
+
+    public void banUser(Long userId, String reason) {
+        BannedUser bannedUser = new BannedUser();
+        bannedUser.setUserId(userId);
+        bannedUser.setReason(reason);
+        bannedUserMapper.insert(bannedUser);
+    }
+}
diff --git a/src/main/java/com/example/myproject/service/PromotionService.java b/src/main/java/com/example/myproject/service/PromotionService.java
index 087c13b..b83bce5 100644
--- a/src/main/java/com/example/myproject/service/PromotionService.java
+++ b/src/main/java/com/example/myproject/service/PromotionService.java
@@ -13,5 +13,9 @@
     
     void deletePromotion(Long promotionId);
     
-    double getCurrentDiscount(Long torrentId);
+//    double getCurrentDiscount(Long torrentId);
+    double getUploadBonus(Long torrentId);
+    double getDownloadDiscount(Long torrentId);
+
+
 } 
\ No newline at end of file
diff --git a/src/main/java/com/example/myproject/service/TorrentService.java b/src/main/java/com/example/myproject/service/TorrentService.java
index 36891d2..e0a4f41 100644
--- a/src/main/java/com/example/myproject/service/TorrentService.java
+++ b/src/main/java/com/example/myproject/service/TorrentService.java
@@ -57,7 +57,9 @@
     byte[] fetch(Long seedId, String passkey) throws IOException;
     
     Result favorite(Long seedId, Long userId);
-    
+    Result getMyfavorite(Long userId);
+
+
     void deleteTorrent(Long seedId);
     
     void updateTorrent(Long seedId, TorrentUpdateDTO updateDTO);
@@ -68,9 +70,12 @@
     
     boolean checkUserUploadRatio(Long userId);
     
-    double calculateDownloadSize(Long torrentId, Long userId);
+//    double calculateDownloadSize(Long torrentId, Long userId);
     
-    void recordDownload(Long torrentId, Long userId, double downloadSize);
+
 
     TorrentEntity selectByInfoHash(String infoHash);
+
+    void processUploadDownload(Long userId, String peerId, String infoHash, Long torrentId, double uploaded, double downloaded);
+
 }
diff --git a/src/main/java/com/example/myproject/service/serviceImpl/PromotionServiceImpl.java b/src/main/java/com/example/myproject/service/serviceImpl/PromotionServiceImpl.java
index 9d34cbc..1cac3a4 100644
--- a/src/main/java/com/example/myproject/service/serviceImpl/PromotionServiceImpl.java
+++ b/src/main/java/com/example/myproject/service/serviceImpl/PromotionServiceImpl.java
@@ -1,10 +1,14 @@
 package com.example.myproject.service.serviceImpl;
 
 import com.example.myproject.entity.Promotion;
+import com.example.myproject.entity.TorrentEntity;
 import com.example.myproject.mapper.PromotionMapper;
 import com.example.myproject.service.PromotionService;
 import com.example.myproject.dto.PromotionCreateDTO;
 
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.swagger.models.auth.In;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -40,10 +44,18 @@
         promotion.setDiscountPercentage(promotionDTO.getDiscountPercentage());
 
         // 把List<Long>转换成逗号分隔字符串
-        String applicableTorrentIdsStr = promotionDTO.getApplicableTorrentIds().stream()
-                .map(String::valueOf)
-                .collect(Collectors.joining(","));
-        promotion.setApplicableTorrentIds(applicableTorrentIdsStr);
+//        String applicableTorrentIdsStr = promotionDTO.getApplicableTorrentIds().stream()
+//                .map(String::valueOf)
+//                .collect(Collectors.joining(","));
+//        promotion.setApplicableTorrentIds(applicableTorrentIdsStr);
+        // 把List<Long>转换成JSON字符串
+        ObjectMapper objectMapper = new ObjectMapper();
+        try {
+            String applicableTorrentIdsJson = objectMapper.writeValueAsString(promotionDTO.getApplicableTorrentIds());
+            promotion.setApplicableTorrentIds(applicableTorrentIdsJson);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException("适用种子ID序列化失败", e);
+        }
 
         promotion.setCreateTime(now);
         promotion.setUpdateTime(now);
@@ -82,17 +94,17 @@
         promotionMapper.updateById(promotion);
     }
 
-    @Override
-    public double getCurrentDiscount(Long torrentId) {
-        LocalDateTime now = LocalDateTime.now();
-        List<Promotion> activePromotions = promotionMapper.findActivePromotionsForTorrent(torrentId, now);
-
-        // 如果有多个促销活动,取折扣最大的
-        return activePromotions.stream()
-                .mapToDouble(Promotion::getDiscountPercentage)
-                .max()
-                .orElse(0.0);
-    }
+//    @Override
+//    public double getCurrentDiscount(Long torrentId) {
+//        LocalDateTime now = LocalDateTime.now();
+//        List<Promotion> activePromotions = promotionMapper.findActivePromotionsForTorrent(torrentId, now);
+//
+//        // 如果有多个促销活动,取折扣最大的
+//        return activePromotions.stream()
+//                .mapToDouble(Promotion::getDiscountPercentage)
+//                .max()
+//                .orElse(0.0);
+//    }
 
     /**
      * 验证种子ID是否存在
@@ -111,4 +123,48 @@
             throw new RuntimeException("以下种子ID不存在: " + invalidIds);
         }
     }
+    @Override
+    public double getUploadBonus(Long torrentId) {
+        double uploadBonusPercentage = getUploadBonusPercentage(torrentId); // 例如 26.4
+        return 1.0 + (uploadBonusPercentage / 100.0); // 转换为倍数,例如 1.264
+    }
+
+    @Override
+    public double getDownloadDiscount(Long torrentId) {
+        double downloadDiscountPercentage = getDownloadDiscountPercentage(torrentId); // 例如 -20.0
+        return 1.0 + (downloadDiscountPercentage / 100.0); // -20.0 → 0.8
+    }
+
+
+    /**
+     * 获取当前种子适用的上传加成百分比(正数),若无返回 0.0
+     */
+    private double getUploadBonusPercentage(Long torrentId) {
+        LocalDateTime now = LocalDateTime.now();
+        List<Promotion> activePromotions = promotionMapper.findActivePromotionsForTorrent(torrentId, now);
+
+        // 取最大的正值加成百分比
+        return activePromotions.stream()
+                .mapToDouble(Promotion::getDiscountPercentage)
+                .filter(p -> p > 0)
+                .max()
+                .orElse(0.0);
+    }
+
+    /**
+     * 获取当前种子适用的下载折扣百分比(负数),若无返回 0.0
+     */
+    private double getDownloadDiscountPercentage(Long torrentId) {
+        LocalDateTime now = LocalDateTime.now();
+        List<Promotion> activePromotions = promotionMapper.findActivePromotionsForTorrent(torrentId, now);
+
+        // 取最小的负值折扣百分比(更大的折扣)
+        return activePromotions.stream()
+                .mapToDouble(Promotion::getDiscountPercentage)
+                .filter(p -> p < 0)
+                .min()
+                .orElse(0.0);
+    }
+
+
 }
diff --git a/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java b/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java
index 4870fd5..210db93 100644
--- a/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java
+++ b/src/main/java/com/example/myproject/service/serviceImpl/TorrentServiceImpl.java
@@ -296,14 +296,19 @@
 // }
 
 package com.example.myproject.service.serviceImpl;
+import java.time.Duration;
 
 import cn.dev33.satoken.stp.StpUtil;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.example.myproject.entity.SuspiciousUser;
 import com.example.myproject.entity.TorrentEntity;
+import com.example.myproject.entity.TorrentReport;
 import com.example.myproject.entity.User;
+import com.example.myproject.mapper.BannedUserMapper;
+import com.example.myproject.mapper.SuspiciousUserMapper;
 import com.example.myproject.mapper.TorrentMapper;
 import com.example.myproject.mapper.UserMapper;
+import com.example.myproject.repository.TorrentReportRepository;
+import com.example.myproject.service.AuditService;
 import com.example.myproject.service.TorrentService;
 import com.example.myproject.service.PromotionService;
 import com.example.myproject.dto.param.TorrentParam;
@@ -315,13 +320,14 @@
 import com.turn.ttorrent.client.SimpleClient;
 import com.turn.ttorrent.common.TorrentMetadata;
 import com.turn.ttorrent.common.TorrentParser;
-import com.turn.ttorrent.common.creation.MetadataBuilder;
 import com.turn.ttorrent.tracker.Tracker;
 import com.turn.ttorrent.tracker.TrackedTorrent;
 import com.example.myproject.common.base.Result;
+import lombok.extern.slf4j.Slf4j;
 
-import com.turn.ttorrent.tracker.TrackedTorrent;
+
 import org.apache.commons.codec.binary.Hex;
+import org.checkerframework.checker.units.qual.A;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -331,19 +337,18 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.net.InetAddress;
-import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.time.LocalTime;
+import java.time.LocalDateTime;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
+@Slf4j
 @Service
 public class TorrentServiceImpl implements TorrentService {
     @Autowired
@@ -352,6 +357,9 @@
     @Autowired
     private TorrentMapper torrentMapper;
 
+    @Autowired
+    private TorrentReportRepository torrentReportRepository;
+
     private final Map<String, TrackedTorrent> torrentRegistry = new HashMap<>();
 
 
@@ -360,6 +368,12 @@
 
     @Autowired
     private PromotionService promotionService;
+    @Autowired
+    SuspiciousUserMapper suspiciousUserMapper;
+    @Autowired
+    BannedUserMapper bannedUserMapper;
+    @Autowired
+    AuditService auditService;
 
     private static final double MIN_UPLOAD_RATIO = 0.5; // 最小上传比例要求
 
@@ -372,6 +386,7 @@
     public TorrentEntity selectBySeedId(Long seedId) {
         return torrentMapper.selectById(seedId);
     }
+
     private final ExecutorService seederExecutor = Executors.newCachedThreadPool();
 
     @Override
@@ -389,7 +404,7 @@
         Long size = metadata.getFiles().stream().map(f -> f.size).reduce(0L, Long::sum);
 
         // 保存种子信息
-        TorrentEntity entity= new TorrentEntity();
+        TorrentEntity entity = new TorrentEntity();
         entity.setUploader(param.getUploader());
         entity.setFileName(file.getOriginalFilename());
         entity.setSize(size);
@@ -404,7 +419,6 @@
     }
 
 
-
     @Override
     public byte[] fetch(Long seedId, String passkey) {
         TorrentEntity torrent = selectBySeedId(seedId);
@@ -422,6 +436,7 @@
 // TODO: 对应本机应用地址
 //            String announce = "http://127.0.0.1:5011/seeds/announce?passkey="+passkey +"&userId=" + StpUtil.getLoginIdAsString();
             String announce = "http://192.168.5.149:5011/seeds/announce?passkey=" + passkey + "&userId=" + StpUtil.getLoginIdAsString();
+//            String announce = "http://172.23.80.1:5011/seeds/announce?passkey=" + passkey + "&userId=" + 1;
 
             decoded.put("announce", new BEValue(announce));
             // 4. 编码成新的 .torrent 文件字节数组
@@ -452,6 +467,12 @@
     }
 
     @Override
+    public Result getMyfavorite(Long userId) {
+        List<TorrentEntity> favorites = torrentMapper.selectMyFavorite(userId);
+        return Result.ok(favorites);
+    }
+
+    @Override
     @Transactional
     public void deleteTorrent(Long seedId) {
         torrentMapper.deleteById(seedId);
@@ -507,58 +528,78 @@
         double uploadRatio = user.getUploaded() / (double) user.getDownloaded();
         return uploadRatio >= MIN_UPLOAD_RATIO;
     }
-    /**
-     * 启动做种客户端
-     */
-    private void startSeeding(Path torrentPath, Path dataDir) throws Exception {
-        SimpleClient seederClient = new SimpleClient();
-        seederClient.downloadTorrent(
-                torrentPath.toString(),
-                dataDir.toString(),
-                InetAddress.getLocalHost());
-        // 保持做种状态(阻塞线程)
-        while (true) {
-            Thread.sleep(60000); // 每60秒检查一次
-        }
-    }
 
 
     @Override
-    public double calculateDownloadSize(Long torrentId, Long userId) {
-        TorrentEntity torrent = selectBySeedId(torrentId);
-        if (torrent == null) {
-            throw new RuntimeException("种子不存在");
-        }
-
-        // 获取当前有效的促销活动
-        double discount = promotionService.getCurrentDiscount(torrentId);
-
-        // 计算实际下载量
-        return torrent.getSize() * (1 - discount / 100.0);
-    }
-
-    @Override
-    @Transactional
-    public void recordDownload(Long torrentId, Long userId, double downloadSize) {
-        // 更新用户下载量
-        userMapper.increaseDownloaded(userId, downloadSize);
-
-        // 更新种子下载次数
-        torrentMapper.increaseDownloads(torrentId);
-    }
-
-    @Override
     public TorrentEntity selectByInfoHash(String infoHash) {
         return torrentMapper.selectByInfoHash(infoHash);
     }
 
-    /**
-     * 计算种子文件的infoHash
-     */
-    private String calculateInfoHash(byte[] torrentData) throws NoSuchAlgorithmException  {
-        MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
-        sha1.update(torrentData);
-        byte[] hashBytes = sha1.digest();
-        return Hex.encodeHexString(hashBytes);
+    @Override
+    public void processUploadDownload(Long userId, String peerId, String infoHash, Long torrentId, double uploaded, double downloaded) {
+        // 查找该peerId和infoHash的最近一条TorrentReport
+        log.info("开始处理上传和下载");
+        Optional<TorrentReport> lastReportOpt = torrentReportRepository.findLatestByPeerIdAndInfoHash(peerId, infoHash);
+
+
+        double lastUploaded = 0;
+        double lastDownloaded = 0;
+        LocalDateTime lastTime = null;
+
+        if (lastReportOpt.isPresent()) {
+            lastUploaded = lastReportOpt.get().getUploaded();
+            lastDownloaded = lastReportOpt.get().getDownloaded();
+            lastTime = lastReportOpt.get().getReportTime();
+        }
+
+        double uploadedOffset = uploaded - lastUploaded;
+        double downloadedOffset = downloaded - lastDownloaded;
+
+        // 防止客户端重启或作弊导致负数,重置为0
+        if (uploadedOffset < 0) uploadedOffset = 0;
+        if (downloadedOffset < 0) downloadedOffset = 0;
+
+        /**
+         * 作弊——速度检测
+         */
+        if (lastTime != null) {
+            long seconds = Duration.between(lastTime, LocalDateTime.now()).getSeconds();
+            if (seconds > 0) {
+                double speedKBs = uploadedOffset / 1024.0 / seconds; // KB/s
+
+                double MAX_SPEED_KB = 10 * 1024;      // 10 MB/s
+                double SUSPICIOUS_SPEED_KB = 2 * 1024; // 2 MB/s
+                int MIN_EXPECTED_LEECHERS = 5;
+
+                //int leechers = torrentReportRepository.countActiveLeechers(infoHash);
+
+                if (speedKBs > MAX_SPEED_KB) {
+                    log.warn("用户 {} 上传速度 {} KB/s 超过限制,执行封禁处理", userId, speedKBs);
+                    auditService.banUser(userId, "上传速度超过最大限速");
+                    return; // 不再处理其他操作
+                }
+//                else if (speedKBs > SUSPICIOUS_SPEED_KB && leechers < MIN_EXPECTED_LEECHERS) {
+//                    log.warn("用户 {} 上传速度异常 {} KB/s,下载人数 {},加入怀疑名单", userId, speedKBs, leechers);
+//                    abnormalUserMapper.insertSuspicious(userId, speedKBs, leechers); // 你也需要实现
+//                }
+                else if (speedKBs > SUSPICIOUS_SPEED_KB) {
+                    log.warn("用户 {} 上传速度异常 {} KB/s, 加入怀疑名单", userId, speedKBs);
+                    auditService.addSuspiciousUser(userId, "上传速度异常:" ,speedKBs );
+                }
+            }
+
+            // 获取促销加成和下载折扣
+            double uploadBonus = promotionService.getUploadBonus(torrentId);       // 比如 1.2
+            log.info("上传优惠比例" + uploadBonus);
+            double downloadDiscount = promotionService.getDownloadDiscount(torrentId); // 比如 0.8
+
+            double bonusUploaded = uploadedOffset * uploadBonus;
+            double bonusDownloaded = downloadedOffset * downloadDiscount;
+
+            // 调用Mapper更新数据库
+            userMapper.updateUserUploadDownload(userId, bonusUploaded, bonusDownloaded);
+            torrentMapper.updateTorrentUploadDownload(torrentId, uploadedOffset, downloadedOffset);
+
+        }
     }
 }
\ No newline at end of file
diff --git a/src/main/resources/mapper/AuditRecordMapper.xml b/src/main/resources/mapper/AuditRecordMapper.xml
new file mode 100644
index 0000000..aa6b018
--- /dev/null
+++ b/src/main/resources/mapper/AuditRecordMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.myproject.mapper.AuditRecordMapper">
+
+</mapper>
diff --git a/src/main/resources/mapper/BannedUserMapper.xml b/src/main/resources/mapper/BannedUserMapper.xml
new file mode 100644
index 0000000..fbdb038
--- /dev/null
+++ b/src/main/resources/mapper/BannedUserMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.myproject.mapper.BannedUserMapper">
+
+</mapper>
diff --git a/src/main/resources/mapper/SuspiciousUserMapper.xml b/src/main/resources/mapper/SuspiciousUserMapper.xml
new file mode 100644
index 0000000..27851b2
--- /dev/null
+++ b/src/main/resources/mapper/SuspiciousUserMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.myproject.mapper.SuspiciousUserMapper">
+
+</mapper>
diff --git a/src/main/resources/mapper/TorrentMapper.xml b/src/main/resources/mapper/TorrentMapper.xml
index d5f018e..8e5419b 100644
--- a/src/main/resources/mapper/TorrentMapper.xml
+++ b/src/main/resources/mapper/TorrentMapper.xml
@@ -99,6 +99,11 @@
         DELETE FROM favorite
         WHERE seed_id = #{seedId} AND user_id = #{userId}
     </delete>
-
+    <select id="selectMyFavorite" resultType="com.example.myproject.entity.TorrentEntity">
+        SELECT t.*
+        FROM torrent t
+        JOIN favorite f ON t.id = f.seed_id
+        WHERE f.user_id = #{userId}
+    </select>
 
 </mapper>
\ No newline at end of file
diff --git a/target/classes/com/example/myproject/MyProjectApplication.class b/target/classes/com/example/myproject/MyProjectApplication.class
index 1ebd349..93fb1c1 100644
--- a/target/classes/com/example/myproject/MyProjectApplication.class
+++ b/target/classes/com/example/myproject/MyProjectApplication.class
Binary files differ
diff --git a/target/classes/com/example/myproject/config/TrackerConfig.class b/target/classes/com/example/myproject/config/TrackerConfig.class
index 0c32d4e..774aa27 100644
--- a/target/classes/com/example/myproject/config/TrackerConfig.class
+++ b/target/classes/com/example/myproject/config/TrackerConfig.class
Binary files differ
diff --git a/target/classes/com/example/myproject/controller/PromotionController.class b/target/classes/com/example/myproject/controller/PromotionController.class
new file mode 100644
index 0000000..75a63cc
--- /dev/null
+++ b/target/classes/com/example/myproject/controller/PromotionController.class
Binary files differ
diff --git a/target/classes/com/example/myproject/controller/TorrentController.class b/target/classes/com/example/myproject/controller/TorrentController.class
index e4ce75e..654356b 100644
--- a/target/classes/com/example/myproject/controller/TorrentController.class
+++ b/target/classes/com/example/myproject/controller/TorrentController.class
Binary files differ
diff --git a/target/classes/com/example/myproject/controller/TrackerController.class b/target/classes/com/example/myproject/controller/TrackerController.class
index bbf5851..d1690b5 100644
--- a/target/classes/com/example/myproject/controller/TrackerController.class
+++ b/target/classes/com/example/myproject/controller/TrackerController.class
Binary files differ
diff --git a/target/classes/com/example/myproject/dto/TrackerProtocol.class b/target/classes/com/example/myproject/dto/TrackerProtocol.class
index 90e9fb4..af14ea5 100644
--- a/target/classes/com/example/myproject/dto/TrackerProtocol.class
+++ b/target/classes/com/example/myproject/dto/TrackerProtocol.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/AuditRecord.class b/target/classes/com/example/myproject/entity/AuditRecord.class
new file mode 100644
index 0000000..3699c9d
--- /dev/null
+++ b/target/classes/com/example/myproject/entity/AuditRecord.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/BannedUser.class b/target/classes/com/example/myproject/entity/BannedUser.class
new file mode 100644
index 0000000..8ca9203
--- /dev/null
+++ b/target/classes/com/example/myproject/entity/BannedUser.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/SuspiciousUser.class b/target/classes/com/example/myproject/entity/SuspiciousUser.class
new file mode 100644
index 0000000..3407b75
--- /dev/null
+++ b/target/classes/com/example/myproject/entity/SuspiciousUser.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/TorrentEntity.class b/target/classes/com/example/myproject/entity/TorrentEntity.class
index a1326b6..44b924b 100644
--- a/target/classes/com/example/myproject/entity/TorrentEntity.class
+++ b/target/classes/com/example/myproject/entity/TorrentEntity.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/TorrentReport$TorrentReportBuilder.class b/target/classes/com/example/myproject/entity/TorrentReport$TorrentReportBuilder.class
index fc8919a..17b87a3 100644
--- a/target/classes/com/example/myproject/entity/TorrentReport$TorrentReportBuilder.class
+++ b/target/classes/com/example/myproject/entity/TorrentReport$TorrentReportBuilder.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/TorrentReport.class b/target/classes/com/example/myproject/entity/TorrentReport.class
index 20c882e..260b34e 100644
--- a/target/classes/com/example/myproject/entity/TorrentReport.class
+++ b/target/classes/com/example/myproject/entity/TorrentReport.class
Binary files differ
diff --git a/target/classes/com/example/myproject/entity/User.class b/target/classes/com/example/myproject/entity/User.class
index d465c51..d3d50a4 100644
--- a/target/classes/com/example/myproject/entity/User.class
+++ b/target/classes/com/example/myproject/entity/User.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/AuditRecordMapper.class b/target/classes/com/example/myproject/mapper/AuditRecordMapper.class
new file mode 100644
index 0000000..231ffe6
--- /dev/null
+++ b/target/classes/com/example/myproject/mapper/AuditRecordMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/BannedUserMapper.class b/target/classes/com/example/myproject/mapper/BannedUserMapper.class
new file mode 100644
index 0000000..da69e74
--- /dev/null
+++ b/target/classes/com/example/myproject/mapper/BannedUserMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/PromotionMapper.class b/target/classes/com/example/myproject/mapper/PromotionMapper.class
index 074c856..909cbb6 100644
--- a/target/classes/com/example/myproject/mapper/PromotionMapper.class
+++ b/target/classes/com/example/myproject/mapper/PromotionMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/SuspiciousUserMapper.class b/target/classes/com/example/myproject/mapper/SuspiciousUserMapper.class
new file mode 100644
index 0000000..ddc85da
--- /dev/null
+++ b/target/classes/com/example/myproject/mapper/SuspiciousUserMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/TorrentMapper.class b/target/classes/com/example/myproject/mapper/TorrentMapper.class
index 5080dfd..56fb640 100644
--- a/target/classes/com/example/myproject/mapper/TorrentMapper.class
+++ b/target/classes/com/example/myproject/mapper/TorrentMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/mapper/UserMapper.class b/target/classes/com/example/myproject/mapper/UserMapper.class
index 74cbed4..d9c95c8 100644
--- a/target/classes/com/example/myproject/mapper/UserMapper.class
+++ b/target/classes/com/example/myproject/mapper/UserMapper.class
Binary files differ
diff --git a/target/classes/com/example/myproject/repository/TorrentReportRepository.class b/target/classes/com/example/myproject/repository/TorrentReportRepository.class
index 77fc905..8abadf5 100644
--- a/target/classes/com/example/myproject/repository/TorrentReportRepository.class
+++ b/target/classes/com/example/myproject/repository/TorrentReportRepository.class
Binary files differ
diff --git a/target/classes/com/example/myproject/scheduler/TorrentAuditTask.class b/target/classes/com/example/myproject/scheduler/TorrentAuditTask.class
new file mode 100644
index 0000000..88e2a9d
--- /dev/null
+++ b/target/classes/com/example/myproject/scheduler/TorrentAuditTask.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/AuditService.class b/target/classes/com/example/myproject/service/AuditService.class
new file mode 100644
index 0000000..29cf4b1
--- /dev/null
+++ b/target/classes/com/example/myproject/service/AuditService.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/DynamicService.class b/target/classes/com/example/myproject/service/DynamicService.class
index 5170c7b..18039bf 100644
--- a/target/classes/com/example/myproject/service/DynamicService.class
+++ b/target/classes/com/example/myproject/service/DynamicService.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/PostService.class b/target/classes/com/example/myproject/service/PostService.class
index 20f263c..706f72d 100644
--- a/target/classes/com/example/myproject/service/PostService.class
+++ b/target/classes/com/example/myproject/service/PostService.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/PromotionService.class b/target/classes/com/example/myproject/service/PromotionService.class
index 6f0963b..f5d48f0 100644
--- a/target/classes/com/example/myproject/service/PromotionService.class
+++ b/target/classes/com/example/myproject/service/PromotionService.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/TorrentService.class b/target/classes/com/example/myproject/service/TorrentService.class
index bac5d31..9fdf389 100644
--- a/target/classes/com/example/myproject/service/TorrentService.class
+++ b/target/classes/com/example/myproject/service/TorrentService.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/UserService.class b/target/classes/com/example/myproject/service/UserService.class
index 3f02c8e..de99a39 100644
--- a/target/classes/com/example/myproject/service/UserService.class
+++ b/target/classes/com/example/myproject/service/UserService.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/serviceImpl/PromotionServiceImpl.class b/target/classes/com/example/myproject/service/serviceImpl/PromotionServiceImpl.class
index bee3056..83cf11d 100644
--- a/target/classes/com/example/myproject/service/serviceImpl/PromotionServiceImpl.class
+++ b/target/classes/com/example/myproject/service/serviceImpl/PromotionServiceImpl.class
Binary files differ
diff --git a/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class b/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class
index 2341ad1..63669c9 100644
--- a/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class
+++ b/target/classes/com/example/myproject/service/serviceImpl/TorrentServiceImpl.class
Binary files differ
diff --git a/target/classes/mapper/AuditRecordMapper.xml b/target/classes/mapper/AuditRecordMapper.xml
new file mode 100644
index 0000000..aa6b018
--- /dev/null
+++ b/target/classes/mapper/AuditRecordMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.myproject.mapper.AuditRecordMapper">
+
+</mapper>
diff --git a/target/classes/mapper/BannedUserMapper.xml b/target/classes/mapper/BannedUserMapper.xml
new file mode 100644
index 0000000..fbdb038
--- /dev/null
+++ b/target/classes/mapper/BannedUserMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.myproject.mapper.BannedUserMapper">
+
+</mapper>
diff --git a/target/classes/mapper/SuspiciousUserMapper.xml b/target/classes/mapper/SuspiciousUserMapper.xml
new file mode 100644
index 0000000..27851b2
--- /dev/null
+++ b/target/classes/mapper/SuspiciousUserMapper.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.example.myproject.mapper.SuspiciousUserMapper">
+
+</mapper>
diff --git a/target/classes/mapper/TorrentMapper.xml b/target/classes/mapper/TorrentMapper.xml
index d5f018e..8e5419b 100644
--- a/target/classes/mapper/TorrentMapper.xml
+++ b/target/classes/mapper/TorrentMapper.xml
@@ -99,6 +99,11 @@
         DELETE FROM favorite
         WHERE seed_id = #{seedId} AND user_id = #{userId}
     </delete>
-
+    <select id="selectMyFavorite" resultType="com.example.myproject.entity.TorrentEntity">
+        SELECT t.*
+        FROM torrent t
+        JOIN favorite f ON t.id = f.seed_id
+        WHERE f.user_id = #{userId}
+    </select>
 
 </mapper>
\ No newline at end of file
diff --git a/uploads/torrents/1749218819331.jpg b/uploads/torrents/1749218819331.jpg
new file mode 100644
index 0000000..4ba04de
--- /dev/null
+++ b/uploads/torrents/1749218819331.jpg
Binary files differ
diff --git a/uploads/torrents/1749219849324.jpg b/uploads/torrents/1749219849324.jpg
new file mode 100644
index 0000000..4ba04de
--- /dev/null
+++ b/uploads/torrents/1749219849324.jpg
Binary files differ
diff --git a/uploads/torrents/1749219884508.jpg b/uploads/torrents/1749219884508.jpg
new file mode 100644
index 0000000..4ba04de
--- /dev/null
+++ b/uploads/torrents/1749219884508.jpg
Binary files differ
diff --git a/uploads/torrents/1749220294853.jpg b/uploads/torrents/1749220294853.jpg
new file mode 100644
index 0000000..4ba04de
--- /dev/null
+++ b/uploads/torrents/1749220294853.jpg
Binary files differ