Merge "Merge branch 'master' of https://gerrit.lilingkun.com/G12Project"
diff --git a/Dockerfile b/Dockerfile
index 2d4db7a..b646295 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,41 +1,14 @@
-# 构建阶段
-FROM maven:3.9.6-amazoncorretto-17 AS build
-
-# 设置工作目录
-WORKDIR /build
-
-# 复制 pom.xml
-COPY pom.xml .
-
-# 下载依赖
-RUN mvn dependency:go-offline
-
-# 复制源代码
-COPY src ./src
-
-# 构建项目
-RUN mvn clean package -DskipTests
-
-# 运行阶段
-FROM amazoncorretto:17 AS final
+# 使用官方 OpenJDK 镜像
+FROM eclipse-temurin:17-jdk-jammy
 
 # 设置工作目录
 WORKDIR /team12
 
-# 设置时区
-ENV TZ=Asia/Shanghai
-RUN yum update -y && \
-    yum install -y tzdata && \
-    ln -fs /usr/share/zoneinfo/$TZ /etc/localtime && \
-    echo $TZ > /etc/timezone && \
-    yum clean all && \
-    rm -rf /var/cache/yum
+# 复制 JAR 文件到容器
+COPY target/*.jar team12.jar
 
-# 从构建阶段复制构建好的 jar 文件
-COPY --from=build /build/target/*.jar team12.jar
-
-# 暴露端口
+# 暴露端口(与 application.yml/server.port 一致)
 EXPOSE 8080
 
-# 启动命令
+# 启动应用
 ENTRYPOINT ["java", "-jar", "team12.jar"]
\ No newline at end of file
diff --git a/src/main/java/com/pt/BackendApplication.java b/src/main/java/com/pt/BackendApplication.java
index 28bc5cb..5f21e15 100644
--- a/src/main/java/com/pt/BackendApplication.java
+++ b/src/main/java/com/pt/BackendApplication.java
@@ -2,8 +2,10 @@
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableScheduling;
 
 @SpringBootApplication
+@EnableScheduling
 public class BackendApplication {
 
     public static void main(String[] args) {
diff --git a/src/main/java/com/pt/constant/Constants.java b/src/main/java/com/pt/constant/Constants.java
index d277ea2..e8cecd3 100644
--- a/src/main/java/com/pt/constant/Constants.java
+++ b/src/main/java/com/pt/constant/Constants.java
@@ -23,4 +23,20 @@
             return value;
         }
     }
+
+    public enum UserLevel {
+        NEWBIE(0),
+        FRESH(1),
+        SENIOR(2),
+        MASTER(3);
+
+        private final int value;
+        UserLevel(int value) {
+            this.value = value;
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
 }
diff --git a/src/main/java/com/pt/controller/AdminController.java b/src/main/java/com/pt/controller/AdminController.java
index 22e2b86..8af5b56 100644
--- a/src/main/java/com/pt/controller/AdminController.java
+++ b/src/main/java/com/pt/controller/AdminController.java
@@ -6,11 +6,7 @@
 import com.pt.service.AdminService;
 import com.pt.utils.JWTUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.http.ResponseEntity;
 
 import java.util.HashMap;
@@ -25,18 +21,18 @@
     private AdminService adminService;
 
     @PostMapping("/login")
-    public ResponseEntity<?> loginAdmin(@RequestParam("username") String username,
-                                        @RequestParam("password") String password) {
+    public ResponseEntity<?> loginAdmin(@RequestBody Map<String, String> request) {
+        String username = request.get("username");
+        String password = request.get("password");
+
         Map<String, Object> ans = new HashMap<>();
         Admin admin = adminService.findByUsernameAndPassword(username, password);
         if (admin != null) {
-            ans.put("result", "Login successful");
-            ans.put("data", Map.of(
-                    "token", JWTUtils.generateToken(username, Constants.UserRole.ADMIN, (int)1.2e8)
-            ));
+            ans.put("message", "Login successful");
+            ans.put("data", JWTUtils.generateToken(username, Constants.UserRole.ADMIN, Constants.DEFAULT_EXPIRE_TIME));
             return ResponseEntity.ok().body(ans);
         } else {
-            ans.put("result", "Invalid username or password");
+            ans.put("message", "Invalid username or password");
             return ResponseEntity.badRequest().body(ans);
         }
     }
diff --git a/src/main/java/com/pt/controller/CommentController.java b/src/main/java/com/pt/controller/CommentController.java
index 17dabb3..00e091d 100644
--- a/src/main/java/com/pt/controller/CommentController.java
+++ b/src/main/java/com/pt/controller/CommentController.java
@@ -23,55 +23,59 @@
     @PostMapping("/add")
     public ResponseEntity<?> addComment(
             @RequestHeader("token") String token,
-            @RequestParam("content") String content,
-            @RequestParam("username") String username,
-            @RequestParam("postId") int postId
+            @RequestBody Map<String, String> request
     ) {
+        String content = request.get("content");
+        String username = request.get("username");
+        int postId = Integer.parseInt(request.get("postId"));
+
         Map<String, Object> ans = new HashMap<>();
 
         if (!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         commentService.addComment(content, username, postId);
-        ans.put("result", "Comment added successfully");
+        ans.put("message", "Comment added successfully");
         return ResponseEntity.ok(ans);
     }
 
     @DeleteMapping("/delete")
     public ResponseEntity<?> deleteComment(
             @RequestHeader("token") String token,
-            @RequestParam("commentId") int commentId,
-            @RequestParam("username") String username
+            @RequestBody Map<String, String> request
     ) {
+        String username = request.get("username");
+        int commentId = Integer.parseInt(request.get("commentId"));
+
         Map<String, Object> ans = new HashMap<>();
 
         if (!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         commentService.deleteComment(commentId);
-        ans.put("result", "Comment deleted successfully");
+        ans.put("message", "Comment deleted successfully");
         return ResponseEntity.ok(ans);
     }
 
     @GetMapping("/get")
     public ResponseEntity<?> getComments(
             @RequestHeader("token") String token,
-            @RequestParam("postId") int postId,
-            @RequestParam("username") String username
+            @RequestParam("username") String username,
+            @RequestParam("postId") int postId
     ) {
         Map<String, Object> ans = new HashMap<>();
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         List<Comment> comments = commentService.getCommentsByPostId(postId);
-        ans.put("result", "Comments retrieved successfully");
+        ans.put("message", "Comments retrieved successfully");
         ans.put("data", Map.of(
            "comments", comments
         ));
diff --git a/src/main/java/com/pt/controller/PostController.java b/src/main/java/com/pt/controller/PostController.java
index 0ab86ed..3723dbd 100644
--- a/src/main/java/com/pt/controller/PostController.java
+++ b/src/main/java/com/pt/controller/PostController.java
@@ -31,10 +31,11 @@
     @PostMapping("/create")
     public ResponseEntity<?> createPost(
             @RequestHeader("token") String token,
-            @RequestParam("title") String title,
-            @RequestParam("content") String content,
-            @RequestParam("author") String author
+            @RequestBody Map<String, String> request
     ) {
+        String title = request.get("title");
+        String content = request.get("content");
+        String author = request.get("author");
 
         Map<String, Object> ans = new HashMap<>();
 
@@ -50,7 +51,7 @@
         }
 
         postService.createPost(title, content, author);
-        ans.put("result", "Post created successfully");
+        ans.put("message", "Post created successfully");
         return ResponseEntity.ok(ans);
     }
 
@@ -70,11 +71,10 @@
             @RequestParam(value = "author", required = false) String author,
             @RequestParam(value = "date", required = false) String date
     ) {
-
         Map<String, Object> ans = new HashMap<>();
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -91,7 +91,7 @@
         if(date != null){
             posts.removeIf(post -> !post.getPublishDate().toString().equals(date));
         }
-        ans.put("result", "Post retrieved successfully");
+        ans.put("message", "Post retrieved successfully");
         ans.put("data", Map.of(
                 "post", posts
         ));
@@ -108,25 +108,26 @@
     @DeleteMapping("/delete")
     public ResponseEntity<?> deletePost(
             @RequestHeader("token") String token,
-            @RequestParam("username") String username,
-            @RequestParam("pid") int pid
+            @RequestBody Map<String, String> request
     ) {
+        String username = request.get("username");
+        int pid = Integer.parseInt(request.get("pid"));
 
         Map<String, Object> ans = new HashMap<>();
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN)){
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         Post post = postService.findPostById(pid);
         if (post == null) {
-            ans.put("result", "Post not found");
+            ans.put("message", "Post not found");
             return ResponseEntity.badRequest().body(ans);
         }
 
         postService.deletePost(post);
-        ans.put("result", "Post deleted successfully");
+        ans.put("message", "Post deleted successfully");
         return ResponseEntity.ok(ans);
     }
 }
diff --git a/src/main/java/com/pt/controller/ResourceController.java b/src/main/java/com/pt/controller/ResourceController.java
index 411e7bc..306851a 100644
--- a/src/main/java/com/pt/controller/ResourceController.java
+++ b/src/main/java/com/pt/controller/ResourceController.java
@@ -7,6 +7,7 @@
 import com.pt.service.UserService;
 import com.pt.utils.JWTUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
@@ -24,15 +25,18 @@
 
     @Autowired
     private ResourceService resourceService;
+
+    @Autowired
     private UserService userService;
 
     @GetMapping("/list/all")
     public ResponseEntity<?> getAllResources(@RequestHeader("token") String token,
                                              @RequestParam("username") String username) {
+
         Map<String, Object> ans = new HashMap<>();
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -46,10 +50,11 @@
     @GetMapping("/list/user")
     public ResponseEntity<?> getUserResources(@RequestHeader("token") String token,
                                               @RequestParam("username") String username) {
+
         Map<String, Object> ans = new HashMap<>();
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -72,13 +77,13 @@
         Map<String, Object> ans = new HashMap<>();
 
         if (!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         User user = userService.findByUsername(username);
         if (user == null || user.getLevel() < 2) {
-            ans.put("result", "Insufficient permissions to publish resources");
+            ans.put("message", "Insufficient permissions to publish resources");
             return ResponseEntity.status(403).body(ans);
         }
 
@@ -86,11 +91,11 @@
             // 传入种子文件字节,同时传入资源其他信息
             resourceService.publishResource(name, description, username, size, torrentFile.getBytes());
         } catch (Exception e) {
-            ans.put("result", "Failed to publish resource: " + e.getMessage());
+            ans.put("message", "Failed to publish resource: " + e.getMessage());
             return ResponseEntity.status(500).body(ans);
         }
 
-        ans.put("result", "Resource published successfully");
+        ans.put("message", "Resource published successfully");
         return ResponseEntity.ok(ans);
     }
 
@@ -104,7 +109,7 @@
 
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -122,10 +127,34 @@
 
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
+        User user = userService.findByUsername(username);
+        if (user == null) {
+            ans.put("message", "User not found");
+            return ResponseEntity.status(404).body(ans);
+        }
+
+        final double MIN_SHARE_RATIO_THRESHOLD = 0.5; // 最低共享率要求
+        final long DOWNLOAD_EXEMPTION_BYTES = 20L * 1024L * 1024L * 1024L; // 20GB下载量豁免
+
+        long uploaded = user.getUploaded();
+        long downloaded = user.getDownloaded();
+
+        // 如果用户的下载量超过豁免值,则检查其共享率
+        if (downloaded > DOWNLOAD_EXEMPTION_BYTES) {
+            // 防止除以零
+            double shareRatio = (downloaded == 0) ? Double.MAX_VALUE : (double) uploaded / downloaded;
+            if (shareRatio < MIN_SHARE_RATIO_THRESHOLD) {
+                ans.put("message", "Share ratio is too low. Please seed more to improve your ratio before downloading new resources.");
+                ans.put("current_share_ratio", String.format("%.2f", shareRatio));
+                ans.put("required_share_ratio", MIN_SHARE_RATIO_THRESHOLD);
+                return ResponseEntity.status(403).body(ans); // 403 Forbidden
+            }
+        }
+
         Resource resource = resourceService.getResourceById(resourceId);
         byte[] file = resourceService.getTorrentFileByResource(resource, username);
         if (file == null) {
@@ -145,7 +174,7 @@
         Map<String, Object> ans = new HashMap<>();
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)){
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -164,18 +193,18 @@
         Resource resource = resourceService.getResourceById(resourceId);
 
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN) || resource == null || !resource.getAuthor().equals(username)) {
-            ans.put("result", "Invalid token or insufficient permissions");
+            ans.put("message", "Invalid token or insufficient permissions");
             return ResponseEntity.badRequest().body(ans);
         }
 
         try {
             resourceService.deleteResource(resourceId);
         } catch (Exception e) {
-            ans.put("result", "Failed to delete resource: " + e.getMessage());
+            ans.put("message", "Failed to delete resource: " + e.getMessage());
             return ResponseEntity.status(500).body(ans);
         }
 
-        ans.put("result", "Resource deleted successfully");
+        ans.put("message", "Resource deleted successfully");
         return ResponseEntity.ok(ans);
     }
 
diff --git a/src/main/java/com/pt/controller/TrackerController.java b/src/main/java/com/pt/controller/TrackerController.java
index 1e0302d..edae09f 100644
--- a/src/main/java/com/pt/controller/TrackerController.java
+++ b/src/main/java/com/pt/controller/TrackerController.java
@@ -10,6 +10,8 @@
 import java.util.Map;
 
 @RestController
+@CrossOrigin(origins = "*")
+@RequestMapping("/api/tracker")
 public class TrackerController {
 
     @Autowired
diff --git a/src/main/java/com/pt/controller/UserController.java b/src/main/java/com/pt/controller/UserController.java
index 7603f9d..7222f36 100644
--- a/src/main/java/com/pt/controller/UserController.java
+++ b/src/main/java/com/pt/controller/UserController.java
@@ -2,6 +2,7 @@
 
 import com.pt.constant.Constants;
 import com.pt.entity.User;
+import com.pt.service.InvitedCodeService;
 import com.pt.utils.JWTUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
@@ -18,6 +19,7 @@
 
     @Autowired
     private UserService userService;
+    private InvitedCodeService invitedCodeService;
 
     @PostMapping("/register")
     public ResponseEntity<?> registerUser(@RequestBody Map<String, String> request) {
@@ -35,6 +37,17 @@
         } else {
             User newUser = new User();
 
+            if(request.get("invitedCode") != null) {
+                String invitedCode = request.get("invitedCode");
+                if (!invitedCodeService.isCodeValid(invitedCode)) {
+                    return ResponseEntity.badRequest().body("Invalid invited code");
+                }
+                else {
+                    newUser.setLevel(Constants.UserLevel.FRESH.getValue());
+                    newUser.setPoints(300);
+                }
+            }
+
             String uid = String.valueOf(System.currentTimeMillis());
             newUser.setUid(uid);
             newUser.setUsername(username);
@@ -43,7 +56,7 @@
             userService.save(newUser);
 
             Map<String, Object> ans = new HashMap<>();
-            ans.put("result", "User registered successfully");
+            ans.put("message", "User registered successfully");
             ans.put("data", newUser);
 
             return ResponseEntity.ok().body(ans);
@@ -51,9 +64,9 @@
     }
 
     @PostMapping("/login")
-    public ResponseEntity<?> loginUser(@RequestParam("username") String username,
-                                       @RequestParam("password") String password) {
-
+    public ResponseEntity<?> loginUser(@RequestBody Map<String, String> request) {
+        String username = request.get("username");
+        String password = request.get("password");
 
         if (username == null || password == null) {
             return ResponseEntity.badRequest().body("Missing username or password");
@@ -63,22 +76,24 @@
         Map<String, Object> ans = new HashMap<>();
         if (user != null) {
             String token = JWTUtils.generateToken(username, Constants.UserRole.USER, Constants.DEFAULT_EXPIRE_TIME);
-            ans.put("result", "Login successful");
+            ans.put("message", "Login successful");
             ans.put("data", token);
             return ResponseEntity.ok().body(ans);
         } else {
-            ans.put("result", "Invalid username or password");
+            ans.put("message", "Invalid username or password");
             return ResponseEntity.badRequest().body(ans);
         }
     }
 
     @PostMapping("/update/username")
     public ResponseEntity<?> updateUsername(@RequestHeader("token") String token,
-                                            @RequestParam("username") String oldUsername,
-                                            @RequestParam("newUsername") String newUsername) {
+                                            @RequestBody Map<String, String> request) {
+        String oldUsername = request.get("username");
+        String newUsername = request.get("newUsername");
+
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, oldUsername, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -86,21 +101,24 @@
         if (user != null) {
             user.setUsername(newUsername);
             userService.save(user);
-            ans.put("result", "Username updated successfully");
+            ans.put("message", "Username updated successfully");
             return ResponseEntity.ok(ans);
         } else {
-            ans.put("result", "User not found");
+            ans.put("message", "User not found");
             return ResponseEntity.badRequest().body(ans);
         }
     }
 
     @PostMapping("/update/password")
     public ResponseEntity<?> updatePassword(@RequestHeader("token") String token,
-                                            @RequestParam("username") String username,
-                                            @RequestParam("newPassword") String newPassword) {
+                                            @RequestBody Map<String, String> request
+                                            ) {
+        String username = request.get("username");
+        String newPassword = request.get("newPassword");
+
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -108,22 +126,23 @@
         if (user != null) {
             user.setPassword(newPassword);
             userService.save(user);
-            ans.put("result", "Password updated successfully");
+            ans.put("message", "Password updated successfully");
             return ResponseEntity.ok(ans);
         } else {
-            ans.put("result", "Invalid username or password");
+            ans.put("message", "Invalid username or password");
             return ResponseEntity.badRequest().body(ans);
         }
     }
 
     @PostMapping("/update/email")
     public ResponseEntity<?> updateEmail(@RequestHeader("token") String token,
-                                         @RequestParam("username") String username,
-                                         @RequestParam("newEmail") String newEmail) {
+                                         @RequestBody Map<String, String> request) {
+        String username = request.get("username");
+        String newEmail = request.get("newEmail");
 
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
@@ -131,45 +150,47 @@
         if (user != null) {
             user.setEmail(newEmail);
             userService.save(user);
-            ans.put("result", "Email updated successfully");
+            ans.put("message", "Email updated successfully");
             return ResponseEntity.ok(ans);
         } else {
-            ans.put("result", "User not found");
+            ans.put("message", "User not found");
             return ResponseEntity.badRequest().body(ans);
         }
     }
 
     @DeleteMapping("/delete")
     public ResponseEntity<?> deleteUser(@RequestHeader("token") String token,
-                                        @RequestParam("username") String username,
-                                        @RequestParam("targetUsername") String targetUsername
-    ) {
+                                        @RequestBody Map<String, String> request) {
+        String username = request.get("username");
+        String targetUsername = request.get("targetUsername");
+
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         User user = userService.findByUsername(targetUsername);
         if (user != null) {
             userService.deleteById(user.getUid());
-            ans.put("result", "User deleted successfully");
+            ans.put("message", "User deleted successfully");
             return ResponseEntity.ok(ans);
         } else {
-            ans.put("result", "User not found");
+            ans.put("message", "User not found");
             return ResponseEntity.badRequest().body(ans);
         }
     }
 
     @GetMapping("/list")
     public ResponseEntity<?> listUsers(@RequestHeader("token") String token,
-                                       @RequestParam("username") String username) {
+                                       @RequestBody Map<String, String> request) {
+        String username = request.get("username");
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.ADMIN)) {
             return ResponseEntity.badRequest().body("Invalid token");
         }
 
         Map<String, Object> ans = new HashMap<>();
-        ans.put("result", "User list retrieved successfully");
+        ans.put("message", "User list retrieved successfully");
         ans.put("data", Map.of(
                 "amount", userService.listAll().size(),
                 "users", userService.listAll()
@@ -180,19 +201,20 @@
     @GetMapping("/get/info")
     public ResponseEntity<?> getUserInfo(@RequestHeader("token") String token,
                                          @RequestParam("username") String username) {
+
         Map<String, Object> ans = new HashMap<>();
         if(!JWTUtils.checkToken(token, username, Constants.UserRole.USER)) {
-            ans.put("result", "Invalid token");
+            ans.put("message", "Invalid token");
             return ResponseEntity.badRequest().body(ans);
         }
 
         User user = userService.findByUsername(username);
         if (user != null) {
-            ans.put("result", "User info retrieved successfully");
+            ans.put("message", "User info retrieved successfully");
             ans.put("data", user);
             return ResponseEntity.ok(ans);
         } else {
-            ans.put("result", "User not found");
+            ans.put("message", "User not found");
             return ResponseEntity.badRequest().body(ans);
         }
     }
diff --git a/src/main/java/com/pt/entity/InvitedCode.java b/src/main/java/com/pt/entity/InvitedCode.java
new file mode 100644
index 0000000..33a1cf8
--- /dev/null
+++ b/src/main/java/com/pt/entity/InvitedCode.java
@@ -0,0 +1,35 @@
+package com.pt.entity;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+
+@Entity
+public class InvitedCode {
+
+    @Id
+    private String code;
+
+    private String owner;
+
+    public InvitedCode() {
+    }
+
+    public InvitedCode(String code, String owner) {
+        this.code = code;
+        this.owner = owner;
+    }
+
+    public String getCode() {
+        return code;
+    }
+    public void setCode(String code) {
+        this.code = code;
+    }
+    public String getOwner() {
+        return owner;
+    }
+    public void setOwner(String owner) {
+        this.owner = owner;
+    }
+
+}
diff --git a/src/main/java/com/pt/entity/User.java b/src/main/java/com/pt/entity/User.java
index 9caab3e..aef2cd3 100644
--- a/src/main/java/com/pt/entity/User.java
+++ b/src/main/java/com/pt/entity/User.java
@@ -14,6 +14,8 @@
     private String email;
     private int level;
     private int points;
+    private long uploaded;
+    private long downloaded;
 
     public User() {
     }
@@ -61,6 +63,22 @@
         this.points = points;
     }
 
+    public long getUploaded() {
+        return uploaded;
+    }
+
+    public void setUploaded(long uploaded) {
+        this.uploaded = uploaded;
+    }
+
+    public long getDownloaded() {
+        return downloaded;
+    }
+
+    public void setDownloaded(long downloaded) {
+        this.downloaded = downloaded;
+    }
+
     @Override
     public String toString() {
         return "{" +
@@ -70,6 +88,8 @@
                 ",\nemail:'" + email + '\'' +
                 ",\nlevel:" + level +
                 ",\npoints:" + points +
+                ",\nuploaded:" + uploaded +
+                ",\ndownloaded:" + downloaded +
                 '}';
     }
 }
diff --git a/src/main/java/com/pt/repository/InvitedCoedRepository.java b/src/main/java/com/pt/repository/InvitedCoedRepository.java
new file mode 100644
index 0000000..5d7a366
--- /dev/null
+++ b/src/main/java/com/pt/repository/InvitedCoedRepository.java
@@ -0,0 +1,15 @@
+package com.pt.repository;
+
+import com.pt.entity.InvitedCode;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+import java.util.List;
+
+public interface InvitedCoedRepository extends JpaRepository<InvitedCode, String> {
+
+    // Method to find an InvitedCode by its code
+    InvitedCode findByCode(String code);
+
+    // Method to find all InvitedCodes by owner
+    List<InvitedCode> findByOwner(String owner);
+}
diff --git a/src/main/java/com/pt/scheduler/UserLevelUpdateScheduler.java b/src/main/java/com/pt/scheduler/UserLevelUpdateScheduler.java
new file mode 100644
index 0000000..64aa6ca
--- /dev/null
+++ b/src/main/java/com/pt/scheduler/UserLevelUpdateScheduler.java
@@ -0,0 +1,36 @@
+package com.pt.scheduler;
+
+import com.pt.service.UserService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * 定时任务,用于定期更新用户的等级。
+ */
+@Component
+public class UserLevelUpdateScheduler {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserLevelUpdateScheduler.class);
+
+    @Autowired
+    private UserService userService;
+
+    /**
+     * 使用CRON表达式定义任务执行时间。
+     * "0 0 * * * ?" 表示在每个小时的整点(例如 01:00, 02:00)执行。
+     * 该任务会调用服务来更新所有用户的等级。
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    public void scheduleUserLevelUpdate() {
+        logger.info("开始执行定时任务:更新所有用户等级...");
+        try {
+            userService.updateAllUsersLevel();
+            logger.info("定时任务完成:所有用户等级已根据最新数据检查并更新。");
+        } catch (Exception e) {
+            logger.error("执行用户等级更新定时任务时发生错误", e);
+        }
+    }
+} 
\ No newline at end of file
diff --git a/src/main/java/com/pt/service/InvitedCodeService.java b/src/main/java/com/pt/service/InvitedCodeService.java
new file mode 100644
index 0000000..cd73452
--- /dev/null
+++ b/src/main/java/com/pt/service/InvitedCodeService.java
@@ -0,0 +1,16 @@
+package com.pt.service;
+
+import com.pt.repository.InvitedCoedRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class InvitedCodeService {
+
+    @Autowired
+    private InvitedCoedRepository invitedCodeRepository;
+
+    public boolean isCodeValid(String code) {
+        return invitedCodeRepository.findByCode(code) != null;
+    }
+}
diff --git a/src/main/java/com/pt/service/UserService.java b/src/main/java/com/pt/service/UserService.java
index bdffeea..6c0a56f 100644
--- a/src/main/java/com/pt/service/UserService.java
+++ b/src/main/java/com/pt/service/UserService.java
@@ -48,4 +48,66 @@
     public List<User> listAll() {
         return userRepository.findAll();
     }
+
+    /**
+     * 根据用户的统计数据(上传量、下载量、积分)更新其等级。
+     * 该方法包含等级提升的规则,且只升不降。
+     * @param userId 要更新等级的用户的ID
+     */
+    public void updateUserLevel(String userId) {
+        User user = userRepository.findById(userId).orElse(null);
+        if (user == null) {
+            // 在实际应用中,这里可能需要记录日志或抛出异常
+            return;
+        }
+
+        long uploaded = user.getUploaded();
+        long downloaded = user.getDownloaded();
+        int points = user.getPoints();
+
+        // 定义数据大小常量
+        final long GB = 1024L * 1024L * 1024L;
+        final long TB = 1024L * GB;
+
+        // 计算分享率。如果下载量为0,分享率视为无限大(只要有上传)
+        double shareRatio = (downloaded == 0 && uploaded > 0) ? Double.MAX_VALUE :
+                            (downloaded == 0 && uploaded == 0) ? 0 : (double) uploaded / downloaded;
+
+        int newLevel = 1; // 默认为1级
+
+        // 等级规则(从高到低判断)
+        // 规则5: 大佬级
+        if (uploaded > 5 * TB && shareRatio > 2.0 && points > 10000) {
+            newLevel = 5;
+        }
+        // 规则4: 专家级
+        else if (uploaded > 1 * TB && shareRatio > 1.5 && points > 2000) {
+            newLevel = 4;
+        }
+        // 规则3: 熟练级
+        else if (uploaded > 200 * GB && shareRatio > 1.0 && points > 500) {
+            newLevel = 3;
+        }
+        // 规则2: 入门级 (获得发布权限)
+        else if (uploaded > 50 * GB && shareRatio > 0.5 && points > 100) {
+            newLevel = 2;
+        }
+
+        // 如果计算出的新等级高于当前等级,则更新用户等级
+        if (newLevel > user.getLevel()) {
+            user.setLevel(newLevel);
+            userRepository.save(user);
+        }
+    }
+
+    /**
+     * 批量更新所有用户的等级。
+     * 适合用于定时任务,定期刷新所有用户的等级。
+     */
+    public void updateAllUsersLevel() {
+        List<User> allUsers = userRepository.findAll();
+        for (User user : allUsers) {
+            updateUserLevel(user.getUid());
+        }
+    }
 }
diff --git a/src/main/java/com/pt/testResponse/TestController.java b/src/main/java/com/pt/testResponse/TestController.java
new file mode 100644
index 0000000..a0dbae9
--- /dev/null
+++ b/src/main/java/com/pt/testResponse/TestController.java
@@ -0,0 +1,15 @@
+package com.pt.testResponse;
+
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@CrossOrigin(origins = "*")
+public class TestController {
+
+    @GetMapping("/api/test")
+    public String testResponse() {
+        return "Hello, world!";
+    }
+}