diff --git a/common/common-framework/pom.xml b/common/common-framework/pom.xml index 0b3edec38..1d7f7eefb 100644 --- a/common/common-framework/pom.xml +++ b/common/common-framework/pom.xml @@ -76,6 +76,12 @@ test + + + cn.hutool + hutool-all + + diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/util/ServiceExceptionUtil.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/util/ServiceExceptionUtil.java index 6fd9940ab..ca00b4b0b 100644 --- a/common/common-framework/src/main/java/cn/iocoder/common/framework/util/ServiceExceptionUtil.java +++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/util/ServiceExceptionUtil.java @@ -30,10 +30,11 @@ public class ServiceExceptionUtil { /** * 错误枚举的接口 */ - public interface Enumerable { + public interface Enumerable { int getCode(); - + String getMessage(); + int getGroup(); } /** @@ -48,6 +49,9 @@ public class ServiceExceptionUtil { public static void put(Integer code, String message) { ServiceExceptionUtil.messages.put(code, message); } + public static void delete(Integer code, String message) { + ServiceExceptionUtil.messages.remove(code, message); + } public static CommonResult error(Enumerable enumerable) { return error(enumerable.getCode()); diff --git a/mall-dependencies/pom.xml b/mall-dependencies/pom.xml index a9d251a8b..b49490bbc 100644 --- a/mall-dependencies/pom.xml +++ b/mall-dependencies/pom.xml @@ -38,6 +38,8 @@ 1.2.56 6.0.16.Final + 5.2.5 + 3.2.5.RELEASE @@ -141,11 +143,25 @@ ${fastjson.version} + + + cn.hutool + hutool-all + ${hutool.version} + + org.hibernate hibernate-validator ${hibernate-validator.version} + + + + com.github.vanroy + spring-boot-starter-data-jest + ${spring-boot-starter-data-jest.version} + diff --git a/order/order-biz/pom.xml b/order/order-biz/pom.xml index 3a30bd194..08e3f4b4f 100644 --- a/order/order-biz/pom.xml +++ b/order/order-biz/pom.xml @@ -48,6 +48,12 @@ 1.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-data-mongodb + + org.mapstruct diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/convert/OrderCommentConvert.java b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/convert/OrderCommentConvert.java deleted file mode 100644 index 8f8ddb4e7..000000000 --- a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/convert/OrderCommentConvert.java +++ /dev/null @@ -1,44 +0,0 @@ -package cn.iocoder.mall.order.biz.convert; - -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -/** - * - * 订单评论 convert - * - * @author wtz - * @time 2019-05-31 18:30 - */ -@Mapper -public interface OrderCommentConvert { - - OrderCommentConvert INSTANCE = Mappers.getMapper(OrderCommentConvert.class); - -// @Mappings({}) -// OrderCommentStateInfoPageBO.OrderCommentStateInfoItem convertOrderCommentStateInfoItem( -// OrderCommentDO orderCommentDO); -// -// @Mappings({}) -// List convertOrderCommentStateInfoItems( -// List orderCommentDOList); -// -// @Mappings({}) -// OrderCommentDO convertOrderCommentDO(OrderCommentCreateDTO orderCommentCreateDTO); -// -// @Mappings({}) -// OrderCommentCreateBO convertOrderCommentCreateBO(OrderCommentDO orderCommentDO); -// -// @Mappings({}) -// OrderCommentInfoBO convertOrderCommentInfoBO(OrderCommentDO orderCommentDO); -// -// @Mappings({}) -// OrderCommentTimeOutBO convertOrderCommentTimeOutBO(OrderCommentDO orderCommentDO); -// -// @Mappings({}) -// List convertOrderCommentTimeOutBOList( -// List orderCommentDOList); - - - -} diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/convert/comment/OrderCommentConvert.java b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/convert/comment/OrderCommentConvert.java new file mode 100644 index 000000000..57a059a10 --- /dev/null +++ b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/convert/comment/OrderCommentConvert.java @@ -0,0 +1,28 @@ +package cn.iocoder.mall.order.biz.convert.comment; + +import cn.iocoder.mall.order.biz.dataobject.comment.OrderCommentDO; +import cn.iocoder.mall.order.biz.dto.comment.OrderCommentAddDTO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * 订单评论转换 + * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/19 23:06 + */ +@Mapper +public interface OrderCommentConvert { + + OrderCommentConvert INSTANCE = Mappers.getMapper(OrderCommentConvert.class); + + /** + * 参数转成 DO + * + * @param orderCommentAddDTO + * @return + */ + OrderCommentDO convert(OrderCommentAddDTO orderCommentAddDTO); + +} diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderCommentDO.java b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dataobject/comment/OrderCommentDO.java similarity index 80% rename from order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderCommentDO.java rename to order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dataobject/comment/OrderCommentDO.java index 916361748..c551b0b83 100644 --- a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dataobject/OrderCommentDO.java +++ b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dataobject/comment/OrderCommentDO.java @@ -1,25 +1,24 @@ -package cn.iocoder.mall.order.biz.dataobject; +package cn.iocoder.mall.order.biz.dataobject.comment; import cn.iocoder.mall.mybatis.dataobject.BaseDO; -import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.experimental.Accessors; +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; /** - * 订单评论表 - * - * @author wtz - * @time 2019-05-14 20:48 + * 订单评论 MONGODB * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/19 22:30 */ @Data @Accessors(chain = true) -@TableName(value = "order_comment") +@Document(collection = "order_comment") public class OrderCommentDO extends BaseDO { - /** - * 评论 id // TODO FROM 芋艿 TO wtz 中英文之间,要有空格 - */ + @Id private Integer id; /** @@ -103,7 +102,7 @@ public class OrderCommentDO extends BaseDO { private Integer replayCount; /** - * 点赞数 // TODO FROM 芋艿 TO wtz collect 是收藏的意思,最好换个单词噢。 + * 点赞数 */ private Integer likeCount; diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dto/comment/OrderCommentAddDTO.java b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dto/comment/OrderCommentAddDTO.java new file mode 100644 index 000000000..885960c5b --- /dev/null +++ b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dto/comment/OrderCommentAddDTO.java @@ -0,0 +1,63 @@ +package cn.iocoder.mall.order.biz.dto.comment; + +import java.io.Serializable; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * 订单评论创建 + * + * @author wtz + * @update xiaofeng + * @time 2019-05-15 20:42 + * @update time 2020-05-13 0:07 + */ +@Data +@Accessors(chain = true) +public class OrderCommentAddDTO implements Serializable { + + @NotNull(message = "订单 id 不能为空") + private Integer orderId; + + @NotEmpty(message = "订单编号不能为空") + private String orderNo; + + @NotNull(message = "商品的 spu id 不能为空") + private Integer productSpuId; + + @NotEmpty(message = "商品的 spu name 不能为空") + private String productSpuName; + + @NotNull(message = "商品的 sku id 不能为空") + private Integer productSkuId; + + @NotEmpty(message = "商品的 sku attrs 不能为空") + private String productSkuAttrs; + + @NotNull(message = "商品的 sku price 不能为空") + private Integer productSkuPrice; + + @NotEmpty(message = "商品的 sku url 不能为空") + private String productSkuPicUrl; + + private Integer userId; + + private String userAvatar; + + @NotEmpty(message = "用户昵称不能为空") + private String userNickName; + + private Integer star; + + private Integer productDescriptionStar; + + private Integer logisticsStar; + + private Integer merchantStar; + + private String commentContent; + + private String commentPics; +} diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/service/comment/OrderCommentService.java b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/service/comment/OrderCommentService.java new file mode 100644 index 000000000..6ea648af3 --- /dev/null +++ b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/service/comment/OrderCommentService.java @@ -0,0 +1,26 @@ +package cn.iocoder.mall.order.biz.service.comment; + +import cn.iocoder.mall.order.biz.bo.comment.OrderCommentBO; +import cn.iocoder.mall.order.biz.dto.comment.OrderCommentAddDTO; +import javax.validation.Valid; +import org.springframework.validation.annotation.Validated; + +/** + * 订单评论业务 + * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/17 15:24 + */ +@Validated +public interface OrderCommentService { + + /** + * 添加订单评论 + * + * @param orderCommentAddDTO + * @return + */ + Boolean addOrderComment(@Valid OrderCommentAddDTO orderCommentAddDTO); + +} diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/service/comment/OrderCommentServiceImpl.java b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/service/comment/OrderCommentServiceImpl.java new file mode 100644 index 000000000..d37963593 --- /dev/null +++ b/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/service/comment/OrderCommentServiceImpl.java @@ -0,0 +1,34 @@ +package cn.iocoder.mall.order.biz.service.comment; + +import cn.iocoder.mall.order.biz.convert.comment.OrderCommentConvert; +import cn.iocoder.mall.order.biz.dataobject.comment.OrderCommentDO; +import cn.iocoder.mall.order.biz.dto.comment.OrderCommentAddDTO; +import javax.validation.Valid; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.stereotype.Service; + +/** + * OrderCommentServiceImpl + * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/17 15:32 + */ +@Service +public class OrderCommentServiceImpl implements OrderCommentService { + + private final MongoTemplate mongoTemplate; + + public OrderCommentServiceImpl(final MongoTemplate mongoTemplate) { + this.mongoTemplate = mongoTemplate; + } + + @Override + public Boolean addOrderComment( + @Valid OrderCommentAddDTO orderCommentAddDTO) { + + OrderCommentDO orderCommentDO = mongoTemplate + .save(OrderCommentConvert.INSTANCE.convert(orderCommentAddDTO)); + return null != orderCommentDO ? Boolean.TRUE : Boolean.FALSE; + } +} diff --git a/order/order-biz/src/main/resources/biz.yaml b/order/order-biz/src/main/resources/biz.yaml index fb1c302dd..3adf8f6ea 100644 --- a/order/order-biz/src/main/resources/biz.yaml +++ b/order/order-biz/src/main/resources/biz.yaml @@ -6,6 +6,12 @@ spring: username: root password: 3WLiVUBEwTbvAfsh + #mongodb + data: + mongodb: + uri: mongodb://localhost/order-comment + + # MyBatis Plus 配置项 mybatis-plus: configuration: diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/UsersCartController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/cart/UsersCartController.java similarity index 99% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/UsersCartController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/cart/UsersCartController.java index 9b8b4e16a..3f4adc508 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/UsersCartController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/cart/UsersCartController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.users; +package cn.iocoder.mall.order.rest.controller.cart; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderCommentReplyController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/comment/OrderCommentReplyController.java similarity index 96% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderCommentReplyController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/comment/OrderCommentReplyController.java index b9787a203..f5e927865 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderCommentReplyController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/comment/OrderCommentReplyController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.users; +package cn.iocoder.mall.order.rest.controller.comment; import cn.iocoder.common.framework.constant.MallConstants; import io.swagger.annotations.Api; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/comment/UsersOrderCommentController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/comment/UsersOrderCommentController.java new file mode 100644 index 000000000..2d61e1d90 --- /dev/null +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/comment/UsersOrderCommentController.java @@ -0,0 +1,48 @@ +package cn.iocoder.mall.order.rest.controller.comment; + +import cn.iocoder.common.framework.constant.MallConstants; +import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.mall.order.biz.service.comment.OrderCommentService; +import cn.iocoder.mall.order.rest.convert.comment.UsersOrderCommentConvert; +import cn.iocoder.mall.order.rest.request.comment.UsersOrderCommentAddRequest; +import cn.iocoder.mall.security.core.context.UserSecurityContextHolder; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * UsersOrderCommentController + * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/12 22:56 + */ +@RestController +@RequestMapping(MallConstants.ROOT_PATH_USER + "/order_comment") +@Api("订单商品评论模块") +public class UsersOrderCommentController { + + private final OrderCommentService orderCommentService; + + public UsersOrderCommentController( + OrderCommentService orderCommentService) { + this.orderCommentService = orderCommentService; + } + + @PostMapping("/add") + @ApiOperation(value = "添加订单评论") + public CommonResult add( + @RequestBody @Validated UsersOrderCommentAddRequest request) { + Integer userId = UserSecurityContextHolder.getContext().getUserId(); + request.setUserId(userId); + + return CommonResult.success(orderCommentService.addOrderComment( + UsersOrderCommentConvert.INSTANCE.convert(request))); + } + + +} diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/admins/AdminOrderReturnController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/AdminOrderReturnController.java similarity index 96% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/admins/AdminOrderReturnController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/AdminOrderReturnController.java index e0a2e3ba6..029d3a00f 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/admins/AdminOrderReturnController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/AdminOrderReturnController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.admins; +package cn.iocoder.mall.order.rest.controller.order; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/admins/AdminsOrderController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/AdminsOrderController.java similarity index 98% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/admins/AdminsOrderController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/AdminsOrderController.java index fa2eb03d6..2d919f2d4 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/admins/AdminsOrderController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/AdminsOrderController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.admins; +package cn.iocoder.mall.order.rest.controller.order; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderController.java similarity index 98% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderController.java index ab0d08c95..925d8592b 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.users; +package cn.iocoder.mall.order.rest.controller.order; import io.swagger.annotations.Api; @@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("users/order") @Api(description = "用户订单") // TODO FROM 芋艿 to 小范,description 已经废弃啦 -public class OrderController { +public class UsersOrderController { // @Reference(validation = "true", version = "${dubbo.provider.OrderReturnService.version}") // private OrderService orderService; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderLogisticsController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderLogisticsController.java similarity index 96% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderLogisticsController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderLogisticsController.java index 43bfd8bfd..4eaa37156 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderLogisticsController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderLogisticsController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.users; +package cn.iocoder.mall.order.rest.controller.order; import io.swagger.annotations.Api; import org.springframework.web.bind.annotation.RequestMapping; @@ -13,7 +13,7 @@ import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("users/order_logistics") @Api(description = "订单物流信息") -public class OrderLogisticsController { +public class UsersOrderLogisticsController { // @Reference(validation = "true", version = "${dubbo.provider.OrderLogisticsService.version}") // private OrderLogisticsService orderLogisticsService; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderReturnController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderReturnController.java similarity index 95% rename from order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderReturnController.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderReturnController.java index d9ea9dfdd..ab9a1e7db 100644 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderReturnController.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/order/UsersOrderReturnController.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.order.rest.controller.users; +package cn.iocoder.mall.order.rest.controller.order; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController; */ @RestController @RequestMapping("users/order_return") -public class OrderReturnController { +public class UsersOrderReturnController { // @Reference(validation = "true", version = "${dubbo.provider.OrderReturnService.version}") // private OrderReturnService orderReturnService; diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderCommentController.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderCommentController.java deleted file mode 100644 index d13a233e7..000000000 --- a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/controller/users/OrderCommentController.java +++ /dev/null @@ -1,61 +0,0 @@ -package cn.iocoder.mall.order.rest.controller.users; - -import cn.iocoder.common.framework.constant.MallConstants; -import io.swagger.annotations.Api; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -/** - * - * 订单评论 Api(user) - * - * @author wtz - * @time 2019-05-27 20:46 - */ -@RestController -@RequestMapping(MallConstants.ROOT_PATH_USER + "/order_comment") -@Api("用户评论模块") -public class OrderCommentController { - -// @Reference(validation = "true", version = "${dubbo.provider.OrderCommentService.version}") -// private OrderCommentService orderCommentService; -// -// @Reference(validation = "true", version = "${dubbo.provider.OrderCommentReplyService.version}") -// private OrderCommentReplyService orderCommentReplyService; -// -// -// @PostMapping("create_order_comment") -// //@RequiresLogin -// @ApiOperation(value = "创建订单评论") -// public CommonResult createOrderComment(@RequestBody @Validated OrderCommentCreateDTO orderCommentCreateDTO) { -// Integer userId = UserSecurityContextHolder.getContext().getUserId(); -// orderCommentCreateDTO.setUserId(userId); -// return success(orderCommentService.createOrderComment(orderCommentCreateDTO)); -// } -// -// @GetMapping("order_comment_page") -// @ApiOperation(value = "获取评论分页") -// public CommonResult getOrderCommentPage(@Validated OrderCommentPageDTO orderCommentPageDTO){ -// return success(orderCommentService.getOrderCommentPage(orderCommentPageDTO)); -// } -// -// @GetMapping("order_comment_info_merchant_reply") -// @ApiOperation(value = "获取评论和商家回复") -// public CommonResult geOrderCommentInfoAndMerchantReply(@RequestParam("commentId") Integer commentId){ -// OrderCommentInfoAndMerchantReplyBO orderCommentInfoAndMerchantReplyBO=new OrderCommentInfoAndMerchantReplyBO(); -// orderCommentInfoAndMerchantReplyBO.setOrderCommentInfoBO(orderCommentService.getOrderCommentInfo(commentId)); -// orderCommentInfoAndMerchantReplyBO.setOrderCommentMerchantReplyBOS(orderCommentReplyService.getOrderCommentMerchantReply(commentId)); -// return success(orderCommentInfoAndMerchantReplyBO); -// } -// -// @GetMapping -// //@RequiresLogin -// @ApiOperation(value = "获取订单评论状态分页") -// public CommonResult getOrderCommentStateInfoPage(@Validated OrderCommentStateInfoPageDTO orderCommentStateInfoPageDTO){ -// //Integer userId = UserSecurityContextHolder.getContext().getUserId(); -// //orderCommentStateInfoPageDTO.setUserId(userId); -// return success(orderCommentService.getOrderCommentStateInfoPage(orderCommentStateInfoPageDTO)); -// } - - -} diff --git a/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/convert/comment/UsersOrderCommentConvert.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/convert/comment/UsersOrderCommentConvert.java new file mode 100644 index 000000000..00d86ec7b --- /dev/null +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/convert/comment/UsersOrderCommentConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.order.rest.convert.comment; + +import cn.iocoder.mall.order.biz.dto.comment.OrderCommentAddDTO; +import cn.iocoder.mall.order.rest.request.comment.UsersOrderCommentAddRequest; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +/** + * UsersOrderCommentConvert + * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/13 0:15 + */ +@Mapper +public interface UsersOrderCommentConvert { + + UsersOrderCommentConvert INSTANCE = Mappers.getMapper(UsersOrderCommentConvert.class); + + + /** + * 保存订单评论参数转换 + * + * @param request + * @return + */ + OrderCommentAddDTO convert(UsersOrderCommentAddRequest request); + +} diff --git a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dto/comment/OrderCommentCreateDTO.java b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/request/comment/UsersOrderCommentAddRequest.java similarity index 85% rename from order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dto/comment/OrderCommentCreateDTO.java rename to order/order-rest/src/main/java/cn/iocoder/mall/order/rest/request/comment/UsersOrderCommentAddRequest.java index 5c788825c..4bd07063c 100644 --- a/order/order-biz/src/main/java/cn/iocoder/mall/order/biz/dto/comment/OrderCommentCreateDTO.java +++ b/order/order-rest/src/main/java/cn/iocoder/mall/order/rest/request/comment/UsersOrderCommentAddRequest.java @@ -1,26 +1,23 @@ -package cn.iocoder.mall.order.biz.dto.comment; +package cn.iocoder.mall.order.rest.request.comment; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import lombok.Data; import lombok.experimental.Accessors; -import javax.validation.constraints.NotEmpty; -import javax.validation.constraints.NotNull; -import java.io.Serializable; - /** - * 订单评论创建 - * - * @author wtz - * @time 2019-05-15 20:42 + * 添加订单评论 * + * @author xiaofeng + * @version 1.0 + * @date 2020/05/12 23:02 */ -@ApiModel("订单创建 DTO") +@ApiModel("用户 - Order 模块 - 添加订单评论") @Data @Accessors(chain = true) -public class OrderCommentCreateDTO implements Serializable { - +public class UsersOrderCommentAddRequest { @ApiModelProperty(value = "订单 id", required = true) @NotNull(message = "订单 id 不能为空") @@ -64,21 +61,22 @@ public class OrderCommentCreateDTO implements Serializable { @NotEmpty(message = "用户昵称不能为空") private String userNickName; - @ApiModelProperty(value = "评价星级", required = true,example = "1-5") + @ApiModelProperty(value = "评价星级", required = true, example = "1-5") private Integer star; - @ApiModelProperty(value = "商品描述星级", required = true,example = "1-5") + @ApiModelProperty(value = "商品描述星级", required = true, example = "1-5") private Integer productDescriptionStar; - @ApiModelProperty(value = "物流评价星级", required = true,example = "1-5") + @ApiModelProperty(value = "物流评价星级", required = true, example = "1-5") private Integer logisticsStar; - @ApiModelProperty(value = "商家评价星级", required = true,example = "1-5") + @ApiModelProperty(value = "商家评价星级", required = true, example = "1-5") private Integer merchantStar; - @ApiModelProperty(value = "商家评价内容", required = true,example = "1-5") + @ApiModelProperty(value = "商家评价内容", required = true, example = "1-5") private String commentContent; @ApiModelProperty(value = "评价图片", required = true) private String commentPics; + } diff --git a/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/ProductErrorCodeEnum.java b/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/ProductErrorCodeEnum.java index f2e7c10ae..3543d2d34 100644 --- a/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/ProductErrorCodeEnum.java +++ b/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/ProductErrorCodeEnum.java @@ -51,6 +51,11 @@ public enum ProductErrorCodeEnum implements ServiceExceptionUtil.Enumerable { return message; } + @Override + public int getGroup() { + return 0; + } + @Override public int getCode() { return code; diff --git a/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/category/ProductCategoryConstants.java b/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/category/ProductCategoryConstants.java deleted file mode 100644 index 4039f3cdf..000000000 --- a/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/category/ProductCategoryConstants.java +++ /dev/null @@ -1,19 +0,0 @@ -package cn.iocoder.mall.product.biz.enums.category; - -public interface ProductCategoryConstants { - - /** - * 状态 - 开启 - */ - Integer STATUS_ENABLE = 1; - /** - * 状态 - 关闭 - */ - Integer STATUS_DISABLE = 2; - - /** - * 父分类编号 - 根节点 - */ - Integer PID_ROOT = 0; - -} \ No newline at end of file diff --git a/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/category/ProductCategoryNodeEnum.java b/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/category/ProductCategoryNodeEnum.java new file mode 100644 index 000000000..9f32d1df7 --- /dev/null +++ b/product/product-biz-api/src/main/java/cn/iocoder/mall/product/biz/enums/category/ProductCategoryNodeEnum.java @@ -0,0 +1,28 @@ +package cn.iocoder.mall.product.biz.enums.category; + +import cn.iocoder.common.framework.core.IntArrayValuable; + +import java.util.Arrays; + +/** + * @Author: jiangweifan + * @Date: 2020/5/12 + * @Description: 商品分类节点枚举 + */ +public enum ProductCategoryNodeEnum{ + + /** + * 根节点 + */ + ROOT(0); + + private final Integer id; + + ProductCategoryNodeEnum(Integer id) { + this.id = id; + } + + public Integer getId() { + return id; + } +} diff --git a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/bo/product/ProductCategoryBO.java b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/bo/product/ProductCategoryBO.java deleted file mode 100644 index 75e9e17c7..000000000 --- a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/bo/product/ProductCategoryBO.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.mall.product.biz.bo.product; - -import lombok.Data; -import lombok.experimental.Accessors; - -import java.io.Serializable; -import java.util.Date; - -/** - * 商品分类 BO - */ -@Data -@Accessors(chain = true) -@Deprecated // TODO jiangweifan 后面确认无使用后删除 -public class ProductCategoryBO implements Serializable { - - /** - * 分类编号 - */ - private Integer id; - /** - * 父分类编号 - * - * 如果不存在父级,则 pid = 0 。 - */ - private Integer pid; - /** - * 名称 - */ - private String name; - /** - * 描述 - */ - private String description; - /** - * 分类图片 - */ - private String picUrl; - /** - * 排序值 - */ - private Integer sort; - /** - * 状态 - * - * 1-开启 - * 2-关闭 - */ - private Integer status; - /** - * 创建时间 - */ - private Date createTime; - -} diff --git a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/convert/sku/ProductSpuConvert.java b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/convert/sku/ProductSpuConvert.java index 624980de3..2c898bdeb 100644 --- a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/convert/sku/ProductSpuConvert.java +++ b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/convert/sku/ProductSpuConvert.java @@ -40,15 +40,9 @@ public interface ProductSpuConvert { }) ProductSpuBO convert(ProductSpuDO spu); - @Named("translatePicUrlsFromString") - default List translatePicUrlsFromString(String picUrls) { - return StringUtil.split(picUrls, ","); - } - @Mappings({}) List convert(List spus); - @Mappings({ @Mapping(source = "picUrls", target = "picUrls", ignore = true) }) @@ -131,4 +125,9 @@ public interface ProductSpuConvert { return spuDetailList; } + @Named("translatePicUrlsFromString") + default List translatePicUrlsFromString(String picUrls) { + return StringUtil.split(picUrls, ","); + } + } diff --git a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao/category/ProductCategoryMapper.java b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao/category/ProductCategoryMapper.java index 792a19e81..1dd557202 100644 --- a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao/category/ProductCategoryMapper.java +++ b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dao/category/ProductCategoryMapper.java @@ -2,6 +2,7 @@ package cn.iocoder.mall.product.biz.dao.category; import cn.iocoder.mall.product.biz.dataobject.category.ProductCategoryDO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import org.springframework.stereotype.Repository; /** @@ -11,5 +12,14 @@ import org.springframework.stereotype.Repository; */ @Repository public interface ProductCategoryMapper extends BaseMapper { - + /** + * 查询商品分类的下一级子分类数量 + * @param productCategoryId + * @return + */ + default Integer selectChildCategoryCount(Integer productCategoryId) { + return this.selectCount( + Wrappers.lambdaQuery().eq(ProductCategoryDO::getPid, productCategoryId) + ); + } } diff --git a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSpuAddDTO.java b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSpuAddDTO.java index d4e0455d1..7543dcf6b 100644 --- a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSpuAddDTO.java +++ b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/dto/sku/ProductSpuAddDTO.java @@ -12,6 +12,7 @@ import java.util.List; */ @Data @Accessors(chain = true) +// TODO FROM 芋艿 to sunderui && q2118cs:貌似重复了,只要保留一个哈 public class ProductSpuAddDTO { // ========== 基本信息 ========= diff --git a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/category/ProductCategoryServiceImpl.java b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/category/ProductCategoryServiceImpl.java index c540ab8fb..2a43d3abc 100644 --- a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/category/ProductCategoryServiceImpl.java +++ b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/category/ProductCategoryServiceImpl.java @@ -11,9 +11,8 @@ import cn.iocoder.mall.product.biz.dto.category.ProductCategoryDeleteDTO; import cn.iocoder.mall.product.biz.dto.category.ProductCategoryUpdateDTO; import cn.iocoder.mall.product.biz.dto.category.ProductCategoryUpdateStatusDTO; import cn.iocoder.mall.product.biz.enums.ProductErrorCodeEnum; -import cn.iocoder.mall.product.biz.enums.category.ProductCategoryConstants; +import cn.iocoder.mall.product.biz.enums.category.ProductCategoryNodeEnum; import cn.iocoder.mall.product.biz.enums.category.ProductCategoryStatusEnum; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -68,7 +67,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_PARENT_NOT_SELF); } // 校验父分类是否存在 - if (!ProductCategoryConstants.PID_ROOT.equals(productCategoryUpdateDTO.getPid()) + if (!ProductCategoryNodeEnum.ROOT.getId().equals(productCategoryUpdateDTO.getPid()) && productCategoryMapper.selectById(productCategoryUpdateDTO.getPid()) == null) { throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS); } @@ -114,9 +113,8 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_DELETE_ONLY_DISABLE); } // 只有不存在子分类才可以删除 - Integer childCount = productCategoryMapper.selectCount( - Wrappers.lambdaQuery().eq(ProductCategoryDO::getPid, productCategoryId) - ); + // TODO FROM 芋艿 to jiangweifan:Wrappers 只用在 Mapper 层 [DONE] + Integer childCount = productCategoryMapper.selectChildCategoryCount(productCategoryId); if (childCount > 0) { throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_DELETE_ONLY_NO_CHILD); } @@ -128,14 +126,14 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { } private void validParent(Integer pid) { - if (!ProductCategoryConstants.PID_ROOT.equals(pid)) { + if (!ProductCategoryNodeEnum.ROOT.getId().equals(pid)) { ProductCategoryDO parentCategory = productCategoryMapper.selectById(pid); // 校验父分类是否存在 if (parentCategory == null) { throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_PARENT_NOT_EXISTS); } // 父分类必须是一级分类 - if (!ProductCategoryConstants.PID_ROOT.equals(parentCategory.getPid())) { + if (!ProductCategoryNodeEnum.ROOT.getId().equals(parentCategory.getPid())) { throw ServiceExceptionUtil.exception(PRODUCT_CATEGORY_PARENT_CAN_NOT_BE_LEVEL2); } } @@ -149,7 +147,7 @@ public class ProductCategoryServiceImpl implements ProductCategoryService { throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_NOT_EXISTS.getCode()); } // 只有禁用的商品分类才可以删除 - if (ProductCategoryConstants.STATUS_DISABLE.equals(productCategory.getStatus())) { + if (ProductCategoryStatusEnum.DISABLED.getStatus().equals(productCategory.getStatus())) { throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_CATEGORY_MUST_ENABLE.getCode()); } // 返回结果 diff --git a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/spu/ProductSpuServiceImpl.java b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/spu/ProductSpuServiceImpl.java index a03d39452..5f3a6f601 100644 --- a/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/spu/ProductSpuServiceImpl.java +++ b/product/product-biz/src/main/java/cn/iocoder/mall/product/biz/service/spu/ProductSpuServiceImpl.java @@ -15,7 +15,7 @@ import cn.iocoder.mall.product.biz.dataobject.spu.ProductSpuDO; import cn.iocoder.mall.product.biz.dto.sku.ProductSkuAddOrUpdateDTO; import cn.iocoder.mall.product.biz.dto.sku.ProductSpuAddDTO; import cn.iocoder.mall.product.biz.enums.ProductErrorCodeEnum; -import cn.iocoder.mall.product.biz.enums.category.ProductCategoryConstants; +import cn.iocoder.mall.product.biz.enums.category.ProductCategoryNodeEnum; import cn.iocoder.mall.product.biz.enums.spu.ProductSpuConstants; import cn.iocoder.mall.product.biz.service.attr.ProductAttrService; import cn.iocoder.mall.product.biz.service.category.ProductCategoryService; @@ -76,7 +76,7 @@ public class ProductSpuServiceImpl implements ProductSpuService { public ProductSpuDetailBO addProductSpu0(Integer adminId, ProductSpuAddDTO productSpuAddDTO) { // 校验商品分类分类存在 ProductCategoryDO category = productCategoryService.validProductCategory(productSpuAddDTO.getCid()); - if (ProductCategoryConstants.PID_ROOT.equals(category.getPid())) { + if (ProductCategoryNodeEnum.ROOT.getId().equals(category.getPid())) { // 商品只能添加到二级分类下 throw ServiceExceptionUtil.exception(ProductErrorCodeEnum.PRODUCT_SPU_CATEGORY_MUST_BE_LEVEL2.getCode()); } diff --git a/product/product-rest/src/main/java/cn/iocoder/mall/product/rest/controller/category/AdminsProductCategoryController.java b/product/product-rest/src/main/java/cn/iocoder/mall/product/rest/controller/category/AdminsProductCategoryController.java index daf7b64d9..77cb69d27 100644 --- a/product/product-rest/src/main/java/cn/iocoder/mall/product/rest/controller/category/AdminsProductCategoryController.java +++ b/product/product-rest/src/main/java/cn/iocoder/mall/product/rest/controller/category/AdminsProductCategoryController.java @@ -7,7 +7,7 @@ import cn.iocoder.mall.product.biz.dto.category.ProductCategoryAddDTO; import cn.iocoder.mall.product.biz.dto.category.ProductCategoryDeleteDTO; import cn.iocoder.mall.product.biz.dto.category.ProductCategoryUpdateDTO; import cn.iocoder.mall.product.biz.dto.category.ProductCategoryUpdateStatusDTO; -import cn.iocoder.mall.product.biz.enums.category.ProductCategoryConstants; +import cn.iocoder.mall.product.biz.enums.category.ProductCategoryNodeEnum; import cn.iocoder.mall.product.biz.service.category.ProductCategoryService; import cn.iocoder.mall.product.rest.convert.category.AdminsProductCategoryConvert; import cn.iocoder.mall.product.rest.request.category.AdminsProductCategoryAddRequest; @@ -49,7 +49,7 @@ public class AdminsProductCategoryController { Map treeNodeMap = productCategories.stream().collect(Collectors.toMap(ProductCategoryBO::getId, AdminsProductCategoryConvert.INSTANCE::convertToTreeNodeResponse)); // 处理父子关系 treeNodeMap.values().stream() - .filter(node -> !node.getPid().equals(ProductCategoryConstants.PID_ROOT)) + .filter(node -> !node.getPid().equals(ProductCategoryNodeEnum.ROOT.getId())) .forEach((childNode) -> { // 获得父节点 AdminsProductCategoryTreeNodeResponse parentNode = treeNodeMap.get(childNode.getPid()); @@ -61,7 +61,7 @@ public class AdminsProductCategoryController { }); // 获得到所有的根节点 List rootNodes = treeNodeMap.values().stream() - .filter(node -> node.getPid().equals(ProductCategoryConstants.PID_ROOT)) + .filter(node -> node.getPid().equals(ProductCategoryNodeEnum.ROOT.getId())) .sorted(Comparator.comparing(AdminsProductCategoryTreeNodeResponse::getSort)) .collect(Collectors.toList()); return success(rootNodes); diff --git a/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/bo/banner/BannerListBO.java b/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/bo/banner/BannerListBO.java index 7cf13983b..935f5897d 100644 --- a/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/bo/banner/BannerListBO.java +++ b/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/bo/banner/BannerListBO.java @@ -15,6 +15,7 @@ import java.util.Date; */ @Data @Accessors(chain = true) +// TODO FROM 芋艿 to 小范:捉摸是不是先统一的 BannerBO;另外,biz 不使用 swagger 注解哈,其他 banner 的 dto 和 bo 也一起改改哈; public class BannerListBO implements Serializable { diff --git a/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/dao/BannerMapper.java b/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/dao/BannerMapper.java index 39cdfb5d0..5d3d46ca3 100644 --- a/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/dao/BannerMapper.java +++ b/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/dao/BannerMapper.java @@ -26,6 +26,7 @@ public interface BannerMapper extends BaseMapper { * @param dto * @return */ + // TODO FROM 芋艿 to 小范:Page 方法哈 default IPage selectBannerList(BannerListDTO dto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); if (StringUtils.isEmpty(dto.getStatus())) { @@ -41,4 +42,4 @@ public interface BannerMapper extends BaseMapper { return result; } -} \ No newline at end of file +} diff --git a/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/service/banner/BannerService.java b/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/service/banner/BannerService.java index aea1db0d2..c526c9339 100644 --- a/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/service/banner/BannerService.java +++ b/promotion/promotion-biz/src/main/java/cn/iocoder/mall/promotion/biz/service/banner/BannerService.java @@ -48,6 +48,7 @@ public interface BannerService { */ void updateBanner(BannerUpdateDTO adminsBannerUpdateDTO); + // TODO FROM 芋艿 to 小范:貌似要把 dto 搞起来,嘿嘿; /** * 更新 - banner 状态 * diff --git a/promotion/promotion-rest/src/main/java/cn/iocoder/mall/promotion/rest/request/banner/BannerAddRequest.java b/promotion/promotion-rest/src/main/java/cn/iocoder/mall/promotion/rest/request/banner/BannerAddRequest.java index 654f363a5..ffb49b443 100644 --- a/promotion/promotion-rest/src/main/java/cn/iocoder/mall/promotion/rest/request/banner/BannerAddRequest.java +++ b/promotion/promotion-rest/src/main/java/cn/iocoder/mall/promotion/rest/request/banner/BannerAddRequest.java @@ -17,7 +17,7 @@ import java.io.Serializable; @Accessors(chain = true) public class BannerAddRequest implements Serializable { - @NotNull + @NotNull // TODO FROM 芋艿 to 小范:提示要加下,哈哈哈 @ApiModelProperty("跳转链接") private Integer url; diff --git a/search/pom.xml b/search/pom.xml index 865c280c6..410ab0701 100644 --- a/search/pom.xml +++ b/search/pom.xml @@ -13,8 +13,13 @@ pom search-application - search-service-api - search-service-impl + search-biz + search-biz-api + + + search-rpc + search-rest + search-rpc-api diff --git a/search/search-application/pom.xml b/search/search-application/pom.xml index 1f0fbc325..0e839c136 100644 --- a/search/search-application/pom.xml +++ b/search/search-application/pom.xml @@ -15,92 +15,15 @@ cn.iocoder.mall - common-framework + search-rest 1.0-SNAPSHOT cn.iocoder.mall - mall-spring-boot + search-rpc 1.0-SNAPSHOT - - cn.iocoder.mall - user-sdk - 1.0-SNAPSHOT - - - cn.iocoder.mall - search-service-api - 1.0-SNAPSHOT - - - cn.iocoder.mall - search-service-impl - 1.0-SNAPSHOT - - - cn.iocoder.mall - system-service-api - 1.0-SNAPSHOT - - - - - org.springframework.boot - spring-boot-starter-web - - - - io.springfox - springfox-swagger2 - - - com.github.xiaoymin - swagger-bootstrap-ui - - - - - com.alibaba.cloud - spring-cloud-starter-alibaba-sentinel - - - - - - org.springframework.boot - spring-boot-starter-actuator - - - - io.micrometer - micrometer-registry-prometheus - - - - - org.springframework.boot - spring-boot-starter-test - test - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - diff --git a/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java b/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java index 228823e29..1f1257971 100644 --- a/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java +++ b/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java @@ -2,13 +2,22 @@ package cn.iocoder.mall.search.application; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.config.ConfigFileApplicationListener; import org.springframework.scheduling.annotation.EnableAsync; @SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.search"}) @EnableAsync(proxyTargetClass = true) public class SearchApplication { - + /** + * 设置需要读取的配置文件的名字。 + * 基于 {@link org.springframework.boot.context.config.ConfigFileApplicationListener#CONFIG_NAME_PROPERTY} 实现。 + */ + private static final String CONFIG_NAME_VALUE = "biz,rest,rpc,application"; public static void main(String[] args) { + + // 设置环境变量 + System.setProperty(ConfigFileApplicationListener.CONFIG_NAME_PROPERTY, CONFIG_NAME_VALUE); + // 解决 ES java.lang.IllegalStateException: availableProcessors is already System.setProperty("es.set.netty.runtime.available.processors", "false"); SpringApplication.run(SearchApplication.class, args); diff --git a/search/search-application/src/main/java/cn/iocoder/mall/search/application/controller/users/UsersProductSearchController.java b/search/search-application/src/main/java/cn/iocoder/mall/search/application/controller/users/UsersProductSearchController.java deleted file mode 100644 index 508356672..000000000 --- a/search/search-application/src/main/java/cn/iocoder/mall/search/application/controller/users/UsersProductSearchController.java +++ /dev/null @@ -1,59 +0,0 @@ -package cn.iocoder.mall.search.application.controller.users; - -import cn.iocoder.common.framework.util.StringUtil; -import cn.iocoder.common.framework.vo.CommonResult; -import cn.iocoder.common.framework.vo.SortingField; -import cn.iocoder.mall.search.api.ProductSearchService; -import cn.iocoder.mall.search.api.bo.ProductConditionBO; -import cn.iocoder.mall.search.api.bo.ProductPageBO; -import cn.iocoder.mall.search.api.dto.ProductConditionDTO; -import cn.iocoder.mall.search.api.dto.ProductSearchPageDTO; -import org.apache.dubbo.config.annotation.Reference; -import io.swagger.annotations.Api; -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.util.Collections; - -import static cn.iocoder.common.framework.vo.CommonResult.success; - -// TODO 芋艿,搜索关键字的配置 -// TODO 芋艿,搜索日志 - -@RestController -@RequestMapping("users/product") -@Api("商品搜索") -public class UsersProductSearchController { - - @Reference(validation = "true", version = "${dubbo.provider.ProductSearchService.version}") - private ProductSearchService productSearchService; - - @GetMapping("/page") // TODO 芋艿,后面把 BO 改成 VO - public CommonResult page(@RequestParam(value = "cid", required = false) Integer cid, - @RequestParam(value = "keyword", required = false) String keyword, - @RequestParam(value = "pageNo", required = false) Integer pageNo, - @RequestParam(value = "pageSize", required = false) Integer pageSize, - @RequestParam(value = "sortField", required = false) String sortField, - @RequestParam(value = "sortOrder", required = false) String sortOrder) { - // 创建 ProductSearchPageDTO 对象 - ProductSearchPageDTO productSearchPageDTO = new ProductSearchPageDTO().setCid(cid).setKeyword(keyword) - .setPageNo(pageNo).setPageSize(pageSize); - if (StringUtil.hasText(sortField) && StringUtil.hasText(sortOrder)) { - productSearchPageDTO.setSorts(Collections.singletonList(new SortingField(sortField, sortOrder))); - } - // 执行搜索 - return success(productSearchService.getSearchPage(productSearchPageDTO)); - } - - @GetMapping("/condition") // TODO 芋艿,后面把 BO 改成 VO - public CommonResult condition(@RequestParam(value = "keyword", required = false) String keyword) { - // 创建 ProductConditionDTO 对象 - ProductConditionDTO productConditionDTO = new ProductConditionDTO().setKeyword(keyword) - .setFields(Collections.singleton(ProductConditionDTO.FIELD_CATEGORY)); - // 执行搜索 - return success(productSearchService.getSearchCondition(productConditionDTO)); - } - -} diff --git a/search/search-application/src/main/resources/application.yaml b/search/search-application/src/main/resources/application.yaml index c531b15d9..4ddc8d284 100644 --- a/search/search-application/src/main/resources/application.yaml +++ b/search/search-application/src/main/resources/application.yaml @@ -1,29 +1,6 @@ spring: application: name: search-application - - # Spring Cloud 配置项 - cloud: - # Spring Cloud Sentinel 配置项 - sentinel: - transport: - dashboard: s1.iocoder.cn:12088 # Sentinel Dashboard 服务地址 - eager: true # 项目启动时,直接连接到 Sentinel - -# server -server: - port: 18086 - servlet: - context-path: /search-api/ - -swagger: - enable: false - - -management: - endpoints: - web: - exposure: - include: health,info,env,metrics,prometheus - metrics: - enabled: true + # Profile 的配置项 + profiles: + active: local diff --git a/search/search-biz-api/pom.xml b/search/search-biz-api/pom.xml new file mode 100644 index 000000000..b8d93c0db --- /dev/null +++ b/search/search-biz-api/pom.xml @@ -0,0 +1,23 @@ + + + + search + cn.iocoder.mall + 1.0-SNAPSHOT + + 4.0.0 + + search-biz-api + + + + + cn.iocoder.mall + common-framework + 1.0-SNAPSHOT + + + + diff --git a/search/search-biz/pom.xml b/search/search-biz/pom.xml new file mode 100644 index 000000000..7a6c27c57 --- /dev/null +++ b/search/search-biz/pom.xml @@ -0,0 +1,110 @@ + + + + search + cn.iocoder.mall + 1.0-SNAPSHOT + + 4.0.0 + + search-biz + + + + + cn.iocoder.mall + mall-spring-boot + 1.0-SNAPSHOT + + + + search-biz-api + cn.iocoder.mall + 1.0-SNAPSHOT + + + + cn.iocoder.mall + product-rpc-api + 1.0-SNAPSHOT + + + + org.springframework.boot + spring-boot-starter-data-elasticsearch + + + + + com.alibaba.cloud + spring-cloud-starter-dubbo + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.alibaba.cloud + spring-cloud-starter-stream-rocketmq + + + + + com.google.guava + guava + + + + org.mapstruct + mapstruct + + + org.mapstruct + mapstruct-jdk8 + + + org.projectlombok + lombok + + + + com.alibaba + fastjson + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-starter-web + + + + + com.github.vanroy + spring-boot-starter-data-jest + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + + diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductBO.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductBO.java new file mode 100644 index 000000000..7ba301041 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductBO.java @@ -0,0 +1,86 @@ +package cn.iocoder.mall.search.biz.bo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 商品 ES BO + */ +@Data +@Accessors(chain = true) +public class ProductBO implements Serializable { + + private Integer id; + + // ========== 基本信息 ========= + /** + * SPU 名字 + */ + private String name; + /** + * 卖点 + */ + private String sellPoint; + /** + * 描述 + */ + private String description; + /** + * 分类编号 + */ + private Integer cid; + /** + * 分类名 + */ + private String categoryName; + /** + * 商品主图地数组 + */ + private List picUrls; + + // ========== 其他信息 ========= + /** + * 是否上架商品(是否可见)。 + * + * true 为已上架 + * false 为已下架 + */ + private Boolean visible; + /** + * 排序字段 + */ + private Integer sort; + + // ========== Sku 相关字段 ========= + /** + * 原价格,单位:分 + */ + private Integer originalPrice; + /** + * 购买价格,单位:分。 + */ + private Integer buyPrice; + /** + * 库存数量 + */ + private Integer quantity; + + // ========== 促销活动相关字段 ========= + // 目前只促销单体商品促销,目前仅限制折扣。 + /** + * 促销活动编号 + */ + private Integer promotionActivityId; + /** + * 促销活动标题 + */ + private String promotionActivityTitle; + /** + * 促销活动类型 + */ + private Integer promotionActivityType; + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductConditionBO.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductConditionBO.java new file mode 100644 index 000000000..b8eebbfe6 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductConditionBO.java @@ -0,0 +1,35 @@ +package cn.iocoder.mall.search.biz.bo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 商品搜索条件返回 BO + */ +@Data +@Accessors(chain = true) +public class ProductConditionBO { + + /** + * 商品分类数组 + */ + private List categories; + + @Data + @Accessors(chain = true) + public static class Category { + + /** + * 分类编号 + */ + private Integer id; + /** + * 分类名称 + */ + private String name; + + } + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductPageBO.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductPageBO.java new file mode 100644 index 000000000..827b7996f --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/bo/ProductPageBO.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.search.biz.bo; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class ProductPageBO implements Serializable { + + /** + * 管理员数组 + */ + private List list; + /** + * 总量 + */ + private Integer total; + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/config/JPAConfiguration.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/config/JPAConfiguration.java new file mode 100644 index 000000000..acb35fd21 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/config/JPAConfiguration.java @@ -0,0 +1,9 @@ +package cn.iocoder.mall.search.biz.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories; + +@Configuration +@EnableElasticsearchRepositories(basePackages = "cn.iocoder.mall.search.biz.dao") +public class JPAConfiguration { +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/constant/FieldAnalyzer.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/constant/FieldAnalyzer.java new file mode 100644 index 000000000..5b5315769 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/constant/FieldAnalyzer.java @@ -0,0 +1,26 @@ +package cn.iocoder.mall.search.biz.constant; + +/** + * ES 字段分析器的枚举类 + * + * 关于 IK 分词,文章 https://blog.csdn.net/xsdxs/article/details/72853288 不错。 + * 目前项目使用的 ES 版本是 6.7.1 ,可以在 https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-7-1 下载。 + * 如果不知道怎么安装 ES ,可以看 https://blog.csdn.net/chengyuqiang/article/details/78837712 简单。 + */ +public class FieldAnalyzer { + + /** + * IK 最大化分词 + * + * 会将文本做最细粒度的拆分 + */ + public static final String IK_MAX_WORD = "ik_max_word"; + + /** + * IK 智能分词 + * + * 会做最粗粒度的拆分 + */ + public static final String IK_SMART = "ik_smart"; + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java new file mode 100644 index 000000000..9227f3615 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.mall.search.biz.convert; + +import cn.iocoder.mall.search.biz.bo.ProductBO; +import cn.iocoder.mall.search.biz.dataobject.ESProductDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface ProductSearchConvert { + + ProductSearchConvert INSTANCE = Mappers.getMapper(ProductSearchConvert.class); + + List convert(List list); + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dao/ProductRepository.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dao/ProductRepository.java new file mode 100644 index 000000000..1b4b869d0 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dao/ProductRepository.java @@ -0,0 +1,69 @@ +package cn.iocoder.mall.search.biz.dao; + +import cn.iocoder.common.framework.util.CollectionUtil; +import cn.iocoder.common.framework.util.StringUtil; +import cn.iocoder.common.framework.vo.SortingField; +import cn.iocoder.mall.search.biz.dataobject.ESProductDO; +import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery; +import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder; +import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders; +import org.elasticsearch.search.sort.SortBuilders; +import org.elasticsearch.search.sort.SortOrder; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +import static org.elasticsearch.index.query.QueryBuilders.matchQuery; + +@Repository +public interface ProductRepository extends ElasticsearchRepository { + + @Deprecated + ESProductDO findByName(String name); + + default Page search(Integer cid, String keyword, Integer pageNo, Integer pageSize, + List sortFields) { + NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder() + .withPageable(PageRequest.of(pageNo - 1, pageSize)); + // 筛选条件 cid + if (cid != null) { + nativeSearchQueryBuilder.withFilter(QueryBuilders.termQuery("cid", cid)); + } + // 筛选 + if (StringUtil.hasText(keyword)) { + FunctionScoreQueryBuilder.FilterFunctionBuilder[] functions = { // TODO 芋艿,分值随便打的 + new FunctionScoreQueryBuilder.FilterFunctionBuilder(matchQuery("name", keyword), + ScoreFunctionBuilders.weightFactorFunction(10)), + new FunctionScoreQueryBuilder.FilterFunctionBuilder(matchQuery("sellPoint", keyword), + ScoreFunctionBuilders.weightFactorFunction(2)), + new FunctionScoreQueryBuilder.FilterFunctionBuilder(matchQuery("categoryName", keyword), + ScoreFunctionBuilders.weightFactorFunction(3)), +// new FunctionScoreQueryBuilder.FilterFunctionBuilder(matchQuery("description", keyword), +// ScoreFunctionBuilders.weightFactorFunction(2)), // TODO 芋艿,目前这么做,如果商品描述很长,在按照价格降序,会命中超级多的关键字。 + }; + FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(functions) + .scoreMode(FunctionScoreQuery.ScoreMode.SUM) + .setMinScore(2F); // TODO 芋艿,需要考虑下 score + nativeSearchQueryBuilder.withQuery(functionScoreQueryBuilder); + } else { + nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery()); + } + // 排序 + if (!CollectionUtil.isEmpty(sortFields)) { + sortFields.forEach(sortField -> nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort(sortField.getField()) + .order(SortOrder.fromString(sortField.getOrder())))); + } else if (StringUtil.hasText(keyword)) { + nativeSearchQueryBuilder.withSort(SortBuilders.scoreSort().order(SortOrder.DESC)); + } else { + nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("sort").order(SortOrder.DESC)); + } + // 执行查询 + return search(nativeSearchQueryBuilder.build()); + } + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dataobject/ESProductDO.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dataobject/ESProductDO.java new file mode 100644 index 000000000..bd06b0abf --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dataobject/ESProductDO.java @@ -0,0 +1,96 @@ +package cn.iocoder.mall.search.biz.dataobject; + +import cn.iocoder.mall.search.biz.constant.FieldAnalyzer; +import lombok.Data; +import lombok.experimental.Accessors; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.Document; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.util.List; + +/** + * 商品 ES DO + */ +@Document(indexName = "product", type = "spu", shards = 1, replicas = 0) +@Data +@Accessors(chain = true) +public class ESProductDO { + + @Id + private Integer id; + + // ========== 基本信息 ========= + /** + * SPU 名字 + */ + @Field(analyzer = FieldAnalyzer.IK_MAX_WORD, type = FieldType.Text) + private String name; + /** + * 卖点 + */ + @Field(analyzer = FieldAnalyzer.IK_MAX_WORD, type = FieldType.Text) + private String sellPoint; + /** + * 描述 + */ + @Field(analyzer = FieldAnalyzer.IK_MAX_WORD, type = FieldType.Text) + private String description; + /** + * 分类编号 + */ + private Integer cid; + /** + * 分类名 + */ + @Field(analyzer = FieldAnalyzer.IK_MAX_WORD, type = FieldType.Text) + private String categoryName; + /** + * 商品主图地数组 + */ + private List picUrls; + + // ========== 其他信息 ========= + /** + * 是否上架商品(是否可见)。 + * + * true 为已上架 + * false 为已下架 + */ + private Boolean visible; + /** + * 排序字段 + */ + private Integer sort; + + // ========== Sku 相关字段 ========= + /** + * 原价格,单位:分 + */ + private Integer originalPrice; + /** + * 购买价格,单位:分。 + */ + private Integer buyPrice; + /** + * 库存数量 + */ + private Integer quantity; + + // ========== 促销活动相关字段 ========= + // 目前只促销单体商品促销,目前仅限制折扣。 + /** + * 促销活动编号 + */ + private Integer promotionActivityId; + /** + * 促销活动标题 + */ + private String promotionActivityTitle; + /** + * 促销活动类型 + */ + private Integer promotionActivityType; + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dto/ProductConditionDTO.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dto/ProductConditionDTO.java new file mode 100644 index 000000000..4bfe0fead --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dto/ProductConditionDTO.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.search.biz.dto; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Collection; + +/** + * 获得商品检索条件 DTO + */ +@Data +@Accessors(chain = true) +public class ProductConditionDTO { + + /** + * Field - 商品分类 + */ + public static final String FIELD_CATEGORY = "category"; + + /** + * 关键字 + */ + private String keyword; + /** + * 需要返回的搜索条件的 fields 名 + */ + private Collection fields; + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dto/ProductSearchPageDTO.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dto/ProductSearchPageDTO.java new file mode 100644 index 000000000..430a32ed0 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/dto/ProductSearchPageDTO.java @@ -0,0 +1,43 @@ +package cn.iocoder.mall.search.biz.dto; + +import cn.iocoder.common.framework.util.CollectionUtil; +import cn.iocoder.common.framework.vo.SortingField; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.Set; + +/** + * 商品检索分页 DTO + */ +@Data +@Accessors(chain = true) +public class ProductSearchPageDTO { + + public static final Set SORT_FIELDS = CollectionUtil.asSet("buyPrice"); + + /** + * 分类编号 + */ + private Integer cid; + /** + * 关键字 + */ + private String keyword; + + /** + * 页码 + */ + private Integer pageNo; + /** + * 分页大小 + */ + private Integer pageSize; + + /** + * 排序字段数组 + */ + private List sorts; + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchService.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchService.java new file mode 100644 index 000000000..50101d746 --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchService.java @@ -0,0 +1,20 @@ +package cn.iocoder.mall.search.biz.service; + + +public interface ProductSearchService { + + Integer rebuild(); + + /** + * 构建商品的搜索索引 + * + * @param id 商品编号 + * @return 构建结果 + */ + Boolean save(Integer id); +// +// ProductPageBO getSearchPage(ProductSearchPageDTO searchPageDTO); +// +// ProductConditionBO getSearchCondition(ProductConditionDTO conditionDTO); + +} diff --git a/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java new file mode 100644 index 000000000..af4b0880c --- /dev/null +++ b/search/search-biz/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java @@ -0,0 +1,147 @@ +package cn.iocoder.mall.search.biz.service; + +import cn.iocoder.common.framework.util.CollectionUtil; +import cn.iocoder.common.framework.vo.SortingField; +import cn.iocoder.mall.search.biz.dao.ProductRepository; +import cn.iocoder.mall.search.biz.dto.ProductSearchPageDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.List; + +@Service +@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.ProductSearchService.version}") +public class ProductSearchServiceImpl implements ProductSearchService { + + private static final Integer REBUILD_FETCH_PER_SIZE = 100; + + @Autowired + private ProductRepository productRepository; + @Autowired + private ElasticsearchTemplate elasticsearchTemplate; // 因为需要使用到聚合操作,只好引入 ElasticsearchTemplate 。 + +// @Reference(validation = "true", version = "${dubbo.consumer.ProductSpuService.version}") +// private ProductSpuService productSpuService; +// @Reference(validation = "true", version = "${dubbo.consumer.ProductCategoryService.version}") +// private ProductCategoryService productCategoryService; +// @Reference(validation = "true", version = "${dubbo.consumer.CartService.version}") +// private CartService cartService; + +// @Override +// public Integer rebuild() { +// // TODO 芋艿,因为目前商品比较少,所以写的很粗暴。等未来重构 +// Integer lastId = null; +// int rebuildCounts = 0; +// while (true) { +// List spus = productSpuService.getProductSpuDetailListForSync(lastId, REBUILD_FETCH_PER_SIZE); +// rebuildCounts += spus.size(); +// // 存储到 ES 中 +// List products = spus.stream().map(this::convert).collect(Collectors.toList()); +// productRepository.saveAll(products); +// // 设置新的 lastId ,或者结束 +// if (spus.size() < REBUILD_FETCH_PER_SIZE) { +// break; +// } else { +// lastId = spus.get(spus.size() - 1).getId(); +// } +// } +// // 返回成功 +// return rebuildCounts; +// } +// +// @Override +// public Boolean save(Integer id) { +// // 获得商品性情 +// ProductSpuDetailBO result = productSpuService.getProductSpuDetail(id); +// // 存储到 ES 中 +// ESProductDO product = convert(result); +// productRepository.save(product); +// // 返回成功 +// return true; +// } +// +// @SuppressWarnings("OptionalGetWithoutIsPresent") +// private ESProductDO convert(ProductSpuDetailBO spu) { +// // 获得最小价格的 SKU ,用于下面的价格计算 +// ProductSpuDetailBO.Sku sku = spu.getSkus().stream().min(Comparator.comparing(ProductSpuDetailBO.Sku::getPrice)).get(); +// // 价格计算 +// CalcSkuPriceBO calSkuPriceResult = cartService.calcSkuPrice(sku.getId()); +// // 拼装结果 +// return ProductSearchConvert.INSTANCE.convert(spu, calSkuPriceResult); +// } +// +// @Override +// public ProductPageBO getSearchPage(ProductSearchPageDTO searchPageDTO) { +// checkSortFieldInvalid(searchPageDTO.getSorts()); +// // 执行查询 +// Page searchPage = productRepository.search(searchPageDTO.getCid(), searchPageDTO.getKeyword(), +// searchPageDTO.getPageNo(), searchPageDTO.getPageSize(), searchPageDTO.getSorts()); +// // 转换结果 +// return new ProductPageBO() +// .setList(ProductSearchConvert.INSTANCE.convert(searchPage.getContent())) +// .setTotal((int) searchPage.getTotalElements()); +// } + + private void checkSortFieldInvalid(List sorts) { + if (CollectionUtil.isEmpty(sorts)) { + return; + } + sorts.forEach(sortingField -> Assert.isTrue(ProductSearchPageDTO.SORT_FIELDS.contains(sortingField.getField()), + String.format("排序字段(%s) 不在允许范围内", sortingField.getField()))); + } + + @Override + public Integer rebuild() { + return null; + } + + @Override + public Boolean save(Integer id) { + return null; + } + +// @Override +// public ProductConditionBO getSearchCondition(ProductConditionDTO conditionDTO) { +// // 创建 ES 搜索条件 +// NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder(); +// // 筛选 +// if (StringUtil.hasText(conditionDTO.getKeyword())) { // 如果有 keyword ,就去匹配 +// nativeSearchQueryBuilder.withQuery(QueryBuilders.multiMatchQuery(conditionDTO.getKeyword(), +// "name", "sellPoint", "categoryName")); +// } else { +// nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery()); +// } +// // 聚合 +// if (conditionDTO.getFields().contains(ProductConditionDTO.FIELD_CATEGORY)) { // 商品分类 +// nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("cids").field("cid")); +// } +// // 执行查询 +// ProductConditionBO condition = elasticsearchTemplate.query(nativeSearchQueryBuilder.build(), response -> { +// ProductConditionBO result = new ProductConditionBO(); +// // categoryIds 聚合 +// Aggregation categoryIdsAggregation = response.getAggregations().get("cids"); +// if (categoryIdsAggregation != null) { +// result.setCategories(new ArrayList<>()); +// for (LongTerms.Bucket bucket : (((LongTerms) categoryIdsAggregation).getBuckets())) { +// result.getCategories().add(new ProductConditionBO.Category().setId(bucket.getKeyAsNumber().intValue())); +// } +// } +// // 返回结果 +// return result; +// }); +// // 聚合其它数据源 +// if (!CollectionUtil.isEmpty(condition.getCategories())) { +// // 查询指定的 ProductCategoryBO 数组,并转换成 ProductCategoryBO Map +// Map categoryMap = productCategoryService.getListByIds( +// condition.getCategories().stream().map(ProductConditionBO.Category::getId).collect(Collectors.toList())) +// .stream().collect(Collectors.toMap(ProductCategoryBO::getId, category -> category)); +// // 设置分类名 +// condition.getCategories().forEach(category -> category.setName(categoryMap.get(category.getId()).getName())); +// } +// // 返回结果 +// return condition; +// } + +} diff --git a/search/search-biz/src/main/resources/biz.properties b/search/search-biz/src/main/resources/biz.properties new file mode 100644 index 000000000..197907aff --- /dev/null +++ b/search/search-biz/src/main/resources/biz.properties @@ -0,0 +1,8 @@ +##################### 业务模块 ##################### +## OAuth2CodeService +modules.oauth2-code-service.access-token-expire-time-millis = 2880000 +modules.oauth2-code-service.refresh-token-expire-time-millis = 43200000 +## OAuth2MobileCodeService +modules.oauth2-mobile-code-service.code-expire-time-millis = 600000 +modules.oauth2-mobile-code-service.send-maximum-quantity-per-day = 10 +modules.oauth2-mobile-code-service.send-frequency = 60000 diff --git a/search/search-biz/src/main/resources/biz.yaml b/search/search-biz/src/main/resources/biz.yaml new file mode 100644 index 000000000..fc41b8a93 --- /dev/null +++ b/search/search-biz/src/main/resources/biz.yaml @@ -0,0 +1,7 @@ +spring: + data: + # Jest 配置项 + jest: + uri: http://127.0.0.1:9200 + + diff --git a/search/search-rest/pom.xml b/search/search-rest/pom.xml new file mode 100644 index 000000000..fa0bbe14f --- /dev/null +++ b/search/search-rest/pom.xml @@ -0,0 +1,42 @@ + + + + search + cn.iocoder.mall + 1.0-SNAPSHOT + + 4.0.0 + + search-rest + 提供 商品搜索服务的 Rest 接口的实现,提供对外调用 + + + + + cn.iocoder.mall + search-biz + 1.0-SNAPSHOT + + + + + cn.iocoder.mall + mall-spring-boot-starter-web + 1.0-SNAPSHOT + + + cn.iocoder.mall + mall-spring-boot-starter-security + 1.0-SNAPSHOT + + + cn.iocoder.mall + mall-spring-boot-starter-swagger + 1.0-SNAPSHOT + + + + + \ No newline at end of file diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/controller/user/UsersProductSearchController.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/controller/user/UsersProductSearchController.java new file mode 100644 index 000000000..9a44420be --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/controller/user/UsersProductSearchController.java @@ -0,0 +1,72 @@ +package cn.iocoder.mall.search.rest.controller.user; + +import cn.iocoder.common.framework.constant.MallConstants; +import cn.iocoder.common.framework.util.StringUtil; +import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.common.framework.vo.SortingField; +import cn.iocoder.mall.search.biz.service.ProductSearchService; +import cn.iocoder.mall.search.rest.response.user.ProductPageResponse; +import io.swagger.annotations.Api; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +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 cn.iocoder.mall.search.rest.request.user.ProductConditionRequest; +import cn.iocoder.mall.search.rest.request.user.ProductSearchPageRequest; +import cn.iocoder.mall.search.rest.response.user.ProductConditionResponse; + +import java.util.Collections; + +import static cn.iocoder.common.framework.vo.CommonResult.success; + +/** + * Created with IDEA + * + * @author : lhl + * @version : 1.0 + * @Time : 19:26 + * @date : 2020/5/14 + */ +@RestController +@RequestMapping(MallConstants.ROOT_PATH_ADMIN + "users/product") +@Api(tags = "商品查询 API") +@Slf4j +@RequiredArgsConstructor(onConstructor = @__(@Autowired)) +public class UsersProductSearchController { + + + private final ProductSearchService productSearchService; + + @GetMapping("/page") // TODO 芋艿,后面把 BO 改成 VO + public CommonResult page(@RequestParam(value = "cid", required = false) Integer cid, + @RequestParam(value = "keyword", required = false) String keyword, + @RequestParam(value = "pageNo", required = false) Integer pageNo, + @RequestParam(value = "pageSize", required = false) Integer pageSize, + @RequestParam(value = "sortField", required = false) String sortField, + @RequestParam(value = "sortOrder", required = false) String sortOrder) { + // 创建 ProductSearchPageDTO 对象 + ProductSearchPageRequest productSearchPageDTO = new ProductSearchPageRequest().setCid(cid).setKeyword(keyword) + .setPageNo(pageNo).setPageSize(pageSize); + if (StringUtil.hasText(sortField) && StringUtil.hasText(sortOrder)) { + productSearchPageDTO.setSorts(Collections.singletonList(new SortingField(sortField, sortOrder))); + } + // 执行搜索 +// return success(productSearchService.getSearchPage(productSearchPageDTO)); + return success(null); + } + + @GetMapping("/condition") // TODO 芋艿,后面把 BO 改成 VO + public CommonResult condition(@RequestParam(value = "keyword", required = false) String keyword) { + // 创建 ProductConditionDTO 对象 + ProductConditionRequest productConditionDTO = new ProductConditionRequest().setKeyword(keyword) + .setFields(Collections.singleton(ProductConditionRequest.FIELD_CATEGORY)); + // 执行搜索 +// return success(productSearchService.getSearchCondition(productConditionDTO)); + return success(null); + } + + +} diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/convert/user/UsersProductSearchConvert.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/convert/user/UsersProductSearchConvert.java new file mode 100644 index 000000000..4fcdac3bd --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/convert/user/UsersProductSearchConvert.java @@ -0,0 +1,35 @@ +package cn.iocoder.mall.search.rest.convert.user; + +import cn.iocoder.mall.search.biz.bo.ProductBO; +import cn.iocoder.mall.search.biz.dataobject.ESProductDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface UsersProductSearchConvert { + + cn.iocoder.mall.search.biz.convert.ProductSearchConvert INSTANCE = Mappers.getMapper(cn.iocoder.mall.search.biz.convert.ProductSearchConvert.class); + +// @Mappings({}) +// ESProductDO convert(ProductSpuDetailBO spu); + +// @Mappings({}) +// default ESProductDO convert(ProductSpuDetailBO spu, CalcSkuPriceBO calcSkuPrice) { +// // Spu 的基础数据 +// ESProductDO product = this.convert(spu); +// product.setOriginalPrice(calcSkuPrice.getOriginalPrice()).setBuyPrice(calcSkuPrice.getBuyPrice()); +// // 设置促销活动相关字段 +// if (calcSkuPrice.getTimeLimitedDiscount() != null) { +// PromotionActivityBO activity = calcSkuPrice.getTimeLimitedDiscount(); +// product.setPromotionActivityId(activity.getId()).setPromotionActivityTitle(activity.getTitle()) +// .setPromotionActivityType(activity.getActivityType()); +// } +// // 返回 +// return product; +// } + + List convert(List list); + +} diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/request/user/UsersProductConditionRequest.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/request/user/UsersProductConditionRequest.java new file mode 100644 index 000000000..c90b0b957 --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/request/user/UsersProductConditionRequest.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.search.rest.request.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Collection; + +/** + * 获得商品检索条件 DTO + */ +@Data +@Accessors(chain = true) +public class UsersProductConditionRequest{ + + /** + * Field - 商品分类 + */ + public static final String FIELD_CATEGORY = "category"; + + /** + * 关键字 + */ + private String keyword; + /** + * 需要返回的搜索条件的 fields 名 + */ + private Collection fields; + +} diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/request/user/UsersProductSearchPageRequest.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/request/user/UsersProductSearchPageRequest.java new file mode 100644 index 000000000..bdb2c52f8 --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/request/user/UsersProductSearchPageRequest.java @@ -0,0 +1,48 @@ +package cn.iocoder.mall.search.rest.request.user; + +import cn.iocoder.common.framework.util.CollectionUtil; +import cn.iocoder.common.framework.vo.SortingField; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.Set; + +/** + * Created with IDEA + * + * @author : lhl + * @version : 1.0 + * @Time : 19:09 + * @date : 2020/5/14 + */ +@Data +@Accessors(chain = true) +public class UsersProductSearchPageRequest { + + public static final Set SORT_FIELDS = CollectionUtil.asSet("buyPrice"); + + /** + * 分类编号 + */ + private Integer cid; + /** + * 关键字 + */ + private String keyword; + + /** + * 页码 + */ + private Integer pageNo; + /** + * 分页大小 + */ + private Integer pageSize; + + /** + * 排序字段数组 + */ + private List sorts; + +} diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductConditionResponse.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductConditionResponse.java new file mode 100644 index 000000000..4b008a8ff --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductConditionResponse.java @@ -0,0 +1,35 @@ +package cn.iocoder.mall.search.rest.response.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 商品搜索条件返回 BO + */ +@Data +@Accessors(chain = true) +public class UsersProductConditionResponse { + + /** + * 商品分类数组 + */ + private List categories; + + @Data + @Accessors(chain = true) + public static class Category { + + /** + * 分类编号 + */ + private Integer id; + /** + * 分类名称 + */ + private String name; + + } + +} diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductPageResponse.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductPageResponse.java new file mode 100644 index 000000000..56ece1465 --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductPageResponse.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.search.rest.response.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class UsersProductPageResponse implements Serializable { + + /** + * 管理员数组 + */ + private List list; + /** + * 总量 + */ + private Integer total; + +} diff --git a/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductResponse.java b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductResponse.java new file mode 100644 index 000000000..5d5127fc7 --- /dev/null +++ b/search/search-rest/src/main/java/cn/iocoder/mall/search/rest/response/user/UsersProductResponse.java @@ -0,0 +1,86 @@ +package cn.iocoder.mall.search.rest.response.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 商品 ES BO + */ +@Data +@Accessors(chain = true) +public class UsersProductResponse implements Serializable { + + private Integer id; + + // ========== 基本信息 ========= + /** + * SPU 名字 + */ + private String name; + /** + * 卖点 + */ + private String sellPoint; + /** + * 描述 + */ + private String description; + /** + * 分类编号 + */ + private Integer cid; + /** + * 分类名 + */ + private String categoryName; + /** + * 商品主图地数组 + */ + private List picUrls; + + // ========== 其他信息 ========= + /** + * 是否上架商品(是否可见)。 + * + * true 为已上架 + * false 为已下架 + */ + private Boolean visible; + /** + * 排序字段 + */ + private Integer sort; + + // ========== Sku 相关字段 ========= + /** + * 原价格,单位:分 + */ + private Integer originalPrice; + /** + * 购买价格,单位:分。 + */ + private Integer buyPrice; + /** + * 库存数量 + */ + private Integer quantity; + + // ========== 促销活动相关字段 ========= + // 目前只促销单体商品促销,目前仅限制折扣。 + /** + * 促销活动编号 + */ + private Integer promotionActivityId; + /** + * 促销活动标题 + */ + private String promotionActivityTitle; + /** + * 促销活动类型 + */ + private Integer promotionActivityType; + +} diff --git a/search/search-rest/src/main/resources/rest.yaml b/search/search-rest/src/main/resources/rest.yaml new file mode 100644 index 000000000..778308fcf --- /dev/null +++ b/search/search-rest/src/main/resources/rest.yaml @@ -0,0 +1,12 @@ +# 服务器的配置项 +server: + port: 18099 + servlet: + context-path: /search-api/ + +# Swagger 配置项 +swagger: + title: 商品查询子系统 + description: 商品查询子系统 + version: 1.0.0 + base-package: cn.iocoder.mall.search.rest.controller diff --git a/search/search-rpc-api/pom.xml b/search/search-rpc-api/pom.xml new file mode 100644 index 000000000..2dd3c6c5c --- /dev/null +++ b/search/search-rpc-api/pom.xml @@ -0,0 +1,33 @@ + + + + search + cn.iocoder.mall + 1.0-SNAPSHOT + + 4.0.0 + + search-rpc-api + + + + + + search-biz-api + cn.iocoder.mall + 1.0-SNAPSHOT + + + + + javax.validation + validation-api + + + org.projectlombok + lombok + + + \ No newline at end of file diff --git a/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/api/user/ProductSearchRPC.java b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/api/user/ProductSearchRPC.java new file mode 100644 index 000000000..57a7e83aa --- /dev/null +++ b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/api/user/ProductSearchRPC.java @@ -0,0 +1,21 @@ +package cn.iocoder.mall.search.biz.api.user; + +import cn.iocoder.common.framework.vo.CommonResult; + +public interface ProductSearchRPC { + + CommonResult rebuild(); + + /** + * 构建商品的搜索索引 + * + * @param id 商品编号 + * @return 构建结果 + */ + CommonResult save(Integer id); + +// ProductPageBO getSearchPage(ProductSearchPageDTO searchPageDTO); +// +// ProductConditionBO getSearchCondition(ProductConditionDTO conditionDTO); + +} diff --git a/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/request/user/ProductConditionRequest.java b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/request/user/ProductConditionRequest.java new file mode 100644 index 000000000..eb9fd74ec --- /dev/null +++ b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/request/user/ProductConditionRequest.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.search.biz.request.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.Collection; + +/** + * 获得商品检索条件 DTO + */ +@Data +@Accessors(chain = true) +public class ProductConditionRequest { + + /** + * Field - 商品分类 + */ + public static final String FIELD_CATEGORY = "category"; + + /** + * 关键字 + */ + private String keyword; + /** + * 需要返回的搜索条件的 fields 名 + */ + private Collection fields; + +} diff --git a/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/request/user/ProductSearchPageRequest.java b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/request/user/ProductSearchPageRequest.java new file mode 100644 index 000000000..a722eea46 --- /dev/null +++ b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/request/user/ProductSearchPageRequest.java @@ -0,0 +1,48 @@ +package cn.iocoder.mall.search.biz.request.user; + +import cn.iocoder.common.framework.util.CollectionUtil; +import cn.iocoder.common.framework.vo.SortingField; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; +import java.util.Set; + +/** + * Created with IDEA + * + * @author : lhl + * @version : 1.0 + * @Time : 19:09 + * @date : 2020/5/14 + */ +@Data +@Accessors(chain = true) +public class ProductSearchPageRequest { + + public static final Set SORT_FIELDS = CollectionUtil.asSet("buyPrice"); + + /** + * 分类编号 + */ + private Integer cid; + /** + * 关键字 + */ + private String keyword; + + /** + * 页码 + */ + private Integer pageNo; + /** + * 分页大小 + */ + private Integer pageSize; + + /** + * 排序字段数组 + */ + private List sorts; + +} diff --git a/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductConditionResponse.java b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductConditionResponse.java new file mode 100644 index 000000000..2b48816f1 --- /dev/null +++ b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductConditionResponse.java @@ -0,0 +1,35 @@ +package cn.iocoder.mall.search.biz.response.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * 商品搜索条件返回 BO + */ +@Data +@Accessors(chain = true) +public class ProductConditionResponse { + + /** + * 商品分类数组 + */ + private List categories; + + @Data + @Accessors(chain = true) + public static class Category { + + /** + * 分类编号 + */ + private Integer id; + /** + * 分类名称 + */ + private String name; + + } + +} diff --git a/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductPageResponse.java b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductPageResponse.java new file mode 100644 index 000000000..56db936ad --- /dev/null +++ b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductPageResponse.java @@ -0,0 +1,22 @@ +package cn.iocoder.mall.search.biz.response.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +@Data +@Accessors(chain = true) +public class ProductPageResponse implements Serializable { + + /** + * 管理员数组 + */ + private List list; + /** + * 总量 + */ + private Integer total; + +} diff --git a/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductResponse.java b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductResponse.java new file mode 100644 index 000000000..31952582b --- /dev/null +++ b/search/search-rpc-api/src/main/java/cn/iocoder/mall/search/biz/response/user/ProductResponse.java @@ -0,0 +1,86 @@ +package cn.iocoder.mall.search.biz.response.user; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; +import java.util.List; + +/** + * 商品 ES BO + */ +@Data +@Accessors(chain = true) +public class ProductResponse implements Serializable { + + private Integer id; + + // ========== 基本信息 ========= + /** + * SPU 名字 + */ + private String name; + /** + * 卖点 + */ + private String sellPoint; + /** + * 描述 + */ + private String description; + /** + * 分类编号 + */ + private Integer cid; + /** + * 分类名 + */ + private String categoryName; + /** + * 商品主图地数组 + */ + private List picUrls; + + // ========== 其他信息 ========= + /** + * 是否上架商品(是否可见)。 + * + * true 为已上架 + * false 为已下架 + */ + private Boolean visible; + /** + * 排序字段 + */ + private Integer sort; + + // ========== Sku 相关字段 ========= + /** + * 原价格,单位:分 + */ + private Integer originalPrice; + /** + * 购买价格,单位:分。 + */ + private Integer buyPrice; + /** + * 库存数量 + */ + private Integer quantity; + + // ========== 促销活动相关字段 ========= + // 目前只促销单体商品促销,目前仅限制折扣。 + /** + * 促销活动编号 + */ + private Integer promotionActivityId; + /** + * 促销活动标题 + */ + private String promotionActivityTitle; + /** + * 促销活动类型 + */ + private Integer promotionActivityType; + +} diff --git a/search/search-rpc/pom.xml b/search/search-rpc/pom.xml new file mode 100644 index 000000000..d46e9e2f4 --- /dev/null +++ b/search/search-rpc/pom.xml @@ -0,0 +1,48 @@ + + + + search + cn.iocoder.mall + 1.0-SNAPSHOT + + 4.0.0 + + search-rpc + + + + + + cn.iocoder.mall + search-rpc-api + 1.0-SNAPSHOT + + + + cn.iocoder.mall + search-biz + 1.0-SNAPSHOT + + + + + com.alibaba.cloud + spring-cloud-starter-dubbo + + + + + com.alibaba.cloud + spring-cloud-starter-alibaba-nacos-discovery + + + + + com.github.vanroy + spring-boot-starter-data-jest + + + + \ No newline at end of file diff --git a/search/search-rpc/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java b/search/search-rpc/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java new file mode 100644 index 000000000..b83142908 --- /dev/null +++ b/search/search-rpc/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java @@ -0,0 +1,35 @@ +package cn.iocoder.mall.search.biz.convert; + +import cn.iocoder.mall.search.biz.bo.ProductBO; +import cn.iocoder.mall.search.biz.dataobject.ESProductDO; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public interface ProductSearchConvert { + + ProductSearchConvert INSTANCE = Mappers.getMapper(ProductSearchConvert.class); + +// @Mappings({}) +// ESProductDO convert(ProductSpuDetailBO spu); + +// @Mappings({}) +// default ESProductDO convert(ProductSpuDetailBO spu, CalcSkuPriceBO calcSkuPrice) { +// // Spu 的基础数据 +// ESProductDO product = this.convert(spu); +// product.setOriginalPrice(calcSkuPrice.getOriginalPrice()).setBuyPrice(calcSkuPrice.getBuyPrice()); +// // 设置促销活动相关字段 +// if (calcSkuPrice.getTimeLimitedDiscount() != null) { +// PromotionActivityBO activity = calcSkuPrice.getTimeLimitedDiscount(); +// product.setPromotionActivityId(activity.getId()).setPromotionActivityTitle(activity.getTitle()) +// .setPromotionActivityType(activity.getActivityType()); +// } +// // 返回 +// return product; +// } + + List convert(List list); + +} diff --git a/search/search-rpc/src/main/java/cn/iocoder/mall/search/biz/rpc/user/ProductSearchRPCImpl.java b/search/search-rpc/src/main/java/cn/iocoder/mall/search/biz/rpc/user/ProductSearchRPCImpl.java new file mode 100644 index 000000000..129068bdf --- /dev/null +++ b/search/search-rpc/src/main/java/cn/iocoder/mall/search/biz/rpc/user/ProductSearchRPCImpl.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.search.biz.rpc.user; + +import cn.iocoder.common.framework.vo.CommonResult; +import cn.iocoder.mall.search.biz.api.user.ProductSearchRPC; +import cn.iocoder.mall.search.biz.service.ProductSearchService; +import org.apache.dubbo.config.annotation.Service; +import org.springframework.beans.factory.annotation.Autowired; + + +@Service(validation = "true", version = "${dubbo.provider.ProductSearchRpc.version}") +public class ProductSearchRPCImpl implements ProductSearchRPC { + + @Autowired + private ProductSearchService productSearchService; + + @Override + public CommonResult rebuild() { + return null; + } + + @Override + public CommonResult save(Integer id){ +// ProductSpuDetailBO productSpuDetail = productSpuService.getProductSpuDetail(spuId); +// return ProductSpuConvert.INSTANCE.convertDetail(productSpuDetail); + return CommonResult.success(true); + } + + +} diff --git a/search/search-rpc/src/main/resources/rpc-local.yaml b/search/search-rpc/src/main/resources/rpc-local.yaml new file mode 100644 index 000000000..e056170af --- /dev/null +++ b/search/search-rpc/src/main/resources/rpc-local.yaml @@ -0,0 +1,14 @@ +spring: + # Spring Cloud 配置项 + cloud: + nacos: + # Spring Cloud Nacos Discovery 配置项 + discovery: + server-addr: s1.iocoder.cn:8848 # Nacos 服务器地址 + namespace: local # Nacos 命名空间 + +# Dubbo 配置项 +dubbo: + # Dubbo 注册中心 + registry: + address: spring-cloud://s1.iocoder.cn:8848 # 指定 Dubbo 服务注册中心的地址 diff --git a/search/search-rpc/src/main/resources/rpc-test.yaml b/search/search-rpc/src/main/resources/rpc-test.yaml new file mode 100644 index 000000000..d3d0e9e69 --- /dev/null +++ b/search/search-rpc/src/main/resources/rpc-test.yaml @@ -0,0 +1,14 @@ +spring: + # Spring Cloud 配置项 + cloud: + nacos: + # Spring Cloud Nacos Discovery 配置项 + discovery: + server-addr: s1.iocoder.cn:8848 # Nacos 服务器地址 + namespace: test # Nacos 命名空间 + +# Dubbo 配置项 +dubbo: + # Dubbo 注册中心 + registry: + address: spring-cloud://s1.iocoder.cn:8848 # 指定 Dubbo 服务注册中心的地址 diff --git a/search/search-rpc/src/main/resources/rpc.yaml b/search/search-rpc/src/main/resources/rpc.yaml new file mode 100644 index 000000000..398fbf430 --- /dev/null +++ b/search/search-rpc/src/main/resources/rpc.yaml @@ -0,0 +1,22 @@ +# Dubbo 配置项 +dubbo: + # Spring Cloud Alibaba Dubbo 专属配置 + cloud: + subscribed-services: 'search-application' # 设置订阅的应用列表,默认为 * 订阅所有应用 + # Dubbo 提供者的协议 + protocol: + name: dubbo + port: -1 + # Dubbo 提供服务的扫描基础包 + scan: + base-packages: cn.iocoder.mall.search.rpc.rpc + # Dubbo 服务提供者的配置 + provider: +# filter: -exception +# ProductSpuService: +# version: 1.0.0 + + # Dubbo 服务消费者的配置 + consumer: +# ProductSpuService: +# version: 1.0.0 diff --git a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/ProductSearchService.java b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/ProductSearchService.java index ca4f714a0..6d4bbf1d6 100644 --- a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/ProductSearchService.java +++ b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/ProductSearchService.java @@ -1,9 +1,9 @@ -package cn.iocoder.mall.search.api; +package cn.iocoder.mall.search.biz; -import cn.iocoder.mall.search.api.bo.ProductConditionBO; -import cn.iocoder.mall.search.api.bo.ProductPageBO; -import cn.iocoder.mall.search.api.dto.ProductConditionDTO; -import cn.iocoder.mall.search.api.dto.ProductSearchPageDTO; +import cn.iocoder.mall.search.biz.bo.ProductConditionBO; +import cn.iocoder.mall.search.biz.bo.ProductPageBO; +import cn.iocoder.mall.search.biz.dto.ProductConditionDTO; +import cn.iocoder.mall.search.biz.dto.ProductSearchPageDTO; public interface ProductSearchService { diff --git a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductBO.java b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductBO.java index acaa15fce..7ba301041 100644 --- a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductBO.java +++ b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductBO.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.api.bo; +package cn.iocoder.mall.search.biz.bo; import lombok.Data; import lombok.experimental.Accessors; diff --git a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductConditionBO.java b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductConditionBO.java index 238b0dbb2..b8eebbfe6 100644 --- a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductConditionBO.java +++ b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductConditionBO.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.api.bo; +package cn.iocoder.mall.search.biz.bo; import lombok.Data; import lombok.experimental.Accessors; diff --git a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductPageBO.java b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductPageBO.java index b18871a53..827b7996f 100644 --- a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductPageBO.java +++ b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/bo/ProductPageBO.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.api.bo; +package cn.iocoder.mall.search.biz.bo; import lombok.Data; import lombok.experimental.Accessors; diff --git a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductConditionDTO.java b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductConditionDTO.java index ff1d54c0b..4bfe0fead 100644 --- a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductConditionDTO.java +++ b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductConditionDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.api.dto; +package cn.iocoder.mall.search.biz.dto; import lombok.Data; import lombok.experimental.Accessors; diff --git a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductSearchPageDTO.java b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductSearchPageDTO.java index bfc465bd1..430a32ed0 100644 --- a/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductSearchPageDTO.java +++ b/search/search-service-api/src/main/java/cn/iocoder/mall/search/api/dto/ProductSearchPageDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.api.dto; +package cn.iocoder.mall.search.biz.dto; import cn.iocoder.common.framework.util.CollectionUtil; import cn.iocoder.common.framework.vo.SortingField; diff --git a/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java b/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java index ed239635d..6a42e33ca 100644 --- a/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java +++ b/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/convert/ProductSearchConvert.java @@ -3,7 +3,7 @@ package cn.iocoder.mall.search.biz.convert; import cn.iocoder.mall.order.api.bo.CalcSkuPriceBO; import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO; import cn.iocoder.mall.promotion.api.bo.PromotionActivityBO; -import cn.iocoder.mall.search.api.bo.ProductBO; +import cn.iocoder.mall.search.biz.bo.ProductBO; import cn.iocoder.mall.search.biz.dataobject.ESProductDO; import org.mapstruct.Mapper; import org.mapstruct.Mappings; diff --git a/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/mq/PayTransactionPaySuccessConsumer.java b/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/mq/PayTransactionPaySuccessConsumer.java index 81d4fa6e9..d2b3156e2 100644 --- a/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/mq/PayTransactionPaySuccessConsumer.java +++ b/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/mq/PayTransactionPaySuccessConsumer.java @@ -1,7 +1,7 @@ package cn.iocoder.mall.search.biz.mq; import cn.iocoder.mall.product.api.message.ProductUpdateMessage; -import cn.iocoder.mall.search.api.ProductSearchService; +import cn.iocoder.mall.search.biz.ProductSearchService; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.springframework.beans.factory.annotation.Autowired; diff --git a/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java b/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java index 1a787a8a2..1adda27c5 100644 --- a/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java +++ b/search/search-service-impl/src/main/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImpl.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.biz.service; +package cn.iocoder.mall.search.biz.api; import cn.iocoder.common.framework.util.CollectionUtil; import cn.iocoder.common.framework.util.StringUtil; @@ -9,11 +9,11 @@ import cn.iocoder.mall.product.api.ProductCategoryService; import cn.iocoder.mall.product.api.ProductSpuService; import cn.iocoder.mall.product.api.bo.ProductCategoryBO; import cn.iocoder.mall.product.api.bo.ProductSpuDetailBO; -import cn.iocoder.mall.search.api.ProductSearchService; -import cn.iocoder.mall.search.api.bo.ProductConditionBO; -import cn.iocoder.mall.search.api.bo.ProductPageBO; -import cn.iocoder.mall.search.api.dto.ProductConditionDTO; -import cn.iocoder.mall.search.api.dto.ProductSearchPageDTO; +import cn.iocoder.mall.search.biz.ProductSearchService; +import cn.iocoder.mall.search.biz.bo.ProductConditionBO; +import cn.iocoder.mall.search.biz.bo.ProductPageBO; +import cn.iocoder.mall.search.biz.dto.ProductConditionDTO; +import cn.iocoder.mall.search.biz.dto.ProductSearchPageDTO; import cn.iocoder.mall.search.biz.convert.ProductSearchConvert; import cn.iocoder.mall.search.biz.dao.ProductRepository; import cn.iocoder.mall.search.biz.dataobject.ESProductDO; diff --git a/search/search-service-impl/src/test/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImplTest.java b/search/search-service-impl/src/test/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImplTest.java index 440478552..06ffc3b2f 100644 --- a/search/search-service-impl/src/test/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImplTest.java +++ b/search/search-service-impl/src/test/java/cn/iocoder/mall/search/biz/service/ProductSearchServiceImplTest.java @@ -1,4 +1,4 @@ -package cn.iocoder.mall.search.biz.service; +package cn.iocoder.mall.search.biz.api; import cn.iocoder.mall.search.biz.dao.ProductRepository; import org.junit.Test; diff --git a/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java b/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java index eb632381f..69a0e2956 100644 --- a/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java +++ b/system/system-biz-api/src/main/java/cn/iocoder/mall/system/biz/enums/SystemErrorCodeEnum.java @@ -7,7 +7,7 @@ import cn.iocoder.common.framework.util.ServiceExceptionUtil; * * system 系统,使用 1-002-000-000 段 */ -public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable { +public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable { // ========== OAUTH2 模块 ========== OAUTH2_UNKNOWN(1001001000, "未知错误"), // 预留 @@ -113,8 +113,16 @@ public enum SystemErrorCodeEnum implements ServiceExceptionUtil.Enumerable { return code; } + @Override public String getMessage() { return message; } + // TODO: 2020-05-22 封装成start的时候,直接在start中定义一个统一的枚举,从中取值; + @Override + public int getGroup() { + return 0; + } + + } diff --git a/system/system-biz/pom.xml b/system/system-biz/pom.xml index 2375b2c26..6f2ee0145 100644 --- a/system/system-biz/pom.xml +++ b/system/system-biz/pom.xml @@ -85,6 +85,22 @@ fastjson + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework + spring-webmvc + compile + + + javax.servlet + servlet-api + compile + + diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/systemlog/AccessLogBO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/systemlog/AccessLogBO.java index c423596f5..ad2f62595 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/systemlog/AccessLogBO.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/bo/systemlog/AccessLogBO.java @@ -6,7 +6,7 @@ import lombok.experimental.Accessors; import java.io.Serializable; import java.util.Date; -/** +/** // TODO FROM 芋艿 to 2447007062:最好加下字段的注释哈; * @author:mac * @descriptio * @create: 2020-5-12 20:43:00 diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/config/ServiceExceptionConfiguration.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/config/ServiceExceptionConfiguration.java index 50400ee5b..56d69ca98 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/config/ServiceExceptionConfiguration.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/config/ServiceExceptionConfiguration.java @@ -20,11 +20,12 @@ public class ServiceExceptionConfiguration { @EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html public void initMessages() { - List list = errorCodeService.getErrorCodeList(); + errorCodeService.deleteSyStemErrorCode(SystemErrorCodeEnum.ADMIN_NOT_FOUND.getGroup()); + errorCodeService.addSystemErrorCodeList(SystemErrorCodeEnum.values()); for (SystemErrorCodeEnum item : SystemErrorCodeEnum.values()) { ServiceExceptionUtil.put(item.getCode(), item.getMessage()); } - for (ErrorCodeBO bo : list) { + for (ErrorCodeBO bo : errorCodeService.getErrorCodeByGroup(SystemErrorCodeEnum.ADMIN_NOT_FOUND.getGroup())) { ServiceExceptionUtil.put(bo.getCode(),bo.getMessage()); } } diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/errorcode/ErrorCodeMapper.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/errorcode/ErrorCodeMapper.java index 1fd45cc24..5314e8e79 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/errorcode/ErrorCodeMapper.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/errorcode/ErrorCodeMapper.java @@ -2,12 +2,14 @@ package cn.iocoder.mall.system.biz.dao.errorcode; import cn.iocoder.mall.mybatis.query.QueryWrapperX; import cn.iocoder.mall.system.biz.dataobject.authorization.RoleDO; +import cn.iocoder.mall.system.biz.dataobject.authorization.RoleResourceDO; import cn.iocoder.mall.system.biz.dataobject.errorcode.ErrorCodeDO; import cn.iocoder.mall.system.biz.dto.authorization.RolePageDTO; import cn.iocoder.mall.system.biz.dto.errorcode.ErrorCodeDTO; import cn.iocoder.mall.system.biz.dto.errorcode.ErrorCodePageDTO; import cn.iocoder.mall.system.biz.enums.SystemErrorCodeEnum; import cn.iocoder.mall.system.biz.enums.errorcode.ErrorCodeTypeEnum; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -42,4 +44,9 @@ public interface ErrorCodeMapper extends BaseMapper { default List selectByGroup(Integer group) { return selectList(new QueryWrapperX().eqIfPresent("group", group)); } + + + default int deleteSyStemErrorCode(int group){ + return delete(new QueryWrapper().eq("group", group)); + } } diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/user/UserMapper.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/user/UserMapper.java index 3cac873f8..fc636771f 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/user/UserMapper.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dao/user/UserMapper.java @@ -1,5 +1,7 @@ package cn.iocoder.mall.system.biz.dao.user; +import cn.iocoder.mall.mybatis.query.QueryWrapperX; +import cn.iocoder.mall.system.biz.dataobject.authorization.RoleDO; import cn.iocoder.mall.system.biz.dataobject.user.UserDO; import cn.iocoder.mall.system.biz.dto.user.UserPageDTO; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -25,12 +27,11 @@ public interface UserMapper extends BaseMapper { * @return */ default IPage selectUserPage(UserPageDTO userPageDTO) { - // TODO FROM 芋艿 to jwf1173:看下 QueryWrapperX 噢,已经提供判空啦 - // TODO FROM 伟帆 to 芋艿: 这里是使用MP原生的判空,支持lambda好,还是使用QueryWrapperX,使用字段名字符串的好呢 + // TODO FROM 芋艿 to jwf1173:看下 QueryWrapperX 噢,已经提供判空啦 [DONE] return this.selectPage(new Page<>(userPageDTO.getPageNo(), userPageDTO.getPageSize()), - Wrappers.query().lambda() - .eq(StringUtils.isNotBlank(userPageDTO.getNickname()), UserDO::getNickname, userPageDTO.getNickname()) - .eq(null != userPageDTO.getStatus(), UserDO::getStatus, userPageDTO.getStatus()) + new QueryWrapperX() + .eq(StringUtils.isNotBlank(userPageDTO.getNickname()), "nickname", userPageDTO.getNickname()) + .eq(null != userPageDTO.getStatus(), "status", userPageDTO.getStatus()) ); } diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/system/AccessLogPageDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/system/AccessLogPageDTO.java index 4af88b553..6e7a6fe85 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/system/AccessLogPageDTO.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/dto/system/AccessLogPageDTO.java @@ -4,14 +4,13 @@ import lombok.Data; import lombok.experimental.Accessors; import javax.validation.constraints.NotNull; -import java.util.Date; /** * 访问日志添加 DTO */ @Data @Accessors(chain = true) -public class AccessLogPageDTO { +public class AccessLogPageDTO { // TODO FROM 芋艿 to 2447007062:有个 PageParams 类哈,可以继承 /** diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/annotation/OperationLogging.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/annotation/OperationLogging.java new file mode 100644 index 000000000..db597757f --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/annotation/OperationLogging.java @@ -0,0 +1,20 @@ +package cn.iocoder.mall.system.biz.log.operation.annotation; + +import java.lang.annotation.*; + +/** + * @author Hccake + * @version 1.0 + * @date 2019/10/15 18:09 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface OperationLogging { + + /** + * 日志信息 + * @return + */ + String value(); +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/aspect/OperationLogAspect.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/aspect/OperationLogAspect.java new file mode 100644 index 000000000..a89b1f2e4 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/aspect/OperationLogAspect.java @@ -0,0 +1,118 @@ +package cn.iocoder.mall.system.biz.log.operation.aspect; + +import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.URLUtil; +import cn.hutool.json.JSONUtil; +import cn.iocoder.common.framework.util.HttpUtil; +import cn.iocoder.common.framework.util.MallUtil; +import cn.iocoder.mall.system.biz.log.operation.annotation.OperationLogging; +import cn.iocoder.mall.system.biz.log.operation.enums.LogStatus; +import cn.iocoder.mall.system.biz.log.operation.event.OperationLogEvent; +import cn.iocoder.mall.system.biz.log.operation.model.dto.OperationLogDTO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.core.annotation.Order; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * @author Hccake + * @version 1.0 + * @date 2019/10/15 18:16 + */ +@Slf4j +@Aspect +@Order(0) +@RequiredArgsConstructor +public class OperationLogAspect { + private final ApplicationEventPublisher publisher; + + @Around("@annotation(operationLogging)") + public Object around(ProceedingJoinPoint joinPoint, OperationLogging operationLogging) throws Throwable { + Signature signature = joinPoint.getSignature(); + String strClassName = joinPoint.getTarget().getClass().getName(); + String strMethodName = signature.getName(); + log.debug("[类名]:{},[方法]:{}", strClassName, strMethodName); + + // 获取日志 + OperationLogDTO operationLogDTO = prodOperationLog(); + operationLogDTO.setMsg(operationLogging.value()); + // 记录参数 + MethodSignature methodSignature = (MethodSignature) signature; + operationLogDTO.setParams(getParams(joinPoint, methodSignature)); + // 开始时间 + long startTime = System.currentTimeMillis(); + Object result; + try { + result = joinPoint.proceed(); + } catch (Throwable throwable) { + operationLogDTO.setStatus(LogStatus.FAIL.getValue()); + throw throwable; + } + // 结束时间 + operationLogDTO.setResponseTime((int) (System.currentTimeMillis() - startTime)); + // 发布事件 + publisher.publishEvent(new OperationLogEvent(operationLogDTO)); + + return result; + } + + + /** + * 获取方法参数 + * @param joinPoint joinPoint + * @param methodSignature 方法签名 + * @return 方法参数的Json字符串形式 + */ + private String getParams(ProceedingJoinPoint joinPoint, MethodSignature methodSignature) { + String[] parameterNames = methodSignature.getParameterNames(); + Object[] args = joinPoint.getArgs(); + if(ArrayUtil.isEmpty(parameterNames)){ + return null; + } + Map paramsMap = new HashMap<>(); + for (int i = 0; i < parameterNames.length; i++) { + paramsMap.put(parameterNames[i], args[i]); + } + return JSONUtil.toJsonStr(paramsMap); + } + + + /** + * 根据请求生成操作日志 + * @return 操作日志DTO + */ + private OperationLogDTO prodOperationLog() { + HttpServletRequest request = ((ServletRequestAttributes) Objects + .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest(); + + return new OperationLogDTO() + .setTraceId(MallUtil.getTraceId()) + .setUri(URLUtil.getPath(request.getRequestURI())) + .setUserAgent(HttpUtil.getUserAgent(request)) + .setIp(HttpUtil.getIp(request)) + .setMethod(request.getMethod()) + // TODO 获取管理员用户名 或者 用户ID + // .setOperator(Objects.requireNonNull(LogUtils.getUsername())) + .setStatus(LogStatus.SUCCESS.getValue()); + } + + + + + + + + +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/enums/LogStatus.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/enums/LogStatus.java new file mode 100644 index 000000000..c6a6ae5d9 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/enums/LogStatus.java @@ -0,0 +1,27 @@ +package cn.iocoder.mall.system.biz.log.operation.enums; + +/** + * @author Hccake + * @version 1.0 + * @date 2020/5/15 14:47 + */ +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 操作状态 + */ +@Getter +@AllArgsConstructor +public enum LogStatus { + /** + * 成功 + */ + SUCCESS(1), + /** + * 失败 + */ + FAIL(0); + + private final int value; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/event/OperationLogEvent.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/event/OperationLogEvent.java new file mode 100644 index 000000000..40051f3a6 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/event/OperationLogEvent.java @@ -0,0 +1,15 @@ +package cn.iocoder.mall.system.biz.log.operation.event; + +import cn.iocoder.mall.system.biz.log.operation.model.dto.OperationLogDTO; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author + * 系统日志事件 + */ +@Getter +@AllArgsConstructor +public class OperationLogEvent { + private final OperationLogDTO operationLogDTO; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/event/OperationLogListener.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/event/OperationLogListener.java new file mode 100644 index 000000000..2a41ef616 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/event/OperationLogListener.java @@ -0,0 +1,26 @@ +package cn.iocoder.mall.system.biz.log.operation.event; + +import cn.iocoder.mall.system.biz.log.operation.service.OperationLogSaveService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.core.annotation.Order; +import org.springframework.scheduling.annotation.Async; + +/** + * @author + * 异步监听日志事件 + */ +@Slf4j +public class OperationLogListener { + + @Autowired + private OperationLogSaveService operationLogSaveService; + + @Async + @Order + @EventListener(OperationLogEvent.class) + public void saveSysLog(OperationLogEvent event) { + operationLogSaveService.saveLog(event.getOperationLogDTO()); + } +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/model/dto/OperationLogDTO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/model/dto/OperationLogDTO.java new file mode 100644 index 000000000..dd675d12c --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/model/dto/OperationLogDTO.java @@ -0,0 +1,87 @@ +package cn.iocoder.mall.system.biz.log.operation.model.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.time.LocalDateTime; + +/** + * 操作日志 + * + * @author hccake + * @date 2020-05-15 15:12:53 + */ +@Data +@Accessors(chain = true) +@ApiModel(value = "操作日志") +public class OperationLogDTO{ + private static final long serialVersionUID = 1L; + + /** + * 链路追踪编号 + */ + @ApiModelProperty(value = "链路追踪编号") + private String traceId; + /** + * 账号编号 + */ + @ApiModelProperty(value = "账号编号") + private Integer accountId; + /** + * 应用名 + */ + @ApiModelProperty(value = "应用名") + private String applicationName; + /** + * 访问地址 + */ + @ApiModelProperty(value = "访问地址") + private String uri; + /** + * 参数 + */ + @ApiModelProperty(value = "参数") + private String params; + /** + * http 方法 + */ + @ApiModelProperty(value = "http 方法") + private String method; + /** + * userAgent + */ + @ApiModelProperty(value = "userAgent") + private String userAgent; + /** + * ip + */ + @ApiModelProperty(value = "ip") + private String ip; + /** + * 请求时间 + */ + @ApiModelProperty(value = "请求时间") + private LocalDateTime startTime; + /** + * 响应时长 -- 毫秒级 + */ + @ApiModelProperty(value = "响应时长 -- 毫秒级") + private Integer responseTime; + /** + * 日志消息 + */ + @ApiModelProperty(value = "日志消息") + private String msg; + /** + * 操作状态 + */ + @ApiModelProperty(value = "操作状态") + private Integer status; + /** + * 创建者 + */ + @ApiModelProperty(value = "创建者") + private String operator; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/model/po/OperationLogPO.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/model/po/OperationLogPO.java new file mode 100644 index 000000000..a6e348630 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/model/po/OperationLogPO.java @@ -0,0 +1,89 @@ +package cn.iocoder.mall.system.biz.log.operation.model.po; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.annotations.ApiModel; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.time.LocalDateTime; + +/** + * 操作日志 + * + * @author hccake + * @date 2020-05-15 15:12:53 + */ +@Data +@TableName("operation_log") +@EqualsAndHashCode(callSuper = true) +@ApiModel(value = "操作日志") +public class OperationLogPO extends Model { + private static final long serialVersionUID = 1L; + + /** + * 编号 + */ + @TableId + private Integer id; + /** + * 链路追踪编号 + */ + private String traceId; + /** + * 账号编号 + */ + private Integer accountId; + /** + * 应用名 + */ + private String applicationName; + /** + * 访问地址 + */ + private String uri; + /** + * 参数 + */ + private String params; + /** + * http 方法 + */ + private String method; + /** + * userAgent + */ + private String userAgent; + /** + * ip + */ + private String ip; + /** + * 请求时间 + */ + private LocalDateTime startTime; + /** + * 响应时长 -- 毫秒级 + */ + private Integer responseTime; + /** + * 日志消息 + */ + private String msg; + /** + * 操作状态 + */ + private Integer status; + /** + * 创建者 + */ + private String operator; + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/service/OperationLogSaveService.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/service/OperationLogSaveService.java new file mode 100644 index 000000000..159d85691 --- /dev/null +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/log/operation/service/OperationLogSaveService.java @@ -0,0 +1,20 @@ +package cn.iocoder.mall.system.biz.log.operation.service; + + +import cn.iocoder.mall.system.biz.log.operation.model.dto.OperationLogDTO; + +/** + * 操作日志业务类 + * @author Hccake + * @version 1.0 + * @date 2019/10/15 19:57 + */ +public interface OperationLogSaveService { + + /** + * 保存操作日志 + * @param operationLogDTO + * @return true/false + */ + boolean saveLog(OperationLogDTO operationLogDTO); +} diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeService.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeService.java index 9a355de6e..d69a5ee39 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeService.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeService.java @@ -1,5 +1,6 @@ package cn.iocoder.mall.system.biz.service.errorcode; +import cn.iocoder.common.framework.util.ServiceExceptionUtil; import cn.iocoder.common.framework.vo.PageResult; import cn.iocoder.mall.system.biz.bo.errorcode.ErrorCodeBO; import cn.iocoder.mall.system.biz.dataobject.errorcode.ErrorCodeDO; @@ -53,6 +54,13 @@ public interface ErrorCodeService extends IService{ */ Boolean addErrorCodeList(List list); + /** + * 批量添加错误码信息,项目启动时初始化错误码信息。 + * @param enumerable 错误码枚举类 + * @return 是否成功 + */ + Boolean addSystemErrorCodeList(ServiceExceptionUtil.Enumerable[] enumerable); + /** * 更新错误码,系统内置错误码是不允许更新 * @param errorCodeUpdateDTO 错误码信息 @@ -64,4 +72,10 @@ public interface ErrorCodeService extends IService{ * @param errorCodeDeleteDTO 只允许删除自定义错误码 */ void deleteErrorCode(ErrorCodeDeleteDTO errorCodeDeleteDTO); + + /** + * 删除分组下的错误码,只提供给服务初始化时候 + * @param group 分组 + */ + void deleteSyStemErrorCode(int group); } diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeServiceImpl.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeServiceImpl.java index c41404780..ad1dffaa9 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeServiceImpl.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/errorcode/ErrorCodeServiceImpl.java @@ -85,6 +85,21 @@ public class ErrorCodeServiceImpl extends ServiceImpl doList = new ArrayList<>(); + for (ServiceExceptionUtil.Enumerable errorCodeEnum : enumerable){ + ErrorCodeDO errorCode = new ErrorCodeDO().setCode(errorCodeEnum.getCode()). + setMessage(errorCodeEnum.getMessage()).setType(ErrorCodeTypeEnum.SYSTEM.getType()) + .setGroup(errorCodeEnum.getGroup()); + errorCode.setCreateTime(new Date()); + errorCode.setDeleted(DeletedStatusEnum.DELETED_NO.getValue()); + doList.add(errorCode); + } + // TODO 插入操作日志 + return this.saveBatch(doList); + } + @Override public void updateErrorCode(ErrorCodeUpdateDTO errorCodeUpdateDTO) { // 校验错误码是否存在 @@ -118,8 +133,12 @@ public class ErrorCodeServiceImpl extends ServiceImpl mobileList, String sign, String templateCode, String template, Map templateParams) { - // 最大发送数为 1000,我们设置为 500 个, 分段发送 int maxSendSize = MAX_BATCH_SIZE; int maxSendSizeCount = mobileList.size() % maxSendSize == 0 ? mobileList.size() / maxSendSize : mobileList.size() / maxSendSize + 1; - + // 处理批量 SendResult sendResult = null; for (int i = 0; i < maxSendSizeCount; i++) { // 分批发送 List batchSendMobile = mobileList .subList(i * maxSendSize, (i + 1) * maxSendSize); - // params CommonRequest request = new CommonRequest(); request.setMethod(MethodType.POST); @@ -111,7 +108,6 @@ public class AliYunSmsClient implements SmsClient { request.putQueryParameter("SignNameJson", JSON.toJSONString(Collections.singletonList(sign))); request.putQueryParameter("TemplateCode", templateCode); request.putQueryParameter("TemplateParamJson", JSON.toJSONString(Collections.singletonList(templateParams))); - // 发送请求 sendResult = doSend(request); } @@ -125,9 +121,7 @@ public class AliYunSmsClient implements SmsClient { CommonResponse response = client.getCommonResponse(request); Result result = JSON.parseObject(response.getData(), Result.class); if (!SUCCESS_CODE.equals(result.getCode())) { - LOGGER.info("发送验证码失败 params {} res {}", JSON.toJSON(request), JSON.toJSON(result)); - // 错误发送失败 return new SendResult() .setIsSuccess(false) @@ -135,7 +129,6 @@ public class AliYunSmsClient implements SmsClient { .setMessage(result.getMessage()); } else { LOGGER.info("发送验证码失败 params {} res", JSON.toJSON(request), JSON.toJSON(result)); - // 发送成功 return new SendResult() .setIsSuccess(true) diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java index 83ce9159a..820650686 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/SmsServiceImpl.java @@ -23,6 +23,7 @@ import cn.iocoder.mall.system.biz.dto.smsTemplate.ListSmsTemplateDTO; import cn.iocoder.mall.system.biz.enums.SystemErrorCodeEnum; import cn.iocoder.mall.system.biz.enums.sms.SmsApplyStatusEnum; import cn.iocoder.mall.system.biz.enums.sms.SmsPlatformEnum; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -70,16 +71,14 @@ public class SmsServiceImpl implements SmsService { @Override public PageResult listSmsTemplate(ListSmsTemplateDTO listSmsTemplateDTO) { + // 获取 template IPage signPage = smsTemplateMapper.listSmsTemplate(listSmsTemplateDTO); - - List templateList - = SmsTemplateConvert.INSTANCE.convert(signPage.getRecords()); - - if (CollectionUtils.isEmpty(templateList)) { + if (CollectionUtils.isEmpty(signPage.getRecords())) { // TODO DOME FROM 芋艿 to 小范,Collections.EMPTY_LIST =》Collections.emptyList();另外,可以考虑直接 Convert 哈 return new PageResult().setList(Collections.emptyList()).setTotal(signPage.getTotal()); } - + // 转换bo + List templateList = SmsTemplateConvert.INSTANCE.convert(signPage.getRecords()); // 获取 sign Set smsSignIds = templateList.stream().map( ListSmsTemplateBO::getSmsSignId).collect(Collectors.toSet()); @@ -88,37 +87,32 @@ public class SmsServiceImpl implements SmsService { new QueryWrapper().in("id", smsSignIds)); List signList = SmsTemplateConvert.INSTANCE.convertTemplateSign(smsSignDOList); - + // sign 转换为 map Map smsSignDOMap = signList .stream().collect(Collectors.toMap(ListSmsTemplateBO.Sign::getId, o -> o)); - // 设置 sign - templateList.forEach(template -> { if (smsSignDOMap.containsKey(template.getSmsSignId())) { template.setSign(smsSignDOMap.get(template.getSmsSignId())); } }); - return new PageResult().setList(templateList).setTotal(signPage.getTotal()); } @Override @Transactional public void addSign(AddSignDTO addSignDTO) { - // 避免重复 SmsSignDO smsSignDO = smsSignMapper.selectOne( new QueryWrapper() .eq("platform", addSignDTO.getPlatform()) .eq("sign", addSignDTO.getSign()) ); - + // 处理 null 情况 if (smsSignDO != null) { // TODO DOME FROM 芋艿 to 小范:可以使用 ServiceExceptionUtil.exception(SystemErrorCodeEnum.SMS_SIGN_IS_EXISTENT); throw ServiceExceptionUtil.exception(SystemErrorCodeEnum.SMS_SIGN_IS_EXISTENT); } - // 保存数据库 smsSignMapper.insert( (SmsSignDO) new SmsSignDO() @@ -133,16 +127,17 @@ public class SmsServiceImpl implements SmsService { @Override public SmsSignBO getSign(Integer signId) { + // 查询数据库 SmsSignDO smsSignDO = smsSignMapper.selectOne( new QueryWrapper() .eq("id", signId) .eq("deleted", DeletedStatusEnum.DELETED_NO.getValue())); - + // 处理 null if (smsSignDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } - + // 转换vo返回 return SmsSignConvert.INSTANCE.convert(smsSignDO); } @@ -154,12 +149,11 @@ public class SmsServiceImpl implements SmsService { new QueryWrapper() .eq("sign", updateSignDTO.getSign()) .eq("platform", updateSignDTO.getPlatform())); - + // 处理 null if (smsSignDO != null) { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_IS_EXISTENT.getMessage()); } - // 更新 smsSignMapper.update( (SmsSignDO) new SmsSignDO() @@ -172,15 +166,13 @@ public class SmsServiceImpl implements SmsService { @Override public void deleteSign(Integer id) { - SmsSignDO smsSignDO = smsSignMapper.selectOne( - new QueryWrapper() - .eq("id", id)); - + // 根据id查询 + SmsSignDO smsSignDO = smsSignMapper.selectById(id); + // 处理 null if (smsSignDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } - // 更新 deleted 为 YES smsSignMapper.delete(new UpdateWrapper() .set("deleted", DeletedStatusEnum.DELETED_YES.getName()) @@ -192,15 +184,13 @@ public class SmsServiceImpl implements SmsService { @Transactional public void addTemplate(Integer smsSignId, String templateCode, String template, Integer platform, Integer smsType) { - - SmsSignDO smsSignDO = smsSignMapper.selectOne( - new QueryWrapper().eq("id", smsSignId)); - + // 根据id查询 + SmsSignDO smsSignDO = smsSignMapper.selectById(smsSignId); + // 处理 null if (smsSignDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } - // 保存数据库 smsTemplateMapper.insert( (SmsTemplateDO) new SmsTemplateDO() @@ -219,16 +209,17 @@ public class SmsServiceImpl implements SmsService { @Override public SmsTemplateBO getTemplate(Integer id, Integer platform) { + // 获取数据 SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( new QueryWrapper() .eq("platform", platform) .eq("id", id)); - + // 处理 null if (smsTemplateDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); } - + // 转换bo返回 return SmsTemplateConvert.INSTANCE.convert(smsTemplateDO); } @@ -236,22 +227,20 @@ public class SmsServiceImpl implements SmsService { @Transactional public void updateTemplate(Integer id, Integer smsSignId, String templateCode, String template, Integer platform, Integer smsType) { - SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( - new QueryWrapper().eq("id", id)); - + // 获取 template + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectById(id); if (smsTemplateDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); } - + // 获取 sign SmsSignDO smsSignDO = smsSignMapper.selectOne( new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); - if (smsSignDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } - + // 更新数据库 smsTemplateMapper.update( (SmsTemplateDO) new SmsTemplateDO() .setSmsSignId(smsSignId) @@ -269,13 +258,12 @@ public class SmsServiceImpl implements SmsService { public void deleteTemplate(Integer id) { SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( new QueryWrapper().eq("id", id)); - + // 处理不存在情况 if (smsTemplateDO == null || smsTemplateDO.getDeleted().equals(DeletedStatusEnum.DELETED_YES.getValue())) { throw new ServiceException(SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); } - // 删除 数据库模板 SmsTemplateDO updateTemplate =new SmsTemplateDO(); updateTemplate.setDeleted(DeletedStatusEnum.DELETED_YES.getValue()); @@ -287,29 +275,24 @@ public class SmsServiceImpl implements SmsService { @Override public void singleSend(String mobile, Integer smsTemplateId, Map params) { - SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( - new QueryWrapper().eq("id", smsTemplateId)); - + // 获取 template + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectById(smsTemplateId); if (smsTemplateDO == null || smsTemplateDO.getDeleted().equals(DeletedStatusEnum.DELETED_YES.getValue())) { throw new ServiceException(SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); } - - SmsSignDO smsSignDO = smsSignMapper.selectOne( - new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); - + // 获取 sign + SmsSignDO smsSignDO = smsSignMapper.selectById(smsTemplateDO.getSmsSignId()); if (smsSignDO == null) { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } - // 获取 client SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform()); // 发送短信 SmsClient.SendResult sendResult = smsClient.singleSend(mobile, smsSignDO.getSign(), smsTemplateDO.getTemplateCode(), smsTemplateDO.getTemplate(), params); - // 添加日志 smsSendMapper.insert( (SmsSendLogDO) new SmsSendLogDO() @@ -322,18 +305,15 @@ public class SmsServiceImpl implements SmsService { @Override public void batchSend(List mobileList, Integer smsTemplateId, Map params) { - SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectOne( - new QueryWrapper().eq("id", smsTemplateId)); - + // 获取 template + SmsTemplateDO smsTemplateDO = smsTemplateMapper.selectById(smsTemplateId); if (smsTemplateDO == null || smsTemplateDO.getDeleted().equals(DeletedStatusEnum.DELETED_YES.getValue())) { throw new ServiceException(SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_TEMPLATE_NOT_EXISTENT.getMessage()); } - - SmsSignDO smsSignDO = smsSignMapper.selectOne( - new QueryWrapper().eq("id", smsTemplateDO.getSmsSignId())); - + // 获取 sign + SmsSignDO smsSignDO = smsSignMapper.selectById(smsTemplateDO.getSmsSignId()); if (smsSignDO == null) { // 添加日志 smsSendMapper.insert( @@ -347,14 +327,11 @@ public class SmsServiceImpl implements SmsService { throw new ServiceException(SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getCode(), SystemErrorCodeEnum.SMS_SIGN_NOT_EXISTENT.getMessage()); } - // 获取 client SmsClient smsClient = getSmsClient(smsTemplateDO.getPlatform()); - // 发送短信 SmsClient.SendResult sendResult = smsClient.batchSend(mobileList, smsSignDO.getSign(), smsTemplateDO.getTemplateCode(), smsTemplateDO.getTemplate(), params); - // 添加日志 smsSendMapper.insert( (SmsSendLogDO) new SmsSendLogDO() @@ -373,18 +350,18 @@ public class SmsServiceImpl implements SmsService { */ private SmsClient getSmsClient(Integer platform) { SmsClient smsClient = null; + // 阿里云和云片 if (SmsPlatformEnum.YunPian.getValue().equals(platform)) { smsClient = smsYunPianClient; } else if (SmsPlatformEnum.AliYun.getValue().equals(platform)) { smsClient = smsAliYunClient; } - + // 没有支持的平台 if (smsClient == null) { throw new ServiceException( SystemErrorCodeEnum.SMS_NOT_SEND_CLIENT.getCode(), SystemErrorCodeEnum.SMS_NOT_SEND_CLIENT.getMessage()); } - return smsClient; } } diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/YunPianSmsClient.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/YunPianSmsClient.java index b1778ff16..749264bb2 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/YunPianSmsClient.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/sms/YunPianSmsClient.java @@ -88,7 +88,6 @@ public class YunPianSmsClient implements SmsClient { */ private static final String URL_SEND_BATCH = "https://sms.yunpian.com/v2/sms/batch_send.json"; - //编码格式。发送编码格式统一用UTF-8 private static String ENCODING = "UTF-8"; @@ -99,7 +98,6 @@ public class YunPianSmsClient implements SmsClient { public SendResult singleSend(String mobile, String sign, String templateCode, String template, Map templateParams) { // build 模板 template = buildTemplate(sign, template, templateParams); - // 请求参数 Map params = new LinkedHashMap<>(); params.put("apikey", apiKey); @@ -114,7 +112,7 @@ public class YunPianSmsClient implements SmsClient { throw new ServiceException(SystemErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(), jsonObject.getString("detail")); } - + // 转换 result return new SendResult() .setIsSuccess(SUCCESS_CODE == jsonObject.getInteger("code")) .setCode(jsonObject.getInteger("code")) @@ -127,7 +125,6 @@ public class YunPianSmsClient implements SmsClient { Map templateParams) { // build 模板 template = buildTemplate(sign, template, templateParams); - // 最大发送数为 1000,我们设置为 500 个, 分段发送 int maxSendSize = MAX_BATCH_SIZE; int maxSendSizeCount = mobileList.size() % maxSendSize == 0 @@ -142,9 +139,7 @@ public class YunPianSmsClient implements SmsClient { sendMobileStr.append(","); sendMobileStr.append(mobileList.get(k)); } - String dividedMobile = sendMobileStr.toString().substring(1); - // 发送手机号 Map params = new LinkedHashMap<>(); params.put("apikey", apiKey); @@ -159,12 +154,10 @@ public class YunPianSmsClient implements SmsClient { throw new ServiceException(SystemErrorCodeEnum.SMS_PLATFORM_FAIL.getCode(), jsonObject.getString("detail")); } - // 用于递增 maxSendSize j = j2; j2 = j + maxSendSize; } - return new SendResult() .setIsSuccess(true) .setCode(SUCCESS_CODE) @@ -181,18 +174,17 @@ public class YunPianSmsClient implements SmsClient { */ private static String buildTemplate(String sign, String template, Map templateParams) { - + // 不处理 empty 数据 if (CollectionUtils.isEmpty(templateParams)) { return template; } - + // 处理template参数 for (Map.Entry entry : templateParams.entrySet()) { String paramsKey = entry.getKey(); String value = entry.getValue(); String paramPlace = String.format(PARAM_TEMPLATE, paramsKey); template = template.replaceAll(paramPlace, value); } - template = String.format(SIGN_TEMPLATE, sign, template); return template; } @@ -234,7 +226,6 @@ public class YunPianSmsClient implements SmsClient { e.printStackTrace(); } } - LOGGER.debug("云片短信平台 res: {}", responseText); return responseText; } diff --git a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/systemlog/SystemLogServiceImpl.java b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/systemlog/SystemLogServiceImpl.java index 85c86f71d..769f4e5c2 100644 --- a/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/systemlog/SystemLogServiceImpl.java +++ b/system/system-biz/src/main/java/cn/iocoder/mall/system/biz/service/systemlog/SystemLogServiceImpl.java @@ -48,7 +48,7 @@ public class SystemLogServiceImpl implements SystemLogService { @SuppressWarnings("Duplicates") public PageResult getAccessLogPage(AccessLogPageDTO accessLogPageDTO) { PageResult accessLogPageBOPageResult = SystemLogConvert.INSTANCE.convertPage( - accessLogMapper.selectPage(accessLogPageDTO)); + accessLogMapper.selectPage(accessLogPageDTO)); // TODO FROM 芋艿 to 2447007062:可以考虑直接 return,简洁 + IDEA 不告警; return accessLogPageBOPageResult; } } diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/systemlog/SystemLogController.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/systemlog/SystemLogController.java index 5f7a1d471..096fa19ec 100644 --- a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/systemlog/SystemLogController.java +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/controller/systemlog/SystemLogController.java @@ -41,7 +41,8 @@ public class SystemLogController { @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) { - + // TODO FROM 芋艿 to 2447007062:不要留这么大的空行; + // TODO FROM 芋艿 to 2447007062:使用 Request 接收参数噢; AccessLogPageDTO accessLogPageDTO = new AccessLogPageDTO().setAccountId(accountId) .setPageNo(pageNo).setPageSize(pageSize); // 查询分页 diff --git a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/systemlog/AccessLogConvert.java b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/systemlog/AccessLogConvert.java index a07b36c4e..e5f20cf7b 100644 --- a/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/systemlog/AccessLogConvert.java +++ b/system/system-rest/src/main/java/cn/iocoder/mall/system/rest/convert/systemlog/AccessLogConvert.java @@ -19,7 +19,7 @@ public interface AccessLogConvert { AccessLogConvert INSTANCE = Mappers.getMapper(AccessLogConvert.class); - @Mappings({}) + @Mappings({}) // TODO FROM 芋艿 to 2447007062:注意空行哟;另外,如果不需要专门 mapping,可以不添加该注解,嘿嘿。 PageResult convert(PageResult result); diff --git a/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/enums/UserErrorCodeEnum.java b/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/enums/UserErrorCodeEnum.java index 6a8279aba..10ce8d339 100644 --- a/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/enums/UserErrorCodeEnum.java +++ b/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/enums/UserErrorCodeEnum.java @@ -35,4 +35,9 @@ public enum UserErrorCodeEnum implements ServiceExceptionUtil.Enumerable { return message; } + @Override + public int getGroup() { + return 0; + } + } diff --git a/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/service/user/UserAddressServiceImpl.java b/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/service/user/UserAddressServiceImpl.java index 90627bc28..dee915614 100644 --- a/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/service/user/UserAddressServiceImpl.java +++ b/user/user-biz/src/main/java/cn/iocoder/mall/user/biz/service/user/UserAddressServiceImpl.java @@ -32,12 +32,10 @@ public class UserAddressServiceImpl implements UserAddressService { @Override @Transactional public void addAddress(UserAddressAddDTO userAddressAddDTO) { - // 转换do,设置默认数据 UsersUserAddressDO userAddressDO = UserAddressConvert.INSTANCE.convert(userAddressAddDTO); userAddressDO.setCreateTime(new Date()); userAddressDO.setDeleted(DeletedStatusEnum.DELETED_NO.getValue()); - // 检查是否设置为默认地址 if (UserAddressHasDefaultEnum.DEFAULT_ADDRESS_YES.getValue() == userAddressAddDTO.getHasDefault()) { UsersUserAddressDO defaultUserAddress = userAddressMapper.selectHasDefault(userAddressAddDTO.getUserId()); @@ -49,7 +47,6 @@ public class UserAddressServiceImpl implements UserAddressService { ); } } - // 保存地址 userAddressMapper.insert(userAddressDO); } @@ -57,19 +54,15 @@ public class UserAddressServiceImpl implements UserAddressService { @Override @Transactional public void updateAddress(UserAddressUpdateDTO userAddressAddDTO) { - // 检查地址 UsersUserAddressDO userAddress = userAddressMapper.selectById(userAddressAddDTO.getId()); - if (userAddress == null) { throw ServiceExceptionUtil.exception(UserErrorCodeEnum.USER_ADDRESS_NOT_EXISTENT.getCode()); } - // 删除的地址不能更新 if (DeletedStatusEnum.DELETED_YES.getValue().equals(userAddress.getDeleted())) { throw ServiceExceptionUtil.exception(UserErrorCodeEnum.USER_ADDRESS_IS_DELETED.getCode()); } - // 检查是否设置为默认地址 // 是:将数据库 default address 设置为 no if (UserAddressHasDefaultEnum.DEFAULT_ADDRESS_YES.getValue() == userAddressAddDTO.getHasDefault()) { @@ -82,7 +75,6 @@ public class UserAddressServiceImpl implements UserAddressService { ); } } - // 转换 vo, 并保存数据 UsersUserAddressDO userAddressDO = UserAddressConvert.INSTANCE.convert(userAddressAddDTO); userAddressDO.setUpdateTime(new Date()); @@ -93,16 +85,13 @@ public class UserAddressServiceImpl implements UserAddressService { public void removeAddress(Integer userId, Integer addressId) { // checked address is exists. UsersUserAddressDO userAddress = userAddressMapper.selectById(addressId); - if (userAddress == null) { throw ServiceExceptionUtil.exception(UserErrorCodeEnum.USER_ADDRESS_NOT_EXISTENT.getCode()); } - if (DeletedStatusEnum.DELETED_YES.getValue().equals(userAddress.getDeleted())) { // skip return; } - // 更新状态为 remove userAddressMapper.updateById( (UsersUserAddressDO) new UsersUserAddressDO() diff --git a/user/user-rpc/src/main/java/cn/iocoder/mall/user/rpc/convert/user/UserAddressRPCConvert.java b/user/user-rpc/src/main/java/cn/iocoder/mall/user/rpc/convert/user/UserAddressRPCConvert.java index 6bda9b153..16056e749 100644 --- a/user/user-rpc/src/main/java/cn/iocoder/mall/user/rpc/convert/user/UserAddressRPCConvert.java +++ b/user/user-rpc/src/main/java/cn/iocoder/mall/user/rpc/convert/user/UserAddressRPCConvert.java @@ -3,7 +3,6 @@ package cn.iocoder.mall.user.rpc.convert.user; import cn.iocoder.mall.user.biz.bo.user.UserAddressBO; import cn.iocoder.mall.user.rpc.response.user.UserAddressResponse; import org.mapstruct.Mapper; -import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; /** @@ -17,7 +16,6 @@ public interface UserAddressRPCConvert { UserAddressRPCConvert INSTANCE = Mappers.getMapper(UserAddressRPCConvert.class); - // TODO DONE FROM 芋艿 to 小范:如果不用映射,可以不用 @Mappings 哈 - @Mappings({}) UserAddressResponse convert(UserAddressBO userAddressBO); + }