更改了sql,测试接口

Change-Id: I412dc58fd46e5bd747cc870afdb1c0a5af09e06b
diff --git a/pom.xml b/pom.xml
index 65998ab..e26fb29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -191,6 +191,12 @@
             <artifactId>jackson-databind</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.pagehelper</groupId>
+            <artifactId>pagehelper-spring-boot-starter</artifactId>
+            <version>1.4.7</version>
+        </dependency>
+
     </dependencies>
 
     <build>
diff --git a/src/main/java/edu/bjtu/groupone/backend/api/WorkController.java b/src/main/java/edu/bjtu/groupone/backend/api/WorkController.java
index b181916..893bbb4 100644
--- a/src/main/java/edu/bjtu/groupone/backend/api/WorkController.java
+++ b/src/main/java/edu/bjtu/groupone/backend/api/WorkController.java
@@ -1,5 +1,6 @@
 package edu.bjtu.groupone.backend.api;
 
+import com.github.pagehelper.PageInfo;
 import edu.bjtu.groupone.backend.domain.dto.WorkResponse;
 import edu.bjtu.groupone.backend.domain.dto.WorkDetailResponse;
 import edu.bjtu.groupone.backend.domain.entity.Result;
@@ -38,7 +39,7 @@
 
     @GetMapping
     @Operation(summary = "获取作品列表", description = "可按分区分页查询作品")
-    public ResponseEntity<Page<WorkResponse>> getWorks(
+    public ResponseEntity<PageInfo<WorkResponse>> getWorks(
             @Parameter(description = "分区 ID(可选)") @RequestParam(required = false) Long categoryId,
             @Parameter(description = "页码,从 1 开始", example = "1") @RequestParam(defaultValue = "1") int page,
             @Parameter(description = "每页数量", example = "20") @RequestParam(defaultValue = "20") int size) {
@@ -74,7 +75,9 @@
             @RequestParam("title") String title,
             @RequestParam("author") String author,
             @RequestParam("categoryId") Long categoryId,
-            @RequestParam("description") String description) {
+            @RequestParam("description") String description,
+            @RequestParam("userId") Long userId,
+            @RequestParam("status") String status) {
         try {
             String coverUrl = aliOSSUtils.upload(cover);
             Work work = new Work();
@@ -82,6 +85,8 @@
             work.setAuthor(author);
             work.setDescription(description);
             work.setCover(coverUrl);
+            work.setUserId(userId);
+            work.setStatus(status);
             Category category = new Category();
             category.setId(categoryId);
             work.setCategory(category);
diff --git a/src/main/java/edu/bjtu/groupone/backend/domain/dto/WorkDetailResponse.java b/src/main/java/edu/bjtu/groupone/backend/domain/dto/WorkDetailResponse.java
index 84065b0..f32d465 100644
--- a/src/main/java/edu/bjtu/groupone/backend/domain/dto/WorkDetailResponse.java
+++ b/src/main/java/edu/bjtu/groupone/backend/domain/dto/WorkDetailResponse.java
@@ -3,6 +3,7 @@
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 import java.util.List;
+import java.util.Map;
 
 @Data
 public class WorkDetailResponse {
@@ -56,4 +57,5 @@
         private String username;
         private String uploadTotal;
     }
+
 } 
\ No newline at end of file
diff --git a/src/main/java/edu/bjtu/groupone/backend/domain/entity/Version.java b/src/main/java/edu/bjtu/groupone/backend/domain/entity/Version.java
index 1cd1706..b926b71 100644
--- a/src/main/java/edu/bjtu/groupone/backend/domain/entity/Version.java
+++ b/src/main/java/edu/bjtu/groupone/backend/domain/entity/Version.java
@@ -1,13 +1,16 @@
 package edu.bjtu.groupone.backend.domain.entity;
 
+import jakarta.persistence.Column;
 import lombok.Data;
 
 @Data
 public class Version {
     private Long id;
+    @Column(name = "work_id", nullable = false)
     private Long workId;
     private String versionNumber;
     private String fileUrl;
     private String description; // 版本描述
     private String createTime;
+
 } 
\ No newline at end of file
diff --git a/src/main/java/edu/bjtu/groupone/backend/domain/entity/Work.java b/src/main/java/edu/bjtu/groupone/backend/domain/entity/Work.java
index 1549ce1..f1620f6 100644
--- a/src/main/java/edu/bjtu/groupone/backend/domain/entity/Work.java
+++ b/src/main/java/edu/bjtu/groupone/backend/domain/entity/Work.java
@@ -1,3 +1,5 @@
+// edu.bjtu.groupone.backend.domain.entity.Work
+
 package edu.bjtu.groupone.backend.domain.entity;
 
 import jakarta.persistence.*;
@@ -5,15 +7,19 @@
 
 @Entity
 @Table(name = "works")
-@Data // 自动生成 getter/setter/toString
-@NoArgsConstructor // JPA 必需的无参构造
-@AllArgsConstructor // 全参构造
-@Builder // 关键修复:添加 Builder 模式
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Builder
 public class Work {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)
     private Long id;
 
+    /** 新增:用户 ID */
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+
     @Column(nullable = false, length = 255)
     private String title;
 
@@ -29,15 +35,21 @@
             foreignKey = @ForeignKey(name = "fk_work_category")
     )
     private Category category;
+
     @Column(columnDefinition = "TEXT")
     private String description;
 
-    @Column(name = "create_time")
+    /** 已有:创建时间 */
+    @Column(name = "create_time", updatable = false)
     private String createTime;
 
+    /** 新增:更新时间 */
+    @Column(name = "update_time")
+    private String updateTime;
+
     @Column(length = 255)
     private String cover;
 
     @Column(nullable = false, length = 20)
     private String status;
-}
\ No newline at end of file
+}
diff --git a/src/main/java/edu/bjtu/groupone/backend/mapper/CommentMapper.java b/src/main/java/edu/bjtu/groupone/backend/mapper/CommentMapper.java
index e45ba4e..d8a69c9 100644
--- a/src/main/java/edu/bjtu/groupone/backend/mapper/CommentMapper.java
+++ b/src/main/java/edu/bjtu/groupone/backend/mapper/CommentMapper.java
@@ -10,13 +10,13 @@
     @Insert("INSERT INTO `comment` (`post_id`, `user_id`, `content`, `create_time`) VALUES (#{postId}, #{userId}, #{content}, #{createTime})")
     void insertComment(Comment comment);
 
-    @Delete("DELETE FROM `comment` WHERE `comment_id` = #{commentId}")
+    @Delete("DELETE FROM `comment` WHERE `id` = #{commentId}")
     void deleteComment(Long commentId);
 
     @Update("UPDATE `comment` SET `post_id` = #{postId}, `user_id` = #{userId}, `content` = #{content}, `create_time` = #{createTime} WHERE `comment_id` = #{commentId}")
     void updateComment(Comment comment);
 
-    @Select("SELECT * FROM `comment` WHERE `comment_id` = #{commentId}")
+    @Select("SELECT * FROM `comment` WHERE `id` = #{commentId}")
     Comment selectCommentById(Long commentId);
 
     @Select("SELECT * FROM `comment` WHERE `post_id` = #{postId}")
diff --git a/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMapper.java b/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMapper.java
index ccf70c3..4ff8505 100644
--- a/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMapper.java
+++ b/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMapper.java
@@ -1,3 +1,5 @@
+// edu.bjtu.groupone.backend.mapper.WorkMapper
+
 package edu.bjtu.groupone.backend.mapper;
 
 import edu.bjtu.groupone.backend.domain.entity.Work;
@@ -11,25 +13,32 @@
 @Mapper
 public interface WorkMapper {
     @Select("SELECT * FROM works WHERE user_id = #{userId} AND status = 'UPLOADING'")
-    List<Work> getUncompletedWorksByUserId(Long userId);
+    List<Work> getUncompletedWorksByUserId(@Param("userId") Long userId);
 
     @Select("SELECT * FROM works WHERE user_id = #{userId} AND status = 'COMPLETED'")
-    List<Work> getCompletedWorksByUserId(Long userId);
+    List<Work> getCompletedWorksByUserId(@Param("userId") Long userId);
 
     @Select("SELECT * FROM works WHERE id = #{id}")
-    Work getWorkById(Long id);
+    Work getWorkById(@Param("id") Long id);
 
-    @Insert("INSERT INTO works (title, description, user_id, status, create_time, update_time) " +
-            "VALUES (#{title}, #{description}, #{userId}, #{status}, NOW(), NOW())")
+    @Insert("INSERT INTO works " +
+            "(title, description, user_id, status, category_id, create_time, update_time) " +
+            "VALUES " +
+            "(#{title}, #{description}, #{userId}, #{status}, #{category.id}, NOW(), NOW())")
     @Options(useGeneratedKeys = true, keyProperty = "id")
     int insertWork(Work work);
 
-    @Update("UPDATE works SET title = #{title}, description = #{description}, status = #{status}, " +
-            "update_time = NOW() WHERE id = #{id}")
+    @Update("UPDATE works SET " +
+            "title       = #{title}, " +
+            "description = #{description}, " +
+            "status      = #{status}, " +
+            "category_id = #{category.id}, " +
+            "update_time = NOW() " +
+            "WHERE id    = #{id}")
     int updateWork(Work work);
 
     @Delete("DELETE FROM works WHERE id = #{id}")
-    int deleteWork(Long id);
+    int deleteWork(@Param("id") Long id);
 
     @Insert("INSERT INTO version (work_id, version_number, file_url, description, create_time) " +
             "VALUES (#{workId}, #{versionNumber}, #{fileUrl}, #{description}, NOW())")
@@ -37,7 +46,7 @@
     int insertVersion(Version version);
 
     @Delete("DELETE FROM version WHERE id = #{id}")
-    int deleteVersion(Long id);
+    int deleteVersion(@Param("id") Long id);
 
     @Insert("INSERT INTO comment (work_id, user_id, content, create_time) " +
             "VALUES (#{workId}, #{userId}, #{content}, NOW())")
@@ -45,18 +54,21 @@
     int insertComment(Comment comment);
 
     @Delete("DELETE FROM comment WHERE id = #{id}")
-    int deleteComment(Long id);
+    int deleteComment(@Param("id") Long id);
 
-    // 新增聚合查询
     @Select("SELECT content FROM comment WHERE work_id = #{workId}")
-    List<String> getCommentsByWorkId(Long workId);
+    List<String> getCommentsByWorkId(@Param("workId") Long workId);
 
     @Select("SELECT version_number, file_url, description FROM version WHERE work_id = #{workId}")
-    List<Map<String, Object>> getVersionsByWorkId(Long workId);
+    List<Map<String, Object>> getVersionsByWorkId(@Param("workId") Long workId);
 
-    @Select("SELECT u.username, u.user_id FROM seeding_user su JOIN user u ON su.user_id = u.user_id WHERE su.work_id = #{workId} AND su.status = 'seeding'")
-    List<Map<String, Object>> getSeedingUsersByWorkId(Long workId);
+    @Select("SELECT u.username, u.user_id FROM seeding_user su " +
+            "JOIN user u ON su.user_id = u.user_id " +
+            "WHERE su.work_id = #{workId} AND su.status = 'seeding'")
+    List<Map<String, Object>> getSeedingUsersByWorkId(@Param("workId") Long workId);
 
-    @Select("SELECT u.username, u.user_id, su.uploaded FROM seeding_user su JOIN user u ON su.user_id = u.user_id WHERE su.work_id = #{workId} AND su.status = 'history'")
-    List<Map<String, Object>> getHistorySeedingUsersByWorkId(Long workId);
-} 
\ No newline at end of file
+    @Select("SELECT u.username, u.user_id, su.uploaded FROM seeding_user su " +
+            "JOIN user u ON su.user_id = u.user_id " +
+            "WHERE su.work_id = #{workId} AND su.status = 'history'")
+    List<Map<String, Object>> getHistorySeedingUsersByWorkId(@Param("workId") Long workId);
+}
diff --git a/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMybatisMapper.java b/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMybatisMapper.java
index c127c8c..58b5067 100644
--- a/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMybatisMapper.java
+++ b/src/main/java/edu/bjtu/groupone/backend/mapper/WorkMybatisMapper.java
@@ -2,6 +2,7 @@
 package edu.bjtu.groupone.backend.mapper;
 
 //import edu.bjtu.groupone.backend.model.Work;
+import edu.bjtu.groupone.backend.domain.dto.WorkResponse;
 import edu.bjtu.groupone.backend.domain.entity.Work;
 import org.apache.ibatis.annotations.*;
 import org.springframework.data.domain.Page;
@@ -14,7 +15,19 @@
 @Repository
 public interface WorkMybatisMapper  {
     // 修正参数类型为 Spring Data 的 Pageable
-    Page<Work> findByCategoryIdIn(List<Long> categoryIds, Pageable pageable);
+    @Select({
+            "<script>",
+            "SELECT *",
+            "  FROM works",
+            " WHERE category_id IN",
+            "   <foreach item='id' collection='categoryIds' open='(' separator=',' close=')'>",
+            "     #{id}",
+            "   </foreach>",
+            " ORDER BY create_time DESC",
+            "</script>"
+    })
+    List<WorkResponse> findByCategoryIdIn(List<Long> categoryIds);
+
     @Insert("INSERT INTO works(title, author, views, category_id, description, create_time) " +
             "VALUES(#{title}, #{author}, #{views}, #{category.id}, #{description}, #{createTime})")
     @Options(useGeneratedKeys = true, keyProperty = "id")
diff --git a/src/main/java/edu/bjtu/groupone/backend/service/WorkService.java b/src/main/java/edu/bjtu/groupone/backend/service/WorkService.java
index 5693bb1..786193d 100644
--- a/src/main/java/edu/bjtu/groupone/backend/service/WorkService.java
+++ b/src/main/java/edu/bjtu/groupone/backend/service/WorkService.java
@@ -1,5 +1,7 @@
 package edu.bjtu.groupone.backend.service;
 
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
 import edu.bjtu.groupone.backend.domain.dto.WorkResponse;
 import edu.bjtu.groupone.backend.domain.entity.Work;
 import edu.bjtu.groupone.backend.mapper.WorkMybatisMapper;
@@ -45,11 +47,13 @@
     @Autowired
     private CommentMapper commentMapper;
 
-    public Page<WorkResponse> getWorks(Long categoryId, int page, int size) {
+    public PageInfo<WorkResponse> getWorks(Long categoryId, int page, int size) {
         List<Long> categoryIds = categoryService.getAllSubcategoryIds(categoryId);
+        System.out.println("categoryIds = " + categoryIds);
         Pageable pageable = PageRequest.of(page-1, size);
-        return workMybatisMapper.findByCategoryIdIn(categoryIds, pageable)
-                .map(this::convertToResponse);
+        PageHelper.startPage(page, size);
+        List<WorkResponse> byCategoryIdIn = workMybatisMapper.findByCategoryIdIn(categoryIds);
+        return new PageInfo<>(byCategoryIdIn);
     }
 
     private WorkResponse convertToResponse(Work work) {
diff --git a/src/main/resources/mapper/WorkMybatisMapper.xml b/src/main/resources/mapper/WorkMybatisMapper.xml
deleted file mode 100644
index dd0d444..0000000
--- a/src/main/resources/mapper/WorkMybatisMapper.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-
-<mapper namespace="edu.bjtu.groupone.backend.mapper.WorkMybatisMapper">
-
-    <!-- 结果集映射 -->
-    <resultMap id="WorkResultMap" type="Work">
-        <id property="id" column="id"/>
-        <result property="title" column="title"/>
-        <result property="description" column="description"/>
-        <result property="categoryId" column="category_id"/>
-        <result property="createTime" column="create_time"/>
-    </resultMap>
-
-    <!-- 查询所有作品 -->
-    <select id="findAll" resultMap="WorkResultMap">
-        SELECT id, title, description, category_id, create_time
-        FROM works
-    </select>
-
-    <!-- 根据分类ID列表分页查询 -->
-    <select id="findByCategoryIdIn" resultMap="WorkResultMap">
-        SELECT * FROM works
-        <where>
-            <if test="categoryIds != null and categoryIds.size() > 0">
-                category_id IN
-                <foreach item="categoryId" collection="categoryIds"
-                         open="(" separator="," close=")">
-                    #{categoryId}
-                </foreach>
-            </if>
-        </where>
-        ORDER BY create_time DESC
-        LIMIT #{pageable.pageSize} OFFSET #{pageable.offset}
-    </select>
-
-</mapper>
\ No newline at end of file
diff --git a/src/test/java/edu/bjtu/groupone/backend/WorkServiceTest.java b/src/test/java/edu/bjtu/groupone/backend/WorkServiceTest.java
deleted file mode 100644
index 118ff01..0000000
--- a/src/test/java/edu/bjtu/groupone/backend/WorkServiceTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package edu.bjtu.groupone.backend;
-
-import com.turn.ttorrent.tracker.Tracker;
-import edu.bjtu.groupone.backend.config.TrafficAwareTracker;
-import edu.bjtu.groupone.backend.domain.dto.WorkResponse;
-import edu.bjtu.groupone.backend.domain.entity.Category;
-import edu.bjtu.groupone.backend.domain.entity.Work;
-import edu.bjtu.groupone.backend.mapper.WorkMybatisMapper;
-import edu.bjtu.groupone.backend.mapper.WorkMapper;
-import edu.bjtu.groupone.backend.service.CategoryService;
-import edu.bjtu.groupone.backend.service.PeerTrafficService;
-import edu.bjtu.groupone.backend.service.WorkService;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
-import org.springframework.data.domain.PageRequest;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.*;
-import static org.mockito.Mockito.*;
-
-@SpringBootTest
-@ExtendWith(MockitoExtension.class)
-class WorkServiceTest {
-
-    @Mock
-    private WorkMybatisMapper workMybatisMapper;
-
-    @Mock
-    private WorkMapper workMapper;
-
-    @Mock
-    private CategoryService categoryService;
-
-    @InjectMocks
-    private WorkService workService;
-
-    private Work testWork;
-    private Category testCategory;
-    private List<Work> works;
-
-    @BeforeEach
-    void setUp() {
-        testCategory = new Category(1L, "Test Category", null);
-
-        testWork = Work.builder()
-                .id(1L)
-                .title("Test Work")
-                .author("Author")
-                .views(100)
-                .category(testCategory)
-                .build();
-
-        Category category = new Category(1L, "文学艺术", null);
-        works = Arrays.asList(
-                Work.builder()
-                        .id(1L)
-                        .title("《我的世界》")
-                        .author("张三")
-                        .views(1234)
-                        .category(category)
-                        .description("一部关于...")
-                        .createTime("2023-06-15")
-                        .build(),
-                Work.builder()
-                        .id(2L)
-                        .title("《你的世界》")
-                        .author("张三")
-                        .views(567)
-                        .category(category)
-                        .description("另一部关于...")
-                        .createTime("2023-06-16")
-                        .build()
-        );
-    }
-
-    @Test
-    void addWork_shouldCallMapper() {
-        workService.addWork(testWork);
-        verify(workMybatisMapper, times(1)).save(testWork);
-    }
-
-    @Test
-    void createWork_shouldCallMapper() {
-        workService.createWork(testWork);
-        verify(workMapper, times(1)).insertWork(testWork);
-    }
-
-    @Test
-    void deleteWork_shouldCallMapper() {
-        workService.deleteWork(1L);
-        verify(workMapper, times(1)).deleteWork(1L);
-    }
-
-    @Test
-    void updateWork_shouldCallMapper() {
-        workService.updateWork(testWork);
-        verify(workMapper, times(1)).updateWork(testWork);
-    }
-
-    @Test
-    void getWorkById_shouldReturnWork() {
-        when(workMybatisMapper.findById(1L)).thenReturn(testWork);
-        Work result = workService.getWorkById(1L);
-        assertEquals(testWork, result);
-        verify(workMybatisMapper, times(1)).findById(1L);
-    }
-
-    @Test
-    void getWorks_shouldReturnPage() {
-        Long categoryId = 1L;
-        int page = 1; // Fix: Use page = 1 to account for WorkService expecting 1-based indexing
-        int size = 10;
-        List<Long> categoryIds = Arrays.asList(1L);
-
-        when(categoryService.getAllSubcategoryIds(categoryId)).thenReturn(categoryIds);
-        Page<Work> workPage = new PageImpl<>(Arrays.asList(testWork));
-        when(workMybatisMapper.findByCategoryIdIn(categoryIds, PageRequest.of(0, size))).thenReturn(workPage);
-
-        Page<WorkResponse> result = workService.getWorks(categoryId, page, size);
-
-        assertEquals(1, result.getContent().size());
-        verify(categoryService, times(1)).getAllSubcategoryIds(categoryId);
-        verify(workMybatisMapper, times(1)).findByCategoryIdIn(categoryIds, PageRequest.of(0, size));
-    }
-
-    @Test
-    void getWorksByAuthor_Success() {
-        when(workMybatisMapper.findByAuthor("张三")).thenReturn(works);
-        List<WorkResponse> result = workService.getWorksByAuthor("张三");
-        assertEquals(2, result.size());
-        assertEquals("《我的世界》", result.get(0).getTitle());
-        assertEquals("《你的世界》", result.get(1).getTitle());
-    }
-
-    @Test
-    void getWorksByAuthor_Empty() {
-        when(workMybatisMapper.findByAuthor(anyString())).thenReturn(List.of());
-        List<WorkResponse> result = workService.getWorksByAuthor("李四");
-        assertTrue(result.isEmpty());
-    }
-
-    @Autowired
-    PeerTrafficService peerTrafficService;
-    @Test
-    public  void test() throws IOException {
-        Tracker tracker;
-        InetSocketAddress trackerAddress = new InetSocketAddress("0.0.0.0", 6969);
-        tracker = new Tracker(trackerAddress);
-        tracker.start();
-    }
-}
\ No newline at end of file