瀏覽代碼

[新增][商品评价]管理后台
1. 显示 / 隐藏评论
2. 商家回复

wangzhs 2 年之前
父節點
當前提交
cbf5ef5953

+ 3 - 0
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 {
     ErrorCode SPU_SKU_NOT_DUPLICATE = new ErrorCode(1008006003, "一个 SPU 下的每个 SKU,必须不重复");
     ErrorCode SKU_STOCK_NOT_ENOUGH = new ErrorCode(1008006004, "商品 SKU 库存不足");
 
+    // ========== 商品 评价 1008007000 ==========
+    ErrorCode COMMENT_NOT_EXISTS = new ErrorCode(1008007000, "商品 评价 不存在");
+
 }

+ 20 - 3
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;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
@@ -11,14 +13,13 @@ import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import javax.validation.Valid;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 @Tag(name = "管理后台 - 商品评价")
 @RestController
@@ -37,4 +38,20 @@ public class ProductCommentController {
         return success(ProductCommentConvert.INSTANCE.convertPage(pageResult));
     }
 
+    @PutMapping("/update/visible")
+    @Operation(summary = "显示 / 隐藏评论")
+    @PreAuthorize("@ss.hasPermission('product:comment:update')")
+    public CommonResult<Boolean> updateCommentVisible(@Valid @RequestBody ProductCommentUpdateVisibleReqVO updateReqVO) {
+        productCommentService.updateCommentVisible(updateReqVO);
+        return success(true);
+    }
+
+    @PutMapping("/reply")
+    @Operation(summary = "商家回复")
+    @PreAuthorize("@ss.hasPermission('product:comment:update')")
+    public CommonResult<Boolean> commentReply(@Valid @RequestBody ProductCommentReplyVO replyVO) {
+        productCommentService.commentReply(replyVO, getLoginUserId());
+        return success(true);
+    }
+
 }

+ 3 - 0
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 {
     @InEnum(ProductCommentScoresEnum.class)
     private Integer scores;
 
+    @Schema(description = "商家是否回复")
+    private Boolean replied;
+
     @Schema(description = "创建时间")
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     private LocalDateTime[] createTime;

+ 22 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentReplyVO.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 商品评价可见修改 Request VO")
+@Data
+@ToString(callSuper = true)
+public class ProductCommentReplyVO {
+
+    @Schema(description = "评价编号", required = true, example = "15721")
+    @NotNull(message = "评价编号不能为空")
+    private Long id;
+
+    @Schema(description = "商家回复内容", required = true, example = "谢谢亲")
+    @NotNull(message = "商家回复内容不能为空")
+    private String replyContent;
+
+}

+ 22 - 0
yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/comment/vo/ProductCommentUpdateVisibleReqVO.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.ToString;
+
+import javax.validation.constraints.NotNull;
+
+@Schema(description = "管理后台 - 商品评价可见修改 Request VO")
+@Data
+@ToString(callSuper = true)
+public class ProductCommentUpdateVisibleReqVO {
+
+    @Schema(description = "评价编号", required = true, example = "15721")
+    @NotNull(message = "评价编号不能为空")
+    private Long id;
+
+    @Schema(description = "是否可见 true:显示 false:隐藏", required = true, example = "false")
+    @NotNull(message = "是否可见不能为空")
+    private Boolean visible;
+
+}

+ 20 - 0
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;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.time.LocalDateTime;
+
 
 /**
  * 商品评论 Mapper
@@ -28,4 +32,20 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
                 .orderByDesc(ProductCommentDO::getId));
     }
 
+    default void updateCommentVisible(Long id, Boolean visible) {
+        LambdaUpdateWrapper<ProductCommentDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<ProductCommentDO>()
+                .set(ProductCommentDO::getVisible, visible)
+                .eq(ProductCommentDO::getId, id);
+        update(null, lambdaUpdateWrapper);
+    }
+
+    default void commentReply(ProductCommentReplyVO replyVO, Long loginUserId) {
+        LambdaUpdateWrapper<ProductCommentDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<ProductCommentDO>()
+                .set(ProductCommentDO::getReplied, Boolean.TRUE)
+                .set(ProductCommentDO::getReplyTime, LocalDateTime.now())
+                .set(ProductCommentDO::getReplyUserId, loginUserId)
+                .set(ProductCommentDO::getReplyContent, replyVO.getReplyContent())
+                .eq(ProductCommentDO::getId, replyVO.getId());
+        update(null, lambdaUpdateWrapper);
+    }
 }

+ 17 - 0
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;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
@@ -23,4 +25,19 @@ public interface ProductCommentService {
      */
     PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO);
 
+    /**
+     * 修改评论是否可见
+     *
+     * @param updateReqVO 修改评论可见
+     */
+    void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO);
+
+    /**
+     * 商家回复
+     *
+     * @param replyVO     商家回复
+     * @param loginUserId 管理后台商家登陆人ID
+     */
+    void commentReply(ProductCommentReplyVO replyVO, Long loginUserId);
+
 }

+ 28 - 0
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;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
 import org.springframework.stereotype.Service;
@@ -9,6 +11,9 @@ import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.COMMENT_NOT_EXISTS;
+
 /**
  * 商品评论 Service 实现类
  *
@@ -26,4 +31,27 @@ public class ProductCommentServiceImpl implements ProductCommentService {
         return productCommentMapper.selectPage(pageReqVO);
     }
 
+    @Override
+    public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) {
+        // 校验评论是否存在
+        validateCommentExists(updateReqVO.getId());
+
+        productCommentMapper.updateCommentVisible(updateReqVO.getId(), updateReqVO.getVisible());
+    }
+
+    @Override
+    public void commentReply(ProductCommentReplyVO replyVO, Long loginUserId) {
+        // 校验评论是否存在
+        validateCommentExists(replyVO.getId());
+
+        productCommentMapper.commentReply(replyVO, loginUserId);
+    }
+
+    private void validateCommentExists(Long id) {
+        if (productCommentMapper.selectById(id) == null) {
+            throw exception(COMMENT_NOT_EXISTS);
+        }
+    }
+
+
 }

+ 44 - 2
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;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyVO;
 import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
+import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
 import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
 import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
 import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
@@ -19,7 +21,7 @@ import java.util.Date;
 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.*;
 
 /**
  * {@link ProductCommentServiceImpl} 的单元测试类
@@ -62,6 +64,7 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
             o.setUserNickname("王二狗");
             o.setSpuName("感冒药");
             o.setScores(ProductCommentScoresEnum.FOUR.getScores());
+            o.setReplied(Boolean.TRUE);
         });
         productCommentMapper.insert(productComment);
 
@@ -78,6 +81,8 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
         productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuName("感康")));
         // 测试 scores 不匹配
         productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setScores(ProductCommentScoresEnum.ONE.getScores())));
+        // 测试 replied 不匹配
+        productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setReplied(Boolean.FALSE)));
 
         // 调用
         ProductCommentPageReqVO productCommentPageReqVO = new ProductCommentPageReqVO();
@@ -86,13 +91,50 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
         productCommentPageReqVO.setSpuId(spuId);
         productCommentPageReqVO.setSpuName("感冒药");
         productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores());
+        productCommentPageReqVO.setReplied(Boolean.TRUE);
 
         PageResult<ProductCommentDO> commentPage = productCommentService.getCommentPage(productCommentPageReqVO);
         PageResult<ProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO));
         assertEquals(result.getTotal(), commentPage.getTotal());
 
         PageResult<ProductCommentDO> all = productCommentService.getCommentPage(new ProductCommentPageReqVO());
-        assertEquals(6, all.getTotal());
+        assertEquals(7, all.getTotal());
     }
 
+    @Test
+    public void testUpdateCommentVisible_success() {
+        // mock 测试
+        ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> {
+            o.setVisible(Boolean.TRUE);
+        });
+        productCommentMapper.insert(productComment);
+
+        Long productCommentId = productComment.getId();
+
+        ProductCommentUpdateVisibleReqVO updateReqVO = new ProductCommentUpdateVisibleReqVO();
+        updateReqVO.setId(productCommentId);
+        updateReqVO.setVisible(Boolean.FALSE);
+        productCommentService.updateCommentVisible(updateReqVO);
+
+        ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId);
+        assertFalse(productCommentDO.getVisible());
+    }
+
+
+    @Test
+    public void testCommentReply_success() {
+        // mock 测试
+        ProductCommentDO productComment = randomPojo(ProductCommentDO.class);
+        productCommentMapper.insert(productComment);
+
+        Long productCommentId = productComment.getId();
+
+        ProductCommentReplyVO replyVO = new ProductCommentReplyVO();
+        replyVO.setId(productCommentId);
+        replyVO.setReplyContent("测试");
+        productCommentService.commentReply(replyVO, 1L);
+
+        ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId);
+        assertEquals("测试", productCommentDO.getReplyContent());
+    }
 }