[新增][商品评价]管理后台分页查询

This commit is contained in:
wangzhs 2023-03-19 18:59:51 +08:00
parent f69d8503a2
commit da53a041da
14 changed files with 389 additions and 2 deletions

View File

@ -0,0 +1,41 @@
package cn.iocoder.yudao.module.product.enums.comment;
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 商品评论的星级枚举
*
* @author wangzhs
*/
@Getter
@AllArgsConstructor
public enum ProductCommentScoresEnum implements IntArrayValuable {
ONE(1, "1星"),
TWO(2, "2星"),
THREE(3, "3星"),
FOUR(4, "4星"),
FIVE(5, "5星");
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ProductCommentScoresEnum::getScores).toArray();
/**
* 星级
*/
private final Integer scores;
/**
* 星级名
*/
private final String name;
@Override
public int[] array() {
return ARRAYS;
}
}

View File

@ -0,0 +1,40 @@
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.ProductCommentRespVO;
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;
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 javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 商品评价")
@RestController
@RequestMapping("/product/comment")
@Validated
public class ProductCommentController {
@Resource
private ProductCommentService productCommentService;
@GetMapping("/page")
@Operation(summary = "获得商品评价分页")
@PreAuthorize("@ss.hasPermission('product:comment:query')")
public CommonResult<PageResult<ProductCommentRespVO>> getCommentPage(@Valid ProductCommentPageReqVO pageVO) {
PageResult<ProductCommentDO> pageResult = productCommentService.getCommentPage(pageVO);
return success(ProductCommentConvert.INSTANCE.convertPage(pageResult));
}
}

View File

@ -0,0 +1,60 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.util.List;
@Data
public class ProductCommentBaseVO {
@Schema(description = "评价人 用户编号", required = true, example = "15721")
@NotNull(message = "评价人 用户编号不能为空")
private Long userId;
@Schema(description = "评价人名称", required = true, example = "张三")
@NotNull(message = "评价人名称不能为空")
private String userNickname;
@Schema(description = "评价人头像", required = true)
@NotNull(message = "评价人头像不能为空")
private String userAvatar;
@Schema(description = "商品SPU编号", required = true, example = "29502")
@NotNull(message = "商品SPU编号不能为空")
private Long spuId;
@Schema(description = "商品SPU名称", required = true, example = "赵六")
@NotNull(message = "商品SPU名称不能为空")
private String spuName;
@Schema(description = "商品SKU编号", required = true, example = "3082")
@NotNull(message = "商品SKU编号不能为空")
private Long skuId;
@Schema(description = "评分星级 1-5分", required = true)
@NotNull(message = "评分星级 1-5分不能为空")
private Integer scores;
@Schema(description = "描述星级 1-5分", required = true)
@NotNull(message = "描述星级 1-5分不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5分", required = true)
@NotNull(message = "服务星级 1-5分不能为空")
private Integer benefitScores;
@Schema(description = "配送星级 1-5分", required = true)
@NotNull(message = "配送星级 1-5分不能为空")
private Integer deliveryScores;
@Schema(description = "评论内容", required = true)
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组以逗号分隔最多上传9张", required = true)
@NotNull(message = "评论图片地址数组以逗号分隔最多上传9张不能为空")
private List<String> picUrls;
}

View File

@ -0,0 +1,12 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(description = "管理后台 - 商品评价创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductCommentCreateReqVO extends ProductCommentBaseVO {
}

View File

@ -0,0 +1,42 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 商品评价分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductCommentPageReqVO extends PageParam {
@Schema(description = "评价人名称", example = "王二狗")
private String userNickname;
@Schema(description = "交易订单编号", example = "24428")
private Long orderId;
@Schema(description = "商品SPU编号", example = "29502")
private Long spuId;
@Schema(description = "商品SPU名称", example = "感冒药")
private String spuName;
@Schema(description = "评分星级 1-5分")
@InEnum(ProductCommentScoresEnum.class)
private Integer scores;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] createTime;
}

View File

@ -0,0 +1,53 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "管理后台 - 商品评价 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ProductCommentRespVO extends ProductCommentBaseVO {
@Schema(description = "订单项编号", required = true, example = "24965")
private Long id;
@Schema(description = "是否匿名:[0:不匿名 1:匿名]", required = true)
private Boolean anonymous;
@Schema(description = "交易订单编号", required = true, example = "24428")
private Long orderId;
@Schema(description = "交易订单项编号", required = true, example = "8233")
private Long orderItemId;
@Schema(description = "是否可见:[1:显示 0:隐藏]", required = true)
private Boolean visible;
@Schema(description = "商家是否回复:[1:回复 0:未回复]", required = true)
private Boolean replied;
@Schema(description = "回复管理员编号", example = "22212")
private Long replyUserId;
@Schema(description = "商家回复内容")
private String replyContent;
@Schema(description = "商家回复时间")
private LocalDateTime replyTime;
@Schema(description = "追加评价内容")
private String additionalContent;
@Schema(description = "追评评价图片地址数组以逗号分隔最多上传9张")
private List<String> additionalPicUrls;
@Schema(description = "追加评价时间")
private LocalDateTime additionalCreateTime;
@Schema(description = "创建时间", required = true)
private LocalDateTime createTime;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.product.convert.comment;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
import java.util.List;
/**
* 商品评价 Convert
*
* @author wangzhs
*/
@Mapper
public interface ProductCommentConvert {
ProductCommentConvert INSTANCE = Mappers.getMapper(ProductCommentConvert.class);
ProductCommentRespVO convert(ProductCommentDO bean);
List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
}

View File

@ -44,7 +44,7 @@ public class ProductCommentDO extends BaseDO {
/**
* 评价人名称
*/
private Long userNickname;
private String userNickname;
/**
* 评价人头像
@ -77,6 +77,11 @@ public class ProductCommentDO extends BaseDO {
*/
private Long spuId;
/**
* 商品 SPU 名称
*/
private String spuName;
/**
* 商品 SKU 编号
* <p>

View File

@ -1,7 +1,10 @@
package cn.iocoder.yudao.module.product.dal.mysql.comment;
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.dal.dataobject.comment.ProductCommentDO;
import org.apache.ibatis.annotations.Mapper;
@ -13,4 +16,16 @@ import org.apache.ibatis.annotations.Mapper;
*/
@Mapper
public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
default PageResult<ProductCommentDO> selectPage(ProductCommentPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<ProductCommentDO>()
.likeIfPresent(ProductCommentDO::getUserNickname, reqVO.getUserNickname())
.eqIfPresent(ProductCommentDO::getOrderId, reqVO.getOrderId())
.eqIfPresent(ProductCommentDO::getSpuId, reqVO.getSpuId())
.eqIfPresent(ProductCommentDO::getScores, reqVO.getScores())
.betweenIfPresent(ProductCommentDO::getCreateTime, reqVO.getCreateTime())
.likeIfPresent(ProductCommentDO::getSpuName, reqVO.getSpuName())
.orderByDesc(ProductCommentDO::getId));
}
}

View File

@ -1,5 +1,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.dal.dataobject.comment.ProductCommentDO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -11,4 +14,13 @@ import org.springframework.validation.annotation.Validated;
@Service
@Validated
public interface ProductCommentService {
/**
* 获得商品评价分页
*
* @param pageReqVO 分页查询
* @return 商品评价分页
*/
PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO);
}

View File

@ -1,9 +1,29 @@
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.dal.dataobject.comment.ProductCommentDO;
import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
/**
* 商品评论 Service 实现类
*
* @author wangzhs
*/
@Service
@Validated
public class ProductCommentServiceImpl implements ProductCommentService {
@Resource
private ProductCommentMapper productCommentMapper;
@Override
public PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO) {
return productCommentMapper.selectPage(pageReqVO);
}
}

View File

@ -1,16 +1,25 @@
package cn.iocoder.yudao.module.product.service.comment;
import cn.hutool.core.date.DateUtil;
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.dal.dataobject.category.ProductCategoryDO;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
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;
import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.Import;
import javax.annotation.Resource;
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;
/**
* {@link ProductCommentServiceImpl} 的单元测试类
@ -23,6 +32,17 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
@Resource
private ProductCommentMapper productCommentMapper;
@Resource
private ProductCommentServiceImpl productCommentService;
public String generateNo() {
return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999);
}
public Long generateId() {
return RandomUtil.randomLong(100000, 999999);
}
@Test
public void testCreateCommentAndGet_success() {
// mock 测试
@ -35,5 +55,44 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
assertPojoEquals(productComment, comment);
}
@Test
public void testGetCommentPage_success() {
// 准备参数
ProductCommentDO productComment = randomPojo(ProductCommentDO.class, o -> {
o.setUserNickname("王二狗");
o.setSpuName("感冒药");
o.setScores(ProductCommentScoresEnum.FOUR.getScores());
});
productCommentMapper.insert(productComment);
Long orderId = productComment.getOrderId();
Long spuId = productComment.getSpuId();
// 测试 userNickname 不匹配
productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setUserNickname("王三")));
// 测试 orderId 不匹配
productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setOrderId(generateId())));
// 测试 spuId 不匹配
productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuId(generateId())));
// 测试 spuName 不匹配
productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setSpuName("感康")));
// 测试 scores 不匹配
productCommentMapper.insert(cloneIgnoreId(productComment, o -> o.setScores(ProductCommentScoresEnum.ONE.getScores())));
// 调用
ProductCommentPageReqVO productCommentPageReqVO = new ProductCommentPageReqVO();
productCommentPageReqVO.setUserNickname("王二");
productCommentPageReqVO.setOrderId(orderId);
productCommentPageReqVO.setSpuId(spuId);
productCommentPageReqVO.setSpuName("感冒药");
productCommentPageReqVO.setScores(ProductCommentScoresEnum.FOUR.getScores());
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());
}
}

View File

@ -92,6 +92,7 @@ CREATE TABLE IF NOT EXISTS `product_comment` (
`order_id` bigint NOT NULL COMMENT '交易订单编号',
`order_item_id` bigint NOT NULL COMMENT '交易订单项编号',
`spu_id` bigint NOT NULL COMMENT '商品SPU编号',
`spu_name` varchar NOT NULL COMMENT '商品SPU名称',
`sku_id` bigint NOT NULL COMMENT '商品SKU编号',
`visible` bit(1) NOT NULL DEFAULT 1 COMMENT '是否可见 1:显示 0:隐藏',
`scores` int NOT NULL COMMENT '评分星级 1-5分',