Merge "add comment, reward, total" into main
diff --git a/src/main/java/com/g9/g9backend/controller/CommentController.java b/src/main/java/com/g9/g9backend/controller/CommentController.java
new file mode 100644
index 0000000..fec8e68
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/controller/CommentController.java
@@ -0,0 +1,94 @@
+package com.g9.g9backend.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.g9.g9backend.pojo.Comment;
+import com.g9.g9backend.pojo.DTO.GetCommentDTO;
+import com.g9.g9backend.service.CommentService;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+@RestController
+@RequestMapping("/comment")
+public class CommentController {
+
+ private final CommentService commentService;
+
+ private final Logger logger = LoggerFactory.getLogger(CommentController.class);
+
+ public CommentController(CommentService commentService) {
+ this.commentService = commentService;
+ }
+
+ @PostMapping
+ public ResponseEntity<String> postComment(@RequestBody Comment comment) {
+ System.out.println(comment.toString());
+ commentService.save(comment);
+
+ logger.info("评论已发布");
+
+ return ResponseEntity.ok("");
+ }
+
+ @DeleteMapping
+ public ResponseEntity<String> deleteComment(@RequestParam Integer commentId) {
+ commentService.removeById(commentId);
+
+ return ResponseEntity.noContent().build();
+ }
+
+ @GetMapping
+ public ResponseEntity<GetCommentDTO> getComment(@RequestParam Integer id,
+ @RequestParam Integer pageNumber,
+ @RequestParam Integer rows,
+ @RequestParam String type) {
+ Page<Comment> commentPage = new Page<>(pageNumber, rows);
+ LambdaQueryWrapper<Comment> rewardQuery = new LambdaQueryWrapper<Comment>()
+ .orderByDesc(Comment::getCreateAt);
+
+
+ if (Objects.equals(type, "资源")) {
+
+ rewardQuery.eq(Comment::getResourceId, id);
+ }
+
+ if (Objects.equals(type, "帖子")) {
+
+ rewardQuery.eq(Comment::getThreadId, id);
+ }
+
+ if (Objects.equals(type, "悬赏")) {
+
+ rewardQuery.eq(Comment::getRewardId, id);
+ }
+
+ Page<Comment> result = commentService.page(commentPage, rewardQuery);
+
+ GetCommentDTO getCommentDTO = wrapCommentPage(result, item -> {
+ GetCommentDTO.Comment comment = new GetCommentDTO.Comment();
+ comment.setCommentId(item.getCommentId());
+ comment.setUserId(item.getUserId());
+ comment.setReplyId(item.getReplyId() != null ? item.getReplyId() : 0);
+ comment.setContent(item.getContent());
+ comment.setCreateAt(item.getCreateAt());
+ return comment;
+ });
+
+ return ResponseEntity.ok(getCommentDTO);
+ }
+
+ @NotNull
+ private <T> GetCommentDTO wrapCommentPage(Page<T> page, Function<T, GetCommentDTO.Comment> mapper) {
+ List<GetCommentDTO.Comment> records = page.getRecords().stream().map(mapper).toList();
+
+ return new GetCommentDTO(records, (int) page.getTotal(), (int) page.getPages(), (int) page.getCurrent(), (int) page.getSize());
+ }
+
+}
diff --git a/src/main/java/com/g9/g9backend/controller/RewardController.java b/src/main/java/com/g9/g9backend/controller/RewardController.java
index c5b316b..3563f41 100644
--- a/src/main/java/com/g9/g9backend/controller/RewardController.java
+++ b/src/main/java/com/g9/g9backend/controller/RewardController.java
@@ -1,9 +1,23 @@
package com.g9.g9backend.controller;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.g9.g9backend.pojo.DTO.GetRewardDTO;
+import com.g9.g9backend.pojo.Reward;
+import com.g9.g9backend.service.RewardService;
+import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.*;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
/**
* RewardController 悬赏控制器类,处理与悬赏相关的请求
@@ -14,5 +28,103 @@
@RequestMapping("/reward")
public class RewardController {
+ private final RewardService rewardService;
+
private final Logger logger = LoggerFactory.getLogger(RewardController.class);
+
+ public RewardController(RewardService rewardService) {
+ this.rewardService = rewardService;
+ }
+
+ @PostMapping
+ public ResponseEntity<String> postReward(@RequestBody Reward reward) {
+ reward.setCompletedBy(null);
+ reward.setResourceId(null);
+ rewardService.save(reward);
+
+ logger.info("悬赏已发布");
+
+ return ResponseEntity.ok("");
+ }
+
+ @DeleteMapping
+ public ResponseEntity<String> deleteReward(@RequestParam Integer rewardId) {
+ rewardService.removeById(rewardId);
+
+ logger.info("悬赏已删除");
+
+ return ResponseEntity.noContent().build();
+ }
+
+ @GetMapping
+ public ResponseEntity<GetRewardDTO> getReward(@RequestParam Integer pageNumber,
+ @RequestParam Integer rows,
+ @RequestParam String searchValue,
+ @RequestParam String option) {
+ Page<Reward> rewardPage = new Page<>(pageNumber, rows);
+ LambdaQueryWrapper<Reward> rewardQuery = new LambdaQueryWrapper<Reward>()
+ .like(StringUtils.isNotBlank(searchValue), Reward::getRewardName, searchValue);
+
+ if (Objects.equals(option, "赏金最高")) {
+
+ rewardQuery.orderByDesc(Reward::getPrice);
+ } else {
+
+ rewardQuery.orderByDesc(Reward::getCreateAt);
+ }
+
+ Page<Reward> result = rewardService.page(rewardPage, rewardQuery);
+
+ GetRewardDTO getRewardDTO = wrapRewardPage(result, item -> {
+ GetRewardDTO.Reward reward = new GetRewardDTO.Reward();
+ reward.setRewardId(item.getRewardId());
+ reward.setRewardName(item.getRewardName());
+ reward.setRewardPicture(item.getRewardPicture());
+ reward.setUserId(item.getUserId());
+ reward.setPrice(item.getPrice());
+ reward.setCreateAt(item.getCreateAt());
+ return reward;
+ });
+
+ return ResponseEntity.ok(getRewardDTO);
+ }
+
+ @NotNull
+ private <T> GetRewardDTO wrapRewardPage(Page<T> page, Function<T, GetRewardDTO.Reward> mapper) {
+ List<GetRewardDTO.Reward> records = page.getRecords().stream().map(mapper).toList();
+
+ return new GetRewardDTO(records, (int) page.getTotal(), (int) page.getPages(), (int) page.getCurrent(), (int) page.getSize());
+ }
+
+ @GetMapping(value = "/info")
+ public ResponseEntity<Reward> getRewardInfo(@RequestParam Integer rewardId) {
+
+ return ResponseEntity.ok(rewardService.getById(rewardId));
+ }
+
+ @PutMapping("/info")
+ public ResponseEntity<String> putReward(@RequestBody Reward reward) {
+ Reward rewardUpdate = rewardService.getById(reward.getRewardId());
+ rewardUpdate.setRewardName(reward.getRewardName());
+ rewardUpdate.setRewardPicture(reward.getRewardPicture());
+ rewardUpdate.setPrice(reward.getPrice());
+ rewardUpdate.setRewardDescription(reward.getRewardDescription());
+ rewardUpdate.setLastUpdateAt(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()));
+ rewardService.updateById(rewardUpdate);
+
+ return ResponseEntity.ok("");
+ }
+
+ @PostMapping(value = "/completion")
+ public ResponseEntity<String> putRewardCompletion(@RequestBody Reward reward) {
+ Reward rewardUpdate = rewardService.getById(reward.getRewardId());
+ rewardUpdate.setCompletedBy(reward.getCompletedBy());
+ rewardUpdate.setCompletedAt(reward.getCompletedAt());
+ rewardUpdate.setResourceId(reward.getResourceId());
+ rewardService.updateById(rewardUpdate);
+
+ return ResponseEntity.ok("");
+ }
+
+
}
diff --git a/src/main/java/com/g9/g9backend/controller/TotalController.java b/src/main/java/com/g9/g9backend/controller/TotalController.java
new file mode 100644
index 0000000..2359586
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/controller/TotalController.java
@@ -0,0 +1,67 @@
+package com.g9.g9backend.controller;
+
+import com.g9.g9backend.service.ResourceService;
+import com.g9.g9backend.service.ThreadService;
+import com.g9.g9backend.service.UserPurchaseService;
+import com.g9.g9backend.service.UserUploadService;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/total")
+public class TotalController {
+
+ private final ThreadService threadService;
+
+ private final UserPurchaseService userPurchaseService;
+
+ private final UserUploadService userUploadService;
+
+ private final ResourceService resourceService;
+
+ public TotalController(ThreadService threadService, UserPurchaseService userPurchaseService, UserUploadService userUploadService, ResourceService resourceService) {
+ this.threadService = threadService;
+ this.userPurchaseService = userPurchaseService;
+ this.userUploadService = userUploadService;
+ this.resourceService = resourceService;
+ }
+
+ private final Logger logger = LoggerFactory.getLogger(TotalController.class);
+
+
+ @GetMapping(value = "/info")
+ public ResponseEntity<Info> getTotalInfo() {
+
+ long threadCount = threadService.count();
+ long downloadCount = userPurchaseService.count();
+ long authorCount = userUploadService.count();
+ long resourceCount = resourceService.count();
+
+ Info info = new Info(threadCount, downloadCount, authorCount, resourceCount);
+ logger.info("统计数据返回:{}", info);
+
+ return ResponseEntity.ok(info);
+ }
+
+ @Data
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class Info {
+
+ private long threadCount;
+
+ private long downloadCount;
+
+ private long authorCount;
+
+ private long resourceCount;
+
+ }
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/Comment.java b/src/main/java/com/g9/g9backend/pojo/Comment.java
index eddc42b..1f6e74f 100644
--- a/src/main/java/com/g9/g9backend/pojo/Comment.java
+++ b/src/main/java/com/g9/g9backend/pojo/Comment.java
@@ -21,13 +21,13 @@
private int userId;
- private int threadId;
+ private Integer threadId;
- private int resourceId;
+ private Integer resourceId;
- private int rewardId;
+ private Integer rewardId;
- private int replyId;
+ private Integer replyId;
private String content;
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetCommentDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetCommentDTO.java
new file mode 100644
index 0000000..0fb7c44
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetCommentDTO.java
@@ -0,0 +1,42 @@
+package com.g9.g9backend.pojo.DTO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class GetCommentDTO {
+
+ private List<Comment> records;
+
+ private long total;
+
+ private long pages;
+
+ private long current;
+
+ private long size;
+
+ @Data
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class Comment {
+
+ private int commentId;
+
+ private int userId;
+
+ private int replyId;
+
+ private String content;
+
+ private Date createAt;
+
+ }
+
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/DTO/GetRewardDTO.java b/src/main/java/com/g9/g9backend/pojo/DTO/GetRewardDTO.java
new file mode 100644
index 0000000..f56b878
--- /dev/null
+++ b/src/main/java/com/g9/g9backend/pojo/DTO/GetRewardDTO.java
@@ -0,0 +1,44 @@
+package com.g9.g9backend.pojo.DTO;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class GetRewardDTO {
+
+ private List<Reward> records;
+
+ private long total;
+
+ private long pages;
+
+ private long current;
+
+ private long size;
+
+ @Data
+ @AllArgsConstructor
+ @NoArgsConstructor
+ public static class Reward {
+
+ private int rewardId;
+
+ private String rewardName;
+
+ private String rewardPicture;
+
+ private int userId;
+
+ private float price;
+
+ private Date createAt;
+
+ }
+
+}
diff --git a/src/main/java/com/g9/g9backend/pojo/Reward.java b/src/main/java/com/g9/g9backend/pojo/Reward.java
index 5812284..08a9de8 100644
--- a/src/main/java/com/g9/g9backend/pojo/Reward.java
+++ b/src/main/java/com/g9/g9backend/pojo/Reward.java
@@ -33,9 +33,9 @@
private Date lastUpdateAt;
- private int completedBy;
+ private Integer completedBy;
private Date completedAt;
- private int resourceId;
+ private Integer resourceId;
}
\ No newline at end of file
diff --git a/src/test/java/com/g9/g9backend/controller/CommentControllerTest.java b/src/test/java/com/g9/g9backend/controller/CommentControllerTest.java
new file mode 100644
index 0000000..d9f9f87
--- /dev/null
+++ b/src/test/java/com/g9/g9backend/controller/CommentControllerTest.java
@@ -0,0 +1,68 @@
+package com.g9.g9backend.controller;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.g9.g9backend.pojo.Comment;
+import com.g9.g9backend.pojo.DTO.GetCommentDTO;
+import com.g9.g9backend.service.CommentService;
+import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentMatchers;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import org.springframework.http.ResponseEntity;
+
+import java.util.Collections;
+import java.util.Date;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+import static org.mockito.BDDMockito.given;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+@ExtendWith(MockitoExtension.class)
+public class CommentControllerTest {
+
+ @Mock
+ private CommentService commentService;
+
+ @InjectMocks
+ private CommentController commentController;
+
+ @Test
+ void testPostComment() {
+ Comment comment = new Comment();
+ ResponseEntity<String> response = commentController.postComment(comment);
+ verify(commentService).save(comment);
+ assertEquals(200, response.getStatusCode().value());
+ }
+
+ @Test
+ void testDeleteComment() {
+ Integer id = 1;
+ ResponseEntity<String> response = commentController.deleteComment(id);
+ verify(commentService).removeById(id);
+ assertEquals(204, response.getStatusCode().value());
+ }
+
+ @Test
+ void testGetCommentWithResourceType() {
+ Comment comment = new Comment();
+ comment.setCommentId(1);
+ comment.setUserId(2);
+ comment.setReplyId(null);
+ comment.setContent("Test");
+ comment.setCreateAt(new Date());
+ comment.setResourceId(1);
+
+ Page<Comment> page = new Page<>();
+ page.setRecords(Collections.singletonList(comment));
+
+ given(commentService.page(ArgumentMatchers.<Page<Comment>>any(), ArgumentMatchers.<LambdaQueryWrapper<Comment>>any())).willReturn(page);
+
+ ResponseEntity<GetCommentDTO> response = commentController.getComment(1, 1, 10, "资源");
+ assertEquals(200, response.getStatusCode().value());
+ assertEquals(1, response.getBody().getRecords().size());
+ }
+}
diff --git a/src/test/java/com/g9/g9backend/controller/RewardControllerTest.java b/src/test/java/com/g9/g9backend/controller/RewardControllerTest.java
new file mode 100644
index 0000000..7f560f7
--- /dev/null
+++ b/src/test/java/com/g9/g9backend/controller/RewardControllerTest.java
@@ -0,0 +1,135 @@
+package com.g9.g9backend.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.g9.g9backend.pojo.Reward;
+import com.g9.g9backend.service.RewardService;
+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.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import java.util.Collections;
+import java.util.Date;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+public class RewardControllerTest {
+
+ private MockMvc mockMvc;
+
+ @InjectMocks
+ private RewardController rewardController;
+
+ @Mock
+ private RewardService rewardService;
+
+ private final ObjectMapper objectMapper = new ObjectMapper();
+
+ @BeforeEach
+ public void setUp() {
+ MockitoAnnotations.openMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(rewardController).build();
+ }
+
+ @Test
+ public void testPostReward() throws Exception {
+ Reward reward = new Reward();
+ reward.setRewardName("测试悬赏");
+
+ mockMvc.perform(post("/reward")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(reward)))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void testDeleteReward() throws Exception {
+ mockMvc.perform(delete("/reward")
+ .param("rewardId", "1"))
+ .andExpect(status().isNoContent());
+ }
+
+ @Test
+ public void testGetReward_sortByPrice() throws Exception {
+ Reward reward = new Reward();
+ reward.setRewardId(1);
+ reward.setRewardName("测试");
+ reward.setPrice(100);
+ reward.setCreateAt(new Date());
+
+ Page<Reward> page = new Page<>(1, 10);
+ page.setRecords(Collections.singletonList(reward));
+ page.setTotal(1);
+
+ when(rewardService.page(any(), any())).thenReturn(page);
+
+ mockMvc.perform(get("/reward")
+ .param("pageNumber", "1")
+ .param("rows", "10")
+ .param("searchValue", "")
+ .param("option", "赏金最高"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.records[0].rewardId").value(1));
+ }
+
+ @Test
+ public void testGetRewardInfo() throws Exception {
+ Reward reward = new Reward();
+ reward.setRewardId(1);
+ reward.setRewardName("详情测试");
+
+ when(rewardService.getById(1)).thenReturn(reward);
+
+ mockMvc.perform(get("/reward/info")
+ .param("rewardId", "1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.rewardId").value(1));
+ }
+
+ @Test
+ public void testPutReward() throws Exception {
+ Reward oldReward = new Reward();
+ oldReward.setRewardId(1);
+
+ when(rewardService.getById(1)).thenReturn(oldReward);
+
+ Reward updateRequest = new Reward();
+ updateRequest.setRewardId(1);
+ updateRequest.setRewardName("更新名称");
+ updateRequest.setRewardDescription("更新描述");
+ updateRequest.setPrice(500);
+ updateRequest.setRewardPicture("pic.png");
+
+ mockMvc.perform(put("/reward/info")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(updateRequest)))
+ .andExpect(status().isOk());
+ }
+
+ @Test
+ public void testPutRewardCompletion() throws Exception {
+ Reward existing = new Reward();
+ existing.setRewardId(1);
+
+ when(rewardService.getById(1)).thenReturn(existing);
+
+ Reward completed = new Reward();
+ completed.setRewardId(1);
+ completed.setCompletedBy(2);
+ completed.setCompletedAt(new Date());
+ completed.setResourceId(3);
+
+ mockMvc.perform(post("/reward/completion")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(completed)))
+ .andExpect(status().isOk());
+ }
+}
diff --git a/src/test/java/com/g9/g9backend/controller/TotalControllerTest.java b/src/test/java/com/g9/g9backend/controller/TotalControllerTest.java
new file mode 100644
index 0000000..35c2484
--- /dev/null
+++ b/src/test/java/com/g9/g9backend/controller/TotalControllerTest.java
@@ -0,0 +1,53 @@
+package com.g9.g9backend.controller;
+
+import com.g9.g9backend.service.ResourceService;
+import com.g9.g9backend.service.ThreadService;
+import com.g9.g9backend.service.UserPurchaseService;
+import com.g9.g9backend.service.UserUploadService;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.http.ResponseEntity;
+
+@ExtendWith(MockitoExtension.class)
+public class TotalControllerTest {
+
+ @Mock
+ private ThreadService threadService;
+
+ @Mock
+ private UserPurchaseService userPurchaseService;
+
+ @Mock
+ private UserUploadService userUploadService;
+
+ @Mock
+ private ResourceService resourceService;
+
+ @InjectMocks
+ private TotalController totalController;
+
+ @Test
+ void testGetTotalInfo() {
+ when(threadService.count()).thenReturn(10L);
+ when(userPurchaseService.count()).thenReturn(20L);
+ when(userUploadService.count()).thenReturn(5L);
+ when(resourceService.count()).thenReturn(50L);
+
+ ResponseEntity<TotalController.Info> response = totalController.getTotalInfo();
+
+ assertEquals(200, response.getStatusCode().value());
+ TotalController.Info info = response.getBody();
+ assertNotNull(info);
+ assertEquals(10L, info.getThreadCount());
+ assertEquals(20L, info.getDownloadCount());
+ assertEquals(5L, info.getAuthorCount());
+ assertEquals(50L, info.getResourceCount());
+ }
+}