Commit cbf5ef5953221b9cb2ed04bfd807931a65916a5e

Authored by wangzhs
1 parent da53a041

[新增][商品评价]管理后台

1. 显示 / 隐藏评论
2. 商家回复
yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/enums/ErrorCodeConstants.java
... ... @@ -42,4 +42,7 @@ public interface ErrorCodeConstants {
42 42 ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
43 43 ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
44 44  
  45 + // ========== 商品 评价 1008007000 ==========
  46 + ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在");
  47 +
45 48 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/ProductCommentController.java
... ... @@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.product.controller.admin.comment;
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
  6 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
6 7 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
  8 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
7 9 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
8 10 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
9 11 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
... ... @@ -11,14 +13,13 @@ import io.swagger.v3.oas.annotations.Operation;
11 13 import io.swagger.v3.oas.annotations.tags.Tag;
12 14 import org.springframework.security.access.prepost.PreAuthorize;
13 15 import org.springframework.validation.annotation.Validated;
14   -import org.springframework.web.bind.annotation.GetMapping;
15   -import org.springframework.web.bind.annotation.RequestMapping;
16   -import org.springframework.web.bind.annotation.RestController;
  16 +import org.springframework.web.bind.annotation.*;
17 17  
18 18 import javax.annotation.Resource;
19 19 import javax.validation.Valid;
20 20  
21 21 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  22 +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
22 23  
23 24 @Tag(name = "管理后台 - 商品评价")
24 25 @RestController
... ... @@ -37,4 +38,20 @@ public class ProductCommentController {
37 38 return success(ProductCommentConvert.INSTANCE.convertPage(pageResult));
38 39 }
39 40  
  41 + @PutMapping("/update/visible")
  42 + @Operation(summary = "显示 / 隐藏评论")
  43 + @PreAuthorize("@ss.hasPermission('product:comment:update')")
  44 + public CommonResult<Boolean> updateCommentVisible(@Valid @RequestBody ProductCommentUpdateVisibleReqVO updateReqVO) {
  45 + productCommentService.updateCommentVisible(updateReqVO);
  46 + return success(true);
  47 + }
  48 +
  49 + @PutMapping("/reply")
  50 + @Operation(summary = "商家回复")
  51 + @PreAuthorize("@ss.hasPermission('product:comment:update')")
  52 + public CommonResult<Boolean> commentReply(@Valid @RequestBody ProductCommentReplyVO replyVO) {
  53 + productCommentService.commentReply(replyVO, getLoginUserId());
  54 + return success(true);
  55 + }
  56 +
40 57 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentPageReqVO.java
... ... @@ -35,6 +35,9 @@ public class ProductCommentPageReqVO extends PageParam {
35 35 @InEnum(ProductCommentScoresEnum.class)
36 36 private Integer scores;
37 37  
  38 + @Schema(description = "商家是否回复")
  39 + private Boolean replied;
  40 +
38 41 @Schema(description = "创建时间")
39 42 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
40 43 private LocalDateTime[] createTime;
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.ToString;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@Schema(description = "管理后台 - 商品评价可见修改 Request VO")
  10 +@Data
  11 +@ToString(callSuper = true)
  12 +public class ProductCommentReplyVO {
  13 +
  14 + @Schema(description = "评价编号", required = true, example = "15721")
  15 + @NotNull(message = "评价编号不能为空")
  16 + private Long id;
  17 +
  18 + @Schema(description = "商家回复内容", required = true, example = "谢谢亲")
  19 + @NotNull(message = "商家回复内容不能为空")
  20 + private String replyContent;
  21 +
  22 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
  2 +
  3 +import io.swagger.v3.oas.annotations.media.Schema;
  4 +import lombok.Data;
  5 +import lombok.ToString;
  6 +
  7 +import javax.validation.constraints.NotNull;
  8 +
  9 +@Schema(description = "管理后台 - 商品评价可见修改 Request VO")
  10 +@Data
  11 +@ToString(callSuper = true)
  12 +public class ProductCommentUpdateVisibleReqVO {
  13 +
  14 + @Schema(description = "评价编号", required = true, example = "15721")
  15 + @NotNull(message = "评价编号不能为空")
  16 + private Long id;
  17 +
  18 + @Schema(description = "是否可见 true:显示 false:隐藏", required = true, example = "false")
  19 + @NotNull(message = "是否可见不能为空")
  20 + private Boolean visible;
  21 +
  22 +}
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/comment/ProductCommentMapper.java
... ... @@ -5,9 +5,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
5 5 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
6 6 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
7 7 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
  8 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
8 9 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
  10 +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
9 11 import org.apache.ibatis.annotations.Mapper;
10 12  
  13 +import java.time.LocalDateTime;
  14 +
11 15  
12 16 /**
13 17 * 商品评论 Mapper
... ... @@ -28,4 +32,20 @@ public interface ProductCommentMapper extends BaseMapperX&lt;ProductCommentDO&gt; {
28 32 .orderByDesc(ProductCommentDO::getId));
29 33 }
30 34  
  35 + default void updateCommentVisible(Long id, Boolean visible) {
  36 + LambdaUpdateWrapper<ProductCommentDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<ProductCommentDO>()
  37 + .set(ProductCommentDO::getVisible, visible)
  38 + .eq(ProductCommentDO::getId, id);
  39 + update(null, lambdaUpdateWrapper);
  40 + }
  41 +
  42 + default void commentReply(ProductCommentReplyVO replyVO, Long loginUserId) {
  43 + LambdaUpdateWrapper<ProductCommentDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<ProductCommentDO>()
  44 + .set(ProductCommentDO::getReplied, Boolean.TRUE)
  45 + .set(ProductCommentDO::getReplyTime, LocalDateTime.now())
  46 + .set(ProductCommentDO::getReplyUserId, loginUserId)
  47 + .set(ProductCommentDO::getReplyContent, replyVO.getReplyContent())
  48 + .eq(ProductCommentDO::getId, replyVO.getId());
  49 + update(null, lambdaUpdateWrapper);
  50 + }
31 51 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentService.java
... ... @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.product.service.comment;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
  5 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
  6 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
5 7 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
6 8 import org.springframework.stereotype.Service;
7 9 import org.springframework.validation.annotation.Validated;
... ... @@ -23,4 +25,19 @@ public interface ProductCommentService {
23 25 */
24 26 PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO);
25 27  
  28 + /**
  29 + * 修改评论是否可见
  30 + *
  31 + * @param updateReqVO 修改评论可见
  32 + */
  33 + void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO);
  34 +
  35 + /**
  36 + * 商家回复
  37 + *
  38 + * @param replyVO 商家回复
  39 + * @param loginUserId 管理后台商家登陆人ID
  40 + */
  41 + void commentReply(ProductCommentReplyVO replyVO, Long loginUserId);
  42 +
26 43 }
... ...
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
... ... @@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.product.service.comment;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
  5 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
  6 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
5 7 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
6 8 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
7 9 import org.springframework.stereotype.Service;
... ... @@ -9,6 +11,9 @@ import org.springframework.validation.annotation.Validated;
9 11  
10 12 import javax.annotation.Resource;
11 13  
  14 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  15 +import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.COMMENT_NOT_EXISTS;
  16 +
12 17 /**
13 18 * 商品评论 Service 实现类
14 19 *
... ... @@ -26,4 +31,27 @@ public class ProductCommentServiceImpl implements ProductCommentService {
26 31 return productCommentMapper.selectPage(pageReqVO);
27 32 }
28 33  
  34 + @Override
  35 + public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) {
  36 + // 校验评论是否存在
  37 + validateCommentExists(updateReqVO.getId());
  38 +
  39 + productCommentMapper.updateCommentVisible(updateReqVO.getId(), updateReqVO.getVisible());
  40 + }
  41 +
  42 + @Override
  43 + public void commentReply(ProductCommentReplyVO replyVO, Long loginUserId) {
  44 + // 校验评论是否存在
  45 + validateCommentExists(replyVO.getId());
  46 +
  47 + productCommentMapper.commentReply(replyVO, loginUserId);
  48 + }
  49 +
  50 + private void validateCommentExists(Long id) {
  51 + if (productCommentMapper.selectById(id) == null) {
  52 + throw exception(COMMENT_NOT_EXISTS);
  53 + }
  54 + }
  55 +
  56 +
29 57 }
... ...
yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java
... ... @@ -5,7 +5,9 @@ import cn.hutool.core.util.RandomUtil;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
6 6 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
7 7 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
  8 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
8 9 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
  10 +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
9 11 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
10 12 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
11 13 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
... ... @@ -19,7 +21,7 @@ import java.util.Date;
19 21 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
20 22 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
21 23 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
22   -import static org.junit.jupiter.api.Assertions.assertEquals;
  24 +import static org.junit.jupiter.api.Assertions.*;
23 25  
24 26 /**
25 27 * {@link ProductCommentServiceImpl} 的单元测试类
... ... @@ -62,6 +64,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
62 64 o.setUserNickname("王二狗");
63 65 o.setSpuName("感冒药");
64 66 o.setScores(ProductCommentScoresEnum.FOUR.getScores());
  67 + o.setReplied(Boolean.TRUE);
65 68 });
66 69 productCommentMapper.insert(productComment);
67 70  
... ... @@ -78,6 +81,8 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
78 81 productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuName("感康")));
79 82 // 测试 scores 不匹配
80 83 productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setScores(ProductCommentScoresEnum.ONE.getScores())));
  84 + // 测试 replied 不匹配
  85 + productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setReplied(Boolean.FALSE)));
81 86  
82 87 // 调用
83 88 ProductCommentPageReqVO productCommentPageReqVO = new ProductCommentPageReqVO();
... ... @@ -86,13 +91,50 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
86 91 productCommentPageReqVO.setSpuId(spuId);
87 92 productCommentPageReqVO.setSpuName("感冒药");
88 93 productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores());
  94 + productCommentPageReqVO.setReplied(Boolean.TRUE);
89 95  
90 96 PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO);
91 97 PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO));
92 98 assertEquals(result.getTotal(), commentPage.getTotal());
93 99  
94 100 PageResult<ProductCommentDO> all = productCommentService.getCommentPage(new ProductCommentPageReqVO());
95   - assertEquals(6, all.getTotal());
  101 + assertEquals(7, all.getTotal());
96 102 }
97 103  
  104 + @Test
  105 + public void testUpdateCommentVisible_success() {
  106 + // mock 测试
  107 + ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> {
  108 + o.setVisible(Boolean.TRUE);
  109 + });
  110 + productCommentMapper.insert(productComment);
  111 +
  112 + Long productCommentId = productComment.getId();
  113 +
  114 + ProductCommentUpdateVisibleReqVO updateReqVO = new ProductCommentUpdateVisibleReqVO();
  115 + updateReqVO.setId(productCommentId);
  116 + updateReqVO.setVisible(Boolean.FALSE);
  117 + productCommentService.updateCommentVisible(updateReqVO);
  118 +
  119 + ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId);
  120 + assertFalse(productCommentDO.getVisible());
  121 + }
  122 +
  123 +
  124 + @Test
  125 + public void testCommentReply_success() {
  126 + // mock 测试
  127 + ProductCommentDO productComment = randomPojo(ProductCommentDO.class);
  128 + productCommentMapper.insert(productComment);
  129 +
  130 + Long productCommentId = productComment.getId();
  131 +
  132 + ProductCommentReplyVO replyVO = new ProductCommentReplyVO();
  133 + replyVO.setId(productCommentId);
  134 + replyVO.setReplyContent("测试");
  135 + productCommentService.commentReply(replyVO, 1L);
  136 +
  137 + ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId);
  138 + assertEquals("测试", productCommentDO.getReplyContent());
  139 + }
98 140 }
... ...