tracker

Change-Id: I8f8ac81f9c4d7c7650cd64d2dade701dc6c11dce
diff --git a/src/main/java/com/ptp/ptplatform/config/WebConfig.java b/src/main/java/com/ptp/ptplatform/config/WebConfig.java
index d0fdb8e..bb81631 100644
--- a/src/main/java/com/ptp/ptplatform/config/WebConfig.java
+++ b/src/main/java/com/ptp/ptplatform/config/WebConfig.java
@@ -18,4 +18,4 @@
                 .allowCredentials(true);  // 是否允许携带凭证
 
     }
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/ptp/ptplatform/controller/InviteCodeController.java b/src/main/java/com/ptp/ptplatform/controller/InviteCodeController.java
index cf482c6..4a4e625 100644
--- a/src/main/java/com/ptp/ptplatform/controller/InviteCodeController.java
+++ b/src/main/java/com/ptp/ptplatform/controller/InviteCodeController.java
@@ -1,4 +1,58 @@
 package com.ptp.ptplatform.controller;
 
+
+import com.ptp.ptplatform.entity.INVITE_CODE;
+import com.ptp.ptplatform.entity.USER;
+import com.ptp.ptplatform.mapper.InviteCodeMapper;
+import com.ptp.ptplatform.mapper.UserMapper;
+import com.ptp.ptplatform.utils.JwtUtils;
+import com.ptp.ptplatform.utils.Result;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@RequestMapping("/invitecode")
 public class InviteCodeController {
+    //mapper和controller
+    @Resource
+    private InviteCodeMapper inviteCodeMapper;
+    @Autowired
+    private UserMapper userMapper;
+    @Autowired
+    private UserController userController;
+
+    //使用魔力值兑换邀请码
+    @PostMapping("/generate")
+    public Result generateInviteCode(HttpServletRequest request) {
+        USER user = userController.getUserInRequest(request);
+        System.out.println(user.getMagicPoints());
+        if (user.getMagicPoints() >= 10) {
+            user.generateInviteCode();
+            INVITE_CODE inviteCode = new INVITE_CODE(user.getUsername());
+
+            inviteCodeMapper.insertInviteCode(inviteCode);
+            userMapper.updateUser(user);
+
+            return Result.ok().data("inviteCode", inviteCode);
+
+        } else {
+            return Result.error(404).setMessage("兑换邀请码失败,魔力值不足。");
+        }
+
+    }
+
+    //用户获取持有的邀请码
+    @GetMapping("/userInviteCode")
+    public Result userInviteCode(HttpServletRequest request) {
+        USER user = userController.getUserInRequest(request);
+
+        List<INVITE_CODE> inviteCode = inviteCodeMapper.selectByUser(user.getUsername());
+        return Result.ok().data("inviteCode", inviteCode);
+    }
+
 }
diff --git a/src/main/java/com/ptp/ptplatform/controller/TorrentController.java b/src/main/java/com/ptp/ptplatform/controller/TorrentController.java
index 3c71ba1..436ecdd 100644
--- a/src/main/java/com/ptp/ptplatform/controller/TorrentController.java
+++ b/src/main/java/com/ptp/ptplatform/controller/TorrentController.java
@@ -1,121 +1,359 @@
-package com.ptp.ptplatform.controller;

-

-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

-import com.ptp.ptplatform.entity.TorrentComment;

-import com.ptp.ptplatform.entity.Torrent;

-import com.ptp.ptplatform.service.TorrentCommentService;

-import com.ptp.ptplatform.service.TorrentService;

-import com.ptp.ptplatform.utils.Result;

-import lombok.AllArgsConstructor;

-import org.springframework.web.bind.annotation.*;

-import com.baomidou.mybatisplus.core.metadata.IPage;

-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

-

-import java.time.LocalDateTime;

-import java.util.ArrayList;

-import java.util.HashMap;

-import java.util.List;

-import java.util.Map;

-

-@RestController

-@RequestMapping("/torrent")

-@AllArgsConstructor

-public class TorrentController {

-    private final TorrentService postService;

-    private final TorrentCommentService commentService;

-

-    // 创建帖子

-    @PostMapping

-    public Result createTorrent(@RequestBody Torrent torrent) {

-        postService.save(torrent);

-        return Result.ok().data("post", torrent);

-    }

-

-    // 列表分页

-    @GetMapping

-    public Result listPosts(@RequestParam(defaultValue = "1") int page,

-                            @RequestParam(defaultValue = "5") int size) {

-        IPage<Torrent> ipage = postService.page(

-                new Page<>(page, size),

-                new QueryWrapper<Torrent>().orderByDesc("create_time")

-        );

-        return Result.ok()

-                .data("records", ipage.getRecords())

-                .data("total", ipage.getTotal());

-    }

-

-    @GetMapping("/{Id}")

-    public Result getPost(@PathVariable int Id) {

-        Torrent torrent = postService.getById(Id);

-        if (torrent == null) {

-            return Result.error(404).setMessage("种子不存在"); // 明确设置404状态码

-        }

-

-        // 获取所有评论(按创建时间排序)

-        List<TorrentComment> allComments = commentService.list(

-                new QueryWrapper<TorrentComment>()

-                        .eq("post_id", Id)

-                        .orderByAsc("create_time")

-        );

-

-        // 构建评论树形结构

-        List<TorrentComment> rootComments = new ArrayList<>();

-        Map<Integer, TorrentComment> commentMap = new HashMap<>();

-

-        // 第一遍:初始化所有评论到map中

-        for (TorrentComment comment : allComments) {

-            comment.setReplies(new ArrayList<>()); // 初始化replies列表

-            commentMap.put(comment.getId(), comment);

-        }

-

-        // 第二遍:构建父子关系

-        for (TorrentComment comment : allComments) {

-            if (comment.getParentId() == 0) {

-                rootComments.add(comment);

-            } else {

-                TorrentComment parent = commentMap.get(comment.getParentId());

-                if (parent != null) {

-                    parent.getReplies().add(comment);

-                }

-            }

-        }

-

-        return Result.ok()

-                .data("torrent", torrent)

-                .data("comments", rootComments);

-    }

-

-    // 点赞帖子

-    @PostMapping("/{Id}/like")

-    public Result likePost(@PathVariable int Id) {

-        postService.incrementLike(Id);

-        return Result.ok();

-    }

-

-    @PostMapping("/{Id}/comments")

-    public Result comment(@PathVariable int Id,

-                          @RequestBody TorrentComment comment) {

-        // 设置评论信息

-        comment.setPostId(Id);

-        comment.setCreateTime(LocalDateTime.now());

-        comment.setLikeCount(0); // 初始化点赞数

-        comment.setParentId(0);  // 默认父评论ID

-        comment.setReplyTo(null); // 主评论 replyTo=null

-

-        // 保存评论

-        boolean saved = commentService.save(comment);

-        if (!saved) {

-            return Result.error(404).setMessage("评论保存失败");

-        }

-

-        // 更新回复数

-        postService.incrementReplyCount(Id);

-

-        // 获取更新后的完整评论(包含数据库生成的ID和时间)

-        TorrentComment newComment = commentService.getById(comment.getId());

-

-        return Result.ok()

-                .data("comment", newComment)  // 返回完整评论数据

-                .data("newReplyCount", postService.getById(Id).getReplyCount());

-    }

+package com.ptp.ptplatform.controller;
+
+import com.ptp.ptplatform.entity.TORRENT;
+import com.ptp.ptplatform.entity.USER;
+import com.ptp.ptplatform.mapper.TorrentMapper;
+import com.ptp.ptplatform.mapper.UserMapper;
+import com.ptp.ptplatform.service.ClientService;
+import com.ptp.ptplatform.service.TrackerService;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.ptp.ptplatform.entity.TorrentComment;
+import com.ptp.ptplatform.service.TorrentCommentService;
+import com.ptp.ptplatform.service.TorrentService;
+import com.ptp.ptplatform.utils.Result;
+import com.turn.ttorrent.common.TorrentStatistic;
+import com.turn.ttorrent.tracker.TrackedPeer;
+import com.turn.ttorrent.tracker.TrackedTorrent;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+import java.util.Map;
+
+import static com.ptp.ptplatform.utils.JwtUtils.getClaimByToken;
+
+//实现种子的增删改查
+@RestController
+@RequestMapping("/torrent")
+@AllArgsConstructor
+public class TorrentController {
+    private final TorrentService postService;
+    private final TorrentCommentService commentService;
+
+    @Resource
+    private TorrentMapper torrentMapper;
+    @Resource
+    private UserMapper userMapper;
+    @Resource
+    private UserController userController;
+
+    private TrackerService ts = new TrackerService();
+    private ClientService cs = new ClientService();
+
+    @GetMapping("/{Id}")
+    public Result getPost(@PathVariable int Id) {
+        TORRENT torrent = postService.getById(Id);
+        if (torrent == null) {
+            return Result.error(404).setMessage("种子不存在"); // 明确设置404状态码
+        }
+
+        // 获取所有评论(按创建时间排序)
+        List<TorrentComment> allComments = commentService.list(
+                new QueryWrapper<TorrentComment>()
+                        .eq("post_id", Id)
+                        .orderByAsc("create_time")
+        );
+
+        // 构建评论树形结构
+        List<TorrentComment> rootComments = new ArrayList<>();
+        Map<Integer, TorrentComment> commentMap = new HashMap<>();
+
+        // 第一遍:初始化所有评论到map中
+        for (TorrentComment comment : allComments) {
+            comment.setReplies(new ArrayList<>()); // 初始化replies列表
+            commentMap.put(comment.getId(), comment);
+        }
+
+        // 第二遍:构建父子关系
+        for (TorrentComment comment : allComments) {
+            if (comment.getParentId() == 0) {
+                rootComments.add(comment);
+            } else {
+                TorrentComment parent = commentMap.get(comment.getParentId());
+                if (parent != null) {
+                    parent.getReplies().add(comment);
+                }
+            }
+        }
+
+        return Result.ok()
+                .data("torrent", torrent)
+                .data("comments", rootComments);
+    }
+
+    // 点赞帖子
+    @PostMapping("/{Id}/like")
+    public Result likePost(@PathVariable int Id) {
+        postService.incrementLike(Id);
+        return Result.ok();
+    }
+
+    @PostMapping("/{Id}/comments")
+    public Result comment(@PathVariable int Id,
+                          @RequestBody TorrentComment comment) {
+        // 设置评论信息
+        comment.setPostId(Id);
+        comment.setCreateTime(LocalDateTime.now());
+        comment.setLikeCount(0); // 初始化点赞数
+        comment.setParentId(0);  // 默认父评论ID
+        comment.setReplyTo(null); // 主评论 replyTo=null
+
+        // 保存评论
+        boolean saved = commentService.save(comment);
+        if (!saved) {
+            return Result.error(404).setMessage("评论保存失败");
+        }
+
+        // 更新回复数
+        postService.incrementReplyCount(Id);
+
+        // 获取更新后的完整评论(包含数据库生成的ID和时间)
+        TorrentComment newComment = commentService.getById(comment.getId());
+
+        return Result.ok()
+                .data("comment", newComment)  // 返回完整评论数据
+                .data("newReplyCount", postService.getById(Id).getReplay_count());
+    }
+
+    @PostConstruct //启动项目时候自动启动tracker服务器
+    public String startTS() {
+        try {
+            ts.startTracker();
+            System.out.println("成功启动tracker服务器");
+            return "成功启动tracker服务器";
+        } catch (Exception e) {
+            System.out.println("启动失败: " + e.getMessage());
+            return "启动失败: " + e.getMessage();
+        }
+    }
+
+    //上传、下载、删除操作
+    //post 要添加数据库 文件和tracker的信息
+    @PostMapping
+    public Result addTorrent(HttpServletRequest request, @RequestBody TORRENT torrent) throws IOException {
+
+        // 1. 检查源文件
+        File file = new File(torrent.getFilePath());
+        if (!file.exists() || !file.isFile()) {
+            return Result.error(404).data("message", "文件不存在或路径无效");
+        }
+        if (!file.getName().endsWith(".torrent")) {
+            return Result.error(404).data("message", "仅支持.torrent文件");
+        }
+
+        // 2. 确定存储目录(改为项目根目录下的torrents文件夹)
+        String projectRoot = System.getProperty("user.dir");
+        String uploadDir = projectRoot + File.separator + "torrents";
+        File torrentsFolder = new File(uploadDir);
+        if (!torrentsFolder.exists() && !torrentsFolder.mkdirs()) {
+            return Result.error(404).data("message", "无法创建存储目录");
+        }
+
+        // 3. 复制文件
+        File uploadedFile = new File(torrentsFolder, file.getName());
+        try {
+            Files.copy(file.toPath(), uploadedFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+            System.out.println("文件保存成功: " + uploadedFile.getAbsolutePath());
+        } catch (IOException e) {
+            System.out.println("文件复制失败" + e);
+            return Result.error(404).data("message", "文件保存失败: " + e.getMessage());
+        }
+
+        // 4. 处理Tracker逻辑
+        try {
+            TrackedTorrent tt = ts.addTrackedTorrent(uploadedFile.getAbsolutePath());
+            TrackedPeer tp = createTrackedPeer(tt);
+            tt.addPeer(tp);
+
+            // 5. 数据库操作
+            torrent.setHash(tt.getHexInfoHash());
+            torrent.setSize(uploadedFile.length());
+            torrent.setUsername(getClaimByToken(request.getHeader("Authorization")).getSubject());
+            torrent.setFilePath(uploadedFile.getAbsolutePath());
+
+            if (torrentMapper.insertTorrent(torrent) == 1) {
+                return Result.ok().data("message", "上传成功")
+                        .data("path", uploadedFile.getAbsolutePath());
+            }
+        } catch (Exception e) {
+            System.out.println("Tracker或数据库操作失败" + e);
+            uploadedFile.delete(); // 回滚:删除已保存的文件
+        }
+
+        return Result.error(404).data("message", "上传失败");
+    }
+
+    //根据本机创建peer对象
+    public static TrackedPeer createTrackedPeer(TrackedTorrent torrent) {
+        try {
+            // 获取本机IP地址
+            InetAddress inetAddress = InetAddress.getLocalHost();
+            String ip = inetAddress.getHostAddress(); // 本机IP地址
+
+            // 假设使用一个随机的端口,这个端口可以根据需求调整
+            int port = 6881; // 这里使用固定端口,也可以通过动态方式分配
+
+            // 创建Peer ID (可以随机生成或从其他地方获取)
+            // 这里使用UUID来生成一个随机的 Peer ID
+            String peerIdString = UUID.randomUUID().toString();
+            ByteBuffer peerId = ByteBuffer.wrap(peerIdString.getBytes());
+
+            // 创建TrackedPeer实例
+            TrackedPeer trackedPeer = new TrackedPeer(torrent, ip, port, peerId);
+
+            return trackedPeer;
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    //种子下载 根据id获取数据
+    // 能成功获取到数据
+    // 能够根据此值,完成对相关数据的修改
+    // getDownloadedBytes:3063963
+    //getUploadedBytes:0
+    @GetMapping("/downloadTorrent")
+    public Result getTorrent(HttpServletRequest request,int id ,String downloadPath) throws Exception {
+        TORRENT torrent = torrentMapper.selectByID(id);
+
+        // 下载完成
+        // 传入变量:下载种子的id 下载到文件的路径
+        cs.downloadTorrent(torrent.getFilePath(), downloadPath);
+
+        //管理种子相关数据
+        TorrentStatistic ts = cs.getStatistics(torrent.getFilePath());
+
+        //修改用户对应的信息
+        USER downloadUser = userController.getUserInRequest(request);
+        USER uploadUser = userMapper.selectByUsername(torrent.getUsername());
+
+        downloadUser.updateDownload(ts.getDownloadedBytes());
+        uploadUser.updateUpload(ts.getDownloadedBytes());
+
+        userMapper.updateUser(downloadUser);
+        userMapper.updateUser(uploadUser);
+
+
+        return Result.ok().data("torrent", torrent);
+    }
+
+    //根据id删除
+    @DeleteMapping("/deleteTorrent/{id}")
+    public Result deleteTorrent(HttpServletRequest request,@PathVariable("id")int id) throws Exception {
+        TORRENT torrent = torrentMapper.selectByID(id);
+
+        String filePath = torrent.getFilePath();
+        try {
+            // 检查文件是否存在
+            if (Files.exists(Paths.get(filePath))) {
+                Files.delete(Paths.get(filePath));  // 删除文件
+                torrentMapper.deleteTorrent(id);
+
+                return Result.ok().message("种子文件删除成功");
+            } else {
+                throw new IOException("File not found: " + filePath);
+            }
+        } catch (IOException e) {
+            // 异常处理
+            e.printStackTrace();
+            // 返回失败结果或其他处理逻辑
+            return Result.error(404).setMessage("种子文件删除失败");
+        }
+    }
+
+    // Controller
+    @GetMapping
+    public Result listPosts(@RequestParam(defaultValue = "1") int page,
+                            @RequestParam(defaultValue = "5") int size) {
+        int offset = (page - 1) * size;
+        List<TORRENT> pagedList = torrentMapper.selectAllTorrentWithPage(offset, size);
+        int total = torrentMapper.countAllTorrent();
+
+        Page<TORRENT> pageResult = new Page<>(page, size);
+        pageResult.setRecords(pagedList);
+        pageResult.setTotal(total);
+
+        return Result.ok()
+                .data("records", pageResult.getRecords())
+                .data("total", pageResult.getTotal());
+    }
+
+    // 获取特定分区下的种子(分页版)
+    @GetMapping("/get/torrentByCategory/{category}")
+    public Result getTorrentByCategory(
+            @PathVariable("category") String category,
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "5") int size) {
+
+        int offset = (page - 1) * size;
+        List<TORRENT> pagedList = torrentMapper.selectTorrentByCategoryWithPage(category, offset, size);
+        int total = torrentMapper.countByCategory(category);
+
+        Page<TORRENT> pageResult = new Page<>(page, size);
+        pageResult.setRecords(pagedList);
+        pageResult.setTotal(total);
+
+        return Result.ok()
+                .data("records", pageResult.getRecords())
+                .data("total", pageResult.getTotal());
+    }
+
+    // 搜索种子关键字(分页版)
+    @GetMapping("/get/torrentByKey/{key}")
+    public Result getTorrentByKey(
+            @PathVariable("key") String key,
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "5") int size) {
+
+        int offset = (page - 1) * size;
+        List<TORRENT> pagedList = torrentMapper.selectTorrentByKeyWithPage(key, offset, size);
+        int total = torrentMapper.countByKey(key);
+
+        Page<TORRENT> pageResult = new Page<>(page, size);
+        pageResult.setRecords(pagedList);
+        pageResult.setTotal(total);
+
+        return Result.ok()
+                .data("records", pageResult.getRecords())
+                .data("total", pageResult.getTotal());
+    }
+
+    // 获取对应用户种子(分页版)
+    @GetMapping("/get/torrentMyself")
+    public Result getTorrentByKey(
+            HttpServletRequest request,
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "5") int size) throws Exception {
+
+        USER user = userController.getUserInRequest(request);
+        int offset = (page - 1) * size;
+        List<TORRENT> pagedList = torrentMapper.selectTorrentByUsernameWithPage(user.getUsername(), offset, size);
+        int total = torrentMapper.countByUsername(user.getUsername());
+
+        Page<TORRENT> pageResult = new Page<>(page, size);
+        pageResult.setRecords(pagedList);
+        pageResult.setTotal(total);
+
+        return Result.ok()
+                .data("records", pageResult.getRecords())
+                .data("total", pageResult.getTotal());
+    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/controller/UserController.java b/src/main/java/com/ptp/ptplatform/controller/UserController.java
index 9265ce7..4587abc 100644
--- a/src/main/java/com/ptp/ptplatform/controller/UserController.java
+++ b/src/main/java/com/ptp/ptplatform/controller/UserController.java
@@ -6,47 +6,58 @@
 import com.ptp.ptplatform.entity.*;
 import com.ptp.ptplatform.mapper.UserMapper;
 import com.ptp.ptplatform.mapper.InviteCodeMapper;
+import com.ptp.ptplatform.utils.SizeCalculation;
 import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 import com.ptp.ptplatform.utils.Result;
 import com.ptp.ptplatform.utils.JwtUtils;
 import com.ptp.ptplatform.entity.USER;
+
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/user")
 @CrossOrigin //启用跨域
 public class UserController {
 
-    @Resource
+    @Autowired
     private UserMapper userMapper;
-    @Resource
+    @Autowired
     private InviteCodeMapper inviteCodeMapper;
 
+
+    //个人中心获取用户登录信息
     @GetMapping("/info") //获取
-    public Result info(String token) {
-        String username = JwtUtils.getClaimByToken(token).getSubject();
-        return Result.ok().data("name", username);
+    public Result info(HttpServletRequest request) {
+        USER user = this.getUserInRequest(request);
+        return Result.ok().data("info", user);
     }
 
     @PostMapping("/login") //用户登录
     public Result login(String username, String password) {
         USER user = userMapper.selectByUsername(username);
 
-        if (user != null) {
-            // 将用户输入的密码进行哈希处理
-            String hashedPassword = user.hashPassword(password);
-
-            // 比较用户输入的密码哈希值和数据库中的密码哈希值
-            if (hashedPassword.equals(user.getPassword())) {
-                String token = JwtUtils.generateToken(user.getUsername());
-                return Result.ok().data("token", token);  // 返回令牌给前端
-            } else {
-                return Result.error(404).setMessage("密码错误");
-            }
-        } else {
+        // 检查用户是否存在
+        if (user == null) {
             return Result.error(404).setMessage("用户不存在");
         }
+
+        System.out.println("password" + user.getPassword());
+
+        // 比较用户输入密码值是否正确
+        if (user.getPassword().equals(password)) {
+            String token = JwtUtils.generateToken(user.getUsername());
+
+            user.setLastLogin(new Date());
+            userMapper.updateUser(user);
+            return Result.ok().data("token", token);  // 返回令牌给前端
+        } else {
+            return Result.error(404).setMessage("密码错误");
+        }
     }
 
     @PostMapping("/regist")
@@ -55,12 +66,12 @@
         if (userCheck == null) {
             //获取邀请码
             INVITE_CODE inviteCode = inviteCodeMapper.selectByCode(code);
-            if(inviteCode != null){
+            if (inviteCode != null) {
                 System.out.println(inviteCode.getIsUsed());
 
-                if(!inviteCode.getIsUsed()){
+                if (!inviteCode.getIsUsed()) {
                     Date time = new Date();
-                    USER user = new USER(username, password, time) ;
+                    USER user = new USER(username, password, time);
 
                     userMapper.insertUser(user);
                     inviteCodeMapper.updateCodeUser(code);
@@ -81,9 +92,46 @@
 
     }
 
-    @PostMapping("/logout")
-    public Result logout(String token) {
-        return Result.ok();
+    //获取允许下载额度的相关信息
+    @GetMapping("/allowDownload")
+    public Result allowDownload(HttpServletRequest request) {
+        USER user = this.getUserInRequest(request);
+        // 总额度 已经使用 剩余 单位是GB
+        int totalSize = SizeCalculation.byteToGB(user.getUpload());
+        int usedSize = SizeCalculation.byteToGB(user.getDownload());
+        int leftSize = totalSize - usedSize;
+
+        // 将变量封装成Map
+        Map<String, Object> dataMap = new HashMap<>();
+        dataMap.put("totalSize", totalSize);
+        dataMap.put("usedSize", usedSize);
+        dataMap.put("leftSize", leftSize);
+
+        return Result.ok().data(dataMap);
+    }
+
+    //修改用户密码
+    @PutMapping("/password")
+    public Result updatePassword(HttpServletRequest request, @RequestBody Map<String, String> passwordMap) {
+        USER user = this.getUserInRequest(request);
+
+        String oldPassword = passwordMap.get("oldPassword");
+        String newPassword = passwordMap.get("newPassword");
+
+        if (user.getPassword().equals(oldPassword)) {
+            user.setPassword(newPassword);
+            userMapper.updateUser(user);
+
+            return Result.ok().setMessage("修改密码成功");
+        }
+        return Result.error(404).setMessage("原密码不正确");
+    }
+
+
+    //从http请求中获取到用户
+    public USER getUserInRequest(HttpServletRequest request) {
+        String UserName = JwtUtils.getClaimByToken(request.getHeader("Authorization")).getSubject();
+        return userMapper.selectByUsername(UserName);
     }
 
 }
diff --git a/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_RECORD.java b/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_RECORD.java
new file mode 100644
index 0000000..3743f4e
--- /dev/null
+++ b/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_RECORD.java
@@ -0,0 +1,23 @@
+package com.ptp.ptplatform.entity;
+
+import java.time.LocalDateTime;
+
+public class DOWNLOAD_RECORD {
+
+    private int id; // 下载记录ID
+    private int userId; // 下载用户ID
+    private int torrentId; // 请求的种子资源ID
+    private String status; // 下载状态(成功、失败、终止)
+    private LocalDateTime downloadTime; // 下载时间
+    private String downloadPath; // 下载路径
+
+    // 构造方法、getter和setter省略
+
+    public DOWNLOAD_RECORD(int userId, int torrentId, String status, LocalDateTime downloadTime, String downloadPath) {
+        this.userId = userId;
+        this.torrentId = torrentId;
+        this.status = status;
+        this.downloadTime = downloadTime;
+        this.downloadPath = downloadPath;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/entity/INVITE_CODE.java b/src/main/java/com/ptp/ptplatform/entity/INVITE_CODE.java
index d0a5a53..a35dd89 100644
--- a/src/main/java/com/ptp/ptplatform/entity/INVITE_CODE.java
+++ b/src/main/java/com/ptp/ptplatform/entity/INVITE_CODE.java
@@ -4,6 +4,7 @@
 
 import jakarta.persistence.*;
 import java.io.Serializable;
+import java.util.UUID;
 
 @Table(name = "invite_code")
 public class INVITE_CODE {
@@ -43,8 +44,10 @@
     // Constructor (optional)
     public INVITE_CODE() {}
 
-    public INVITE_CODE(String code, String generateUser) {
-        this.code = code;
+    //code是10位随机生成密码
+    public INVITE_CODE(String generateUser) {
+        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
+        this.code = uuid.substring(0, 8);
         this.generateUser = generateUser;
         this.isUsed = false;
     }
diff --git a/src/main/java/com/ptp/ptplatform/entity/TORRENT.java b/src/main/java/com/ptp/ptplatform/entity/TORRENT.java
new file mode 100644
index 0000000..afbb264
--- /dev/null
+++ b/src/main/java/com/ptp/ptplatform/entity/TORRENT.java
@@ -0,0 +1,62 @@
+package com.ptp.ptplatform.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 jakarta.persistence.GeneratedValue;

+import jakarta.persistence.GenerationType;

+import jakarta.persistence.Id;

+import lombok.Data;

+import java.time.LocalDateTime;

+import java.util.Date;

+

+@Data

+@TableName("torrent") // 使用MyBatis-Plus的注解指定表名

+public class TORRENT {

+

+    @Id

+    @GeneratedValue(strategy = GenerationType.IDENTITY)

+    private Integer id;

+

+    private String torrentName; // 文件名

+    private String description; // 描述

+    private String category; // 分类

+    private String region; // 地区

+    private String resolution; // 分辨率

+    private String subtitle; // 字幕状态

+

+    private Long size; // 种子对应文件大小

+    private String hash; // torrent编码

+    private String username; // 创建用户

+    private String filePath;

+    private int like_count;

+    private int replay_count;

+

+    @TableField(value = "create_time") // 使用@TableField注解处理时间字段

+    private Date createTime; // 创建时间

+

+    // 构造函数

+    public TORRENT(String hash, String torrentName, String description, String category, String region, String resolution, String subtitle, Long size, String username, String filePath) {

+        this.hash = hash;

+        this.torrentName = torrentName;

+        this.description = description;

+        this.category = category;

+        this.region = region;

+        this.resolution = resolution;

+        this.subtitle = subtitle;

+        this.size = size;

+        this.username = username;

+        this.filePath = filePath;

+        this.like_count = 0;

+        this.replay_count = 0;

+    }

+

+    public void setLikeCount(int like_count) {

+        this.like_count = like_count;

+    }

+

+    public int getLikeCount() {

+        return this.like_count;

+    }

+}
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/entity/Torrent.java b/src/main/java/com/ptp/ptplatform/entity/Torrent.java
deleted file mode 100644
index 2c6c6d3..0000000
--- a/src/main/java/com/ptp/ptplatform/entity/Torrent.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.ptp.ptplatform.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 lombok.Data;

-import java.time.LocalDateTime;

-

-@Data

-@TableName("torrent")

-public class Torrent {

-    @TableId(value = "id", type = IdType.AUTO)

-    private Integer id;

-

-    @TableField("torrentName") // 明确指定数据库列名

-    private String torrentName;

-

-    private String description;

-    private String category;

-    private String region;

-    private String resolution;

-    private String subtitle;

-    private Long size;

-    private String hash;

-

-    private LocalDateTime createTime;

-

-    private String username;

-

-    @TableField("filePath") // 明确指定数据库列名

-    private String filePath;

-

-    private Integer likeCount;

-    private Integer replyCount;

-

-

-

-}
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/entity/USER.java b/src/main/java/com/ptp/ptplatform/entity/USER.java
index a33847c..ac51eb4 100644
--- a/src/main/java/com/ptp/ptplatform/entity/USER.java
+++ b/src/main/java/com/ptp/ptplatform/entity/USER.java
@@ -27,10 +27,10 @@
     @Temporal(TemporalType.DATE)
     private Date lastLogin;
 
-    private int upload;
-    private int download;
-    private int shareRate;
-    private int magicPoints;
+    private long upload;
+    private long download;
+    private double shareRate;//分享率 前端展示数据应该为 90.23%这种
+    private long magicPoints;// 魔力值
 
     public enum Authority {
         USER, ADMIN, LIMIT, BAN
@@ -86,23 +86,23 @@
         this.lastLogin = lastLogin;
     }
 
-    public int getUpload() {
+    public long getUpload() {
         return upload;
     }
 
-    public void setUpload(int upload) {
+    public void setUpload(long upload) {
         this.upload = upload;
     }
 
-    public int getDownload() {
+    public long getDownload() {
         return download;
     }
 
-    public void setDownload(int download) {
+    public void setDownload(long download) {
         this.download = download;
     }
 
-    public int getShareRate() {
+    public double getShareRate() {
         return shareRate;
     }
 
@@ -110,8 +110,8 @@
         this.shareRate = shareRate;
     }
 
-    public int getMagicPoints() {
-        return magicPoints;
+    public long getMagicPoints() {
+        return this.magicPoints;
     }
 
     public void setMagicPoints(int magicPoints) {
@@ -125,32 +125,41 @@
         this.username = username;
         this.registTime = registTime;
 
-        this.password = hashPassword(password);;
+        this.password = password;
 
         this.authority = Authority.USER;
         this.level = 0;
         this.lastLogin = null;
         this.upload = 0;
         this.download = 0;
-        this.shareRate = 100;
+        this.shareRate = 1;
         this.magicPoints = 0;
     }
 
-    public String hashPassword(String password) {
-        try {
-            // 使用SHA-256算法
-            MessageDigest digest = MessageDigest.getInstance("SHA-256");
-            byte[] hashBytes = digest.digest(password.getBytes());
-
-            // 将字节数组转换为十六进制字符串
-            StringBuilder hexString = new StringBuilder();
-            for (byte b : hashBytes) {
-                hexString.append(String.format("%02x", b));
-            }
-
-            return hexString.toString();
-        } catch (NoSuchAlgorithmException e) {
-            throw new RuntimeException("Error hashing password", e);
-        }
+    //对上传量下载量的处理 返回更新后的数据结果
+    public long updateUpload(long addUpload) {
+        this.upload += addUpload;
+        this.shareRate = (double) this.upload / this.download;
+        return upload;
     }
+
+    public long updateDownload(long addDownload) {
+        this.download += addDownload;
+        this.shareRate = (double) this.upload / this.download;
+        return download;
+    }
+
+    //生成邀请码,魔力值扣除
+    public void generateInviteCode() {
+        this.magicPoints -= 10;
+    }
+
+    // 每天运行的计算魔力值程序
+    // 添加种子,验证同一用户的全部种子存活与否
+    public long updateMagicPoints(long addMagicPoints) {
+
+        return 0;
+    }
+
+
 }
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/entity/testdata.java b/src/main/java/com/ptp/ptplatform/entity/testdata.java
deleted file mode 100644
index 7d6d88e..0000000
--- a/src/main/java/com/ptp/ptplatform/entity/testdata.java
+++ /dev/null
@@ -1,15 +0,0 @@
-// model类 负责管理数据库数据和sb的映射
-
-package com.ptp.ptplatform.entity;
-
-public class testdata {
-    private String name;
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
-}
diff --git a/src/main/java/com/ptp/ptplatform/mapper/DownloadRecordMapper.java b/src/main/java/com/ptp/ptplatform/mapper/DownloadRecordMapper.java
new file mode 100644
index 0000000..4cb8c90
--- /dev/null
+++ b/src/main/java/com/ptp/ptplatform/mapper/DownloadRecordMapper.java
@@ -0,0 +1,10 @@
+package com.ptp.ptplatform.mapper;
+
+import com.ptp.ptplatform.entity.DOWNLOAD_RECORD;
+import org.apache.ibatis.annotations.Insert;
+
+public interface DownloadRecordMapper {
+    @Insert("INSERT INTO download_record (username, torrent_id, status, download_time, download_path) " +
+            "VALUES (#{username}, #{torrentId}, #{status}, #{downloadTime}, #{downloadPath})")
+    void insertDownloadRecord(DOWNLOAD_RECORD downloadRecord);
+}
diff --git a/src/main/java/com/ptp/ptplatform/mapper/InviteCodeMapper.java b/src/main/java/com/ptp/ptplatform/mapper/InviteCodeMapper.java
index 612c7fb..b58e01b 100644
--- a/src/main/java/com/ptp/ptplatform/mapper/InviteCodeMapper.java
+++ b/src/main/java/com/ptp/ptplatform/mapper/InviteCodeMapper.java
@@ -2,17 +2,27 @@
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ptp.ptplatform.entity.INVITE_CODE;
+import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 import org.springframework.web.service.annotation.PutExchange;
 
+import java.util.List;
+
 @Mapper
 public interface InviteCodeMapper extends BaseMapper<INVITE_CODE> {
     //查询
     @Select("SELECT * FROM invite_code WHERE code = #{code}")
     INVITE_CODE selectByCode(String code);
 
+    @Select("SELECT * FROM invite_code WHERE generateUser = #{username}")
+    List<INVITE_CODE> selectByUser(String username);
+
     @Update("UPDATE invite_code SET isused = true WHERE code = #{code}")
     int updateCodeUser(String code);
+
+    // 插入新数据
+    @Insert("INSERT INTO invite_code (code, generateUser, isUsed) VALUES (#{code}, #{generateUser}, #{isUsed})")
+    int insertInviteCode(INVITE_CODE inviteCode);
 }
diff --git a/src/main/java/com/ptp/ptplatform/mapper/TorrentMapper.java b/src/main/java/com/ptp/ptplatform/mapper/TorrentMapper.java
index ff612b3..b4ec407 100644
--- a/src/main/java/com/ptp/ptplatform/mapper/TorrentMapper.java
+++ b/src/main/java/com/ptp/ptplatform/mapper/TorrentMapper.java
@@ -1,8 +1,76 @@
 package com.ptp.ptplatform.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.ptp.ptplatform.entity.Torrent;
-import org.apache.ibatis.annotations.Mapper;
+import com.ptp.ptplatform.entity.TORRENT;
+import org.apache.ibatis.annotations.*;
 
-@Mapper
-public interface TorrentMapper extends BaseMapper<Torrent> {}
\ No newline at end of file
+import java.util.List;
+
+public interface TorrentMapper extends BaseMapper<TORRENT> {
+    // 根据hash查询Torrent
+    @Select("SELECT * FROM torrent WHERE hash = #{hash}")
+    TORRENT selectByHash(String hash);
+
+    @Select("SELECT * FROM torrent WHERE id = #{id}")
+    TORRENT selectByID(int id);
+
+    // Mapper接口
+    @Select("SELECT * FROM torrent ORDER BY create_time DESC LIMIT #{offset}, #{size}")
+    List<TORRENT> selectAllTorrentWithPage(@Param("offset") int offset, @Param("size") int size);
+
+    @Select("SELECT COUNT(*) FROM torrent")
+    int countAllTorrent();
+
+    @Select("SELECT * FROM torrent WHERE category = #{category}")
+    List<TORRENT> selectTorrentByCategory(String category);
+
+    @Select("SELECT * FROM torrent WHERE torrentName LIKE CONCAT('%', #{key}, '%')")
+    List<TORRENT> selectTorrentByKey(String key);
+
+    @Select("SELECT * FROM torrent WHERE username = #{username}")
+    List<TORRENT> selectTorrentByUsername(String username);
+
+    //分页查询部分
+    // 在TorrentMapper.java中添加以下方法
+
+    // 分页查询特定分类
+    @Select("SELECT * FROM torrent WHERE category = #{category} ORDER BY create_time DESC LIMIT #{offset}, #{size}")
+    List<TORRENT> selectTorrentByCategoryWithPage(@Param("category") String category,
+                                                  @Param("offset") int offset,
+                                                  @Param("size") int size);
+
+    @Select("SELECT COUNT(*) FROM torrent WHERE category = #{category}")
+    int countByCategory(@Param("category") String category);
+
+    // 分页搜索关键字
+    @Select("SELECT * FROM torrent WHERE torrentName LIKE CONCAT('%',#{key},'%') OR description LIKE CONCAT('%',#{key},'%') ORDER BY create_time DESC LIMIT #{offset}, #{size}")
+    List<TORRENT> selectTorrentByKeyWithPage(@Param("key") String key,
+                                             @Param("offset") int offset,
+                                             @Param("size") int size);
+
+    @Select("SELECT COUNT(*) FROM torrent WHERE torrentName LIKE CONCAT('%',#{key},'%') OR description LIKE CONCAT('%',#{key},'%')")
+    int countByKey(@Param("key") String key);
+
+    // 分页查询用户种子
+    @Select("SELECT * FROM torrent WHERE username = #{username} ORDER BY create_time DESC LIMIT #{offset}, #{size}")
+    List<TORRENT> selectTorrentByUsernameWithPage(@Param("username") String username,
+                                                  @Param("offset") int offset,
+                                                  @Param("size") int size);
+
+    @Select("SELECT COUNT(*) FROM torrent WHERE username = #{username}")
+    int countByUsername(@Param("username") String username);
+
+    // 插入Torrent
+    @Insert("INSERT INTO torrent (torrentName, description, category, region, resolution, subtitle, size, hash, username, create_time, filePath) " +
+            "VALUES (#{torrentName}, #{description}, #{category}, #{region}, #{resolution}, #{subtitle}, #{size}, #{hash}, #{username}, CURRENT_TIMESTAMP, #{filePath})")
+    int insertTorrent(TORRENT torrent);
+
+    // 更新Torrent信息
+    @Update("UPDATE torrent SET torrentName = #{torrentName}, description = #{description}, category = #{category}, " +
+            "tags = #{tags}, size = #{size}, username = #{username} WHERE hash = #{hash}")
+    int updateTorrent(TORRENT torrent);
+
+    // 删除Torrent
+    @Delete("DELETE FROM torrent WHERE id = #{id}")
+    int deleteTorrent(int id);
+}
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/mapper/UserMapper.java b/src/main/java/com/ptp/ptplatform/mapper/UserMapper.java
index 024807e..f17d0dd 100644
--- a/src/main/java/com/ptp/ptplatform/mapper/UserMapper.java
+++ b/src/main/java/com/ptp/ptplatform/mapper/UserMapper.java
@@ -6,6 +6,7 @@
 import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
 
 @Mapper
 public interface UserMapper extends BaseMapper<USER> {
@@ -20,4 +21,17 @@
     @Insert("INSERT INTO user (username, password, registTime) " +
             "VALUES (#{username}, #{password}, #{registTime})")
     int insertUser(USER user);
+
+    // 更新用户信息
+    @Update("UPDATE user SET " +
+            "password = #{password}, " +
+            "authority = #{authority}, " +
+            "level = #{level}, " +
+            "lastLogin = #{lastLogin}, " +
+            "upload = #{upload}, " +
+            "download = #{download}, " +
+            "shareRate = #{shareRate}, " +
+            "magicPoints = #{magicPoints} " +
+            "WHERE username = #{username}")
+    int updateUser(USER user);
 }
diff --git a/src/main/java/com/ptp/ptplatform/service/ClientService.java b/src/main/java/com/ptp/ptplatform/service/ClientService.java
new file mode 100644
index 0000000..39cdc76
--- /dev/null
+++ b/src/main/java/com/ptp/ptplatform/service/ClientService.java
@@ -0,0 +1,34 @@
+package com.ptp.ptplatform.service;
+
+import com.turn.ttorrent.client.SimpleClient;
+import com.turn.ttorrent.common.TorrentStatistic;
+import org.springframework.stereotype.Service;
+
+import java.net.InetAddress;
+
+@Service
+public class ClientService {
+    SimpleClient client = new SimpleClient();
+
+    public boolean downloadTorrent(String torrentFilePath, String outputDirectory) throws Exception {
+
+
+        InetAddress address = InetAddress.getLocalHost(); // 使用本地地址
+
+        try {
+            // 开始下载torrent
+            client.downloadTorrent(torrentFilePath, outputDirectory, address);
+            System.out.println("下载完成");
+            return true;
+        } catch (Exception e) {
+            // 下载失败,输出异常信息
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    public TorrentStatistic getStatistics(String torrentFilePath) throws Exception {
+        TorrentStatistic ts = client.getStatistics(torrentFilePath);
+        return ts;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/service/TorrentService.java b/src/main/java/com/ptp/ptplatform/service/TorrentService.java
index f3d0222..1891067 100644
--- a/src/main/java/com/ptp/ptplatform/service/TorrentService.java
+++ b/src/main/java/com/ptp/ptplatform/service/TorrentService.java
@@ -1,10 +1,10 @@
 package com.ptp.ptplatform.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.ptp.ptplatform.entity.Torrent;
+import com.ptp.ptplatform.entity.TORRENT;
 
-public interface TorrentService extends IService<Torrent> {
-    Torrent getTorrentById(Integer id);  // Add this method
+public interface TorrentService extends IService<TORRENT> {
+    TORRENT getTorrentById(Integer id);  // Add this method
     void incrementLike(int postId);
     void incrementReplyCount(int postId);
 
diff --git a/src/main/java/com/ptp/ptplatform/service/TrackerService.java b/src/main/java/com/ptp/ptplatform/service/TrackerService.java
new file mode 100644
index 0000000..29bc95f
--- /dev/null
+++ b/src/main/java/com/ptp/ptplatform/service/TrackerService.java
@@ -0,0 +1,74 @@
+package com.ptp.ptplatform.service;
+
+import com.turn.ttorrent.tracker.TrackedTorrent;
+import com.turn.ttorrent.tracker.Tracker;
+import jakarta.annotation.PostConstruct;
+import jakarta.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+//封装的对tracker的操作
+@Service
+public class TrackerService {
+
+    private Tracker tracker;
+
+    public void startTracker() throws Exception {
+        // 创建一个Tracker对象,监听端口6969
+        tracker = new Tracker(6969);
+
+        // 过滤目录下的.torrent文件
+        FilenameFilter filter = new FilenameFilter() {
+            @Override
+            public boolean accept(File dir, String name) {
+                return name.endsWith(".torrent");
+            }
+        };
+
+        // 获取当前项目根目录的路径并拼接torrents文件夹路径
+        String torrentDirectory = System.getProperty("user.dir") + File.separator + "torrents";
+        System.out.println("文件路径: " + torrentDirectory);
+
+        // 遍历目录中的所有torrent文件,传递给tracker
+        for (File file : new File(torrentDirectory).listFiles(filter)) {
+
+            TrackedTorrent tt = tracker.announce(TrackedTorrent.load(file));
+            System.out.println("种子文件: " + tt);
+        }
+
+        // 设置允许接收外部torrent
+        tracker.setAcceptForeignTorrents(true);
+
+        // 启动tracker服务
+        tracker.start(true);
+
+    }
+
+    public void stopTracker() {
+        if (tracker != null) {
+            tracker.stop();
+        }
+    }
+
+    public Collection<TrackedTorrent> getTrackedTorrents() {
+        return tracker.getTrackedTorrents();
+    }
+
+    public TrackedTorrent getTrackedTorrent(String hash) {
+        return tracker.getTrackedTorrent(hash);
+    }
+
+    public TrackedTorrent addTrackedTorrent(String filePath) throws IOException {
+        File file = new File(filePath);
+        return tracker.announce(TrackedTorrent.load(file));
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/ptp/ptplatform/service/impl/TorrentServiceImpl.java b/src/main/java/com/ptp/ptplatform/service/impl/TorrentServiceImpl.java
index a6eba54..3281d83 100644
--- a/src/main/java/com/ptp/ptplatform/service/impl/TorrentServiceImpl.java
+++ b/src/main/java/com/ptp/ptplatform/service/impl/TorrentServiceImpl.java
@@ -1,24 +1,24 @@
 package com.ptp.ptplatform.service.impl;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.ptp.ptplatform.entity.Torrent;
+import com.ptp.ptplatform.entity.TORRENT;
 import com.ptp.ptplatform.mapper.TorrentMapper;
 import com.ptp.ptplatform.service.TorrentService;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 @Service
-public class TorrentServiceImpl extends ServiceImpl<TorrentMapper, Torrent> implements TorrentService {
+public class TorrentServiceImpl extends ServiceImpl<TorrentMapper, TORRENT> implements TorrentService {
 
     @Override
-    public Torrent getTorrentById(Integer id) {
+    public TORRENT getTorrentById(Integer id) {
         return this.getById(id); // 直接调用 MyBatis-Plus 提供的 getById 方法
     }
     @Override
     @Transactional
     public void incrementLike(int postId) {
         this.update(null,
-                new com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<Torrent>()
+                new com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<TORRENT>()
                         .eq("id", postId)
                         .setSql("like_count = like_count + 1")
         );
@@ -28,7 +28,7 @@
     @Transactional
     public void incrementReplyCount(int postId) {
         this.update(null,
-                new com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<Torrent>()
+                new com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper<TORRENT>()
                         .eq("id", postId)
                         .setSql("reply_count = reply_count + 1")
         );
diff --git a/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java b/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java
index 57bff31..0728819 100644
--- a/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java
+++ b/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java
@@ -1,13 +1,21 @@
 package com.ptp.ptplatform.utils;
 
+import com.ptp.ptplatform.entity.USER;
+import com.ptp.ptplatform.mapper.UserMapper;
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.Jwts;
 import io.jsonwebtoken.SignatureAlgorithm;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
 
 import javax.xml.crypto.Data;
 import java.util.Date;
 
+
 public class JwtUtils {
+
     private static long expire = 36000;
     private static String secret = "abcdefgg";
 
diff --git a/src/main/java/com/ptp/ptplatform/utils/Result.java b/src/main/java/com/ptp/ptplatform/utils/Result.java
index 0bda7eb..527fc42 100644
--- a/src/main/java/com/ptp/ptplatform/utils/Result.java
+++ b/src/main/java/com/ptp/ptplatform/utils/Result.java
@@ -2,6 +2,7 @@
 import java.util.HashMap;
 import java.util.Map;
 
+//AAAAAAAAAAAAAaaaaa
 public class Result {
     private Boolean success;
     private Integer code;
@@ -74,4 +75,8 @@
         this.setData(map);
         return this;
     }
+
+    public boolean isSuccess(){
+        return success;
+    }
 }
diff --git a/src/main/java/com/ptp/ptplatform/utils/SizeCalculation.java b/src/main/java/com/ptp/ptplatform/utils/SizeCalculation.java
new file mode 100644
index 0000000..863e376
--- /dev/null
+++ b/src/main/java/com/ptp/ptplatform/utils/SizeCalculation.java
@@ -0,0 +1,9 @@
+package com.ptp.ptplatform.utils;
+
+//实现将字节大小转化为GB
+public class SizeCalculation {
+
+    public static int byteToGB(long bytes) {
+        return (int) (bytes / 1024 / 1024 / 1024);
+    }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 730af5c..70338d3 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -26,4 +26,12 @@
 
 # MyBatis-Plus properties
 mybatis-plus.mapper-locations=classpath:/mapper/*.xml
-mybatis-plus.type-aliases-package=com.example.demo.model
\ No newline at end of file
+mybatis-plus.type-aliases-package=com.example.demo.model
+
+# Tracker??
+bittorrent.tracker.torrent-dir=./torrents
+
+# ??????
+spring.servlet.multipart.enabled=true
+spring.servlet.multipart.max-file-size=10MB
+spring.servlet.multipart.max-request-size=10MB
\ No newline at end of file
diff --git a/src/test/java/com/ptp/ptplatform/controller/InviteCodeTest.java b/src/test/java/com/ptp/ptplatform/controller/InviteCodeTest.java
new file mode 100644
index 0000000..9c000f3
--- /dev/null
+++ b/src/test/java/com/ptp/ptplatform/controller/InviteCodeTest.java
@@ -0,0 +1,116 @@
+package com.ptp.ptplatform.controller;
+
+import com.ptp.ptplatform.entity.INVITE_CODE;
+import com.ptp.ptplatform.entity.USER;
+import com.ptp.ptplatform.mapper.InviteCodeMapper;
+import com.ptp.ptplatform.mapper.UserMapper;
+import com.ptp.ptplatform.utils.JwtUtils;
+import com.ptp.ptplatform.utils.Result;
+import jakarta.servlet.http.HttpServletRequest;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.http.ResponseEntity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class InviteCodeTest {
+
+    @Mock
+    private InviteCodeMapper inviteCodeMapper;
+
+    @Mock
+    private UserMapper userMapper;
+
+    @Mock
+    private UserController userController;
+
+    @Mock
+    private HttpServletRequest request;
+
+    @InjectMocks
+    private InviteCodeController inviteCodeController;
+
+    private USER testUser;
+    private INVITE_CODE testInviteCode;
+
+    @BeforeEach
+    void setUp() {
+        MockitoAnnotations.openMocks(this);
+
+        testUser = new USER();
+        testUser.setUsername("testUser");
+        testUser.setMagicPoints(15);
+
+        testInviteCode = new INVITE_CODE(testUser.getUsername());
+        testInviteCode.setCode("TESTCODE123");
+    }
+
+    @Test
+    void generateInviteCode_Success() {
+        // Arrange
+        when(userController.getUserInRequest(request)).thenReturn(testUser);
+        when(inviteCodeMapper.insertInviteCode(any(INVITE_CODE.class))).thenReturn(1);
+
+        // Act
+        Result result = inviteCodeController.generateInviteCode(request);
+
+        // Assert
+        assertTrue(result.isSuccess());
+        assertNotNull(result.getData().get("inviteCode"));
+        verify(userMapper, times(1)).updateUser(testUser);
+    }
+
+    @Test
+    void generateInviteCode_Fail_NotEnoughMagicPoints() {
+        // Arrange
+        testUser.setMagicPoints(5);
+        when(userController.getUserInRequest(request)).thenReturn(testUser);
+
+        // Act
+        Result result = inviteCodeController.generateInviteCode(request);
+
+        // Assert
+        assertFalse(result.isSuccess());
+        assertEquals("兑换邀请码失败,魔力值不足。", result.getMessage());
+        verify(inviteCodeMapper, never()).insertInviteCode(any());
+        verify(userMapper, never()).updateUser(any());
+    }
+
+    @Test
+    void userInviteCode_Success() {
+        // Arrange
+        List<INVITE_CODE> inviteCodes = new ArrayList<>();
+        inviteCodes.add(testInviteCode);
+
+        when(userController.getUserInRequest(request)).thenReturn(testUser);
+        when(inviteCodeMapper.selectByUser(testUser.getUsername())).thenReturn(inviteCodes);
+
+        // Act
+        Result result = inviteCodeController.userInviteCode(request);
+
+        // Assert
+        assertTrue(result.isSuccess());
+        assertEquals(inviteCodes, result.getData().get("inviteCode"));
+    }
+
+    @Test
+    void userInviteCode_EmptyList() {
+        // Arrange
+        when(userController.getUserInRequest(request)).thenReturn(testUser);
+        when(inviteCodeMapper.selectByUser(testUser.getUsername())).thenReturn(new ArrayList<>());
+
+        // Act
+        Result result = inviteCodeController.userInviteCode(request);
+
+        // Assert
+        assertTrue(result.isSuccess());
+        assertTrue(((List<?>) result.getData().get("inviteCode")).isEmpty());
+    }
+}
\ No newline at end of file
diff --git a/src/test/java/com/ptp/ptplatform/controller/TorrentCommentControllerTest.java b/src/test/java/com/ptp/ptplatform/controller/TORRENTCommentControllerTest.java
similarity index 99%
rename from src/test/java/com/ptp/ptplatform/controller/TorrentCommentControllerTest.java
rename to src/test/java/com/ptp/ptplatform/controller/TORRENTCommentControllerTest.java
index 585a546..40abc63 100644
--- a/src/test/java/com/ptp/ptplatform/controller/TorrentCommentControllerTest.java
+++ b/src/test/java/com/ptp/ptplatform/controller/TORRENTCommentControllerTest.java
@@ -16,7 +16,7 @@
 import static org.junit.jupiter.api.Assertions.*;

 import static org.mockito.Mockito.*;

 

-class TorrentCommentControllerTest {

+class TORRENTCommentControllerTest {

 

     @Mock

     private TorrentCommentService commentService;

diff --git a/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java b/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java
new file mode 100644
index 0000000..f383d5e
--- /dev/null
+++ b/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java
@@ -0,0 +1,78 @@
+package com.ptp.ptplatform.controller;

+

+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

+import com.ptp.ptplatform.entity.TORRENT;

+import com.ptp.ptplatform.entity.TorrentComment;

+import com.ptp.ptplatform.service.TorrentCommentService;

+import com.ptp.ptplatform.service.TorrentService;

+import com.ptp.ptplatform.utils.Result;

+import org.junit.jupiter.api.BeforeEach;

+import org.junit.jupiter.api.Test;

+import org.mockito.InjectMocks;

+import org.mockito.Mock;

+import org.mockito.MockitoAnnotations;

+

+import java.time.LocalDateTime;

+import java.util.ArrayList;

+import java.util.List;

+

+import static org.junit.jupiter.api.Assertions.*;

+import static org.mockito.ArgumentMatchers.any;

+import static org.mockito.Mockito.*;

+

+class TORRENTControllerTest {

+

+    @Mock

+    private TorrentService torrentService;

+

+    @Mock

+    private TorrentCommentService commentService;

+

+    @InjectMocks

+    private TorrentController torrentController;

+

+    @BeforeEach

+    void setUp() {

+        MockitoAnnotations.openMocks(this);

+    }

+

+    @Test

+    void getTorrentById_ShouldReturnTorrent_WhenTorrentExists() {

+        // 1. 使用构造函数创建测试数据

+        TORRENT mockTORRENT = new TORRENT(

+                "d3b07384d113edec49eaa6238ad5ff00", // hash

+                "Ubuntu 22.04 ISO",                // torrentName

+                "Official Ubuntu Linux distribution", // description

+                "Software",                        // category

+                "美国",                            // region

+                "1080p",                          // resolution

+                "中文字幕",                        // subtitle

+                2048L,                            // size (2GB)

+                "admin",                          // username

+                "/downloads/ubuntu-22.04.iso"      // filePath

+        );

+        mockTORRENT.setId(1);

+        mockTORRENT.setLikeCount(200);

+

+        // 模拟空评论列表

+        List<TorrentComment> emptyComments = new ArrayList<>();

+

+        // 2. 模拟服务层行为

+        when(torrentService.getById(1)).thenReturn(mockTORRENT);

+        when(commentService.list(any(QueryWrapper.class))).thenReturn(emptyComments);

+

+        // 3. 调用控制器方法

+        Result result = torrentController.getPost(1);

+

+        // 4. 验证结果

+        assertEquals(200, result.getCode());

+        assertNotNull(result.getData().get("torrent"));

+        TORRENT returnedTORRENT = (TORRENT) result.getData().get("torrent");

+        assertEquals("Ubuntu 22.04 ISO", returnedTORRENT.getTorrentName());

+        assertEquals(200, returnedTORRENT.getLikeCount());

+

+        // 5. 验证服务层调用

+        verify(torrentService, times(1)).getById(1);

+        verify(commentService, times(1)).list(any(QueryWrapper.class));

+    }

+}
\ No newline at end of file
diff --git a/src/test/java/com/ptp/ptplatform/controller/TorrentControllerTest.java b/src/test/java/com/ptp/ptplatform/controller/TorrentControllerTest.java
deleted file mode 100644
index 9c4fbfa..0000000
--- a/src/test/java/com/ptp/ptplatform/controller/TorrentControllerTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.ptp.ptplatform.controller;

-

-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

-import com.ptp.ptplatform.entity.Torrent;

-import com.ptp.ptplatform.entity.TorrentComment;

-import com.ptp.ptplatform.service.TorrentCommentService;

-import com.ptp.ptplatform.service.TorrentService;

-import com.ptp.ptplatform.utils.Result;

-import org.junit.jupiter.api.BeforeEach;

-import org.junit.jupiter.api.Test;

-import org.mockito.InjectMocks;

-import org.mockito.Mock;

-import org.mockito.MockitoAnnotations;

-

-import java.time.LocalDateTime;

-import java.util.ArrayList;

-import java.util.List;

-

-import static org.junit.jupiter.api.Assertions.*;

-import static org.mockito.ArgumentMatchers.any;

-import static org.mockito.Mockito.*;

-

-class TorrentControllerTest {

-

-    @Mock

-    private TorrentService torrentService;

-

-    @Mock

-    private TorrentCommentService commentService;

-

-    @InjectMocks

-    private TorrentController torrentController;

-

-    @BeforeEach

-    void setUp() {

-        MockitoAnnotations.openMocks(this);

-    }

-

-    @Test

-    void getTorrentById_ShouldReturnTorrent_WhenTorrentExists() {

-        // 1. 构造测试数据

-        Torrent mockTorrent = new Torrent();

-        mockTorrent.setId(1);

-        mockTorrent.setTorrentName("Ubuntu 22.04 ISO");

-        mockTorrent.setDescription("Official Ubuntu Linux distribution");

-        mockTorrent.setCategory("Software");

-        mockTorrent.setFilePath("/downloads/ubuntu-22.04.iso");

-        mockTorrent.setCreateTime(LocalDateTime.of(2023, 5, 1, 10, 0));

-        mockTorrent.setRegion("美国");

-        mockTorrent.setLikeCount(200);

-

-        // 模拟空评论列表

-        List<TorrentComment> emptyComments = new ArrayList<>();

-

-        // 2. 模拟服务层行为

-        when(torrentService.getById(1)).thenReturn(mockTorrent);

-        when(commentService.list(any(QueryWrapper.class))).thenReturn(emptyComments);

-

-        // 3. 调用控制器方法

-        Result result = torrentController.getPost(1);

-

-        // 4. 验证结果

-        assertEquals(200, result.getCode());

-        assertNotNull(result.getData().get("torrent"));

-        Torrent returnedTorrent = (Torrent) result.getData().get("torrent");

-        assertEquals("Ubuntu 22.04 ISO", returnedTorrent.getTorrentName());

-        assertEquals(200, returnedTorrent.getLikeCount());

-

-        // 5. 验证服务层调用

-        verify(torrentService, times(1)).getById(1);

-        verify(commentService, times(1)).list(any(QueryWrapper.class));

-    }

-

-    @Test

-    void getTorrentDetails_ShouldReturnError_WhenTorrentNotExists() {

-        when(torrentService.getById(999)).thenReturn(null);

-

-        Result result = torrentController.getPost(999);

-

-        assertEquals(500, result.getCode());

-        assertEquals("种子不存在", result.getMessage());

-        verify(torrentService, times(1)).getById(999);

-        verify(commentService, never()).list(any(QueryWrapper.class));

-    }

-

-    @Test

-    void createTorrent_ShouldSuccess_WithValidData() {

-        Torrent newTorrent = new Torrent();

-        newTorrent.setTorrentName("New Torrent");

-        newTorrent.setDescription("Test creation");

-        newTorrent.setFilePath("/downloads/test.torrent");

-        newTorrent.setRegion("中国");

-

-        when(torrentService.save(any(Torrent.class))).thenReturn(true);

-

-        Result result = torrentController.createTorrent(newTorrent);

-

-        assertEquals(200, result.getCode());

-        assertEquals("成功", result.getMessage());

-        verify(torrentService, times(1)).save(any(Torrent.class));

-    }

-}
\ No newline at end of file
diff --git a/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java b/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java
index ebe2353..a413bda 100644
--- a/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java
+++ b/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java
@@ -6,13 +6,19 @@
 import com.ptp.ptplatform.mapper.UserMapper;
 import com.ptp.ptplatform.utils.JwtUtils;
 import com.ptp.ptplatform.utils.Result;
+import com.ptp.ptplatform.utils.SizeCalculation;
+import io.jsonwebtoken.Claims;
+import jakarta.servlet.http.HttpServletRequest;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
+import org.mockito.MockedStatic;
 import org.mockito.MockitoAnnotations;
 
 import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.Mockito.*;
@@ -26,169 +32,249 @@
     private InviteCodeMapper inviteCodeMapper;
 
     @Mock
-    private JwtUtils jwtUtils;
+    private HttpServletRequest request;
 
     @InjectMocks
     private UserController userController;
 
+    private USER testUser;
+    private INVITE_CODE testInviteCode;
+
     @BeforeEach
     void setUp() {
         MockitoAnnotations.openMocks(this);
+
+        testUser = new USER();
+        testUser.setUsername("testUser");
+        testUser.setPassword("testPassword");
+        testUser.setLastLogin(new Date());
+        testUser.setUpload(1073741824L); // 1GB in bytes
+        testUser.setDownload(536870912L); // 0.5GB in bytes
+
+        testInviteCode = new INVITE_CODE("testUser");
+        testInviteCode.setCode("TESTCODE123");
+        testInviteCode.setIsUsed(false);
     }
 
-//    @Test
-//    void testLogin_Success() {
-//        // 准备测试数据
-//        String username = "testUser";
-//        String password = "testPass";
-//        String hashedPassword = "hashedTestPass";
-//        String token = "generatedToken";
-//
-//        // 创建 mock 对象
-//        USER mockUser = mock(USER.class);
-//        // 使用Mockito方式定义行为
-//        when(mockUser.getUsername()).thenReturn(username);
-//        when(mockUser.getPassword()).thenReturn(hashedPassword);
-//        // 如果 hashPassword 需要被调用
-//        when(mockUser.hashPassword(password)).thenReturn(hashedPassword);
-//
-//        // 模拟Mapper行为
-//        when(userMapper.selectByUsername(username)).thenReturn(mockUser);
-//        when(jwtUtils.generateToken(username)).thenReturn(token);
-//
-//        // 执行测试
-//        Result result = userController.login(username, password);
-//
-//        // 验证结果
-//        assertEquals(200, result.getCode());
-//        assertEquals(token, result.getData().get("token"));
-//        verify(userMapper, times(1)).selectByUsername(username);
-//        verify(jwtUtils, times(1)).generateToken(username);
-//    }
+    @Test
+    void info_Success() {
+        // Arrange
+        when(request.getHeader("Authorization")).thenReturn("validToken");
+
+        Claims mockClaims = mock(Claims.class);
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());
+
+        try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
+            when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
+
+            // Act
+            Result result = userController.info(request);
+
+            // Assert
+            assertTrue(result.isSuccess());
+            assertEquals(testUser, result.getData().get("info"));
+        }
+    }
 
     @Test
-    void testLogin_UserNotFound() {
-        String username = "nonExistUser";
-        String password = "anyPass";
+    void login_Success() {
+        // Arrange
+        when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
-        when(userMapper.selectByUsername(username)).thenReturn(null);
+        // Act
+        Result result = userController.login(testUser.getUsername(), testUser.getPassword());
 
-        Result result = userController.login(username, password);
+        // Assert
+        assertTrue(result.isSuccess());
+        assertNotNull(result.getData().get("token"));
+        verify(userMapper, times(1)).updateUser(testUser);
+    }
 
-        assertEquals(500, result.getCode());
+    @Test
+    void login_Fail_WrongPassword() {
+        // Arrange
+        when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
+
+        // Act
+        Result result = userController.login(testUser.getUsername(), "wrongPassword");
+
+        // Assert
+        assertFalse(result.isSuccess());
+        assertEquals("密码错误", result.getMessage());
+        verify(userMapper, never()).updateUser(any());
+    }
+
+    @Test
+    void login_Fail_UserNotFound() {
+        // Arrange
+        when(userMapper.selectByUsername("nonexistentUser")).thenReturn(null);
+
+        // Act
+        Result result = userController.login("nonexistentUser", "anyPassword");
+
+        // Assert
+        assertFalse(result.isSuccess());
         assertEquals("用户不存在", result.getMessage());
     }
 
-//    @Test
-//    void testLogin_WrongPassword() {
-//        String username = "testUser";
-//        String password = "wrongPass";
-//        String hashedPassword = "hashedTestPass";
-//
-//        USER mockUser = new USER();
-//        mockUser.setUsername(username);
-//        mockUser.setPassword(hashedPassword);
-//
-//        when(userMapper.selectByUsername(username)).thenReturn(mockUser);
-//        when(mockUser.hashPassword(password)).thenReturn("wrongHash");
-//
-//        Result result = userController.login(username, password);
-//
-//        assertEquals(500, result.getCode());
-//        assertEquals("密码错误", result.getMessage());
-//    }
-
     @Test
-    void testRegister_Success() {
-        String username = "newUser";
-        String password = "newPass";
-        String code = "validCode";
-        Date now = new Date();
+    void regist_Success() {
+        // Arrange
+        when(userMapper.selectByUsername("newUser")).thenReturn(null);
+        when(inviteCodeMapper.selectByCode("VALIDCODE")).thenReturn(testInviteCode);
 
-        INVITE_CODE mockInviteCode = new INVITE_CODE();
-        mockInviteCode.setIsUsed(false);
+        // Act
+        Result result = userController.regist("newUser", "newPassword", "VALIDCODE");
 
-        when(userMapper.selectByUsername(username)).thenReturn(null);
-        when(inviteCodeMapper.selectByCode(code)).thenReturn(mockInviteCode);
-
-        Result result = userController.regist(username, password, code);
-
-        assertEquals(200, result.getCode());
+        // Assert
+        assertTrue(result.isSuccess());
         assertEquals("新建用户成功", result.getMessage());
         verify(userMapper, times(1)).insertUser(any(USER.class));
-        verify(inviteCodeMapper, times(1)).updateCodeUser(code);
+        verify(inviteCodeMapper, times(1)).updateCodeUser("VALIDCODE");
     }
 
     @Test
-    void testRegister_UsernameExists() {
-        String username = "existingUser";
-        String password = "anyPass";
-        String code = "anyCode";
+    void regist_Fail_UsernameExists() {
+        // Arrange
+        when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
-        USER existingUser = new USER();
-        when(userMapper.selectByUsername(username)).thenReturn(existingUser);
+        // Act
+        Result result = userController.regist(testUser.getUsername(), "anyPassword", "anyCode");
 
-        Result result = userController.regist(username, password, code);
-
-        assertEquals(500, result.getCode());
+        // Assert
+        assertFalse(result.isSuccess());
         assertEquals("用户名已存在,注册失败", result.getMessage());
         verify(userMapper, never()).insertUser(any());
     }
 
     @Test
-    void testRegister_InvalidCode() {
-        String username = "newUser";
-        String password = "newPass";
-        String code = "invalidCode";
+    void regist_Fail_InvalidCode() {
+        // Arrange
+        when(userMapper.selectByUsername("newUser")).thenReturn(null);
+        when(inviteCodeMapper.selectByCode("INVALIDCODE")).thenReturn(null);
 
-        when(userMapper.selectByUsername(username)).thenReturn(null);
-        when(inviteCodeMapper.selectByCode(code)).thenReturn(null);
+        // Act
+        Result result = userController.regist("newUser", "newPassword", "INVALIDCODE");
 
-        Result result = userController.regist(username, password, code);
-
-        assertEquals(500, result.getCode());
+        // Assert
+        assertFalse(result.isSuccess());
         assertEquals("邀请码不存在,注册失败", result.getMessage());
         verify(userMapper, never()).insertUser(any());
     }
 
     @Test
-    void testRegister_UsedCode() {
-        String username = "newUser";
-        String password = "newPass";
-        String code = "usedCode";
+    void regist_Fail_UsedCode() {
+        // Arrange
+        testInviteCode.setIsUsed(true);
+        when(userMapper.selectByUsername("newUser")).thenReturn(null);
+        when(inviteCodeMapper.selectByCode("USEDCODE")).thenReturn(testInviteCode);
 
-        INVITE_CODE usedCode = new INVITE_CODE();
-        usedCode.setIsUsed(true);
+        // Act
+        Result result = userController.regist("newUser", "newPassword", "USEDCODE");
 
-        when(userMapper.selectByUsername(username)).thenReturn(null);
-        when(inviteCodeMapper.selectByCode(code)).thenReturn(usedCode);
-
-        Result result = userController.regist(username, password, code);
-
-        assertEquals(500, result.getCode());
+        // Assert
+        assertFalse(result.isSuccess());
         assertEquals("邀请码已经被使用,注册失败", result.getMessage());
         verify(userMapper, never()).insertUser(any());
     }
 
-//    @Test
-//    void testGetUserInfo_Success() {
-//        String token = "validToken";
-//        String username = "testUser";
-//
-//        when(jwtUtils.getClaimByToken(token).getSubject()).thenReturn(username);
-//
-//        Result result = userController.info(token);
-//
-//        assertEquals(200, result.getCode());
-//        assertEquals(username, result.getData().get("name"));
-//    }
+    @Test
+    void allowDownload_Success() {
+        // Arrange
+        when(request.getHeader("Authorization")).thenReturn("validToken");
+
+        Claims mockClaims = mock(Claims.class);
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());
+
+        try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
+            when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
+
+            // Act
+            Result result = userController.allowDownload(request);
+
+            // Assert
+            assertTrue(result.isSuccess());
+            Map<String, Object> data = result.getData();
+            assertEquals(1, data.get("totalSize")); // 1GB
+            assertEquals(0, data.get("usedSize")); // 0.5GB (but SizeCalculation.byteToGB rounds down)
+            assertEquals(1, data.get("leftSize")); // 0.5GB rounded up
+        }
+    }
 
     @Test
-    void testLogout() {
-        String token = "anyToken";
+    void updatePassword_Success() {
+        // Arrange
+        when(request.getHeader("Authorization")).thenReturn("validToken");
 
-        Result result = userController.logout(token);
+        Claims mockClaims = mock(Claims.class);
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());
 
-        assertEquals(200, result.getCode());
+        try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
+
+            when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
+
+            Map<String, String> passwordMap = new HashMap<>();
+            passwordMap.put("oldPassword", testUser.getPassword());
+            passwordMap.put("newPassword", "newPassword123");
+
+            // Act
+            Result result = userController.updatePassword(request, passwordMap);
+
+            // Assert
+            assertTrue(result.isSuccess());
+            assertEquals("修改密码成功", result.getMessage());
+            verify(userMapper, times(1)).updateUser(testUser);
+        }
+    }
+
+    @Test
+    void updatePassword_Fail_WrongOldPassword() {
+        // Arrange
+        when(request.getHeader("Authorization")).thenReturn("validToken");
+
+        // 创建模拟的 Claims 对象
+        Claims mockClaims = mock(Claims.class);
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());  // 模拟 getSubject() 返回用户名
+
+        try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
+            // 模拟 JwtUtils.getClaimByToken 返回模拟的 Claims 对象
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
+
+            when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
+
+            Map<String, String> passwordMap = new HashMap<>();
+            passwordMap.put("oldPassword", "wrongPassword");
+            passwordMap.put("newPassword", "newPassword123");
+
+            // Act
+            Result result = userController.updatePassword(request, passwordMap);
+
+            // Assert
+            assertFalse(result.isSuccess());
+            assertEquals("原密码不正确", result.getMessage());
+            verify(userMapper, never()).updateUser(any());
+        }
+    }
+
+    @Test
+    void getUserInRequest_Success() {
+        // Arrange
+        when(request.getHeader("Authorization")).thenReturn("validToken");
+        Claims mockClaims = mock(Claims.class);
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());  // 模拟 getSubject() 返回用户名
+
+        try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
+            when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
+
+            // Act
+            USER result = userController.getUserInRequest(request);
+
+            // Assert
+            assertEquals(testUser, result);
+        }
     }
 }
\ No newline at end of file