Merge branch 'feature/mall_product' of https://gitee.com/joly_xiaobai/ruoyi-vue-pro into mall_product

# Conflicts:
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/order/vo/TradeOrderBaseVO.java
This commit is contained in:
xiaobai
2023-06-19 13:06:00 +08:00
553 changed files with 13449 additions and 2554 deletions

View File

@@ -0,0 +1,22 @@
package cn.iocoder.yudao.module.product.api.comment;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
/**
* 产品评论 API 接口
*
* @author HUIHUI
*/
public interface ProductCommentApi {
// TODO @puhuiLong orderId 放到 createReqDTO 里噶?
/**
* 创建评论
*
* @param createReqDTO 评论参数
* @param orderId 订单 id
* @return 返回评论创建后的 id
*/
Long createComment(ProductCommentCreateReqDTO createReqDTO, Long orderId);
}

View File

@@ -0,0 +1,73 @@
package cn.iocoder.yudao.module.product.api.comment.dto;
import lombok.Data;
import java.util.List;
/**
* 评论创建请求 DTO
*
* @author HUIHUI
*/
@Data
public class ProductCommentCreateReqDTO {
/**
* 商品 SKU 编号
*/
private Long skuId;
/**
* 交易订单项编号
*/
private Long orderItemId;
// TODO @huihuispuId、spuName 去查询哇?通过 skuId
/**
* 商品 SPU 编号
*/
private Long spuId;
/**
* 商品 SPU 名称
*/
private String spuName;
/**
* 评分星级 1-5 分
*/
private Integer scores;
/**
* 描述星级 1-5 分
*/
private Integer descriptionScores;
/**
* 服务星级 1-5 分
*/
private Integer benefitScores;
/**
* 评论内容
*/
private String content;
/**
* 评论图片地址数组,以逗号分隔最多上传 9 张
*/
private List<String> picUrls;
/**
* 是否匿名
*/
private Boolean anonymous;
/**
* 评价人
*/
private Long userId;
// TODO @puhui999是不是 userNickname、userAvatar 去掉?通过 userId 查询
/**
* 评价人名称
*/
private String userNickname;
/**
* 评价人头像
*/
private String userAvatar;
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.product.api.comment;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
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 org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
/**
* 商品评论 API 实现类
*
* @author HUIHUI
*/
@Service
@Validated
public class ProductCommentApiImpl implements ProductCommentApi {
@Resource
private ProductCommentService productCommentService;
@Override
public Long createComment(ProductCommentCreateReqDTO createReqDTO, Long orderId) {
ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqDTO, orderId);
return productCommentService.createComment(commentDO);
}
}

View File

@@ -12,22 +12,22 @@ import javax.validation.constraints.NotNull;
@Data
public class ProductBrandBaseVO {
@Schema(description = "品牌名称", required = true, example = "苹果")
@Schema(description = "品牌名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果")
@NotNull(message = "品牌名称不能为空")
private String name;
@Schema(description = "品牌图片", required = true)
@Schema(description = "品牌图片", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "品牌图片不能为空")
private String picUrl;
@Schema(description = "品牌排序", required = true, example = "1")
@Schema(description = "品牌排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "品牌排序不能为空")
private Integer sort;
@Schema(description = "品牌描述", example = "描述")
private String description;
@Schema(description = "状态", required = true, example = "0")
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "状态不能为空")
private Integer status;

View File

@@ -13,10 +13,10 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class ProductBrandRespVO extends ProductBrandBaseVO {
@Schema(description = "品牌编号", required = true, example = "1")
@Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class ProductBrandUpdateReqVO extends ProductBrandBaseVO {
@Schema(description = "品牌编号", required = true, example = "1")
@Schema(description = "品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "品牌编号不能为空")
private Long id;

View File

@@ -13,25 +13,25 @@ import javax.validation.constraints.NotNull;
@Data
public class ProductCategoryBaseVO {
@Schema(description = "父分类编号", required = true, example = "1")
@Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "父分类编号不能为空")
private Long parentId;
@Schema(description = "分类名称", required = true, example = "办公文具")
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具")
@NotBlank(message = "分类名称不能为空")
private String name;
@Schema(description = "移动端分类图", required = true)
@Schema(description = "移动端分类图", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "移动端分类图不能为空")
private String picUrl;
@Schema(description = "PC 端分类图")
private String bigPicUrl;
@Schema(description = "分类排序", required = true, example = "1")
@Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sort;
@Schema(description = "开启状态", required = true, example = "0")
@Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@NotNull(message = "开启状态不能为空")
private Integer status;

View File

@@ -13,10 +13,10 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class ProductCategoryRespVO extends ProductCategoryBaseVO {
@Schema(description = "分类编号", required = true, example = "2")
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Long id;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -14,7 +14,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class ProductCategoryUpdateReqVO extends ProductCategoryBaseVO {
@Schema(description = "分类编号", required = true, example = "2")
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
@NotNull(message = "分类编号不能为空")
private Long id;

View File

@@ -35,8 +35,7 @@ public class ProductCommentController {
return success(ProductCommentConvert.INSTANCE.convertPage(pageResult));
}
// TODO @puhui999update-visible
@PutMapping("/update/visible")
@PutMapping("/update-visible")
@Operation(summary = "显示 / 隐藏评论")
@PreAuthorize("@ss.hasPermission('product:comment:update')")
public CommonResult<Boolean> updateCommentVisible(@Valid @RequestBody ProductCommentUpdateVisibleReqVO updateReqVO) {
@@ -47,8 +46,8 @@ public class ProductCommentController {
@PutMapping("/reply")
@Operation(summary = "商家回复")
@PreAuthorize("@ss.hasPermission('product:comment:update')")
public CommonResult<Boolean> commentReply(@Valid @RequestBody ProductCommentReplyVO replyVO) {
productCommentService.commentReply(replyVO, getLoginUserId());
public CommonResult<Boolean> commentReply(@Valid @RequestBody ProductCommentReplyReqVO replyVO) {
productCommentService.replyComment(replyVO, getLoginUserId());
return success(true);
}
@@ -56,8 +55,7 @@ public class ProductCommentController {
@Operation(summary = "添加自评")
@PreAuthorize("@ss.hasPermission('product:comment:update')")
public CommonResult<Boolean> createComment(@Valid @RequestBody ProductCommentCreateReqVO createReqVO) {
// TODO @puhui999不用 ProductCommentConvert.INSTANCE.convert(createReqVO) 哈;多写一个 create 方法即可;
productCommentService.createComment(ProductCommentConvert.INSTANCE.convert(createReqVO), Boolean.TRUE);
productCommentService.createComment(createReqVO);
return success(true);
}

View File

@@ -10,17 +10,15 @@ import java.util.List;
@Data
public class ProductCommentBaseVO {
// TODO @puhui999把 example 补充下
@Schema(description = "评价人名称", required = true, example = "张三")
@Schema(description = "评价人名称", required = true, example = "小姑凉")
@NotNull(message = "评价人名称不能为空")
private String userNickname;
@Schema(description = "评价人头像", required = true)
@Schema(description = "评价人头像", required = true, example = "https://www.iocoder.cn/xx.png")
@NotNull(message = "评价人头像不能为空")
private String userAvatar;
@Schema(description = "商品 SPU 编号", required = true, example = "29502")
@Schema(description = "商品 SPU 编号", required = true, example = "清凉丝滑透气小短袖")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@@ -28,28 +26,28 @@ public class ProductCommentBaseVO {
@NotNull(message = "商品 SPU 名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", required = true, example = "3082")
@Schema(description = "商品 SKU 编号", required = true, example = "1")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "评分星级 1-5分", required = true)
@Schema(description = "评分星级 1-5 ", required = true, example = "5")
@NotNull(message = "评分星级不能为空")
private Integer scores;
@Schema(description = "描述星级 1-5分", required = true)
@Schema(description = "描述星级 1-5 ", required = true, example = "5")
@NotNull(message = "描述星级不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5分", required = true)
@Schema(description = "服务星级 1-5 ", required = true, example = "5")
@NotNull(message = "服务星级分不能为空")
private Integer benefitScores;
@Schema(description = "评论内容", required = true)
@Schema(description = "评论内容", required = true, example = "穿起来非常丝滑凉快")
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传9", required = true)
@Size(max = 9, message = "评论图片地址数组长度不能超过9")
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 ", required = true, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 ")
private List<String> picUrls;
}

View File

@@ -1,7 +1,11 @@
package cn.iocoder.yudao.module.product.controller.admin.comment.vo;
import lombok.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "管理后台 - 商品评价创建 Request VO")
@Data
@@ -9,4 +13,13 @@ import io.swagger.v3.oas.annotations.media.Schema;
@ToString(callSuper = true)
public class ProductCommentCreateReqVO extends ProductCommentBaseVO {
// TODO @puhui999是不是也放到父类里
@Schema(description = "评价人", required = true, example = "16868")
@NotNull(message = "评价人不能为空")
private Long userId;
@Schema(description = "评价订单项", required = true, example = "19292")
@NotNull(message = "评价订单项不能为空")
private Long orderItemId;
}

View File

@@ -31,11 +31,11 @@ public class ProductCommentPageReqVO extends PageParam {
@Schema(description = "商品SPU名称", example = "感冒药")
private String spuName;
@Schema(description = "评分星级 1-5")
@Schema(description = "评分星级 1-5", example = "5")
@InEnum(ProductCommentScoresEnum.class)
private Integer scores;
@Schema(description = "商家是否回复")
@Schema(description = "商家是否回复", example = "true")
private Boolean replied;
@Schema(description = "创建时间")

View File

@@ -7,11 +7,10 @@ import lombok.ToString;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
// TODO @puhui999ReqVO
@Schema(description = "管理后台 - 商品评价可见修改 Request VO")
@Data
@ToString(callSuper = true)
public class ProductCommentReplyVO {
public class ProductCommentReplyReqVO {
@Schema(description = "评价编号", required = true, example = "15721")
@NotNull(message = "评价编号不能为空")

View File

@@ -16,7 +16,7 @@ public class ProductCommentRespVO extends ProductCommentBaseVO {
@Schema(description = "订单项编号", required = true, example = "24965")
private Long id;
@Schema(description = "是否匿名[false:不匿名 true:匿名]", required = true)
@Schema(description = "是否匿名", required = true, example = "false")
private Boolean anonymous;
@Schema(description = "交易订单编号", required = true, example = "24428")

View File

@@ -9,10 +9,10 @@ import java.util.List;
@Data
public class ProductPropertyAndValueRespVO {
@Schema(description = "属性项的编号", required = true, example = "1024")
@Schema(description = "属性项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "属性项的名称", required = true, example = "颜色")
@Schema(description = "属性项的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String name;
/**
@@ -24,10 +24,10 @@ public class ProductPropertyAndValueRespVO {
@Data
public static class Value {
@Schema(description = "属性值的编号", required = true, example = "2048")
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long id;
@Schema(description = "属性值的名称", required = true, example = "红色")
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String name;
}

View File

@@ -12,7 +12,7 @@ import javax.validation.constraints.NotBlank;
@Data
public class ProductPropertyBaseVO {
@Schema(description = "名称", required = true, example = "颜色")
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
@NotBlank(message = "名称不能为空")
private String name;

View File

@@ -20,7 +20,7 @@ public class ProductPropertyPageReqVO extends PageParam {
@Schema(description = "名称", example = "颜色")
private String name;
@Schema(description = "状态", required = true, example = "1")
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)

View File

@@ -13,10 +13,10 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class ProductPropertyRespVO extends ProductPropertyBaseVO {
@Schema(description = "编号", required = true, example = "1024")
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class ProductPropertyUpdateReqVO extends ProductPropertyBaseVO {
@Schema(description = "主键", required = true, example = "1")
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "主键不能为空")
private Long id;

View File

@@ -13,11 +13,11 @@ import javax.validation.constraints.NotNull;
@Data
public class ProductPropertyValueBaseVO {
@Schema(description = "属性项的编号", required = true, example = "1024")
@Schema(description = "属性项的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "属性项的编号不能为空")
private Long propertyId;
@Schema(description = "名称", required = true, example = "红色")
@Schema(description = "名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
@NotEmpty(message = "名称名字不能为空")
private String name;

View File

@@ -7,16 +7,16 @@ import lombok.Data;
@Data
public class ProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", required = true, example = "1")
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", required = true, example = "颜色")
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", required = true, example = "1024")
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", required = true, example = "红色")
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}

View File

@@ -18,7 +18,7 @@ public class ProductPropertyValuePageReqVO extends PageParam {
@Schema(description = "名称", example = "红色")
private String name;
@Schema(description = "状态", required = true, example = "1")
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
}

View File

@@ -13,7 +13,7 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class ProductPropertyValueRespVO extends ProductPropertyValueBaseVO {
@Schema(description = "编号", required = true, example = "10")
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Long id;
@Schema(description = "创建时间")

View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class ProductPropertyValueUpdateReqVO extends ProductPropertyValueBaseVO {
@Schema(description = "主键", required = true, example = "1024")
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "主键不能为空")
private Long id;

View File

@@ -16,11 +16,11 @@ import java.util.List;
@Data
public class ProductSkuBaseVO {
@Schema(description = "商品 SKU 名字", required = true, example = "清凉小短袖")
@Schema(description = "商品 SKU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
@NotEmpty(message = "商品 SKU 名字不能为空")
private String name;
@Schema(description = "销售价格,单位:分", required = true, example = "1999")
@Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
@NotNull(message = "销售价格,单位:分不能为空")
private Integer price;
@@ -33,11 +33,11 @@ public class ProductSkuBaseVO {
@Schema(description = "条形码", example = "15156165456")
private String barCode;
@Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
@NotNull(message = "图片地址不能为空")
private String picUrl;
@Schema(description = "库存", required = true, example = "200")
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
@NotNull(message = "库存不能为空")
private Integer stock;

View File

@@ -7,24 +7,24 @@ import lombok.Data;
@Data
public class ProductSkuOptionRespVO {
@Schema(description = "主键", required = true, example = "1024")
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "商品 SKU 名字", example = "红色")
private String name;
@Schema(description = "销售价格", required = true, example = "100")
@Schema(description = "销售价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private String price;
@Schema(description = "库存", required = true, example = "100")
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
private Integer stock;
// ========== 商品 SPU 信息 ==========
@Schema(description = "商品 SPU 编号", required = true, example = "1")
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long spuId;
@Schema(description = "商品 SPU 名字", required = true, example = "iPhone 11")
@Schema(description = "商品 SPU 名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "iPhone 11")
private String spuName;
}

View File

@@ -12,7 +12,7 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductSkuRespVO extends ProductSkuBaseVO {
@Schema(description = "主键", required = true, example = "1024")
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
}

View File

@@ -16,90 +16,90 @@ import java.util.List;
@Data
public class ProductSpuBaseVO {
@Schema(description = "商品名称", required = true, example = "清凉小短袖")
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
@NotEmpty(message = "商品名称不能为空")
private String name;
@Schema(description = "关键字", required = true, example = "清凉丝滑不出汗")
@Schema(description = "关键字", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉丝滑不出汗")
@NotEmpty(message = "商品关键字不能为空")
private String keyword;
@Schema(description = "商品简介", required = true, example = "清凉小短袖简介")
@Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖简介")
@NotEmpty(message = "商品简介不能为空")
private String introduction;
@Schema(description = "商品详情", required = true, example = "清凉小短袖详情")
@Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖详情")
@NotEmpty(message = "商品详情不能为空")
private String description;
@Schema(description = "商品分类编号", required = true, example = "1")
@Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品分类不能为空")
private Long categoryId;
@Schema(description = "商品品牌编号", required = true, example = "1")
@Schema(description = "商品品牌编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品品牌不能为空")
private Long brandId;
@Schema(description = "商品封面图", required = true, example = "https://www.iocoder.cn/xx.png")
@Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
@NotEmpty(message = "商品封面图不能为空")
private String picUrl;
@Schema(description = "商品轮播图", required = true, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
private List<String> sliderPicUrls;
@Schema(description = "商品视频", example = "https://www.iocoder.cn/xx.mp4")
private String videoUrl;
@Schema(description = "单位", required = true, example = "1")
@Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品单位不能为空")
private Integer unit;
@Schema(description = "排序字段", required = true, example = "1")
@Schema(description = "排序字段", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品排序字段不能为空")
private Integer sort;
// ========== SKU 相关字段 =========
@Schema(description = "规格类型", required = true, example = "true")
@Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品规格类型不能为空")
private Boolean specType;
// ========== 物流相关字段 =========
@Schema(description = "物流配置模板编号", required = true, example = "111")
@Schema(description = "物流配置模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
@NotNull(message = "物流配置模板编号不能为空")
private Long deliveryTemplateId;
// ========== 营销相关字段 =========
@Schema(description = "是否热卖推荐", required = true, example = "true")
@Schema(description = "是否热卖推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品推荐不能为空")
private Boolean recommendHot;
@Schema(description = "是否优惠推荐", required = true, example = "true")
@Schema(description = "是否优惠推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品推荐不能为空")
private Boolean recommendBenefit;
@Schema(description = "是否精品推荐", required = true, example = "true")
@Schema(description = "是否精品推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品推荐不能为空")
private Boolean recommendBest;
@Schema(description = "是否新品推荐", required = true, example = "true")
@Schema(description = "是否新品推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品推荐不能为空")
private Boolean recommendNew;
@Schema(description = "是否优品推荐", required = true, example = "true")
@Schema(description = "是否优品推荐", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品推荐不能为空")
private Boolean recommendGood;
@Schema(description = "赠送积分", required = true, example = "111")
@Schema(description = "赠送积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
@NotNull(message = "商品赠送积分不能为空")
private Integer giveIntegral;
@Schema(description = "赠送的优惠劵编号的数组", example = "[1, 10]") // TODO 这块前端还未实现
private List<Long> giveCouponTemplateIds;
@Schema(description = "分销类型", required = true, example = "true")
@Schema(description = "分销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
@NotNull(message = "商品分销类型不能为空")
private Boolean subCommissionType;

View File

@@ -18,28 +18,28 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class ProductSpuRespVO extends ProductSpuBaseVO {
@Schema(description = "spuId", required = true, example = "111")
@Schema(description = "spuId", requiredMode = Schema.RequiredMode.REQUIRED, example = "111")
private Long id;
@Schema(description = "商品价格", required = true, example = "1999")
@Schema(description = "商品价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer price;
@Schema(description = "商品销量", required = true, example = "2000")
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
private Integer salesCount;
@Schema(description = "市场价,单位使用:分", required = true, example = "199")
@Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199")
private Integer marketPrice;
@Schema(description = "成本价,单位使用:分", required = true, example = "19")
@Schema(description = "成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19")
private Integer costPrice;
@Schema(description = "商品库存", required = true, example = "10000")
@Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000")
private Integer stock;
@Schema(description = "商品创建时间", required = true, example = "2023-05-24 00:00:00")
@Schema(description = "商品创建时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-05-24 00:00:00")
private LocalDateTime createTime;
@Schema(description = "商品状态", required = true, example = "1")
@Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
}

View File

@@ -14,33 +14,33 @@ import lombok.ToString;
@ToString(callSuper = true)
public class ProductSpuSimpleRespVO {
@Schema(description = "主键", required = true, example = "213")
@Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "213")
private Long id;
@Schema(description = "商品名称", required = true, example = "清凉小短袖")
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "清凉小短袖")
private String name;
@Schema(description = "商品价格,单位使用:分", required = true, example = "1999")
@Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer price;
@Schema(description = "商品市场价,单位使用:分", required = true, example = "199")
@Schema(description = "商品市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "199")
private Integer marketPrice;
@Schema(description = "商品成本价,单位使用:分", required = true, example = "19")
@Schema(description = "商品成本价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "19")
private Integer costPrice;
@Schema(description = "商品库存", required = true, example = "2000")
@Schema(description = "商品库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
private Integer stock;
// ========== 统计相关字段 =========
@Schema(description = "商品销量", required = true, example = "200")
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "200")
private Integer salesCount;
@Schema(description = "商品虚拟销量", required = true, example = "20000")
@Schema(description = "商品虚拟销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20000")
private Integer virtualSalesCount;
@Schema(description = "商品浏览量", required = true, example = "2000")
@Schema(description = "商品浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "2000")
private Integer browseCount;
}

View File

@@ -23,17 +23,17 @@ import java.util.List;
@ToString(callSuper = true)
public class ProductSpuUpdateReqVO extends ProductSpuBaseVO {
@Schema(description = "商品编号", required = true, example = "1")
@Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品编号不能为空")
private Long id;
@Schema(description = "商品销量", required = true, example = "1999")
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer salesCount;
@Schema(description = "浏览量", required = true, example = "1999")
@Schema(description = "浏览量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1999")
private Integer browseCount;
@Schema(description = "商品状态", required = true, example = "1")
@Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(ProductSpuStatusEnum.class)
private Integer status;

View File

@@ -10,18 +10,18 @@ import javax.validation.constraints.NotNull;
@Schema(description = "用户 APP - 商品分类 Response VO")
public class AppCategoryRespVO {
@Schema(description = "分类编号", required = true, example = "2")
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
private Long id;
@Schema(description = "父分类编号", required = true, example = "1")
@Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "父分类编号不能为空")
private Long parentId;
@Schema(description = "分类名称", required = true, example = "办公文具")
@Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "办公文具")
@NotBlank(message = "分类名称不能为空")
private String name;
@Schema(description = "分类图片", required = true)
@Schema(description = "分类图片", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "分类图片不能为空")
private String picUrl;

View File

@@ -1,53 +1,50 @@
package cn.iocoder.yudao.module.product.controller.app.comment;
import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentCreateReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert;
import cn.iocoder.yudao.module.product.service.comment.ProductCommentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
// TODO @puhui999AppCommentController = AppProductCommentController
@Tag(name = "用户 APP - 商品评价")
@RestController
@RequestMapping("/product/comment")
@Validated
public class AppCommentController {
public class AppProductCommentController {
@Resource
private ProductCommentService productCommentService;
@Resource
private MemberUserApi memberUserApi;
// TODO @puhui999可以实现下
@GetMapping("/list")
@Operation(summary = "获得最近的 n 条商品评价")
@Parameters({
@Parameter(name = "spuId", description = "商品 SPU 编号", required = true, example = "1024"),
@Parameter(name = "count", description = "数量", required = true, example = "10")
})
public CommonResult<List<AppCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId,
@RequestParam(value = "count", defaultValue = "10") Integer count) {
public CommonResult<List<AppProductCommentRespVO>> getCommentList(@RequestParam("spuId") Long spuId,
@RequestParam(value = "count", defaultValue = "10") Integer count) {
List<AppProductPropertyValueDetailRespVO> list = new ArrayList<>();
AppProductPropertyValueDetailRespVO item1 = new AppProductPropertyValueDetailRespVO();
@@ -72,7 +69,7 @@ public class AppCommentController {
list.add(item3);
// TODO 生成 mock 的数据
AppCommentRespVO appCommentRespVO = new AppCommentRespVO();
AppProductCommentRespVO appCommentRespVO = new AppProductCommentRespVO();
appCommentRespVO.setUserId((long) (new Random().nextInt(100000) + 10000));
appCommentRespVO.setUserNickname("用户" + new Random().nextInt(100));
appCommentRespVO.setUserAvatar("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
@@ -85,7 +82,6 @@ public class AppCommentController {
appCommentRespVO.setReplyContent("回复内容" + new Random().nextInt(100));
appCommentRespVO.setReplyTime(LocalDateTime.now().minusDays(new Random().nextInt(30)));
appCommentRespVO.setCreateTime(LocalDateTime.now().minusDays(new Random().nextInt(30)));
appCommentRespVO.setFinalScore(new Random().nextInt(5) + 1);
appCommentRespVO.setSpuId((long) (new Random().nextInt(100000) + 10000));
appCommentRespVO.setSpuName("商品" + new Random().nextInt(100));
appCommentRespVO.setSkuId((long) (new Random().nextInt(100000) + 10000));
@@ -101,30 +97,15 @@ public class AppCommentController {
@GetMapping("/page")
@Operation(summary = "获得商品评价分页")
public CommonResult<PageResult<AppCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
public CommonResult<PageResult<AppProductCommentRespVO>> getCommentPage(@Valid AppCommentPageReqVO pageVO) {
return success(productCommentService.getCommentPage(pageVO, Boolean.TRUE));
}
// TODO @puhui999方法改成 getCommentStatistics然后搞个对应的 vo想了下这样更优雅
@GetMapping("/statistics")
@Operation(summary = "获得商品的评价统计") // TODO @puhui999@RequestParam 针对 spuId
public CommonResult<Map<String, Object>> getCommentStatistics(@Valid Long spuId) {
// TODO 生成 mock 的数据
if (true) {
return success(MapUtil.<String, Object>builder("allCount", 10L).put("goodPercent", "10.33").build());
}
return null;
// return success(productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE));
}
@PostMapping(value = "/create")
@Operation(summary = "创建商品评价")
public CommonResult<Boolean> createComment(@RequestBody AppCommentCreateReqVO createReqVO) {
// TODO: 2023/3/20 要不要判断订单商品是否存在
// TODO @ouhui999这个接口搞到交易那比较合适
MemberUserRespDTO user = memberUserApi.getUser(getLoginUserId());
productCommentService.createComment(ProductCommentConvert.INSTANCE.convert(user, createReqVO), Boolean.FALSE);
return success(true);
// TODO @puhuiget-statistics方法改成 getCommentStatisticsgetCommentPageTabsCount 也改掉哈
@GetMapping("/getCommentStatistics")
@Operation(summary = "获得商品的评价统计")
public CommonResult<AppCommentStatisticsRespVO> getCommentPage(@Valid @RequestParam("spuId") Long spuId) {
return success(productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE));
}
}

View File

@@ -1,50 +0,0 @@
package cn.iocoder.yudao.module.product.controller.app.comment.vo;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.util.List;
// TODO @puhui999C 端可以不要 base 哈。
@Data
public class AppCommentBaseVO {
@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 = "商品 SKU 属性", required = true)
private List<AppProductPropertyValueDetailRespVO> skuProperties; // TODO puhui999这个需要从数据库查询哈
@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 = "评论内容", required = true)
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组以逗号分隔最多上传9张", required = true)
@Size(max = 9, message = "评论图片地址数组长度不能超过9张")
private List<String> picUrls;
}

View File

@@ -1,31 +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.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
// TODO @puhui999不应该继承 AppCommentCreateReqVO
@Schema(description = "用户APP - 商品评价创建 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppCommentCreateReqVO extends AppCommentBaseVO {
@Schema(description = "是否匿名", required = true, example = "true")
@NotNull(message = "是否匿名不能为空")
private Boolean anonymous;
// TODO @puhui999:不应该传递 orderId
@Schema(description = "交易订单编号", required = true, example = "12312")
@NotNull(message = "交易订单编号不能为空")
private Long orderId;
@Schema(description = "交易订单项编号", required = true, example = "2312312")
@NotNull(message = "交易订单项编号不能为空")
private Long orderItemId;
}

View File

@@ -8,61 +8,25 @@ import lombok.ToString;
import javax.validation.constraints.NotNull;
@Schema(description = "用户APP - 商品评价分页 Request VO")
@Schema(description = "用户 App - 商品评价分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppCommentPageReqVO extends PageParam {
// TODO @puhui999不传递就是 all
/**
* 所有
*/
public static final Integer ALL = 0;
/**
* 所有数量 key
*/
public static final String ALL_COUNT = "allCount";
// TODO @puhui999good 好评;
/**
* 好评
*/
public static final Integer FAVOURABLE_COMMENT = 1;
// TODO @puhui999medium 中评;然后 mediumCount 就好啦;
/**
* 好评数量 key
*/
public static final String FAVOURABLE_COMMENT_COUNT = "favourableCommentCount";
public static final Integer GOOD_COMMENT = 1;
/**
* 中评
*/
public static final Integer MEDIOCRE_COMMENT = 2;
/**
* 中评数量 key
*/
public static final String MEDIOCRE_COMMENT_COUNT = "mediocreCommentCount";
/**
* 差评
*/
public static final Integer NEGATIVE_COMMENT = 3;
/**
* 差评数量 key
*/
public static final String NEGATIVE_COMMENT_COUNT = "negativeCommentCount";
// TODO @puhui999这个挪到 DO 那没问题的哈NICKNAME_ANONYMOUS
/**
* 默认匿名昵称
*/
public static final String ANONYMOUS_NICKNAME = "匿名用户";
@Schema(description = "商品SPU编号", example = "29502")
@NotNull(message = "商品SPU编号不能为空")
private Long spuId;

View File

@@ -1,57 +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.EqualsAndHashCode;
import lombok.ToString;
import java.time.LocalDateTime;
@Schema(description = "用户APP - 商品评价 Response VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppCommentRespVO extends AppCommentBaseVO {
// TODO puhui999把 example 也补充下哈
@Schema(description = "评价人的用户编号", required = true, example = "15721")
private Long userId;
@Schema(description = "评价人名称", required = true, example = "张三")
private String userNickname;
@Schema(description = "评价人头像", required = true)
private String userAvatar;
@Schema(description = "订单项编号", required = true, example = "24965")
private Long id;
@Schema(description = "是否匿名", 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 = "商家是否回复", required = true)
private Boolean replyStatus;
@Schema(description = "回复管理员编号", example = "22212")
private Long replyUserId;
@Schema(description = "商家回复内容")
private String replyContent;
@Schema(description = "商家回复时间")
private LocalDateTime replyTime;
@Schema(description = "创建时间", required = true)
private LocalDateTime createTime;
@Schema(description = "最终评分", required = true)
private Integer finalScore;
}

View File

@@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.product.controller.app.comment.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
@Schema(description = "APP - 商品评价页评论分类数统计 Response VO")
@Data
@ToString(callSuper = true)
public class AppCommentStatisticsRespVO {
@Schema(description = "所有评论数量", required = true, example = "15721")
private Long allCount;
@Schema(description = "好评数量", required = true, example = "15721")
private Long goodCount;
@Schema(description = "中评数量", required = true, example = "15721")
private Long mediocreCount;
@Schema(description = "差评数量", required = true, example = "15721")
private Long negativeCount;
}

View File

@@ -0,0 +1,56 @@
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 = "是否匿名", required = true, example = "true")
@NotNull(message = "是否匿名不能为空")
private Boolean anonymous;
@Schema(description = "交易订单项编号", required = true, example = "2312312")
@NotNull(message = "交易订单项编号不能为空")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", required = true, example = "91192")
@NotNull(message = "商品SPU编号不能为空")
private Long spuId;
@Schema(description = "商品 SPU 名称", required = true, example = "清凉丝滑小短袖")
@NotNull(message = "商品SPU名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", required = true, example = "81192")
@NotNull(message = "商品SKU编号不能为空")
private Long skuId;
@Schema(description = "评分星级 1-5 分", required = true, example = "5")
@NotNull(message = "评分星级 1-5 分不能为空")
private Integer scores;
@Schema(description = "描述星级 1-5 分", required = true, example = "5")
@NotNull(message = "描述星级 1-5 分不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5 分", required = true, example = "5")
@NotNull(message = "服务星级 1-5 分不能为空")
private Integer benefitScores;
@Schema(description = "评论内容", required = true, example = "哇,真的很丝滑凉快诶,好评")
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", required = true, example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
@Size(max = 9, message = "评论图片地址数组长度不能超过 9 张")
private List<String> picUrls;
}

View File

@@ -0,0 +1,109 @@
package cn.iocoder.yudao.module.product.controller.app.comment.vo;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.List;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 用户 App - 商品评价详情 Response VO
*
* @author HUIHUI
*/
@Schema(description = "用户 App - 商品评价详情 Response VO")
@Data
@ToString(callSuper = true)
public class AppProductCommentRespVO {
@Schema(description = "评价人的用户编号", required = true, example = "15721")
private Long userId;
@Schema(description = "评价人名称", required = true, example = "张三")
private String userNickname;
@Schema(description = "评价人头像", required = true, example = "https://www.iocoder.cn/xx.png")
private String userAvatar;
@Schema(description = "订单项编号", required = true, example = "24965")
private Long id;
@Schema(description = "是否匿名", required = true, example = "false")
private Boolean anonymous;
@Schema(description = "交易订单编号", required = true, example = "24428")
private Long orderId;
@Schema(description = "交易订单项编号", required = true, example = "8233")
private Long orderItemId;
@Schema(description = "商家是否回复", required = true, example = "true")
private Boolean replyStatus;
@Schema(description = "回复管理员编号", example = "22212")
private Long replyUserId;
@Schema(description = "商家回复内容", example = "亲,你的好评就是我的动力(*^▽^*)")
private String replyContent;
@Schema(description = "商家回复时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime replyTime;
@Schema(description = "追加评价内容", example = "穿了很久都很丝滑诶")
private String additionalContent;
@Schema(description = "追评评价图片地址数组,以逗号分隔最多上传 9 张", example = "[https://www.iocoder.cn/xx.png, https://www.iocoder.cn/xxx.png]")
private List<String> additionalPicUrls;
@Schema(description = "追加评价时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime additionalTime;
@Schema(description = "创建时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime createTime;
@Schema(description = "商品SPU编号", required = true, example = "91192")
@NotNull(message = "商品SPU编号不能为空")
private Long spuId;
@Schema(description = "商品SPU名称", required = true, example = "清凉丝滑小短袖")
@NotNull(message = "商品SPU名称不能为空")
private String spuName;
@Schema(description = "商品SKU编号", required = true, example = "81192")
@NotNull(message = "商品SKU编号不能为空")
private Long skuId;
@Schema(description = "商品 SKU 属性", required = true)
private List<AppProductPropertyValueDetailRespVO> skuProperties;
@Schema(description = "评分星级 1-5 分", required = true, example = "5")
@NotNull(message = "评分星级 1-5 分不能为空")
private Integer scores;
@Schema(description = "描述星级 1-5 分", required = true, example = "5")
@NotNull(message = "描述星级 1-5 分不能为空")
private Integer descriptionScores;
@Schema(description = "服务星级 1-5 分", required = true, example = "5")
@NotNull(message = "服务星级 1-5 分不能为空")
private Integer benefitScores;
@Schema(description = "评论内容", required = true, example = "哇,真的很丝滑凉快诶,好评")
@NotNull(message = "评论内容不能为空")
private String content;
@Schema(description = "评论图片地址数组,以逗号分隔最多上传 9 张", required = true, 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,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户APP - 商品收藏分页查询 Request VO")
@Schema(description = "用户 App - 商品收藏分页查询 Request VO")
@Data
public class AppFavoritePageReqVO extends PageParam {
}

View File

@@ -4,7 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
@Schema(description = "用户APP - 商品收藏 Response VO")
@Schema(description = "用户 App - 商品收藏 Response VO")
@Data
public class AppFavoriteRespVO {

View File

@@ -7,16 +7,16 @@ import lombok.Data;
@Data
public class AppProductPropertyValueDetailRespVO {
@Schema(description = "属性的编号", required = true, example = "1")
@Schema(description = "属性的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long propertyId;
@Schema(description = "属性的名称", required = true, example = "颜色")
@Schema(description = "属性的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "颜色")
private String propertyName;
@Schema(description = "属性值的编号", required = true, example = "1024")
@Schema(description = "属性值的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long valueId;
@Schema(description = "属性值的名称", required = true, example = "红色")
@Schema(description = "属性值的名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "红色")
private String valueName;
}

View File

@@ -10,55 +10,55 @@ import java.util.List;
@Data
public class AppProductSpuDetailRespVO {
@Schema(description = "商品 SPU 编号", required = true, example = "1")
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
// ========== 基本信息 =========
@Schema(description = "商品名称", required = true, example = "芋道")
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
private String name;
@Schema(description = "商品简介", required = true, example = "我是一个快乐简介")
@Schema(description = "商品简介", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是一个快乐简介")
private String introduction;
@Schema(description = "商品详情", required = true, example = "我是商品描述")
@Schema(description = "商品详情", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是商品描述")
private String description;
@Schema(description = "商品分类编号", required = true, example = "1")
@Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long categoryId;
@Schema(description = "商品封面图", required = true)
@Schema(description = "商品封面图", requiredMode = Schema.RequiredMode.REQUIRED)
private String picUrl;
@Schema(description = "商品轮播图", required = true)
@Schema(description = "商品轮播图", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> sliderPicUrls;
@Schema(description = "商品视频", required = true)
@Schema(description = "商品视频", requiredMode = Schema.RequiredMode.REQUIRED)
private String videoUrl;
@Schema(description = "单位名", required = true, example = "")
@Schema(description = "单位名", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
private String unitName;
// ========== 营销相关字段 =========
@Schema(description = "活动排序数组", required = true, example = "1024")
@Schema(description = "活动排序数组", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private List<Integer> activityOrders;
// ========== SKU 相关字段 =========
@Schema(description = "规格类型", required = true, example = "true")
@Schema(description = "规格类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean specType;
@Schema(description = "商品价格,单位使用:分", required = true, example = "1024")
@Schema(description = "商品价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer price;
@Schema(description = "市场价,单位使用:分", required = true, example = "1024")
@Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer marketPrice;
@Schema(description = "VIP 价格,单位使用:分", required = true, example = "968") // 通过会员等级,计算出折扣后价格
@Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
private Integer vipPrice;
@Schema(description = "库存", required = true, example = "666")
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
private Integer stock;
/**
@@ -68,7 +68,7 @@ public class AppProductSpuDetailRespVO {
// ========== 统计相关字段 =========
@Schema(description = "商品销量", required = true, example = "1024")
@Schema(description = "商品销量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer salesCount;
@Schema(description = "用户 App - 商品 SPU 明细的 SKU 信息")
@@ -83,19 +83,19 @@ public class AppProductSpuDetailRespVO {
*/
private List<AppProductPropertyValueDetailRespVO> properties;
@Schema(description = "销售价格,单位:分", required = true, example = "1024")
@Schema(description = "销售价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer price;
@Schema(description = "市场价,单位使用:分", required = true, example = "1024")
@Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer marketPrice;
@Schema(description = "VIP 价格,单位使用:分", required = true, example = "968") // 通过会员等级,计算出折扣后价格
@Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
private Integer vipPrice;
@Schema(description = "图片地址", required = true, example = "https://www.iocoder.cn/xx.png")
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.png")
private String picUrl;
@Schema(description = "库存", required = true, example = "1")
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer stock;
@Schema(description = "商品重量", example = "1") // 单位kg 千克

View File

@@ -0,0 +1,39 @@
package cn.iocoder.yudao.module.product.controller.app.spu.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.List;
@Schema(description = "用户 App - 商品 SPU 分页项 Response VO")
@Data
public class AppProductSpuPageItemRespVO {
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道")
@NotEmpty(message = "商品名称不能为空")
private String name;
@Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "分类编号不能为空")
private Long categoryId;
@Schema(description = "商品图片的数组", requiredMode = Schema.RequiredMode.REQUIRED)
private List<String> picUrls;
@Schema(description = " 最小价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer minPrice;
@Schema(description = "最大价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer maxPrice;
// ========== 统计相关字段 =========
@Schema(description = "商品销量", example = "1024")
private Integer salesCount;
}

View File

@@ -1,15 +1,21 @@
package cn.iocoder.yudao.module.product.convert.comment;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentCreateReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
/**
@@ -24,50 +30,44 @@ public interface ProductCommentConvert {
ProductCommentRespVO convert(ProductCommentDO bean);
@Mapping(target = "allCount", source = "allCount")
@Mapping(target = "goodCount", source = "goodCount")
@Mapping(target = "mediocreCount", source = "mediocreCount")
@Mapping(target = "negativeCount", source = "negativeCount")
AppCommentStatisticsRespVO convert(Long allCount, Long goodCount, Long mediocreCount, Long negativeCount);
List<ProductCommentRespVO> convertList(List<ProductCommentDO> list);
List<AppProductPropertyValueDetailRespVO> convertList01(List<ProductSkuDO.Property> properties);
PageResult<ProductCommentRespVO> convertPage(PageResult<ProductCommentDO> page);
PageResult<AppCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult);
PageResult<AppProductCommentRespVO> convertPage02(PageResult<ProductCommentDO> pageResult);
// TODO @puhui999用 mapstruct 的映射
default ProductCommentDO convert(MemberUserRespDTO user, AppCommentCreateReqVO createReqVO) {
ProductCommentDO productComment = new ProductCommentDO();
productComment.setUserId(user.getId());
productComment.setUserNickname(user.getNickname());
productComment.setUserAvatar(user.getAvatar());
productComment.setAnonymous(createReqVO.getAnonymous());
productComment.setOrderId(createReqVO.getOrderId());
productComment.setOrderItemId(createReqVO.getOrderItemId());
productComment.setSpuId(createReqVO.getSpuId());
productComment.setSpuName(createReqVO.getSpuName());
productComment.setSkuId(createReqVO.getSkuId());
productComment.setScores(createReqVO.getScores());
productComment.setDescriptionScores(createReqVO.getDescriptionScores());
productComment.setBenefitScores(createReqVO.getBenefitScores());
productComment.setContent(createReqVO.getContent());
productComment.setPicUrls(createReqVO.getPicUrls());
return productComment;
/**
* 计算综合评分
*
* @param descriptionScores 描述星级
* @param benefitScores 服务星级
* @return 综合评分
*/
@Named("convertScores")
default Integer convertScores(Integer descriptionScores, Integer benefitScores) {
// 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2
BigDecimal sumScore = new BigDecimal(descriptionScores + benefitScores);
BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN);
return divide.intValue();
}
// TODO @puhui999用 mapstruct 的映射
default ProductCommentDO convert(ProductCommentCreateReqVO createReq) {
ProductCommentDO productComment = new ProductCommentDO();
productComment.setUserId(0L);
productComment.setUserNickname(createReq.getUserNickname());
productComment.setUserAvatar(createReq.getUserAvatar());
productComment.setAnonymous(Boolean.FALSE);
productComment.setOrderId(0L);
productComment.setOrderItemId(0L);
productComment.setSpuId(createReq.getSpuId());
productComment.setSpuName(createReq.getSpuName());
productComment.setSkuId(createReq.getSkuId());
productComment.setScores(createReq.getScores());
productComment.setDescriptionScores(createReq.getDescriptionScores());
productComment.setBenefitScores(createReq.getBenefitScores());
productComment.setContent(createReq.getContent());
productComment.setPicUrls(createReq.getPicUrls());
return productComment;
}
@Mapping(target = "orderId", source = "orderId")
@Mapping(target = "scores", expression = "java(convertScores(createReqDTO.getDescriptionScores(), createReqDTO.getBenefitScores()))")
ProductCommentDO convert(ProductCommentCreateReqDTO createReqDTO, Long orderId);
@Mapping(target = "userId", constant = "0L")
@Mapping(target = "orderId", constant = "0L")
@Mapping(target = "orderItemId", constant = "0L")
@Mapping(target = "anonymous", expression = "java(Boolean.FALSE)")
@Mapping(target = "scores", expression = "java(convertScores(createReq.getDescriptionScores(), createReq.getBenefitScores()))")
ProductCommentDO convert(ProductCommentCreateReqVO createReq);
}

View File

@@ -28,6 +28,11 @@ import java.util.List;
@AllArgsConstructor
public class ProductCommentDO extends BaseDO {
/**
* 默认匿名昵称
*/
public static final String NICKNAME_ANONYMOUS = "匿名用户";
/**
* 评论编号,主键自增
*/
@@ -92,7 +97,7 @@ public class ProductCommentDO extends BaseDO {
/**
* 评分星级
*
* 1-5分
* 1-5
*/
private Integer scores;
/**

View File

@@ -6,14 +6,10 @@ 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.controller.app.comment.vo.AppCommentPageReqVO;
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
public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
@@ -29,9 +25,10 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
}
// TODO 芋艿:在看看这块
// TODO @puhui999直接使用 scores 来算好评、中评、差评
static void appendTabQuery(LambdaQueryWrapperX<ProductCommentDO> queryWrapper, Integer type) {
// 构建好评查询语句:好评计算 (商品评分星级+服务评分星级) >= 8
if (ObjectUtil.equal(type, AppCommentPageReqVO.FAVOURABLE_COMMENT)) {
if (ObjectUtil.equal(type, AppCommentPageReqVO.GOOD_COMMENT)) {
queryWrapper.apply("(scores + benefit_scores) >= 8");
}
// 构建中评查询语句:中评计算 (商品评分星级+服务评分星级) > 4 且 (商品评分星级+服务评分星级) < 8
@@ -55,33 +52,14 @@ public interface ProductCommentMapper extends BaseMapperX<ProductCommentDO> {
return selectPage(reqVO, queryWrapper);
}
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::getReplyStatus, Boolean.TRUE)
.set(ProductCommentDO::getReplyTime, LocalDateTime.now())
.set(ProductCommentDO::getReplyUserId, loginUserId)
.set(ProductCommentDO::getReplyContent, replyVO.getReplyContent())
.eq(ProductCommentDO::getId, replyVO.getId());
update(null, lambdaUpdateWrapper);
}
// TODO @puhui999使用 select 替代 find
default ProductCommentDO findByUserIdAndOrderIdAndSpuId(Long userId, Long orderId, Long spuId) {
default ProductCommentDO selectByUserIdAndOrderIdAndSpuId(Long userId, Long orderId, Long spuId) {
return selectOne(new LambdaQueryWrapperX<ProductCommentDO>()
.eq(ProductCommentDO::getUserId, userId)
.eq(ProductCommentDO::getOrderId, orderId)
.eq(ProductCommentDO::getSpuId, spuId));
}
// TODO @puhui999selectCountBySpuId 即可
default Long selectTabCount(Long spuId, Boolean visible, Integer type) {
default Long selectCountBySpuId(Long spuId, Boolean visible, Integer type) {
LambdaQueryWrapperX<ProductCommentDO> queryWrapper = new LambdaQueryWrapperX<ProductCommentDO>()
.eqIfPresent(ProductCommentDO::getSpuId, spuId)
.eqIfPresent(ProductCommentDO::getVisible, visible);

View File

@@ -1,17 +1,17 @@
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.ProductCommentCreateReqVO;
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.ProductCommentReplyReqVO;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.util.Map;
/**
* 商品评论 Service 接口
*
@@ -36,14 +36,13 @@ public interface ProductCommentService {
*/
void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO);
// TODO @puhui999replyComment
/**
* 商家回复
*
* @param replyVO 商家回复
* @param loginUserId 管理后台商家登陆人 ID
*/
void commentReply(ProductCommentReplyVO replyVO, Long loginUserId);
void replyComment(ProductCommentReplyReqVO replyVO, Long loginUserId);
/**
* 获得商品评价分页
@@ -52,15 +51,24 @@ public interface ProductCommentService {
* @param visible 是否可见
* @return 商品评价分页
*/
PageResult<AppCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible);
/**
* 创建商品评论
* 后台管理员创建评论使用
*
* @param productComment 创建实体
* @param system 是否系统评价
* @param createReqVO 商品评价创建 Request VO 对象
*/
void createComment(ProductCommentDO productComment, Boolean system);
void createComment(ProductCommentCreateReqVO createReqVO);
/**
* 创建评论
* 创建商品评论 APP 端创建商品评论使用
*
* @param commentDO 评论对象
* @return 返回评论 id
*/
Long createComment(ProductCommentDO commentDO);
/**
* 获得商品的评价统计
@@ -69,6 +77,6 @@ public interface ProductCommentService {
* @param visible 是否可见
* @return 评价统计
*/
Map<String, Long> getCommentPageTabsCount(Long spuId, Boolean visible);
AppCommentStatisticsRespVO getCommentPageTabsCount(Long spuId, Boolean visible);
}

View File

@@ -1,31 +1,39 @@
package cn.iocoder.yudao.module.product.service.comment;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO;
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.ProductCommentReplyReqVO;
import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.property.vo.value.AppProductPropertyValueDetailRespVO;
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.dataobject.sku.ProductSkuDO;
import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper;
import cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.module.trade.enums.ErrorCodeConstants.ORDER_NOT_FOUND;
/**
* 商品评论 Service 实现类
@@ -45,95 +53,120 @@ public class ProductCommentServiceImpl implements ProductCommentService {
@Resource
private ProductSpuService productSpuService;
@Override
public PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO) {
return productCommentMapper.selectPage(pageReqVO);
}
@Resource
@Lazy
private ProductSkuService productSkuService;
@Override
@Transactional(rollbackFor = Exception.class)
public void updateCommentVisible(ProductCommentUpdateVisibleReqVO updateReqVO) {
// 校验评论是否存在
validateCommentExists(updateReqVO.getId());
ProductCommentDO productCommentDO = validateCommentExists(updateReqVO.getId());
productCommentDO.setVisible(updateReqVO.getVisible());
// 更新可见状态
// TODO @puhui999直接使用 update 操作
productCommentMapper.updateCommentVisible(updateReqVO.getId(), updateReqVO.getVisible());
productCommentMapper.updateById(productCommentDO);
}
@Override
public void commentReply(ProductCommentReplyVO replyVO, Long loginUserId) {
@Transactional(rollbackFor = Exception.class)
public void replyComment(ProductCommentReplyReqVO replyVO, Long loginUserId) {
// 校验评论是否存在
validateCommentExists(replyVO.getId());
ProductCommentDO productCommentDO = validateCommentExists(replyVO.getId());
productCommentDO.setReplyTime(LocalDateTime.now());
productCommentDO.setReplyUserId(loginUserId);
productCommentDO.setReplyStatus(Boolean.TRUE);
productCommentDO.setReplyContent(replyVO.getReplyContent());
// 回复评论
// TODO @puhui999直接使用 update 操作
productCommentMapper.commentReply(replyVO, loginUserId);
productCommentMapper.updateById(productCommentDO);
}
@Override
public Map<String, Long> getCommentPageTabsCount(Long spuId, Boolean visible) {
Map<String, Long> countMap = new HashMap<>(4);
// 查询商品 id = spuId 的所有评论数量
countMap.put(AppCommentPageReqVO.ALL_COUNT,
productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.ALL));
// 查询商品 id = spuId 的所有好评数量
countMap.put(AppCommentPageReqVO.FAVOURABLE_COMMENT_COUNT,
productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.FAVOURABLE_COMMENT));
// 查询商品 id = spuId 的所有中评数量
countMap.put(AppCommentPageReqVO.MEDIOCRE_COMMENT_COUNT,
productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT));
// 查询商品 id = spuId 的所有差评数量
countMap.put(AppCommentPageReqVO.NEGATIVE_COMMENT_COUNT,
productCommentMapper.selectTabCount(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT));
return countMap;
@Transactional(rollbackFor = Exception.class)
public void createComment(ProductCommentCreateReqVO createReqVO) {
// 校验订单
// TODO @puhui999不校验哈尽可能解耦
Long orderId = tradeOrderApi.validateOrder(createReqVO.getUserId(), createReqVO.getOrderItemId());
// 校验评论
validateComment(createReqVO.getSpuId(), createReqVO.getUserId(), orderId);
ProductCommentDO commentDO = ProductCommentConvert.INSTANCE.convert(createReqVO);
productCommentMapper.insert(commentDO);
}
@Override
public PageResult<AppCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
// TODO @puhui999逻辑可以在 controller 做哈。让 service 简介一点;因为是 view 需要不展示昵称
PageResult<AppCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage02(productCommentMapper.selectPage(pageVO, visible));
@Transactional(rollbackFor = Exception.class)
public Long createComment(ProductCommentDO commentDO) {
// 校验评论
validateComment(commentDO.getSpuId(), commentDO.getUserId(), commentDO.getOrderId());
productCommentMapper.insert(commentDO);
return commentDO.getId();
}
private void validateComment(Long spuId, Long userId, Long orderId) {
ProductSpuDO spu = productSpuService.getSpu(spuId);
if (null == spu) {
throw exception(SPU_NOT_EXISTS);
}
// 判断当前订单的当前商品用户是否评价过
ProductCommentDO exist = productCommentMapper.selectByUserIdAndOrderIdAndSpuId(userId, orderId, spuId);
if (null != exist) {
throw exception(ORDER_SPU_COMMENT_EXISTS);
}
}
private ProductCommentDO validateCommentExists(Long id) {
ProductCommentDO productComment = productCommentMapper.selectById(id);
if (productComment == null) {
throw exception(COMMENT_NOT_EXISTS);
}
return productComment;
}
@Override
public AppCommentStatisticsRespVO getCommentPageTabsCount(Long spuId, Boolean visible) {
return ProductCommentConvert.INSTANCE.convert(
// 查询商品 id = spuId 的所有评论数量
productCommentMapper.selectCountBySpuId(spuId, visible, null),
// 查询商品 id = spuId 的所有好评数量
productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.GOOD_COMMENT),
// 查询商品 id = spuId 的所有中评数量
productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.MEDIOCRE_COMMENT),
// 查询商品 id = spuId 的所有差评数量
productCommentMapper.selectCountBySpuId(spuId, visible, AppCommentPageReqVO.NEGATIVE_COMMENT)
);
}
@Override
public PageResult<AppProductCommentRespVO> getCommentPage(AppCommentPageReqVO pageVO, Boolean visible) {
PageResult<AppProductCommentRespVO> result = ProductCommentConvert.INSTANCE.convertPage02(
productCommentMapper.selectPage(pageVO, visible));
// TODO @puhui999要不这块放到 controller 里拼接?
Set<Long> skuIds = result.getList().stream().map(AppProductCommentRespVO::getSkuId).collect(Collectors.toSet());
List<ProductSkuDO> skuList = productSkuService.getSkuList(skuIds);
Map<Long, ProductSkuDO> skuDOMap = new HashMap<>(skuIds.size());
if (CollUtil.isNotEmpty(skuList)) {
skuDOMap.putAll(skuList.stream().collect(Collectors.toMap(ProductSkuDO::getId, c -> c)));
}
result.getList().forEach(item -> {
// 判断用户是否选择匿名
if (ObjectUtil.equal(item.getAnonymous(), true)) {
item.setUserNickname(AppCommentPageReqVO.ANONYMOUS_NICKNAME);
item.setUserNickname(ProductCommentDO.NICKNAME_ANONYMOUS);
}
ProductSkuDO productSkuDO = skuDOMap.get(item.getSkuId());
if (productSkuDO != null) {
List<AppProductPropertyValueDetailRespVO> skuProperties = ProductCommentConvert.INSTANCE.convertList01(productSkuDO.getProperties());
item.setSkuProperties(skuProperties);
}
// TODO @puhui999直接插入的时候计算到 scores 字段里;这样就去掉 finalScore 字段哈
// 计算评价最终综合评分 最终星数 = (商品评星 + 服务评星) / 2
BigDecimal sumScore = new BigDecimal(item.getScores() + item.getBenefitScores());
BigDecimal divide = sumScore.divide(BigDecimal.valueOf(2L), 0, RoundingMode.DOWN);
item.setFinalScore(divide.intValue());
});
return result;
}
@Override
public void createComment(ProductCommentDO productComment, Boolean system) {
// TODO @puhui999这里不区分是否为 system直接都校验
if (!system) {
// TODO 判断订单是否存在 fix
// TODO @puhui999改成 order 那有个 comment 接口,哪里校验下;商品评论这里不校验订单是否存在哈
TradeOrderRespDTO order = tradeOrderApi.getOrder(productComment.getOrderId());
if (null == order) {
throw exception(ORDER_NOT_FOUND);
}
ProductSpuDO spu = productSpuService.getSpu(productComment.getSpuId());
if (null == spu) {
throw exception(SPU_NOT_EXISTS);
}
// 判断当前订单的当前商品用户是否评价过
ProductCommentDO exist = productCommentMapper.findByUserIdAndOrderIdAndSpuId(productComment.getId(), productComment.getOrderId(), productComment.getSpuId());
if (null != exist) {
throw exception(ORDER_SPU_COMMENT_EXISTS);
}
}
productCommentMapper.insert(productComment);
}
private void validateCommentExists(Long id) {
ProductCommentDO productComment = productCommentMapper.selectById(id);
if (productComment == null) {
throw exception(COMMENT_NOT_EXISTS);
}
public PageResult<ProductCommentDO> getCommentPage(ProductCommentPageReqVO pageReqVO) {
return productCommentMapper.selectPage(pageReqVO);
}
}

View File

@@ -5,15 +5,17 @@ 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.ProductCommentReplyReqVO;
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.controller.app.comment.vo.AppCommentPageReqVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO;
import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppProductCommentRespVO;
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 cn.iocoder.yudao.module.product.service.sku.ProductSkuService;
import cn.iocoder.yudao.module.product.service.spu.ProductSpuService;
import cn.iocoder.yudao.module.trade.api.order.TradeOrderApi;
import org.junit.jupiter.api.Test;
@@ -24,7 +26,6 @@ import org.springframework.context.annotation.Lazy;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
@@ -52,6 +53,8 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
private TradeOrderApi tradeOrderApi;
@MockBean
private ProductSpuService productSpuService;
@MockBean
private ProductSkuService productSkuService;
public String generateNo() {
return DateUtil.format(new Date(), "yyyyMMddHHmmss") + RandomUtil.randomInt(100000, 999999);
@@ -135,23 +138,23 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
assertEquals(8, all.getTotal());
// 测试获取所有商品分页评论数据
PageResult<AppCommentRespVO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
PageResult<AppProductCommentRespVO> result1 = productCommentService.getCommentPage(new AppCommentPageReqVO(), Boolean.TRUE);
assertEquals(7, result1.getTotal());
// 测试获取所有商品分页中评数据
PageResult<AppCommentRespVO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
PageResult<AppProductCommentRespVO> result2 = productCommentService.getCommentPage(new AppCommentPageReqVO().setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
assertEquals(2, result2.getTotal());
// 测试获取指定 spuId 商品分页中评数据
PageResult<AppCommentRespVO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
PageResult<AppProductCommentRespVO> result3 = productCommentService.getCommentPage(new AppCommentPageReqVO().setSpuId(spuId).setType(AppCommentPageReqVO.MEDIOCRE_COMMENT), Boolean.TRUE);
assertEquals(2, result3.getTotal());
// 测试分页 tab count
Map<String, Long> tabsCount = productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE);
assertEquals(6, tabsCount.get(AppCommentPageReqVO.ALL_COUNT));
assertEquals(4, tabsCount.get(AppCommentPageReqVO.FAVOURABLE_COMMENT_COUNT));
assertEquals(2, tabsCount.get(AppCommentPageReqVO.MEDIOCRE_COMMENT_COUNT));
assertEquals(0, tabsCount.get(AppCommentPageReqVO.NEGATIVE_COMMENT_COUNT));
AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentPageTabsCount(spuId, Boolean.TRUE);
assertEquals(6, tabsCount.getAllCount());
assertEquals(4, tabsCount.getGoodCount());
assertEquals(2, tabsCount.getMediocreCount());
assertEquals(0, tabsCount.getNegativeCount());
}
@@ -183,10 +186,10 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest {
Long productCommentId = productComment.getId();
ProductCommentReplyVO replyVO = new ProductCommentReplyVO();
ProductCommentReplyReqVO replyVO = new ProductCommentReplyReqVO();
replyVO.setId(productCommentId);
replyVO.setReplyContent("测试");
productCommentService.commentReply(replyVO, 1L);
productCommentService.replyComment(replyVO, 1L);
ProductCommentDO productCommentDO = productCommentMapper.selectById(productCommentId);
assertEquals("测试", productCommentDO.getReplyContent());

View File

@@ -126,36 +126,82 @@ CREATE TABLE IF NOT EXISTS `product_property_value` (
PRIMARY KEY("id")
) COMMENT '规格值';
CREATE TABLE IF NOT EXISTS `product_comment` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '评价编号',
`user_id` bigint NOT NULL COMMENT ' 评价ID 用户编号',
`user_nickname` varchar(128) NOT NULL COMMENT '评价人名称',
`user_avatar` varchar(255) NOT NULL COMMENT '评价人头像',
`anonymous` bit(1) NOT NULL DEFAULT 0 COMMENT '是否匿名 0:不匿名 1:匿名',
`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 '是否可见 true:显示 false:隐藏',
`scores` int NOT NULL COMMENT '评分星级 1-5分',
`description_scores` int NOT NULL COMMENT '描述星级 1-5分',
`benefit_scores` int NOT NULL COMMENT '服务星级 1-5分',
`delivery_scores` int NOT NULL COMMENT '配送星级 1-5分',
`content` varchar(2000) NOT NULL COMMENT '评论内容',
`pic_urls` varchar(1024) DEFAULT '' COMMENT '评论图片地址数组以逗号分隔最多上传9张',
`replied` bit(1) NOT NULL DEFAULT 0 COMMENT '商家是否回复 1:回复 0:未回复',
`reply_user_id` bigint COMMENT '回复管理员编号',
`reply_content` varchar(2000) COMMENT '商家回复内容',
`reply_time` datetime COMMENT '商家回复时间',
`additional_content` varchar(2000) COMMENT '追加评价内容',
`additional_pic_urls` varchar(1024) COMMENT '追评评价图片地址数组以逗号分隔最多上传9张',
`additional_time` datetime COMMENT '追加评价时间',
"creator" varchar(64) DEFAULT '',
"create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updater" varchar(64) DEFAULT '',
"update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-- TODO @puhui999格式不太对哈
CREATE TABLE IF NOT EXISTS `product_comment`
(
`id`
bigint
NOT
NULL
AUTO_INCREMENT
COMMENT
'评论编号主键自增',
`user_id`
bigint
DEFAULT
NULL
COMMENT
'评价人的用户编号关联 MemberUserDO id 编号',
`user_nickname`
varchar
(
255
) DEFAULT NULL COMMENT '评价人名称',
`user_avatar` varchar
(
1024
) DEFAULT NULL COMMENT '评价人头像',
`anonymous` bit
(
1
) DEFAULT NULL COMMENT '是否匿名',
`order_id` bigint DEFAULT NULL COMMENT '交易订单编号关联 TradeOrderDO id 编号',
`order_item_id` bigint DEFAULT NULL COMMENT '交易订单项编号关联 TradeOrderItemDO id 编号',
`spu_id` bigint DEFAULT NULL COMMENT '商品 SPU 编号关联 ProductSpuDO id',
`spu_name` varchar
(
255
) DEFAULT NULL COMMENT '商品 SPU 名称',
`sku_id` bigint DEFAULT NULL COMMENT '商品 SKU 编号关联 ProductSkuDO id 编号',
`visible` bit
(
1
) DEFAULT NULL COMMENT '是否可见true:显示false:隐藏',
`scores` tinyint DEFAULT NULL COMMENT '评分星级1-5 ',
`description_scores` tinyint DEFAULT NULL COMMENT '描述星级1-5 ',
`benefit_scores` tinyint DEFAULT NULL COMMENT '服务星级1-5 ',
`content` varchar
(
1024
) DEFAULT NULL COMMENT '评论内容',
`pic_urls` varchar
(
4096
) DEFAULT NULL COMMENT '评论图片地址数组',
`reply_status` bit
(
1
) DEFAULT NULL COMMENT '商家是否回复',
`reply_user_id` bigint DEFAULT NULL COMMENT '回复管理员编号关联 AdminUserDO id 编号',
`reply_content` varchar
(
1024
) DEFAULT NULL COMMENT '商家回复内容',
`reply_time` datetime DEFAULT NULL COMMENT '商家回复时间',
`creator` varchar
(
64
) DEFAULT '' COMMENT '创建者',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`updater` varchar
(
64
) DEFAULT '' COMMENT '更新者',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
"deleted" bit NOT NULL DEFAULT FALSE,
"tenant_id" bigint not null default '0',
PRIMARY KEY (`id`)
) COMMENT '商品评价';
"tenant_id" bigint not null default '0',
PRIMARY KEY
(
`id`
)
) COMMENT '产品评论表';

View File

@@ -15,23 +15,23 @@ import javax.validation.constraints.NotNull;
@Data
public class BannerBaseVO {
@Schema(description = "标题", required = true)
@Schema(description = "标题", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "标题不能为空")
private String title;
@Schema(description = "跳转链接", required = true)
@Schema(description = "跳转链接", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "跳转链接不能为空")
private String url;
@Schema(description = "图片地址", required = true)
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "图片地址不能为空")
private String picUrl;
@Schema(description = "排序", required = true)
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "状态", required = true)
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "状态不能为空")
@InEnum(CommonStatusEnum.class)
private Integer status;

View File

@@ -4,22 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
* @author xia
*/
@Schema(description = "管理后台 - Banner Response VO")
@Data
@ToString(callSuper = true)
public class BannerRespVO extends BannerBaseVO {
@Schema(description = "banner编号", required = true)
@NotNull(message = "banner编号不能为空")
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED)
private Long id;
@Schema(description = "创建时间", required = true)
private LocalDateTime createTime;
}

View File

@@ -16,7 +16,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class BannerUpdateReqVO extends BannerBaseVO {
@Schema(description = "banner 编号", required = true)
@Schema(description = "banner 编号", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "banner 编号不能为空")
private Long id;

View File

@@ -24,31 +24,31 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE
public class CouponBaseVO {
// ========== 基本信息 BEGIN ==========
@Schema(description = "优惠劵模板编号", required = true, example = "1024")
@Schema(description = "优惠劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "优惠劵模板编号不能为空")
private Integer templateId;
@Schema(description = "优惠劵名", required = true, example = "春节送送送")
@Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送")
@NotNull(message = "优惠劵名不能为空")
private String name;
@Schema(description = "优惠码状态", required = true, example = "1")
@Schema(description = "优惠码状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
// ========== 基本信息 END ==========
// ========== 领取情况 BEGIN ==========
@Schema(description = "用户编号", required = true, example = "1")
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "领取方式", required = true, example = "1")
@Schema(description = "领取方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "领取方式不能为空")
private Integer takeType;
// ========== 领取情况 END ==========
// ========== 使用规则 BEGIN ==========
@Schema(description = "是否设置满多少金额可用", required = true, example = "100") // 单位0 - 不限制
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位0 - 不限制
@NotNull(message = "是否设置满多少金额可用不能为空")
private Integer usePrice;
@@ -62,7 +62,7 @@ public class CouponBaseVO {
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private LocalDateTime validEndTime;
@Schema(description = "商品范围", required = true, example = "1")
@Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品范围不能为空")
@InEnum(PromotionProductScopeEnum.class)
private Integer productScope;
@@ -72,7 +72,7 @@ public class CouponBaseVO {
// ========== 使用规则 END ==========
// ========== 使用效果 BEGIN ==========
@Schema(description = "优惠类型", required = true, example = "1")
@Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "优惠类型不能为空")
@InEnum(PromotionDiscountTypeEnum.class)
private Integer discountType;

View File

@@ -13,10 +13,10 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class CouponRespVO extends CouponBaseVO {
@Schema(description = "优惠劵编号", required = true, example = "1024")
@Schema(description = "优惠劵编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -29,27 +29,27 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE
@Data
public class CouponTemplateBaseVO {
@Schema(description = "优惠劵名", required = true, example = "春节送送送")
@Schema(description = "优惠劵名", requiredMode = Schema.RequiredMode.REQUIRED, example = "春节送送送")
@NotNull(message = "优惠劵名不能为空")
private String name;
@Schema(description = "发行总量", required = true, example = "1024") // -1 - 则表示不限制发放数量
@Schema(description = "发行总量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") // -1 - 则表示不限制发放数量
@NotNull(message = "发行总量不能为空")
private Integer totalCount;
@Schema(description = "每人限领个数", required = true, example = "66") // -1 - 则表示不限制
@Schema(description = "每人限领个数", requiredMode = Schema.RequiredMode.REQUIRED, example = "66") // -1 - 则表示不限制
@NotNull(message = "每人限领个数不能为空")
private Integer takeLimitCount;
@Schema(description = "领取方式", required = true, example = "1")
@Schema(description = "领取方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "领取方式不能为空")
private Integer takeType;
@Schema(description = "是否设置满多少金额可用", required = true, example = "100") // 单位0 - 不限制
@Schema(description = "是否设置满多少金额可用", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 单位0 - 不限制
@NotNull(message = "是否设置满多少金额可用不能为空")
private Integer usePrice;
@Schema(description = "商品范围", required = true, example = "1")
@Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品范围不能为空")
@InEnum(PromotionProductScopeEnum.class)
private Integer productScope;
@@ -57,7 +57,7 @@ public class CouponTemplateBaseVO {
@Schema(description = "商品 SPU 编号的数组", example = "1,3")
private List<Long> productSpuIds;
@Schema(description = "生效日期类型", required = true, example = "1")
@Schema(description = "生效日期类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "生效日期类型不能为空")
@InEnum(CouponTemplateValidityTypeEnum.class)
private Integer validityType;
@@ -80,7 +80,7 @@ public class CouponTemplateBaseVO {
@Min(value = 1L, message = "开始天数必须大于 1")
private Integer fixedEndTerm;
@Schema(description = "优惠类型", required = true, example = "1")
@Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "优惠类型不能为空")
@InEnum(PromotionDiscountTypeEnum.class)
private Integer discountType;

View File

@@ -15,20 +15,20 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class CouponTemplateRespVO extends CouponTemplateBaseVO {
@Schema(description = "模板编号", required = true, example = "1024")
@Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "状态", required = true, example = "1")
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@InEnum(CommonStatusEnum.class)
private Integer status;
@Schema(description = "领取优惠券的数量", required = true, example = "1024")
@Schema(description = "领取优惠券的数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer takeCount;
@Schema(description = "使用优惠券的次数", required = true, example = "2048")
@Schema(description = "使用优惠券的次数", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Integer useCount;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class CouponTemplateUpdateReqVO extends CouponTemplateBaseVO {
@Schema(description = "模板编号", required = true, example = "1024")
@Schema(description = "模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "模板编号不能为空")
private Long id;

View File

@@ -11,11 +11,11 @@ import javax.validation.constraints.NotNull;
@Data
public class CouponTemplateUpdateStatusReqVO {
@Schema(description = "优惠劵模板编号", required = true, example = "1024")
@Schema(description = "优惠劵模板编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "优惠劵模板编号不能为空")
private Long id;
@Schema(description = "状态", required = true, example = "1")
@Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "状态不能为空")
@InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}")
private Integer status;

View File

@@ -22,16 +22,16 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data
public class DiscountActivityBaseVO {
@Schema(description = "活动标题", required = true, example = "一个标题")
@Schema(description = "活动标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "一个标题")
@NotNull(message = "活动标题不能为空")
private String name;
@Schema(description = "开始时间", required = true)
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startTime;
@Schema(description = "结束时间", required = true)
@Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime endTime;
@@ -43,15 +43,15 @@ public class DiscountActivityBaseVO {
@Data
public static class Product {
@Schema(description = "商品 SPU 编号", required = true, example = "1")
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@Schema(description = "商品 SKU 编号", required = true, example = "1")
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "优惠类型", required = true, example = "1")
@Schema(description = "优惠类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "优惠类型不能为空")
@InEnum(PromotionDiscountTypeEnum.class)
private Integer discountType;

View File

@@ -14,14 +14,14 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class DiscountActivityRespVO extends DiscountActivityBaseVO {
@Schema(description = "活动编号", required = true, example = "1024")
@Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Long id;
@Schema(description = "活动状态", required = true, example = "1")
@Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "活动状态不能为空")
private Integer status;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -16,7 +16,7 @@ import java.util.List;
@ToString(callSuper = true)
public class DiscountActivityUpdateReqVO extends DiscountActivityBaseVO {
@Schema(description = "活动编号", required = true, example = "1024")
@Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "活动编号不能为空")
private Long id;

View File

@@ -25,16 +25,16 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data
public class RewardActivityBaseVO {
@Schema(description = "活动标题", required = true, example = "满啦满啦")
@Schema(description = "活动标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "满啦满啦")
@NotNull(message = "活动标题不能为空")
private String name;
@Schema(description = "开始时间", required = true)
@Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime startTime;
@Schema(description = "结束时间", required = true)
@Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@Future(message = "结束时间必须大于当前时间")
@@ -43,12 +43,12 @@ public class RewardActivityBaseVO {
@Schema(description = "备注", example = "biubiubiu")
private String remark;
@Schema(description = "条件类型", required = true, example = "1")
@Schema(description = "条件类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "条件类型不能为空")
@InEnum(value = PromotionConditionTypeEnum.class, message = "条件类型必须是 {value}")
private Integer conditionType;
@Schema(description = "商品范围", required = true, example = "1")
@Schema(description = "商品范围", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品范围不能为空")
@InEnum(value = PromotionConditionTypeEnum.class, message = "商品范围必须是 {value}")
private Integer productScope;
@@ -66,18 +66,18 @@ public class RewardActivityBaseVO {
@Data
public static class Rule {
@Schema(description = "优惠门槛", required = true, example = "100") // 1. 满 N 元,单位:分; 2. 满 N 件
@Schema(description = "优惠门槛", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") // 1. 满 N 元,单位:分; 2. 满 N 件
@Min(value = 1L, message = "优惠门槛必须大于等于 1")
private Integer limit;
@Schema(description = "优惠价格", required = true, example = "100")
@Schema(description = "优惠价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@Min(value = 1L, message = "优惠价格必须大于等于 1")
private Integer discountPrice;
@Schema(description = "是否包邮", required = true, example = "true")
@Schema(description = "是否包邮", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
private Boolean freeDelivery;
@Schema(description = "赠送的积分", required = true, example = "100")
@Schema(description = "赠送的积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
@Min(value = 1L, message = "赠送的积分必须大于等于 1")
private Integer point;

View File

@@ -13,13 +13,13 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class RewardActivityRespVO extends RewardActivityBaseVO {
@Schema(description = "活动编号", required = true, example = "1024")
@Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer id;
@Schema(description = "活动状态", required = true, example = "1")
@Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer status;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class RewardActivityUpdateReqVO extends RewardActivityBaseVO {
@Schema(description = "活动编号", required = true, example = "1024")
@Schema(description = "活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "活动编号不能为空")
private Long id;

View File

@@ -19,17 +19,17 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.TIME_ZONE_DE
@Data
public class SeckillActivityBaseVO {
@Schema(description = "秒杀活动名称", required = true, example = "晚九点限时秒杀")
@Schema(description = "秒杀活动名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "晚九点限时秒杀")
@NotNull(message = "秒杀活动名称不能为空")
private String name;
@Schema(description = "活动开始时间", required = true)
@Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "活动开始时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
private LocalDateTime startTime;
@Schema(description = "活动结束时间", required = true)
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "活动结束时间不能为空")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT)
@@ -40,15 +40,15 @@ public class SeckillActivityBaseVO {
@Data
public static class Product {
@Schema(description = "商品 SPU 编号", required = true, example = "1")
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@Schema(description = "商品 SKU 编号", required = true, example = "1")
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "秒杀金额", required = true, example = "12.00")
@Schema(description = "秒杀金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "12.00")
@NotNull(message = "秒杀金额不能为空")
private Integer seckillPrice;

View File

@@ -19,11 +19,11 @@ public class SeckillActivityCreateReqVO extends SeckillActivityBaseVO {
@Schema(description = "备注", example = "限时秒杀活动")
private String remark;
@Schema(description = "排序", required = true, example = "1")
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "秒杀时段id", required = true, example = "1,3")
@Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,3")
@NotEmpty(message = "参与场次不能为空")
private List<Long> timeIds;

View File

@@ -14,22 +14,22 @@ import java.util.List;
@ToString(callSuper = true)
public class SeckillActivityRespVO extends SeckillActivityBaseVO {
@Schema(description = "秒杀活动id", required = true, example = "1")
@Schema(description = "秒杀活动id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "付款订单数", required = true, example = "1")
@Schema(description = "付款订单数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer orderCount;
@Schema(description = "付款人数", required = true, example = "1")
@Schema(description = "付款人数", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer userCount;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
@Schema(description = "秒杀时段id", required = true, example = "1,3")
@Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,3")
private List<Long> timeIds;
@Schema(description = "排序", required = true, example = "1")
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer sort;
@Schema(description = "备注", example = "限时秒杀活动")

View File

@@ -16,18 +16,18 @@ import java.util.List;
@ToString(callSuper = true)
public class SeckillActivityUpdateReqVO extends SeckillActivityBaseVO {
@Schema(description = "秒杀活动编号", required = true, example = "224")
@Schema(description = "秒杀活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "224")
@NotNull(message = "秒杀活动编号不能为空")
private Long id;
@Schema(description = "备注", example = "限时秒杀活动")
private String remark;
@Schema(description = "排序", required = true, example = "1")
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "排序不能为空")
private Integer sort;
@Schema(description = "秒杀时段id", required = true, example = "1,3")
@Schema(description = "秒杀时段id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1,3")
@NotEmpty(message = "秒杀时段id不能为空")
private List<Long> timeIds;

View File

@@ -13,15 +13,15 @@ import java.time.LocalTime;
@Data
public class SeckillTimeBaseVO {
@Schema(description = "秒杀时段名称", required = true, example = "上午场")
@Schema(description = "秒杀时段名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "上午场")
@NotNull(message = "秒杀时段名称不能为空")
private String name;
@Schema(description = "开始时间点", required = true, example = "16:30:40")
@Schema(description = "开始时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "16:30:40")
@NotNull(message = "开始时间点不能为空")
private LocalTime startTime;
@Schema(description = "结束时间点", required = true, example = "16:30:40")
@Schema(description = "结束时间点", requiredMode = Schema.RequiredMode.REQUIRED, example = "16:30:40")
@NotNull(message = "结束时间点不能为空")
private LocalTime endTime;

View File

@@ -13,13 +13,13 @@ import java.time.LocalDateTime;
@ToString(callSuper = true)
public class SeckillTimeRespVO extends SeckillTimeBaseVO {
@Schema(description = "编号", required = true, example = "1")
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "秒杀活动数量", required = true, example = "1")
@Schema(description = "秒杀活动数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer seckillActivityCount;
@Schema(description = "创建时间", required = true)
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@@ -13,7 +13,7 @@ import javax.validation.constraints.NotNull;
@ToString(callSuper = true)
public class SeckillTimeUpdateReqVO extends SeckillTimeBaseVO {
@Schema(description = "编号", required = true, example = "1")
@Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "编号不能为空")
private Long id;

View File

@@ -1,42 +1,42 @@
package cn.iocoder.yudao.module.promotion.controller.app.banner;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.promotion.controller.admin.banner.vo.BannerRespVO;
import cn.iocoder.yudao.module.promotion.convert.banner.BannerConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.banner.BannerDO;
import cn.iocoder.yudao.module.promotion.service.banner.BannerService;
import cn.iocoder.yudao.module.promotion.controller.app.banner.vo.AppBannerRespVO;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
/**
* @author: XIA
*/
@RestController
@RequestMapping("/market/banner")
@Tag(name = "用户APP- 首页Banner")
@RequestMapping("/promotion/banner")
@Tag(name = "用户 APP - 首页 Banner")
@Validated
public class AppBannerController {
@Resource
private BannerService bannerService;
// TODO @xia新建一个 AppBannerRespVO只返回必要的字段。status 要过滤下。然后 sort 下结果
@GetMapping("/list")
@Operation(summary = "获得banner列表")
@PreAuthorize("@ss.hasPermission('market:banner:query')")
public CommonResult<List<BannerRespVO>> getBannerList() {
List<BannerDO> list = bannerService.getBannerList();
return success(BannerConvert.INSTANCE.convertList(list));
@Operation(summary = "获得 banner 列表")
// todo @芋艿swagger 注解,待补全
// TODO @芋艿:可以增加缓存,提升性能
// TODO @芋艿position = 1 时首页position = 10 时,拼团活动页
public CommonResult<List<AppBannerRespVO>> getBannerList(@RequestParam("position") Integer position) {
List<AppBannerRespVO> bannerList = new ArrayList<>();
AppBannerRespVO banner1 = new AppBannerRespVO();
banner1.setUrl("https://www.example.com/link1");
banner1.setPicUrl("https://api.java.crmeb.net/crmebimage/public/content/2022/08/04/0f78716213f64bfa83f191d51a832cbf73f6axavoy.jpg");
bannerList.add(banner1);
AppBannerRespVO banner2 = new AppBannerRespVO();
banner2.setUrl("https://www.example.com/link2");
banner2.setPicUrl("https://api.java.crmeb.net/crmebimage/public/content/2023/01/11/be09e755268b43ee90b0db3a3e1b7132r7a6t2wvsm.jpg");
bannerList.add(banner2);
return success(bannerList);
}
}

View File

@@ -0,0 +1,20 @@
package cn.iocoder.yudao.module.promotion.controller.app.banner.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Schema(description = "用户 App - Banner Response VO")
@Data
public class AppBannerRespVO {
@Schema(description = "跳转链接", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "跳转链接不能为空")
private String url;
@Schema(description = "图片地址", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "图片地址不能为空")
private String picUrl;
}

View File

@@ -0,0 +1,129 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityDetailRespVO;
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity.AppCombinationActivityRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "用户 APP - 拼团活动")
@RestController
@RequestMapping("/promotion/combination-activity")
@Validated
public class AppCombinationActivityController {
@GetMapping("/list")
@Operation(summary = "获得拼团活动列表", description = "用于小程序首页")
// TODO 芋艿:增加 Spring Cache
// TODO 芋艿:缺少 swagger 注解
public CommonResult<List<AppCombinationActivityRespVO>> getCombinationActivityList(
@RequestParam(name = "count", defaultValue = "6") Integer count) {
List<AppCombinationActivityRespVO> activityList = new ArrayList<>();
AppCombinationActivityRespVO activity1 = new AppCombinationActivityRespVO();
activity1.setId(1L);
activity1.setName("618 大拼团");
activity1.setUserSize(3);
activity1.setSpuId(2048L);
activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
activity1.setMarketPrice(50);
activity1.setCombinationPrice(100);
activityList.add(activity1);
AppCombinationActivityRespVO activity2 = new AppCombinationActivityRespVO();
activity2.setId(2L);
activity2.setName("双十一拼团");
activity2.setUserSize(5);
activity2.setSpuId(4096L);
activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
activity2.setMarketPrice(100);
activity2.setCombinationPrice(200);
activityList.add(activity2);
return success(activityList);
}
@GetMapping("/page")
@Operation(summary = "获得拼团活动分页")
public CommonResult<PageResult<AppCombinationActivityRespVO>> getCombinationActivityPage(PageParam pageParam) {
List<AppCombinationActivityRespVO> activityList = new ArrayList<>();
AppCombinationActivityRespVO activity1 = new AppCombinationActivityRespVO();
activity1.setId(1L);
activity1.setName("618 大拼团");
activity1.setUserSize(3);
activity1.setSpuId(2048L);
activity1.setPicUrl("商品图片地址");
activity1.setMarketPrice(50);
activity1.setCombinationPrice(100);
activityList.add(activity1);
AppCombinationActivityRespVO activity2 = new AppCombinationActivityRespVO();
activity2.setId(2L);
activity2.setName("双十一拼团");
activity2.setUserSize(5);
activity2.setSpuId(4096L);
activity2.setPicUrl("商品图片地址");
activity2.setMarketPrice(100);
activity2.setCombinationPrice(200);
activityList.add(activity2);
return success(new PageResult<>(activityList, 2L));
}
@GetMapping("/get-detail")
@Operation(summary = "获得拼团活动明细")
@Parameter(name = "id", description = "活动编号", required = true, example = "1024")
public CommonResult<AppCombinationActivityDetailRespVO> getCombinationActivityDetail(@RequestParam("id") Long id) {
// TODO 芋艿:如果禁用的时候,需要抛出异常;
AppCombinationActivityDetailRespVO obj = new AppCombinationActivityDetailRespVO();
// 设置其属性的值
obj.setId(id);
obj.setName("晚九点限时秒杀");
obj.setStatus(1);
obj.setStartTime(LocalDateTime.of(2023, 6, 15, 0, 0, 0));
obj.setEndTime(LocalDateTime.of(2023, 6, 20, 23, 59, 0));
obj.setUserSize(2);
obj.setSuccessCount(100);
obj.setSpuId(633L);
obj.setSingleLimitCount(2);
obj.setTotalLimitCount(3);
// 创建一个Product对象的列表
List<AppCombinationActivityDetailRespVO.Product> productList = new ArrayList<>();
// 创建三个新的Product对象并设置其属性的值
AppCombinationActivityDetailRespVO.Product product1 = new AppCombinationActivityDetailRespVO.Product();
product1.setSkuId(1L);
product1.setCombinationPrice(100);
// 将第一个Product对象添加到列表中
productList.add(product1);
// 创建第二个Product对象并设置其属性的值
AppCombinationActivityDetailRespVO.Product product2 = new AppCombinationActivityDetailRespVO.Product();
product2.setSkuId(2L);
product2.setCombinationPrice(200);
// 将第二个Product对象添加到列表中
productList.add(product2);
// 创建第三个Product对象并设置其属性的值
AppCombinationActivityDetailRespVO.Product product3 = new AppCombinationActivityDetailRespVO.Product();
product3.setSkuId(3L);
product3.setCombinationPrice(300);
// 将第三个Product对象添加到列表中
productList.add(product3);
// 将Product列表设置为对象的属性值
obj.setProducts(productList);
return success(obj);
}
}

View File

@@ -0,0 +1,109 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordDetailRespVO;
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordRespVO;
import cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record.AppCombinationRecordSummaryRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.Max;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "用户 APP - 拼团活动")
@RestController
@RequestMapping("/promotion/combination-record")
@Validated
public class AppCombinationRecordController {
@GetMapping("/get-summary")
@Operation(summary = "获得拼团活动的概要信息", description = "用于小程序首页")
// TODO 芋艿:增加 @Cache 缓存1 分钟过期
public CommonResult<AppCombinationRecordSummaryRespVO> getCombinationSummary() {
AppCombinationRecordSummaryRespVO summary = new AppCombinationRecordSummaryRespVO();
summary.setUserCount(1024);
summary.setAvatars(new ArrayList<>());
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTLjFK35Wvia9lJKHoXfQuHhk0qZbvpPNxrAiaEKF7aL2k4I8kuqrdTWwliamdPHeyAA7DjAg725X2GIQ/132");
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTK1pXgdj5DvBMwrbe8v3tFibSWeQATEsAibt3fllD8XwJ460P2r6KS3WCQvDefuv1bVpDhNCle6CTCA/132");
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTL7KRGHBE62N0awFyBesmmxiaCicf1fJ7E7UCh6zA8GWlT1QC1zT01gG4OxI7BWDESkdPZ5o7tno4hA/132");
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/ouwtwJycbic2JrCoZjETict0klxd1uRuicRneKk00ewMcCClxVcVHQT91Sh9MJGtwibf1fOicD1WpwSP4icJM6eQq1AA/132");
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/RpUrhwens58qc99OcGs993xL4M5QPOe05ekqF9Eia440kRicAlicicIdQWicHBmy2bzLgHzHguWEzHHxnIgeictL7bLA/132");
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/S4tfqmxc8GZGsKc1K4mnhpvtG16gtMrLnTQfDibhr7jJich9LRI5RQKZDoqEjZM3azMib5nic7F4ZXKMEgYyLO08KA/132");
summary.getAvatars().add("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
return success(summary);
}
@GetMapping("/get-head-list")
@Operation(summary = "获得最近 n 条拼团记录(团长发起的)")
// TODO @芋艿:注解要补全
public CommonResult<List<AppCombinationRecordRespVO>> getHeadCombinationRecordList(
@RequestParam(value = "activityId", required = false) Long activityId,
@RequestParam("status") Integer status,
@RequestParam(value = "count", defaultValue = "20") @Max(20) Integer count) {
List<AppCombinationRecordRespVO> list = new ArrayList<>();
for (int i = 1; i <= count; i++) {
AppCombinationRecordRespVO record = new AppCombinationRecordRespVO();
record.setId((long) i);
record.setNickname("用户" + i);
record.setAvatar("头像" + i);
record.setExpireTime(new Date());
record.setUserSize(10);
record.setUserCount(i);
record.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
record.setActivityId(1L);
record.setSpuName("活动:" + i);
list.add(record);
}
return success(list);
}
@GetMapping("/get-detail")
@Operation(summary = "获得拼团记录明细")
@Parameter(name = "id", description = "拼团记录编号", required = true, example = "1024")
public CommonResult<AppCombinationRecordDetailRespVO> getCombinationRecordDetail(@RequestParam("id") Long id) {
AppCombinationRecordDetailRespVO detail = new AppCombinationRecordDetailRespVO();
// 团长
AppCombinationRecordRespVO headRecord = new AppCombinationRecordRespVO();
headRecord.setId(1L);
headRecord.setNickname("用户" + 1);
headRecord.setAvatar("头像" + 1);
headRecord.setExpireTime(DateUtils.addTime(Duration.ofDays(1)));
headRecord.setUserSize(10);
headRecord.setUserCount(3);
headRecord.setStatus(1);
headRecord.setActivityId(10L);
headRecord.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
headRecord.setCombinationPrice(100);
detail.setHeadRecord(headRecord);
// 团员
List<AppCombinationRecordRespVO> list = new ArrayList<>();
for (int i = 1; i <= 2; i++) {
AppCombinationRecordRespVO record = new AppCombinationRecordRespVO();
record.setId((long) i);
record.setNickname("用户" + i);
record.setAvatar("头像" + i);
record.setExpireTime(new Date());
record.setUserSize(10);
record.setUserCount(i);
record.setStatus(1);
list.add(record);
}
detail.setMemberRecords(list);
// 订单编号
detail.setOrderId(100L);
return success(detail);
}
}

View File

@@ -0,0 +1,58 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 拼团活动明细 Response VO")
@Data
public class AppCombinationActivityDetailRespVO {
@Schema(description = "拼团活动编号", required = true, example = "1024")
private Long id;
@Schema(description = "拼团活动名称", required = true, example = "618 大拼团")
private String name;
@Schema(description = "活动状态", required = true, example = "1")
private Integer status;
@Schema(description = "活动开始时间", required = true)
private LocalDateTime startTime;
@Schema(description = "活动结束时间", required = true)
private LocalDateTime endTime;
@Schema(description = "拼团人数", required = true, example = "3")
private Integer userSize;
@Schema(description = "成功的拼团数量", required = true, example = "100")
private Integer successCount;
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
private Long spuId;
@Schema(description = "总共限购数量", example = "10")
private Integer totalLimitCount;
@Schema(description = "单次限购数量", example = "5")
private Integer singleLimitCount;
@Schema(description = "商品信息数组", required = true)
private List<Product> products;
@Schema(description = "商品信息")
@Data
public static class Product {
@Schema(description = "商品 SKU 编号", required = true, example = "4096")
private Long skuId;
@Schema(description = "拼团金额,单位:分", required = true, example = "100")
private Integer combinationPrice;
}
}

View File

@@ -0,0 +1,31 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.activity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 拼团活动 Response VO")
@Data
public class AppCombinationActivityRespVO {
@Schema(description = "拼团活动编号", required = true, example = "1024")
private Long id;
@Schema(description = "拼团活动名称", required = true, example = "618 大拼团")
private String name;
@Schema(description = "拼团人数", required = true, example = "3")
private Integer userSize;
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
private Long spuId;
@Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
private String picUrl;
@Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
private Integer marketPrice;
@Schema(description = "拼团金额,单位:分", required = true, example = "100") // 从拼团商品里取最低价
private Integer combinationPrice;
}

View File

@@ -0,0 +1,21 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "用户 App - 拼团记录详细 Response VO")
@Data
public class AppCombinationRecordDetailRespVO {
@Schema(description = "团长的拼团记录", required = true)
private AppCombinationRecordRespVO headRecord;
@Schema(description = "成员的拼团记录", required = true)
private List<AppCombinationRecordRespVO> memberRecords;
@Schema(description = "当前用户参团记录对应的订单编号", required = true, example = "1024") // 如果没参团,返回 null
private Long orderId;
}

View File

@@ -0,0 +1,45 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.Date;
@Schema(description = "用户 App - 拼团记录 Response VO")
@Data
public class AppCombinationRecordRespVO {
@Schema(description = "拼团记录编号", required = true, example = "1024")
private Long id;
@Schema(description = "拼团活动编号", required = true, example = "1024")
private Long activityId;
@Schema(description = "用户昵称", required = true, example = "1024")
private String nickname;
@Schema(description = "用户头像", required = true, example = "1024")
private String avatar;
@Schema(description = "过期时间", required = true)
private Date expireTime;
@Schema(description = "可参团人数", required = true, example = "10")
private Integer userSize;
@Schema(description = "已参团人数", required = true, example = "5")
private Integer userCount;
@Schema(description = "拼团状态", required = true, example = "1")
private Integer status;
@Schema(description = "商品名字", required = true, example = "我是大黄豆")
private String spuName;
@Schema(description = "商品图片", required = true, example = "https://www.iocoder.cn/1.png")
private String picUrl;
@Schema(description = "拼团金额,单位:分", required = true, example = "100")
private Integer combinationPrice;
}

View File

@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.promotion.controller.app.combination.vo.record;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "用户 App - 拼团记录的简要概括 Response VO")
@Data
public class AppCombinationRecordSummaryRespVO {
@Schema(description = "拼团用户数量", required = true, example = "1024")
private Integer userCount;
@Schema(description = "拼团用户头像列表", required = true) // 只返回最近的 7 个
private List<String> avatars;
}

View File

@@ -1,7 +1,12 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.AppSeckillActivitiDetailRespVO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityDetailRespVO;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityRespVO;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -23,43 +28,104 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Validated
public class AppSeckillActivityController {
@GetMapping("/get-now")
@Operation(summary = "获得当前秒杀活动") // 提供给首页使用
// TODO 芋艿:需要增加 spring cache
public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
AppSeckillActivityNowRespVO respVO = new AppSeckillActivityNowRespVO();
respVO.setConfig(new AppSeckillConfigRespVO().setId(10L).setStartTime("01:00").setEndTime("09:59"));
List<AppSeckillActivityRespVO> activityList = new ArrayList<>();
AppSeckillActivityRespVO activity1 = new AppSeckillActivityRespVO();
activity1.setId(1L);
activity1.setName("618 大秒杀");
activity1.setSpuId(2048L);
activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
activity1.setMarketPrice(50);
activity1.setSeckillPrice(100);
activityList.add(activity1);
AppSeckillActivityRespVO activity2 = new AppSeckillActivityRespVO();
activity2.setId(2L);
activity2.setName("双十一大秒杀");
activity2.setSpuId(4096L);
activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
activity2.setMarketPrice(100);
activity2.setSeckillPrice(200);
activityList.add(activity2);
respVO.setActivities(activityList);
return success(respVO);
}
@GetMapping("/page")
@Operation(summary = "获得秒杀活动分页")
// TODO @芋艿:分页参数
public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) {
List<AppSeckillActivityRespVO> activityList = new ArrayList<>();
AppSeckillActivityRespVO activity1 = new AppSeckillActivityRespVO();
activity1.setId(1L);
activity1.setName("618 大秒杀");
activity1.setSpuId(2048L);
activity1.setPicUrl("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
activity1.setMarketPrice(50);
activity1.setSeckillPrice(100);
activity1.setUnitName("");
activity1.setStock(1);
activity1.setTotalStock(2);
activityList.add(activity1);
AppSeckillActivityRespVO activity2 = new AppSeckillActivityRespVO();
activity2.setId(2L);
activity2.setName("双十一大秒杀");
activity2.setSpuId(4096L);
activity2.setPicUrl("https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132");
activity2.setMarketPrice(100);
activity2.setSeckillPrice(200);
activity2.setUnitName("");
activity2.setStock(2);
activity2.setTotalStock(3);
activityList.add(activity2);
return success(new PageResult<>(activityList, 100L));
}
@GetMapping("/get-detail")
@Operation(summary = "获得秒杀活动明细")
@Parameter(name = "id", description = "活动编号", required = true, example = "1024")
public CommonResult<AppSeckillActivitiDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
public CommonResult<AppSeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
// TODO 芋艿:如果禁用的时候,需要抛出异常;
AppSeckillActivitiDetailRespVO obj = new AppSeckillActivitiDetailRespVO();
AppSeckillActivityDetailRespVO obj = new AppSeckillActivityDetailRespVO();
// 设置其属性的值
obj.setId(id);
obj.setName("晚九点限时秒杀");
obj.setStatus(1);
obj.setStartTime(LocalDateTime.of(2023, 6, 11, 0, 0, 0));
obj.setEndTime(LocalDateTime.of(2023, 6, 11, 23, 59, 0));
obj.setStartTime(LocalDateTime.of(2023, 6, 16, 0, 0, 0));
obj.setEndTime(LocalDateTime.of(2023, 6, 20, 23, 59, 0));
obj.setSpuId(633L);
obj.setSingleLimitCount(2);
obj.setTotalLimitCount(3);
obj.setStock(100);
obj.setTotalStock(200);
// 创建一个Product对象的列表
List<AppSeckillActivitiDetailRespVO.Product> productList = new ArrayList<>();
List<AppSeckillActivityDetailRespVO.Product> productList = new ArrayList<>();
// 创建三个新的Product对象并设置其属性的值
AppSeckillActivitiDetailRespVO.Product product1 = new AppSeckillActivitiDetailRespVO.Product();
AppSeckillActivityDetailRespVO.Product product1 = new AppSeckillActivityDetailRespVO.Product();
product1.setSkuId(1L);
product1.setSeckillPrice(100);
product1.setQuota(50);
product1.setLimitCount(3);
product1.setStock(50);
// 将第一个Product对象添加到列表中
productList.add(product1);
// 创建第二个Product对象并设置其属性的值
AppSeckillActivitiDetailRespVO.Product product2 = new AppSeckillActivitiDetailRespVO.Product();
AppSeckillActivityDetailRespVO.Product product2 = new AppSeckillActivityDetailRespVO.Product();
product2.setSkuId(2L);
product2.setSeckillPrice(200);
product2.setQuota(100);
product2.setLimitCount(4);
product2.setStock(100);
// 将第二个Product对象添加到列表中
productList.add(product2);
// 创建第三个Product对象并设置其属性的值
AppSeckillActivitiDetailRespVO.Product product3 = new AppSeckillActivitiDetailRespVO.Product();
AppSeckillActivityDetailRespVO.Product product3 = new AppSeckillActivityDetailRespVO.Product();
product3.setSkuId(3L);
product3.setSeckillPrice(300);
product3.setQuota(150);
product3.setLimitCount(5);
product3.setStock(150);
// 将第三个Product对象添加到列表中
productList.add(product3);
// 将Product列表设置为对象的属性值

View File

@@ -0,0 +1,36 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
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 java.util.Arrays;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "用户 App - 秒杀时间段")
@RestController
@RequestMapping("/promotion/seckill-config")
@Validated
public class AppSeckillConfigController {
@GetMapping("/list")
@Operation(summary = "获得秒杀时间段列表")
public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() {
return success(Arrays.asList(
new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59")
.setSliderPicUrls(Arrays.asList("https://demo26.crmeb.net/uploads/attach/2021/11/15/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
"https://thirdwx.qlogo.cn/mmopen/vi_32/Q0j4TwGTfTKXMYJOomfp7cebz3cIeb8sHk3GGSIJtWEgREe3j7J1WoAbTvIOicpcNdFkWAziatBSMod8b5RyS4CQ/132")),
new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"),
new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"),
new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59")
));
}
}

View File

@@ -1,4 +1,4 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo;
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -6,9 +6,9 @@ import lombok.Data;
import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 秒杀活动 Response VO")
@Schema(description = "用户 App - 秒杀活动的详细 Response VO")
@Data
public class AppSeckillActivitiDetailRespVO {
public class AppSeckillActivityDetailRespVO {
@Schema(description = "秒杀活动编号", required = true, example = "1024")
private Long id;
@@ -30,7 +30,19 @@ public class AppSeckillActivitiDetailRespVO {
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
private Long spuId;
@Schema(description = "商品 SPU 名字", required = true)
@Schema(description = "总共限购数量", example = "10")
private Integer totalLimitCount;
@Schema(description = "单次限购数量", example = "5")
private Integer singleLimitCount;
@Schema(description = "秒杀库存(剩余)", required = true, example = "50")
private Integer stock;
@Schema(description = "秒杀库存(总计)", required = true, example = "100")
private Integer totalStock;
@Schema(description = "商品信息数组", required = true)
private List<Product> products;
@Schema(description = "商品信息")
@@ -44,10 +56,7 @@ public class AppSeckillActivitiDetailRespVO {
private Integer seckillPrice;
@Schema(description = "秒杀限量库存", required = true, example = "50")
private Integer quota;
@Schema(description = "limitCount", required = true, example = "10")
private Integer limitCount;
private Integer stock;
}

View File

@@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity;
import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "用户 App - 当前秒杀活动 Response VO")
@Data
public class AppSeckillActivityNowRespVO {
@Schema(description = "秒杀时间段", required = true)
private AppSeckillConfigRespVO config;
@Schema(description = "秒杀活动数组", required = true)
private List<AppSeckillActivityRespVO> activities;
}

View File

@@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
@Schema(description = "用户 App - 商品评价分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AppSeckillActivityPageReqVO extends PageParam {
@Schema(description = "秒杀配置编号", example = "1024")
private Long configId;
}

View File

@@ -0,0 +1,34 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Schema(description = "用户 App - 秒杀活动 Response VO")
@Data
public class AppSeckillActivityRespVO {
@Schema(description = "秒杀活动编号", required = true, example = "1024")
private Long id;
@Schema(description = "秒杀活动名称", required = true, example = "晚九点限时秒杀")
private String name;
@Schema(description = "商品 SPU 编号", required = true, example = "2048")
private Long spuId;
@Schema(description = "商品图片", required = true, example = "4096") // 从 SPU 的 picUrl 读取
private String picUrl;
@Schema(description = "单位名", requiredMode = Schema.RequiredMode.REQUIRED, example = "")
private String unitName;
@Schema(description = "商品市场价,单位:分", required = true, example = "50") // 从 SPU 的 marketPrice 读取
private Integer marketPrice;
@Schema(description = "秒杀库存(剩余)", required = true, example = "100")
private Integer stock;
@Schema(description = "秒杀库存(总共)", required = true, example = "200")
private Integer totalStock;
@Schema(description = "秒杀金额,单位:分", required = true, example = "100") // 从秒杀商品里取最低价
private Integer seckillPrice;
}

View File

@@ -0,0 +1,23 @@
package cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Schema(description = "用户 App - 秒杀时间段 Response VO")
@Data
public class AppSeckillConfigRespVO {
@Schema(description = "秒杀时间段编号", required = true, example = "1024")
private Long id;
@Schema(description = "开始时间点", required = true, example = "09:00")
private String startTime;
@Schema(description = "结束时间点", required = true, example = "09:59")
private String endTime;
@Schema(description = "轮播图", required = true)
private List<String> sliderPicUrls;
}

View File

@@ -1,7 +1,5 @@
package cn.iocoder.yudao.module.trade.api.order;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
/**
* 订单 API 接口
*
@@ -10,11 +8,12 @@ import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
public interface TradeOrderApi {
/**
* 获取订单通过订单 id
* 验证订单
*
* @param id id
* @return 订单信息 Response DTO
* @param userId 用户 id
* @param orderItemId 订单项 id
* @return 校验通过返回订单 id
*/
TradeOrderRespDTO getOrder(Long id);
Long validateOrder(Long userId, Long orderItemId);
}

View File

@@ -45,19 +45,26 @@ public interface ErrorCodeConstants {
// ========== Cart 模块 1011002000 ==========
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1011002000, "购物车项不存在");
// ========== 物流配送模块 1011003000 ==========
ErrorCode DELIVERY_EXPRESS_NOT_EXISTS = new ErrorCode(1011003000, "快递公司不存在");
// TODO @jason最好每个模块一段哈。express 一个exmpresstemplate 一个pickup 一个
ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011003001, "已经存在该编码的快递公司");
ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011003002, "运费模板不存在");
ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011003003, "已经存在该运费模板名");
ErrorCode DELIVERY_EXPRESS_USER_ADDRESS_IS_EMPTY = new ErrorCode(1011003004, "计算快递运费时,收件人地址编号为空"); // TODO @jaosn这个错误码放到 Price 这块
ErrorCode PRODUCT_EXPRESS_TEMPLATE_NOT_FOUND = new ErrorCode(1011003005, "找不到到商品对应的运费模板"); // TODO @jaosn这个错误码放到 Price 这块
ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011003006, "快递查询接口异常");
ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011003007, "快递查询返回失败, 原因:{}");
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011003008, "自提门店不存在");
// ========== Price 相关 1011003000 ============
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011003000, "支付价格计算异常,原因:价格小于等于 0");
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_USER_ADDR_IS_EMPTY = new ErrorCode(1011003001, "计算快递运费异常,收件人地址编号为空");
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1011003002, "计算快递运费异常,找不到对应的运费模板");
// ========== 物流 Express 模块 1011004000 ==========
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1011004000, "快递公司不存在");
ErrorCode EXPRESS_CODE_DUPLICATE = new ErrorCode(1011004001, "已经存在该编码的快递公司");
ErrorCode EXPRESS_CLIENT_NOT_PROVIDE = new ErrorCode(1011004002, "需要接入快递服务商比如【快递100】");
ErrorCode EXPRESS_API_QUERY_ERROR = new ErrorCode(1011004101, "快递查询接口异常");
ErrorCode EXPRESS_API_QUERY_FAILED = new ErrorCode(1011004102, "快递查询返回失败,原因:{}");
// ========== 物流 Template 模块 1011005000 ==========
ErrorCode EXPRESS_TEMPLATE_NAME_DUPLICATE = new ErrorCode(1011005000, "已经存在该运费模板名");
ErrorCode EXPRESS_TEMPLATE_NOT_EXISTS = new ErrorCode(1011005001, "运费模板不存在");
// ========== 物流 PICK_UP 模块 1011006000 ==========
ErrorCode PICK_UP_STORE_NOT_EXISTS = new ErrorCode(1011006000, "自提门店不存在");
// ========== Price 相关 1011004000 ============
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1011004000, "支付价格计算异常,原因:价格小于等于 0");
}

View File

@@ -19,23 +19,38 @@ import static cn.hutool.core.util.ArrayUtil.firstMatch;
@Getter
public enum TradeAfterSaleStatusEnum implements IntArrayValuable {
APPLY(10,"申请中", // 【申请售后】
"会员申请退款"),
SELLER_AGREE(20, "卖家通过", // 卖家通过售后;【商品待退货】
"商家同意退款"),
BUYER_DELIVERY(30,"待卖家收货", // 买家已退货,等待卖家收货;【商家待收货】
"会员填写退货物流信息"),
WAIT_REFUND(40, "等待平台退款", // 卖家已收货,等待平台退款;等待退款【等待退款】
"商家收货"),
COMPLETE(50, "完成", // 完成退款【退款成功】
"商家确认退款"),
BUYER_CANCEL(61, "买家取消售后", // 【买家取消】
"会员取消退款"),
SELLER_DISAGREE(62,"卖家拒绝", // 卖家拒绝售后;商家拒绝【商家拒绝】
"商家拒绝退款"),
SELLER_REFUSE(63,"卖家拒绝收货", // 卖家拒绝收货,终止售后;【商家收货
"商家拒绝收货"),
/**
* 【申请售后】
*/
APPLY(10,"申请中", "会员申请退款"),
/**
* 卖家通过售后;【商品待退货】
*/
SELLER_AGREE(20, "卖家通过", "商家同意退款"),
/**
* 买家已退货,等待卖家收货;【商家待收货】
*/
BUYER_DELIVERY(30,"待卖家收货", "会员填写退货物流信息"),
/**
* 卖家已收货,等待平台退款;等待退款【等待退款】
*/
WAIT_REFUND(40, "等待平台退款", "商家收货"),
/**
* 完成退款【退款成功】
*/
COMPLETE(50, "完成", "商家确认退款"),
/**
* 【买家取消】
*/
BUYER_CANCEL(61, "买家取消售后", "会员取消退款"),
/**
* 卖家拒绝售后;商家拒绝【商家拒绝】
*/
SELLER_DISAGREE(62,"卖家拒绝", "商家拒绝退款"),
/**
* 卖家拒绝收货,终止售后;【商家拒收货】
*/
SELLER_REFUSE(63,"卖家拒绝收货", "商家拒绝收货"),
;
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeAfterSaleStatusEnum::getStatus).toArray();

View File

@@ -58,6 +58,11 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-ip</artifactId>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-trade</artifactId>
<version>${revision}</version>
</dependency>
<!-- Web 相关 -->
<dependency>
@@ -93,6 +98,7 @@
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-excel</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -1,13 +1,15 @@
package cn.iocoder.yudao.module.trade.api.order;
import cn.iocoder.yudao.module.trade.api.order.dto.TradeOrderRespDTO;
import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
import cn.iocoder.yudao.module.trade.service.order.TradeOrderService;
import org.springframework.stereotype.Service;
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.trade.enums.ErrorCodeConstants.ORDER_ITEM_NOT_FOUND;
/**
* 订单 API 接口实现类
*
@@ -21,8 +23,14 @@ public class TradeOrderApiImpl implements TradeOrderApi {
private TradeOrderService tradeOrderService;
@Override
public TradeOrderRespDTO getOrder(Long id) {
return TradeOrderConvert.INSTANCE.convert(tradeOrderService.getOrder(id));
public Long validateOrder(Long userId, Long orderItemId) {
// 校验订单项,订单项存在订单就存在
TradeOrderItemDO item = tradeOrderService.getOrderItem(userId, orderItemId);
if (item == null) {
throw exception(ORDER_ITEM_NOT_FOUND);
}
return item.getOrderId();
}
}

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.aftersale;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.trade.core.annotations.AfterSaleLog;
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.product.api.property.ProductPropertyValueApi;
@@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSal
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSalePageReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRefuseReqVO;
import cn.iocoder.yudao.module.trade.controller.admin.aftersale.vo.TradeAfterSaleRespPageItemVO;
import cn.iocoder.yudao.module.trade.controller.app.aftersale.vo.AppTradeAfterSaleCreateReqVO;
import cn.iocoder.yudao.module.trade.convert.aftersale.TradeAfterSaleConvert;
import cn.iocoder.yudao.module.trade.dal.dataobject.aftersale.TradeAfterSaleDO;
import cn.iocoder.yudao.module.trade.service.aftersale.TradeAfterSaleService;
@@ -110,4 +112,20 @@ public class TradeAfterSaleController {
return success(true);
}
// TODO @陈賝:后续要删除下
/**
* 售后日志测试
*
* @param createReqVO
* @return cn.iocoder.yudao.framework.common.pojo.CommonResult<java.lang.Long>
* @author 陈賝
* @date 2023/6/14 21:39
*/
@PostMapping(value = "/create")
@AfterSaleLog(id = "#createReqVO.orderItemId", content = "'申请售后:售后编号['+#createReqVO.orderItemId+'] , '", operateType = "#createReqVO.operateType")
public CommonResult<Long> createAfterSale(@RequestBody AppTradeAfterSaleCreateReqVO createReqVO) {
return success(1L);
// return success(afterSaleService.createAfterSale(getLoginUserId(), createReqVO));
}
}

View File

@@ -17,27 +17,27 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
@Data
public class TradeAfterSaleBaseVO {
@Schema(description = "售后流水号", required = true, example = "202211190847450020500077")
@Schema(description = "售后流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "202211190847450020500077")
@NotNull(message = "售后流水号不能为空")
private String no;
@Schema(description = "售后状态", required = true, example = "10")
@Schema(description = "售后状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "售后状态不能为空")
private Integer status;
@Schema(description = "售后类型", required = true, example = "20")
@Schema(description = "售后类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "20")
@NotNull(message = "售后类型不能为空")
private Integer type;
@Schema(description = "售后方式", required = true, example = "10")
@Schema(description = "售后方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
@NotNull(message = "售后方式不能为空")
private Integer way;
@Schema(description = "用户编号", required = true, example = "30337")
@Schema(description = "用户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30337")
@NotNull(message = "用户编号不能为空")
private Long userId;
@Schema(description = "申请原因", required = true, example = "不喜欢")
@Schema(description = "申请原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "不喜欢")
@NotNull(message = "申请原因不能为空")
private String applyReason;
@@ -47,34 +47,34 @@ public class TradeAfterSaleBaseVO {
@Schema(description = "补充凭证图片", example = "https://www.iocoder.cn/1.png")
private List<String> applyPicUrls;
@Schema(description = "订单编号", required = true, example = "18078")
@Schema(description = "订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18078")
@NotNull(message = "订单编号不能为空")
private Long orderId;
@Schema(description = "订单流水号", required = true, example = "2022111917190001")
@Schema(description = "订单流水号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2022111917190001")
@NotNull(message = "订单流水号不能为空")
private Long orderNo;
@Schema(description = "订单项编号", required = true, example = "572")
@Schema(description = "订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "572")
@NotNull(message = "订单项编号不能为空")
private Long orderItemId;
@Schema(description = "商品 SPU 编号", required = true, example = "2888")
@Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2888")
@NotNull(message = "商品 SPU 编号不能为空")
private Long spuId;
@Schema(description = "商品 SPU 名称", required = true, example = "李四")
@Schema(description = "商品 SPU 名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
@NotNull(message = "商品 SPU 名称不能为空")
private String spuName;
@Schema(description = "商品 SKU 编号", required = true, example = "15657")
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15657")
@NotNull(message = "商品 SKU 编号不能为空")
private Long skuId;
@Schema(description = "商品图片", example = "https://www.iocoder.cn/2.png")
private String picUrl;
@Schema(description = "购买数量", required = true, example = "20012")
@Schema(description = "购买数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20012")
@NotNull(message = "购买数量不能为空")
private Integer count;
@@ -88,7 +88,7 @@ public class TradeAfterSaleBaseVO {
@Schema(description = "审批备注", example = "不香")
private String auditReason;
@Schema(description = "退款金额,单位:分", required = true, example = "18077")
@Schema(description = "退款金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "18077")
@NotNull(message = "退款金额,单位:分不能为空")
private Integer refundPrice;

View File

@@ -10,11 +10,11 @@ import javax.validation.constraints.NotNull;
@Data
public class TradeAfterSaleDisagreeReqVO {
@Schema(description = "售后编号", required = true, example = "1024")
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "审批备注", required = true, example = "你猜")
@Schema(description = "审批备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
@NotEmpty(message = "审批备注不能为空")
private String auditReason;

View File

@@ -9,11 +9,11 @@ import javax.validation.constraints.NotNull;
@Data
public class TradeAfterSaleRefuseReqVO {
@Schema(description = "售后编号", required = true, example = "1024")
@Schema(description = "售后编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
@NotNull(message = "售后编号不能为空")
private Long id;
@Schema(description = "收货备注", required = true, example = "你猜")
@Schema(description = "收货备注", requiredMode = Schema.RequiredMode.REQUIRED, example = "你猜")
@NotNull(message = "收货备注不能为空")
private String refuseMemo;

Some files were not shown because too many files have changed in this diff Show More