mall + promotion:review 秒杀、评论代码

This commit is contained in:
YunaiV 2023-06-23 21:14:36 +08:00
parent b16632ea41
commit 2efdbf93cb
34 changed files with 58 additions and 139 deletions

View File

@ -30,6 +30,7 @@ public interface ProductSkuApi {
*/ */
List<ProductSkuRespDTO> getSkuList(Collection<Long> ids); List<ProductSkuRespDTO> getSkuList(Collection<Long> ids);
// TODO puhui999入参用 Collection<Long> 更通用
/** /**
* 批量查询 SKU 数组 * 批量查询 SKU 数组
* *

View File

@ -28,7 +28,6 @@ public class ProductSpuApiImpl implements ProductSpuApi {
@Override @Override
public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) { public List<ProductSpuRespDTO> getSpuList(Collection<Long> spuIds) {
// TODO 需不需要判断集合中是否有 null
if (CollectionUtil.isEmpty(spuIds)) { if (CollectionUtil.isEmpty(spuIds)) {
return Collections.emptyList(); return Collections.emptyList();
} }

View File

@ -26,6 +26,7 @@ public class ProductCommentBaseVO {
@NotNull(message = "评价人头像不能为空") @NotNull(message = "评价人头像不能为空")
private String userAvatar; private String userAvatar;
// TODO @puhuispuIdspuName 是不是只有 ProductCommentRespVO 有呀
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖") @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑透气小短袖")
@NotNull(message = "商品 SPU 编号不能为空") @NotNull(message = "商品 SPU 编号不能为空")
private Long spuId; private Long spuId;
@ -54,7 +55,7 @@ public class ProductCommentBaseVO {
@NotNull(message = "评论内容不能为空") @NotNull(message = "评论内容不能为空")
private String content; private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls; private List<String> picUrls;

View File

@ -35,6 +35,7 @@ public class ProductCommentPageReqVO extends PageParam {
@InEnum(ProductCommentScoresEnum.class) @InEnum(ProductCommentScoresEnum.class)
private Integer scores; private Integer scores;
// TODO @puhui999replyStatus
@Schema(description = "商家是否回复", example = "true") @Schema(description = "商家是否回复", example = "true")
private Boolean replied; private Boolean replied;

View File

@ -7,7 +7,7 @@ import lombok.ToString;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 商品评价可见修改 Request VO") @Schema(description = "管理后台 - 商品评价的商家回复 Request VO")
@Data @Data
@ToString(callSuper = true) @ToString(callSuper = true)
public class ProductCommentReplyReqVO { public class ProductCommentReplyReqVO {

View File

@ -56,19 +56,20 @@ public class AppProductCommentController {
public CommonResult<List<AppProductCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId, public CommonResult<List<AppProductCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId,
@RequestParam(value = "count", defaultValue = "10") Integer count) { @RequestParam(value = "count", defaultValue = "10") Integer count) {
return success(productCommentService.getCommentList(spuId, count)); return success(productCommentService.getCommentList(spuId, count));
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得商品评价分页") @Operation(summary = "获得商品评价分页")
public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) { public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
PageResult<AppProductCommentRespVO> page = productCommentService.getCommentPage(pageVO, Boolean.TRUE); PageResult<AppProductCommentRespVO> page = productCommentService.getCommentPage(pageVO, Boolean.TRUE);
// TODO @puhui CollUtils 有简化 convertmap list 的方法
Set<Long> skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet()); Set<Long> skuIds = page.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet());
List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds); List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size()); Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size());
if (CollUtil.isNotEmpty(skuList)) { if (CollUtil.isNotEmpty(skuList)) {
skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c))); skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c)));
} }
// TODO @puihui999下面也可以放到 convert 里哈
page.getList().forEach(item -> { page.getList().forEach(item -> {
// 判断用户是否选择匿名 // 判断用户是否选择匿名
if (ObjectUtil.equal(item.getAnonymous(), true)) { if (ObjectUtil.equal(item.getAnonymous(), true)) {
@ -83,6 +84,7 @@ public class AppProductCommentController {
return success(page); return success(page);
} }
// TODO 芋艿需要搞下
@GetMapping("/getCommentStatistics") @GetMapping("/getCommentStatistics")
@Operation(summary = "获得商品的评价统计") @Operation(summary = "获得商品的评价统计")
public CommonResult<AppCommentStatisticsRespVO> getCommentStatistics(@Valid @RequestParam("spuId") Long spuId) { public CommonResult<AppCommentStatisticsRespVO> getCommentStatistics(@Valid @RequestParam("spuId") Long spuId) {

View File

@ -1,56 +0,0 @@
package cn.iocoder.yudao.module.product.controller.app.comment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
@Schema(description = "用户 App - 商品评价创建 Request VO")
@Data
@ToString(callSuper = true)
public class AppProductCommentCreateReqVO {
@Schema(description = "是否匿名", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "是否匿名不能为空")
private Boolean anonymous;
@Schema(description = "交易订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2312312")
@NotNull(message = "交易订单项编号不能为空")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192")
@NotNull(message = "商品SPU编号不能为空")
private Long spuId;
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖")
@NotNull(message = "商品SPU名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192")
@NotNull(message = "商品SKU编号不能为空")
private Long skuId;
@Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "评分星级 1-5 分不能为空")
private Integer scores;
@Schema(description = "描述星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "描述星级 1-5 分不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "服务星级 1-5 分不能为空")
private Integer benefitScores;
@Schema(description = "评论内容", requiredMode = Schema.RequiredMode.REQUIRED, example = "哇,真的很丝滑凉快诶,好评")
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls;
}

View File

@ -4,15 +4,12 @@ import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProdu
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.ToString; import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/** /**
* 用户 App - 商品评价详情 Response VO * 用户 App - 商品评价详情 Response VO
* *
@ -54,7 +51,6 @@ public class AppProductCommentRespVO {
private String replyContent; private String replyContent;
@Schema(description = "商家回复时间") @Schema(description = "商家回复时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime replyTime; private LocalDateTime replyTime;
@Schema(description = "追加评价内容", example = "穿了很久都很丝滑诶") @Schema(description = "追加评价内容", example = "穿了很久都很丝滑诶")
@ -64,23 +60,21 @@ public class AppProductCommentRespVO {
private List<String> additionalPicUrls; private List<String> additionalPicUrls;
@Schema(description = "追加评价时间") @Schema(description = "追加评价时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime additionalTime; private LocalDateTime additionalTime;
@Schema(description = "创建时间") @Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime createTime; private LocalDateTime createTime;
@Schema(description = "商品SPU编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192") @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "91192")
@NotNull(message = "商品SPU编号不能为空") @NotNull(message = "商品 SPU 编号不能为空")
private Long spuId; private Long spuId;
@Schema(description = "商品SPU名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖") @Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑小短袖")
@NotNull(message = "商品SPU名称不能为空") @NotNull(message = "商品 SPU 名称不能为空")
private String spuName; private String spuName;
@Schema(description = "商品SKU编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192") @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "81192")
@NotNull(message = "商品SKU编号不能为空") @NotNull(message = "商品 SKU 编号不能为空")
private Long skuId; private Long skuId;
@Schema(description = "商品 SKU 属性", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "商品 SKU 属性", requiredMode = Schema.RequiredMode.REQUIRED)
@ -102,7 +96,7 @@ public class AppProductCommentRespVO {
@NotNull(message = "评论内容不能为空") @NotNull(message = "评论内容不能为空")
private String content; private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]") @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls; private List<String> picUrls;

View File

@ -32,6 +32,7 @@ public interface ProductCommentConvert {
ProductCommentRespVO convert(ProductCommentDO bean); ProductCommentRespVO convert(ProductCommentDO bean);
// TODO @puhui999这里貌似字段对上就不用 mapping 可以测试下看看哈
@Mapping(target = "allCount", source = "allCount") @Mapping(target = "allCount", source = "allCount")
@Mapping(target = "goodCount", source = "goodCount") @Mapping(target = "goodCount", source = "goodCount")
@Mapping(target = "mediocreCount", source = "mediocreCount") @Mapping(target = "mediocreCount", source = "mediocreCount")

View File

@ -25,7 +25,6 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
.orderByDesc(ProductCommentDO::getId)); .orderByDesc(ProductCommentDO::getId));
} }
// TODO 芋艿在看看这块
static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) { static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
// 构建好评查询语句好评计算 总评 >= 4 // 构建好评查询语句好评计算 总评 >= 4
if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) { if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {

View File

@ -149,13 +149,15 @@ public class ProductCommentServiceImpl implements ProductCommentService {
@Override @Override
public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) { public List<AppProductCommentRespVO> getCommentList(Long spuId, Integer count) {
// 校验商品 spu 是否存在 // 校验商品 spu 是否存在
// TODO @puhui 这里校验可以去掉哈
ProductSpuDO spuDO = validateSpu(spuId); ProductSpuDO spuDO = validateSpu(spuId);
return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuDO.getId(), count).getList()); return ProductCommentConvert.INSTANCE.convertList02(productCommentMapper.selectCommentList(spuDO.getId(), count).getList());
} }
// TODO @puhui 可以放到 controller convert
@Override @Override
public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) { public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
// TODO @puhui 可以放到 controller convert
return ProductCommentConvert.INSTANCE.convertPage02( return ProductCommentConvert.INSTANCE.convertPage02(
productCommentMapper.selectPage(pageVO, visible)); productCommentMapper.selectPage(pageVO, visible));
} }

View File

@ -20,6 +20,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data @Data
public class SeckillActivityBaseVO { public class SeckillActivityBaseVO {
// TODO @puhui999对应单 spuId
@Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]") @Schema(description = "秒杀活动商品id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[121,1212]")
@NotNull(message = "秒杀活动商品不能为空") @NotNull(message = "秒杀活动商品不能为空")
private List<Long> spuIds; private List<Long> spuIds;
@ -45,7 +46,7 @@ public class SeckillActivityBaseVO {
@NotNull(message = "排序不能为空") @NotNull(message = "排序不能为空")
private Integer sort; private Integer sort;
@Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]") @Schema(description = "秒杀时段 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1,2,3]")
@NotNull(message = "秒杀时段不能为空") @NotNull(message = "秒杀时段不能为空")
private List<Long> configIds; private List<Long> configIds;
@ -55,6 +56,7 @@ public class SeckillActivityBaseVO {
@Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683") @Schema(description = "单次限够数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "31683")
private Integer singleLimitCount; private Integer singleLimitCount;
// TODO @puhui999这个应该是计算出来的字段只返回create update 不用哈
@Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @Schema(description = "秒杀总库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer totalStock; private Integer totalStock;

View File

@ -9,11 +9,6 @@ import lombok.ToString;
import java.util.List; import java.util.List;
/**
* 管理后台 - 秒杀活动创建 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀活动创建 Request VO") @Schema(description = "管理后台 - 秒杀活动创建 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)

View File

@ -7,11 +7,6 @@ import lombok.ToString;
import java.util.List; import java.util.List;
/**
* 管理后台 - 秒杀活动的详细 Response VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀活动的详细 Response VO") @Schema(description = "管理后台 - 秒杀活动的详细 Response VO")
@Data @Data
@ToString(callSuper = true) @ToString(callSuper = true)

View File

@ -28,5 +28,4 @@ public class SeckillActivityRespVO extends SeckillActivityBaseVO {
@Schema(description = "活动状态 开启0 禁用1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @Schema(description = "活动状态 开启0 禁用1", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
private Integer status; private Integer status;
} }

View File

@ -1,22 +1,13 @@
package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity; package cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO; import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductUpdateReqVO;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
/**
* 管理后台 - 秒杀活动更新 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀活动更新 Request VO") @Schema(description = "管理后台 - 秒杀活动更新 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -29,5 +20,4 @@ public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
@Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "秒杀商品", requiredMode = Schema.RequiredMode.REQUIRED)
private List<SeckillProductUpdateReqVO> products; private List<SeckillProductUpdateReqVO> products;
} }

View File

@ -5,11 +5,6 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
/**
* 管理后台 秒杀时段创建 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀时段创建 Request VO") @Schema(description = "管理后台 - 秒杀时段创建 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)

View File

@ -6,6 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
// TODO @puhuiVO 上不写注释已经有注解啦
/** /**
* 管理后台 - 秒杀时段分页 Request VO * 管理后台 - 秒杀时段分页 Request VO
* *

View File

@ -4,17 +4,9 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 管理后台 - 秒杀时段 Response VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀时段 Response VO") @Schema(description = "管理后台 - 秒杀时段 Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -28,7 +20,6 @@ public class SeckillConfigRespVO extends SeckillConfigBaseVO {
private Integer seckillActivityCount; private Integer seckillActivityCount;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime createTime; private LocalDateTime createTime;
} }

View File

@ -7,11 +7,6 @@ import lombok.NoArgsConstructor;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
/**
* 管理后台 - 秒杀时段配置精简信息 Response VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀时段配置精简信息 Response VO") @Schema(description = "管理后台 - 秒杀时段配置精简信息 Response VO")
@Data @Data
@NoArgsConstructor @NoArgsConstructor

View File

@ -7,11 +7,6 @@ import lombok.ToString;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
/**
* 管理后台 - 秒杀时段更新 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 秒杀时段更新 Request VO") @Schema(description = "管理后台 - 秒杀时段更新 Request VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)

View File

@ -7,11 +7,6 @@ import lombok.Data;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
/**
* 管理后台 - 修改时段配置状态 Request VO
*
* @author HUIHUI
*/
@Schema(description = "管理后台 - 修改时段配置状态 Request VO") @Schema(description = "管理后台 - 修改时段配置状态 Request VO")
@Data @Data
public class SeckillConfigUpdateStatusReqVo { public class SeckillConfigUpdateStatusReqVo {
@ -20,7 +15,7 @@ public class SeckillConfigUpdateStatusReqVo {
@NotNull(message = "时段配置编号不能为空") @NotNull(message = "时段配置编号不能为空")
private Long id; private Long id;
@Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @Schema(description = "状态见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空") @NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status; private Integer status;

View File

@ -14,6 +14,7 @@ import javax.validation.constraints.NotNull;
@Data @Data
public class SeckillProductBaseVO { public class SeckillProductBaseVO {
// TODO @puhuispuId 不用传递因为一个秒杀活动只对应一个 SPU ;
@Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563") @Schema(description = "商品spu_id", requiredMode = Schema.RequiredMode.REQUIRED, example = "30563")
@NotNull(message = "商品spu_id不能为空") @NotNull(message = "商品spu_id不能为空")
private Long spuId; private Long spuId;

View File

@ -59,6 +59,7 @@ public class AppActivityController {
} }
Map<Long, List<AppActivityRespVO>> map = new HashMap<>(); Map<Long, List<AppActivityRespVO>> map = new HashMap<>();
map.put(109L, randomList); map.put(109L, randomList);
map.put(2L, randomList);
return success(map); return success(map);
} }

View File

@ -69,7 +69,6 @@ public interface SeckillActivityConvert {
&& ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice()); && ObjectUtil.equals(productDO.getSeckillPrice(), productVO.getSeckillPrice());
//&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota()) //&& ObjectUtil.equals(productDO.getQuota(), productVO.getQuota())
//&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount()); //&& ObjectUtil.equals(productDO.getLimitCount(), productVO.getLimitCount());
} }
default List<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) { default List<SeckillProductDO> convertList(SeckillActivityDO seckillActivity, List<SeckillProductCreateReqVO> products) {

View File

@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
@ -34,10 +35,14 @@ public class SeckillProductDO extends BaseDO {
private Long id; private Long id;
/** /**
* 秒杀活动 id * 秒杀活动 id
*
* 关联 {@link SeckillActivityDO#getId()}
*/ */
private Long activityId; private Long activityId;
/** /**
* 秒杀时段 id * 秒杀时段 id
*
* 关联 {@link SeckillConfigDO#getId()}
*/ */
@TableField(typeHandler = LongListTypeHandler.class) @TableField(typeHandler = LongListTypeHandler.class)
private List<Long> configIds; private List<Long> configIds;
@ -57,8 +62,10 @@ public class SeckillProductDO extends BaseDO {
* 秒杀库存 * 秒杀库存
*/ */
private Integer stock; private Integer stock;
/** /**
* 秒杀商品状态 * 秒杀商品状态
*
* 枚举 {@link CommonStatusEnum 对应的类} * 枚举 {@link CommonStatusEnum 对应的类}
*/ */
private Integer activityStatus; private Integer activityStatus;

View File

@ -38,13 +38,14 @@ public class SeckillConfigDO extends BaseDO {
* 结束时间点 * 结束时间点
*/ */
private String endTime; private String endTime;
// TODO puhui999应该是轮播图 private List<String> sliderPicUrls;
/** /**
* 秒杀主图 * 秒杀主图
*/ */
private String picUrl; private String picUrl;
/** /**
* 状态 开启0 禁用1 * 状态
* <p> *
* 枚举 {@link CommonStatusEnum 对应的类} * 枚举 {@link CommonStatusEnum 对应的类}
*/ */
private Integer status; private Integer status;

View File

@ -17,6 +17,7 @@ import java.util.List;
*/ */
@Mapper @Mapper
public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> { public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
default PageResult<SeckillActivityDO> selectPage(SeckillActivityPageReqVO reqVO) { default PageResult<SeckillActivityDO> selectPage(SeckillActivityPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<SeckillActivityDO>() return selectPage(reqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
.likeIfPresent(SeckillActivityDO::getName, reqVO.getName()) .likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
@ -30,4 +31,5 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
return selectList(new LambdaQueryWrapperX<SeckillActivityDO>() return selectList(new LambdaQueryWrapperX<SeckillActivityDO>()
.eqIfPresent(SeckillActivityDO::getStatus, status)); .eqIfPresent(SeckillActivityDO::getStatus, status));
} }
} }

View File

@ -65,22 +65,24 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
validateProductSkuExistence(createReqVO.getSpuIds(), createReqVO.getProducts()); validateProductSkuExistence(createReqVO.getSpuIds(), createReqVO.getProducts());
// 插入秒杀活动 // 插入秒杀活动
SeckillActivityDO seckillActivity = SeckillActivityConvert.INSTANCE.convert(createReqVO) SeckillActivityDO activity = SeckillActivityConvert.INSTANCE.convert(createReqVO)
.setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime())); .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
seckillActivityMapper.insert(seckillActivity); seckillActivityMapper.insert(activity);
// 插入商品 // 插入商品
List<SeckillProductDO> productDOs = SeckillActivityConvert.INSTANCE.convertList(seckillActivity, createReqVO.getProducts()); List<SeckillProductDO> product = SeckillActivityConvert.INSTANCE.convertList(activity, createReqVO.getProducts());
seckillProductMapper.insertBatch(productDOs); seckillProductMapper.insertBatch(product);
return seckillActivity.getId(); return activity.getId();
} }
private <T extends SeckillProductBaseVO> void validateProductSkuExistence(List<Long> spuIds, List<T> products) { private <T extends SeckillProductBaseVO> void validateProductSkuExistence(List<Long> spuIds, List<T> products) {
Set<Long> convertedSpuIds = CollectionUtils.convertSet(products, T::getSpuId);
// 校验 spu 个数是否相等 // 校验 spu 个数是否相等
// TODO @puhui999不用校验 SPU 只校验 sku 对应的 spuId 是否一致
Set<Long> convertedSpuIds = CollectionUtils.convertSet(products, T::getSpuId);
if (ObjectUtil.notEqual(spuIds.size(), convertedSpuIds.size())) { if (ObjectUtil.notEqual(spuIds.size(), convertedSpuIds.size())) {
throw exception(SKU_NOT_EXISTS); throw exception(SKU_NOT_EXISTS);
} }
// 获取所选 spu下的所有 sku // 获取所选 spu下的所有 sku
// TODO @puhui999变量可以简单一点skus
List<ProductSkuRespDTO> skuRespDTOs = productSkuApi.getSkuListBySpuId(spuIds); List<ProductSkuRespDTO> skuRespDTOs = productSkuApi.getSkuListBySpuId(spuIds);
// 校验 sku 个数是否一致 // 校验 sku 个数是否一致
Set<Long> skuIdsSet = CollectionUtils.convertSet(products, T::getSkuId); Set<Long> skuIdsSet = CollectionUtils.convertSet(products, T::getSkuId);
@ -153,6 +155,7 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
* @param updateReqVO 更新的请求VO * @param updateReqVO 更新的请求VO
*/ */
private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) { private void updateSeckillProduct(SeckillActivityUpdateReqVO updateReqVO) {
// TODO puhui999要不这里简单一点删除原本的插入新增的不做的这么细致
// TODO puhui999后续完善 // TODO puhui999后续完善
//List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId()); //List<SeckillProductDO> seckillProductDOs = seckillProductMapper.selectListByActivityId(updateReqVO.getId());
//List<SeckillProductUpdateReqVO> products = updateReqVO.getProducts(); //List<SeckillProductUpdateReqVO> products = updateReqVO.getProducts();

View File

@ -82,6 +82,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
private void validateSeckillConfigConflict(String startTime, String endTime) { private void validateSeckillConfigConflict(String startTime, String endTime) {
LocalTime startTime1 = LocalTime.parse(startTime); LocalTime startTime1 = LocalTime.parse(startTime);
LocalTime endTime1 = LocalTime.parse(endTime); LocalTime endTime1 = LocalTime.parse(endTime);
// TODO @puhui999 这个可以用 validator 里的 assertTrue 去做哈
// 检查选择的时间是否相等 // 检查选择的时间是否相等
if (startTime1.equals(endTime1)) { if (startTime1.equals(endTime1)) {
throw exception(SECKILL_TIME_EQUAL); throw exception(SECKILL_TIME_EQUAL);
@ -93,11 +94,13 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
// 查询出所有的时段配置 // 查询出所有的时段配置
List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList(); List<SeckillConfigDO> configDOs = seckillConfigMapper.selectList();
// 过滤出重叠的时段 ids // 过滤出重叠的时段 ids
// TODO @puhui999感觉 findOne 就可以了
Set<Long> ids = configDOs.stream().filter((config) -> { Set<Long> ids = configDOs.stream().filter((config) -> {
LocalTime startTime2 = LocalTime.parse(config.getStartTime()); LocalTime startTime2 = LocalTime.parse(config.getStartTime());
LocalTime endTime2 = LocalTime.parse(config.getEndTime()); LocalTime endTime2 = LocalTime.parse(config.getEndTime());
// 判断时间是否重叠 // 判断时间是否重叠
// 开始时间在已配置时段的结束时间之前 结束时间在已配置时段的开始时间之后 [] // 开始时间在已配置时段的结束时间之前 结束时间在已配置时段的开始时间之后 []
// todo @puhui999LocalDateUtils 可以写个工具类是否是有重叠的时间感觉别的场景可能也会有需要
return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2) return startTime1.isBefore(endTime2) && endTime1.isAfter(startTime2)
// 开始时间在已配置时段的开始时间之前 结束时间在已配置时段的开始时间之后 (] () // 开始时间在已配置时段的开始时间之前 结束时间在已配置时段的开始时间之后 (] ()
|| startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2) || startTime1.isBefore(startTime2) && endTime1.isAfter(startTime2)
@ -127,6 +130,7 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
if (seckillConfigMapper.selectBatchIds(configIds).size() != configIds.size()) { if (seckillConfigMapper.selectBatchIds(configIds).size() != configIds.size()) {
throw exception(SECKILL_TIME_NOT_EXISTS); throw exception(SECKILL_TIME_NOT_EXISTS);
} }
// TODO @puhui999应该要校验个 status 如果有禁用的也不行
} }
@Override @Override
@ -134,11 +138,13 @@ public class SeckillConfigServiceImpl implements SeckillConfigService {
return seckillConfigMapper.selectPage(pageVO); return seckillConfigMapper.selectPage(pageVO);
} }
// TODO @puhui999:写个查询状态的; 尽可能通用哈
@Override @Override
public List<SeckillConfigDO> getListAllSimple() { public List<SeckillConfigDO> getListAllSimple() {
return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus()); return seckillConfigMapper.selectList(SeckillConfigDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
} }
// TODO @puhui999: 这个要不合并到更新操作里? 不单独有个操作咧;
@Override @Override
public void updateSeckillConfigStatus(Long id, Integer status) { public void updateSeckillConfigStatus(Long id, Integer status) {
// 校验秒杀时段是否存在 // 校验秒杀时段是否存在

View File

@ -29,7 +29,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
* @author 芋道源码 * @author 芋道源码
*/ */
@Import(SeckillConfigServiceImpl.class) @Import(SeckillConfigServiceImpl.class)
@Disabled // TODO 芋艿未来开启 @Disabled // TODO 芋艿未来开启后续要 review
public class SeckillConfigServiceImplTest extends BaseDbUnitTest { public class SeckillConfigServiceImplTest extends BaseDbUnitTest {
@Resource @Resource

View File

@ -29,7 +29,6 @@ public class TradeOrderApiImpl implements TradeOrderApi {
if (item == null) { if (item == null) {
throw exception(ORDER_ITEM_NOT_FOUND); throw exception(ORDER_ITEM_NOT_FOUND);
} }
return item.getOrderId(); return item.getOrderId();
} }

View File

@ -140,6 +140,7 @@ public class AppTradeOrderController {
@PostMapping("/item/create-comment") @PostMapping("/item/create-comment")
@Operation(summary = "创建交易订单项的评价") @Operation(summary = "创建交易订单项的评价")
public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) { public CommonResult<Long> createOrderItemComment(@RequestBody AppTradeOrderItemCommentCreateReqVO createReqVO) {
// TODO @puhui999这个逻辑最好写到 service
Long loginUserId = getLoginUserId(); Long loginUserId = getLoginUserId();
// 先通过订单项 ID 查询订单项是否存在 // 先通过订单项 ID 查询订单项是否存在
TradeOrderItemDO orderItemDO = tradeOrderService.getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId); TradeOrderItemDO orderItemDO = tradeOrderService.getOrderItemByIdAndUserId(createReqVO.getOrderItemId(), loginUserId);
@ -151,6 +152,7 @@ public class AppTradeOrderController {
if (orderDO == null) { if (orderDO == null) {
throw exception(ORDER_NOT_FOUND); throw exception(ORDER_NOT_FOUND);
} }
// TODO @puhui999要校验订单已完成但是未评价
ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItemDO); ProductCommentCreateReqDTO productCommentCreateReqDTO = TradeOrderConvert.INSTANCE.convert04(createReqVO, orderItemDO);
return success(productCommentApi.createComment(productCommentCreateReqDTO)); return success(productCommentApi.createComment(productCommentCreateReqDTO));

View File

@ -19,6 +19,7 @@ public class AppTradeOrderItemCommentCreateReqVO {
@NotNull(message = "交易订单项编号不能为空") @NotNull(message = "交易订单项编号不能为空")
private Long orderItemId; private Long orderItemId;
// TODO @puhui999貌似不用这个字段哈
@Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5") @Schema(description = "评分星级 1-5 分", requiredMode = Schema.RequiredMode.REQUIRED, example = "5")
@NotNull(message = "评分星级 1-5 分不能为空") @NotNull(message = "评分星级 1-5 分不能为空")
private Integer scores; private Integer scores;
@ -35,7 +36,7 @@ public class AppTradeOrderItemCommentCreateReqVO {
@NotNull(message = "评论内容不能为空") @NotNull(message = "评论内容不能为空")
private String content; private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xx.png]") @Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张") @Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls; private List<String> picUrls;