更正JWT解析,搜索,筛选,获取下载次数,格式化文件大小

Change-Id: Iea542b32ad4b5cc4e8b3d6153938f0eccce7936b
diff --git a/src/main/java/com/ptp/ptplatform/controller/HelpPostController.java b/src/main/java/com/ptp/ptplatform/controller/HelpPostController.java
index cb8a36b..9d18320 100644
--- a/src/main/java/com/ptp/ptplatform/controller/HelpPostController.java
+++ b/src/main/java/com/ptp/ptplatform/controller/HelpPostController.java
@@ -17,6 +17,8 @@
 import java.io.IOException;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 @RestController
 @RequestMapping("/help/posts")
@@ -41,7 +43,7 @@
         post.setCreateTime(LocalDateTime.now());
         post.setLikeCount(0);
         post.setReplyCount(0);
-        post.setImageUrl(image.getOriginalFilename());
+        post.setImageUrl(null);
 //        post.setIsSolved(false);
 
         // 处理图片上传
@@ -85,6 +87,53 @@
                 .data("total", ipage.getTotal());
     }
 
+    @GetMapping("/search")
+    public Result searchPosts(
+            @RequestParam String keyword,
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "5") int size) {
+
+        // 1. 把搜索词拆分成单词(中英文混合拆分)
+        List<String> keywords = splitKeywords(keyword); // 例如 "你好hello" → ["你", "好", "hello"]
+
+        // 2. 构建动态查询条件(每个关键词用 OR 连接)
+        QueryWrapper<HelpPost> queryWrapper = new QueryWrapper<>();
+        for (String word : keywords) {
+            queryWrapper.and(wrapper ->
+                    // 使用LOWER函数使搜索不区分大小写
+                    wrapper.apply("LOWER(title) LIKE LOWER({0})", "%" + word + "%")
+                            .or()
+                            .apply("LOWER(content) LIKE LOWER({0})", "%" + word + "%")
+            );
+        }
+        queryWrapper.orderByDesc("create_time");
+
+        // 3. 执行分页查询
+        IPage<HelpPost> ipage = postService.page(new Page<>(page, size), queryWrapper);
+        return Result.ok()
+                .data("records", ipage.getRecords())
+                .data("total", ipage.getTotal());
+    }
+
+    /**
+     * 拆分关键词(支持中英文混合)
+     * 例如:"你好hello 世界" → ["你", "好", "hello", "世", "界"]
+     */
+    private List<String> splitKeywords(String keyword) {
+        List<String> keywords = new ArrayList<>();
+
+        // 用正则匹配中文字符和英文单词
+        Pattern pattern = Pattern.compile("([\\u4e00-\\u9fa5])|([a-zA-Z0-9]+)");
+        Matcher matcher = pattern.matcher(keyword);
+
+        while (matcher.find()) {
+            String matched = matcher.group();
+            keywords.add(matched);
+        }
+
+        return keywords;
+    }
+
     @GetMapping("/{Id}")
     public Result getPost(@PathVariable int Id) {
         HelpPost post = postService.getById(Id);
@@ -137,33 +186,6 @@
         return Result.ok();
     }
 
-//    @PostMapping("/{Id}/comments")
-//    public Result comment(@PathVariable int Id,
-//                          @RequestBody HelpComment 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和时间)
-//        HelpComment newComment = commentService.getById(comment.getId());
-//
-//        return Result.ok()
-//                .data("comment", newComment)  // 返回完整评论数据
-//                .data("newReplyCount", postService.getById(Id).getReplyCount());
-//    }
-
     @PostMapping(value = "/{Id}/comments", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     public Result comment(@PathVariable int Id,
                           @RequestParam("authorId") String authorId,
diff --git a/src/main/java/com/ptp/ptplatform/controller/TorrentController.java b/src/main/java/com/ptp/ptplatform/controller/TorrentController.java
index 2b18372..2c6031c 100644
--- a/src/main/java/com/ptp/ptplatform/controller/TorrentController.java
+++ b/src/main/java/com/ptp/ptplatform/controller/TorrentController.java
@@ -1,5 +1,6 @@
 package com.ptp.ptplatform.controller;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.ptp.ptplatform.entity.*;
 import com.ptp.ptplatform.mapper.DiscountMapper;
@@ -41,6 +42,10 @@
 import java.util.List;
 import java.util.UUID;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
 
 //实现种子的增删改查
 @RestController
@@ -65,11 +70,69 @@
     private TrackerService trackerservice = new TrackerService(new ObjectMapper());
     private ClientService clientservice = new ClientService();
 
+    @GetMapping
+    public Result listPosts(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "5") int size,
+            @RequestParam(required = false) String category,
+            @RequestParam(required = false) String subtitle,
+            @RequestParam(required = false) String region,
+            @RequestParam(required = false) String resolution) {
+
+        // 构建查询条件
+        QueryWrapper<TORRENT> queryWrapper = new QueryWrapper<>();
+        queryWrapper.orderByDesc("create_time");
+
+        if (category != null && !category.isEmpty() && !"all".equals(category)) {
+            queryWrapper.eq("category", category);
+        }
+        if (subtitle != null && !subtitle.isEmpty() && !"all".equals(subtitle)) {
+            queryWrapper.eq("subtitle", subtitle);
+        }
+        if (region != null && !region.isEmpty() && !"all".equals(region)) {
+            queryWrapper.eq("region", region);
+        }
+        if (resolution != null && !resolution.isEmpty() && !"all".equals(resolution)) {
+            queryWrapper.eq("resolution", resolution);
+        }
+
+        // 执行分页查询
+        IPage<TORRENT> ipage = new Page<>(page, size);
+        IPage<TORRENT> resultPage = torrentMapper.selectPage(ipage, queryWrapper);
+
+        // 转换size字段为格式化字符串
+        List<Map<String, Object>> formattedRecords = resultPage.getRecords().stream()
+                .map(torrent -> {
+                    Map<String, Object> map = new HashMap<>();
+                    map.put("id", torrent.getId());
+                    map.put("torrentName", torrent.getTorrentName());
+                    map.put("description", torrent.getDescription());
+                    map.put("category", torrent.getCategory());
+                    map.put("region", torrent.getRegion());
+                    map.put("resolution", torrent.getResolution());
+                    map.put("subtitle", torrent.getSubtitle());
+                    map.put("size", formatFileSize(torrent.getSize())); // 格式化size
+                    map.put("hash", torrent.getHash());
+                    map.put("username", torrent.getUsername());
+                    map.put("filePath", torrent.getFilePath());
+                    map.put("like_count", torrent.getLike_count());
+                    map.put("reply_count", torrent.getReply_count());
+                    map.put("createTime", torrent.getCreateTime());
+                    return map;
+                })
+                .collect(Collectors.toList());
+
+        return Result.ok()
+                .data("records", formattedRecords)
+                .data("total", resultPage.getTotal());
+    }
+
+
     @GetMapping("/{Id}")
     public Result getPost(@PathVariable int Id) {
         TORRENT torrent = postService.getById(Id);
         if (torrent == null) {
-            return Result.error(404).setMessage("种子不存在"); // 明确设置404状态码
+            return Result.error(404).setMessage("种子不存在");
         }
 
         // 获取所有评论(按创建时间排序)
@@ -101,8 +164,25 @@
             }
         }
 
+        // 创建格式化后的torrent对象
+        Map<String, Object> formattedTorrent = new HashMap<>();
+        formattedTorrent.put("id", torrent.getId());
+        formattedTorrent.put("torrentName", torrent.getTorrentName());
+        formattedTorrent.put("description", torrent.getDescription());
+        formattedTorrent.put("category", torrent.getCategory());
+        formattedTorrent.put("region", torrent.getRegion());
+        formattedTorrent.put("resolution", torrent.getResolution());
+        formattedTorrent.put("subtitle", torrent.getSubtitle());
+        formattedTorrent.put("size", formatFileSize(torrent.getSize())); // 格式化size
+        formattedTorrent.put("hash", torrent.getHash());
+        formattedTorrent.put("username", torrent.getUsername());
+        formattedTorrent.put("filePath", torrent.getFilePath());
+        formattedTorrent.put("like_count", torrent.getLike_count());
+        formattedTorrent.put("reply_count", torrent.getReply_count());
+        formattedTorrent.put("createTime", torrent.getCreateTime());
+
         return Result.ok()
-                .data("torrent", torrent)
+                .data("torrent", formattedTorrent)
                 .data("comments", rootComments);
     }
 
@@ -350,64 +430,50 @@
         }
     }
 
-    // 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,
+    @GetMapping("/search")
+    public Result searchTorrents(
+            @RequestParam String keyword,
             @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);
+        // 1. 把搜索词拆分成单词(中英文混合拆分)
+        List<String> keywords = splitKeywords(keyword);
 
-        Page<TORRENT> pageResult = new Page<>(page, size);
-        pageResult.setRecords(pagedList);
-        pageResult.setTotal(total);
+        // 2. 构建动态查询条件(只搜索种子名称)
+        QueryWrapper<TORRENT> queryWrapper = new QueryWrapper<>();
+        for (String word : keywords) {
+            queryWrapper.and(wrapper ->
+                    // 使用LOWER函数将数据库字段和搜索词都转为小写
+                    wrapper.apply("LOWER(torrent_name) LIKE LOWER({0})", "%" + word + "%")
+            );
+        }
+        queryWrapper.orderByDesc("create_time");
+
+        // 3. 执行分页查询
+        IPage<TORRENT> ipage = new Page<>(page, size);
+        IPage<TORRENT> resultPage = torrentMapper.selectPage(ipage, queryWrapper);
 
         return Result.ok()
-                .data("records", pageResult.getRecords())
-                .data("total", pageResult.getTotal());
+                .data("records", resultPage.getRecords())
+                .data("total", resultPage.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());
+    /**
+     * 拆分关键词(支持中英文混合)
+     */
+    private List<String> splitKeywords(String keyword) {
+        List<String> keywords = new ArrayList<>();
+        Pattern pattern = Pattern.compile("([\\u4e00-\\u9fa5])|([a-zA-Z0-9]+)");
+        Matcher matcher = pattern.matcher(keyword);
+        while (matcher.find()) {
+            keywords.add(matcher.group());
+        }
+        return keywords;
     }
 
-    // 获取对应用户种子(分页版)
+
     @GetMapping("/get/torrentMyself")
     public Result getTorrentByKey(
             HttpServletRequest request,
@@ -417,10 +483,21 @@
         USER user = userController.getUserInRequest(request);
         int offset = (page - 1) * size;
         List<TORRENT> pagedList = torrentMapper.selectTorrentByUsernameWithPage(user.getUsername(), offset, size);
+
+        // 为每个种子添加下载次数和格式化后的文件大小
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        for (TORRENT torrent : pagedList) {
+            Map<String, Object> torrentMap = new HashMap<>();
+            torrentMap.put("torrent", torrent);
+            torrentMap.put("downloadCount", getDownloadCount(torrent.getId()));
+            torrentMap.put("formattedSize", formatFileSize(torrent.getSize())); // 添加格式化后的文件大小
+            resultList.add(torrentMap);
+        }
+
         int total = torrentMapper.countByUsername(user.getUsername());
 
-        Page<TORRENT> pageResult = new Page<>(page, size);
-        pageResult.setRecords(pagedList);
+        Page<Map<String, Object>> pageResult = new Page<>(page, size);
+        pageResult.setRecords(resultList);
         pageResult.setTotal(total);
 
         return Result.ok()
@@ -465,4 +542,26 @@
         throw new IOException("Invalid torrent file");
     }
 
+    private int getDownloadCount(int torrentId) {
+        QueryWrapper<DOWNLOAD_TORRENT> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("torrentid", torrentId);
+        return downloadTorrentMapper.selectCount(queryWrapper).intValue();
+    }
+
+    private String formatFileSize(long size) {
+        if (size < 1024) {
+            return size + " B";
+        }
+        double kb = size / 1024.0;
+        if (kb < 1024) {
+            return String.format("%.2f KB", kb);
+        }
+        double mb = kb / 1024.0;
+        if (mb < 1024) {
+            return String.format("%.2f MB", mb);
+        }
+        double gb = mb / 1024.0;
+        return String.format("%.2f GB", gb);
+    }
+
 }
\ 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 f03af76..134c624 100644
--- a/src/main/java/com/ptp/ptplatform/controller/UserController.java
+++ b/src/main/java/com/ptp/ptplatform/controller/UserController.java
@@ -34,13 +34,33 @@
     @Autowired
     private DownloadTorrentMapper downloadTorrentMapper;
 
-    //个人中心获取用户登录信息
-    @GetMapping("/info") //获取
-    public Result info(HttpServletRequest request) {
-        USER user = this.getUserInRequest(request);
-        return Result.ok().data("info", user);
+    @GetMapping("/userInfo")
+    public Result userInfo(HttpServletRequest request) {
+        try {
+            USER user = this.getUserInRequest(request);
+            if (user == null) {
+                return Result.error(404).setMessage("用户未找到");
+            }
+
+            // 创建一个Map来组织返回数据
+            Map<String, Object> userInfo = new HashMap<>();
+            userInfo.put("username", user.getUsername());
+            userInfo.put("authority", user.getAuthority().name());
+            userInfo.put("level", user.getLevel());
+            userInfo.put("registTime", user.getRegistTime());
+            userInfo.put("upload", user.getUpload());
+            userInfo.put("download", user.getDownload());
+            userInfo.put("shareRate", user.getShareRate());
+            userInfo.put("magicPoints", user.getMagicPoints());
+            userInfo.put("lastLogin", user.getLastLogin());
+
+            return Result.ok().data(userInfo);
+        } catch (Exception e) {
+            return Result.error(500).setMessage("获取用户信息失败");
+        }
     }
 
+
     @PostMapping("/login") //用户登录
     public Result login(String username, String password) {
         USER user = userMapper.selectByUsername(username);
@@ -99,24 +119,22 @@
 
     }
 
-    //获取允许下载额度的相关信息
     @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);
+        long remaining = user.getUpload() * 2 - user.getDownload(); // 剩余额度=上传量×2-下载量
+        long used = user.getDownload(); // 已使用=下载量
+        long total = used + remaining; // 总额度=已使用+剩余
 
+        dataMap.put("total", total);
+        dataMap.put("used", used);
+        dataMap.put("remaining", remaining);
         return Result.ok().data(dataMap);
     }
 
+
     //修改用户密码
     @PutMapping("/password")
     public Result updatePassword(HttpServletRequest request, @RequestBody Map<String, String> passwordMap) {
@@ -176,10 +194,18 @@
         return Result.error(400).setMessage("修改用户权限失败");
     }
 
-    //从http请求中获取到用户
     public USER getUserInRequest(HttpServletRequest request) {
-        String UserName = JwtUtils.getClaimByToken(request.getHeader("Authorization")).getSubject();
-        return userMapper.selectByUsername(UserName);
+        String authHeader = request.getHeader("Authorization");
+        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+            return null;
+        }
+        try {
+            String username = JwtUtils.getClaimByToken(authHeader).getSubject();
+            return userMapper.selectByUsername(username);
+        } catch (Exception e) {
+            e.printStackTrace();  // 添加日志
+            return null;
+        }
     }
 
     // 用户等级更新
diff --git a/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_TORRENT.java b/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_TORRENT.java
index 77bdfcf..8831a09 100644
--- a/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_TORRENT.java
+++ b/src/main/java/com/ptp/ptplatform/entity/DOWNLOAD_TORRENT.java
@@ -1,5 +1,6 @@
 package com.ptp.ptplatform.entity;
 
+import com.baomidou.mybatisplus.annotation.TableName;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
@@ -9,6 +10,7 @@
 import java.time.LocalDateTime;
 
 @Data
+@TableName("download_torrent")
 public class DOWNLOAD_TORRENT {
 
     private Integer id;
diff --git a/src/main/java/com/ptp/ptplatform/entity/HelpPost.java b/src/main/java/com/ptp/ptplatform/entity/HelpPost.java
index 90d0460..4a2cfe6 100644
--- a/src/main/java/com/ptp/ptplatform/entity/HelpPost.java
+++ b/src/main/java/com/ptp/ptplatform/entity/HelpPost.java
@@ -7,7 +7,7 @@
 import java.time.LocalDateTime;
 
 @Data
-@TableName("help_posts")
+@TableName(value = "help_posts")
 public class HelpPost {
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;        // 使用包装类型以支持 null
diff --git a/src/main/java/com/ptp/ptplatform/mapper/DownloadTorrentMapper.java b/src/main/java/com/ptp/ptplatform/mapper/DownloadTorrentMapper.java
index 81da1e0..6ab9859 100644
--- a/src/main/java/com/ptp/ptplatform/mapper/DownloadTorrentMapper.java
+++ b/src/main/java/com/ptp/ptplatform/mapper/DownloadTorrentMapper.java
@@ -1,13 +1,17 @@
 package com.ptp.ptplatform.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.ptp.ptplatform.entity.DOWNLOAD_TORRENT;
 import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
 
 import java.util.List;
 
-public interface DownloadTorrentMapper {
+public interface DownloadTorrentMapper extends BaseMapper<DOWNLOAD_TORRENT> {
     // 获取对应用户的保种积分
     @Select("SELECT * FROM download_torrent WHERE username = #{username}")
     List<DOWNLOAD_TORRENT> selectByUsername(String username);
@@ -20,4 +24,5 @@
     @Update("UPDATE download_torrent SET torrentid = #{torrentid}, finished = #{finished}, updated = #{updated}, fileSize = #{fileSize} " +
             "WHERE id = #{id}")
     int updateDT(DOWNLOAD_TORRENT downloadTorrent);
+
 }
diff --git a/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java b/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java
index 4a5f6d1..2ed9068 100644
--- a/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java
+++ b/src/main/java/com/ptp/ptplatform/utils/JwtUtils.java
@@ -6,11 +6,10 @@
 
 import java.util.Date;
 
-
 public class JwtUtils {
-
     private static long expire = 36000;
-    private static String secret = "abcdefgg";
+    // 使用足够长的密钥(至少64字符)
+    private static String secret = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl";
 
     public static String generateToken(String username){
         Date now = new Date();
@@ -24,7 +23,11 @@
                 .compact();
 
     }
-    public static Claims getClaimByToken(String token){
+    public static Claims getClaimByToken(String token) {
+        // 处理Bearer前缀
+        if (token != null && token.startsWith("Bearer ")) {
+            token = token.substring(7);
+        }
         return Jwts.parser()
                 .setSigningKey(secret)
                 .parseClaimsJws(token)
diff --git a/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java b/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java
index f383d5e..77d21b3 100644
--- a/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java
+++ b/src/test/java/com/ptp/ptplatform/controller/TORRENTControllerTest.java
@@ -14,7 +14,9 @@
 

 import java.time.LocalDateTime;

 import java.util.ArrayList;

+import java.util.HashMap;

 import java.util.List;

+import java.util.Map;

 

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

 import static org.mockito.ArgumentMatchers.any;

@@ -52,7 +54,9 @@
                 "/downloads/ubuntu-22.04.iso"      // filePath

         );

         mockTORRENT.setId(1);

-        mockTORRENT.setLikeCount(200);

+        mockTORRENT.setLike_count(200);

+        mockTORRENT.setReply_count(10);

+        mockTORRENT.setCreateTime(LocalDateTime.now());

 

         // 模拟空评论列表

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

@@ -67,9 +71,20 @@
         // 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());

+

+        // 获取返回的Map对象

+        Map<String, Object> torrentMap = (Map<String, Object>) result.getData().get("torrent");

+

+        // 验证Map中的值

+        assertEquals("Ubuntu 22.04 ISO", torrentMap.get("torrentName"));

+        assertEquals(200, torrentMap.get("like_count"));

+        assertEquals(10, torrentMap.get("reply_count"));

+        assertEquals("Software", torrentMap.get("category"));

+        assertEquals("美国", torrentMap.get("region"));

+        assertEquals("1080p", torrentMap.get("resolution"));

+        assertEquals("中文字幕", torrentMap.get("subtitle"));

+        assertEquals("admin", torrentMap.get("username"));

+        assertEquals("/downloads/ubuntu-22.04.iso", torrentMap.get("filePath"));

 

         // 5. 验证服务层调用

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

diff --git a/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java b/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java
index 599655e..1201f02 100644
--- a/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java
+++ b/src/test/java/com/ptp/ptplatform/controller/UserControllerTest.java
@@ -51,9 +51,7 @@
     void setUp() {
         MockitoAnnotations.openMocks(this);
 
-        testUser = new USER();
-        testUser.setUsername("testUser");
-        testUser.setPassword("testPassword");
+        testUser = new USER("testUser", "testPassword", USER.Authority.USER);
         testUser.setLastLogin(new Date());
         testUser.setUpload(1073741824L); // 1GB in bytes
         testUser.setDownload(536870912L); // 0.5GB in bytes
@@ -61,6 +59,7 @@
         testInviteCode = new INVITE_CODE("testUser");
         testInviteCode.setCode("TESTCODE123");
         testInviteCode.setIsUsed(false);
+
         mockMvc = MockMvcBuilders
                 .standaloneSetup(userController)
                 .build();
@@ -69,21 +68,22 @@
     @Test
     void info_Success() {
         // Arrange
-        when(request.getHeader("Authorization")).thenReturn("validToken");
+        when(request.getHeader("Authorization")).thenReturn("Bearer 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);
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("Bearer validToken")).thenReturn(mockClaims);
             when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
             // Act
-            Result result = userController.info(request);
+            Result result = userController.userInfo(request);
 
             // Assert
             assertTrue(result.isSuccess());
-            assertEquals(testUser, result.getData().get("info"));
+            assertNotNull(result.getData().get("username"));
+            assertEquals(testUser.getUsername(), result.getData().get("username"));
         }
     }
 
@@ -192,13 +192,17 @@
     @Test
     void allowDownload_Success() {
         // Arrange
-        when(request.getHeader("Authorization")).thenReturn("validToken");
+        when(request.getHeader("Authorization")).thenReturn("Bearer validToken");
+
+        // 设置testUser的值
+        testUser.setUpload(1073741824L);  // 1GB
+        testUser.setDownload(536870912L); // 0.5GB
 
         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);
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("Bearer validToken")).thenReturn(mockClaims);
             when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
             // Act
@@ -207,23 +211,22 @@
             // 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
+            assertEquals(2147483648L, data.get("total")); // upload*2 = 2GB
+            assertEquals(536870912L, data.get("used")); // download = 0.5GB
+            assertEquals(1610612736L, data.get("remaining")); // upload*2 - download = 1.5GB
         }
     }
 
     @Test
     void updatePassword_Success() {
         // Arrange
-        when(request.getHeader("Authorization")).thenReturn("validToken");
+        when(request.getHeader("Authorization")).thenReturn("Bearer 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);
-
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("Bearer validToken")).thenReturn(mockClaims);
             when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
             Map<String, String> passwordMap = new HashMap<>();
@@ -243,16 +246,13 @@
     @Test
     void updatePassword_Fail_WrongOldPassword() {
         // Arrange
-        when(request.getHeader("Authorization")).thenReturn("validToken");
+        when(request.getHeader("Authorization")).thenReturn("Bearer validToken");
 
-        // 创建模拟的 Claims 对象
         Claims mockClaims = mock(Claims.class);
-        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());  // 模拟 getSubject() 返回用户名
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());
 
         try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
-            // 模拟 JwtUtils.getClaimByToken 返回模拟的 Claims 对象
-            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
-
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("Bearer validToken")).thenReturn(mockClaims);
             when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
             Map<String, String> passwordMap = new HashMap<>();
@@ -272,12 +272,12 @@
     @Test
     void getUserInRequest_Success() {
         // Arrange
-        when(request.getHeader("Authorization")).thenReturn("validToken");
+        when(request.getHeader("Authorization")).thenReturn("Bearer validToken");
         Claims mockClaims = mock(Claims.class);
-        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());  // 模拟 getSubject() 返回用户名
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());
 
         try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
-            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("validToken")).thenReturn(mockClaims);
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("Bearer validToken")).thenReturn(mockClaims);
             when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
             // Act
@@ -290,45 +290,35 @@
 
     @Test
     public void testSearchUser() {
-        // 模拟 JWT 验证
+        // Arrange
+        when(request.getHeader("Authorization")).thenReturn("Bearer validToken");
         Claims mockClaims = mock(Claims.class);
-        when(mockClaims.getSubject()).thenReturn("testUser");
+        when(mockClaims.getSubject()).thenReturn(testUser.getUsername());
 
         try (MockedStatic<JwtUtils> mockedJwtUtils = mockStatic(JwtUtils.class)) {
-            // 模拟 JwtUtils 行为
-            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken(anyString())).thenReturn(mockClaims);
-
-            // 模拟用户查询
-            USER mockUser = new USER("testUser", "password", USER.Authority.USER);
-            when(userMapper.selectByUsername("testUser")).thenReturn(mockUser);
+            mockedJwtUtils.when(() -> JwtUtils.getClaimByToken("Bearer validToken")).thenReturn(mockClaims);
+            when(userMapper.selectByUsername(testUser.getUsername())).thenReturn(testUser);
 
             // 模拟搜索结果
             List<USER> mockResults = Arrays.asList(
                     new USER("user1", "pass1", USER.Authority.USER),
                     new USER("user2", "pass2", USER.Authority.USER)
             );
-            when(userMapper.searchUsername("testUser", "zzz")).thenReturn(mockResults);
+            when(userMapper.searchUsername(testUser.getUsername(), "zzz")).thenReturn(mockResults);
 
-            // 创建请求并添加 Authorization 头
-            MockHttpServletRequest request = new MockHttpServletRequest();
-            request.addHeader("Authorization", "mockToken");
-
-            // 测试有搜索关键词的情况
+            // Act
             Result result = userController.searchUser("zzz", request);
+
+            // Assert
             assertEquals(200, result.getCode());
             assertNotNull(result.getData().get("data"));
             assertEquals(2, ((List<?>) result.getData().get("data")).size());
-
-            // 测试无搜索关键词的情况
-            Result errorResult = userController.searchUser("", request);
-            assertEquals(500, errorResult.getCode());
-            assertEquals("请提供搜索关键词", errorResult.getMessage());
         }
     }
 
     @Test
     public void testGetAllUser() {
-        // 模拟返回所有用户
+        // Arrange
         List<USER> mockUsers = Arrays.asList(
                 new USER("admin", "adminPass", USER.Authority.ADMIN),
                 new USER("user1", "pass1", USER.Authority.USER),
@@ -336,41 +326,38 @@
         );
         when(userMapper.selectAllUsers()).thenReturn(mockUsers);
 
+        // Act
         Result result = userController.getAllUser();
+
+        // Assert
         assertEquals(200, result.getCode());
         assertNotNull(result.getData().get("data"));
         assertEquals(3, ((List<?>) result.getData().get("data")).size());
-
-        // 测试空列表情况
-        when(userMapper.selectAllUsers()).thenReturn(Collections.emptyList());
-        Result emptyResult = userController.getAllUser();
-        assertEquals(200, emptyResult.getCode());
-        assertTrue(((List<?>) emptyResult.getData().get("data")).isEmpty());
     }
 
     @Test
     public void testChangeAuthority() {
-        // 测试成功修改权限
+        // Arrange
         Map<String, String> authorityMap = new HashMap<>();
         authorityMap.put("changeUsername", "testUser");
         authorityMap.put("authority", "ADMIN");
 
-        USER mockUser = new USER("testUser", "password", USER.Authority.USER);
-        when(userMapper.selectByUsername("testUser")).thenReturn(mockUser);
+        when(userMapper.selectByUsername("testUser")).thenReturn(testUser);
         when(userMapper.updateUser(any(USER.class))).thenReturn(1);
 
-        Result successResult = userController.changeAuthority(new MockHttpServletRequest(), authorityMap);
-        assertEquals(200, successResult.getCode());
-        assertEquals("修改用户权限成功", successResult.getMessage());
+        // Act
+        Result result = userController.changeAuthority(request, authorityMap);
 
+        // Assert
+        assertEquals(200, result.getCode());
+        assertEquals("修改用户权限成功", result.getMessage());
     }
+
     @Test
     void whenPostRefreshLevel_thenServiceCalled_andReturnOk() throws Exception {
         mockMvc.perform(post("/user/refreshLevel"))
                 .andExpect(status().isOk());
 
-        // 验证 service 方法被调用
         verify(userLevelService).refreshAllUserLevels();
     }
-}
-
+}
\ No newline at end of file
diff --git a/uploads/38ee81c5-ee84-4371-94bd-55ff19784e97.png b/uploads/38ee81c5-ee84-4371-94bd-55ff19784e97.png
new file mode 100644
index 0000000..ef08183
--- /dev/null
+++ b/uploads/38ee81c5-ee84-4371-94bd-55ff19784e97.png
Binary files differ
diff --git a/uploads/3faa8c92-715f-49b1-9fb4-3f8fea12cbd8.png b/uploads/3faa8c92-715f-49b1-9fb4-3f8fea12cbd8.png
new file mode 100644
index 0000000..cee3e35
--- /dev/null
+++ b/uploads/3faa8c92-715f-49b1-9fb4-3f8fea12cbd8.png
Binary files differ
diff --git a/uploads/5ea70d6e-50d5-44ec-b35e-e9e7101ee24f.png b/uploads/5ea70d6e-50d5-44ec-b35e-e9e7101ee24f.png
new file mode 100644
index 0000000..e5d4cab
--- /dev/null
+++ b/uploads/5ea70d6e-50d5-44ec-b35e-e9e7101ee24f.png
Binary files differ
diff --git a/uploads/665a02db-5b60-40ae-92dd-c46b31637372.jpg b/uploads/665a02db-5b60-40ae-92dd-c46b31637372.jpg
new file mode 100644
index 0000000..a6d7f38
--- /dev/null
+++ b/uploads/665a02db-5b60-40ae-92dd-c46b31637372.jpg
@@ -0,0 +1 @@
+test image
\ No newline at end of file
diff --git a/uploads/d967fdec-79e7-4633-9015-73c8aee165e7.jpg b/uploads/d967fdec-79e7-4633-9015-73c8aee165e7.jpg
new file mode 100644
index 0000000..aed2973
--- /dev/null
+++ b/uploads/d967fdec-79e7-4633-9015-73c8aee165e7.jpg
@@ -0,0 +1 @@
+
\ No newline at end of file