错误码分组
This commit is contained in:
commit
76c19d7a75
|
@ -76,6 +76,12 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool 工具集,减少重复开发各种Util-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -30,10 +30,11 @@ public class ServiceExceptionUtil {
|
|||
/**
|
||||
* 错误枚举的接口
|
||||
*/
|
||||
public interface Enumerable {
|
||||
public interface Enumerable<V extends Enum> {
|
||||
|
||||
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 <T> CommonResult<T> error(Enumerable enumerable) {
|
||||
return error(enumerable.getCode());
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
<!-- 工具类相关 -->
|
||||
<fastjson.version>1.2.56</fastjson.version>
|
||||
<hibernate-validator.version>6.0.16.Final</hibernate-validator.version>
|
||||
<hutool.version>5.2.5</hutool.version>
|
||||
<spring-boot-starter-data-jest.version>3.2.5.RELEASE</spring-boot-starter-data-jest.version>
|
||||
</properties>
|
||||
|
||||
<!-- 依赖管理 -->
|
||||
|
@ -141,11 +143,25 @@
|
|||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- hutool 工具类-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 自动化配置 Spring Data Jest -->
|
||||
<dependency>
|
||||
<groupId>com.github.vanroy</groupId>
|
||||
<artifactId>spring-boot-starter-data-jest</artifactId>
|
||||
<version>${spring-boot-starter-data-jest.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
@ -48,6 +48,12 @@
|
|||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- mongodb 相关-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
|
|
|
@ -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<OrderCommentStateInfoPageBO.OrderCommentStateInfoItem> convertOrderCommentStateInfoItems(
|
||||
// List<OrderCommentDO> orderCommentDOList);
|
||||
//
|
||||
// @Mappings({})
|
||||
// OrderCommentDO convertOrderCommentDO(OrderCommentCreateDTO orderCommentCreateDTO);
|
||||
//
|
||||
// @Mappings({})
|
||||
// OrderCommentCreateBO convertOrderCommentCreateBO(OrderCommentDO orderCommentDO);
|
||||
//
|
||||
// @Mappings({})
|
||||
// OrderCommentInfoBO convertOrderCommentInfoBO(OrderCommentDO orderCommentDO);
|
||||
//
|
||||
// @Mappings({})
|
||||
// OrderCommentTimeOutBO convertOrderCommentTimeOutBO(OrderCommentDO orderCommentDO);
|
||||
//
|
||||
// @Mappings({})
|
||||
// List<OrderCommentTimeOutBO> convertOrderCommentTimeOutBOList(
|
||||
// List<OrderCommentDO> orderCommentDOList);
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -6,6 +6,12 @@ spring:
|
|||
username: root
|
||||
password: 3WLiVUBEwTbvAfsh
|
||||
|
||||
#mongodb
|
||||
data:
|
||||
mongodb:
|
||||
uri: mongodb://localhost/order-comment
|
||||
|
||||
|
||||
# MyBatis Plus 配置项
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
|
@ -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<Boolean> add(
|
||||
@RequestBody @Validated UsersOrderCommentAddRequest request) {
|
||||
Integer userId = UserSecurityContextHolder.getContext().getUserId();
|
||||
request.setUserId(userId);
|
||||
|
||||
return CommonResult.success(orderCommentService.addOrderComment(
|
||||
UsersOrderCommentConvert.INSTANCE.convert(request)));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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<OrderCommentCreateBO> 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<OrderCommentPageBO> getOrderCommentPage(@Validated OrderCommentPageDTO orderCommentPageDTO){
|
||||
// return success(orderCommentService.getOrderCommentPage(orderCommentPageDTO));
|
||||
// }
|
||||
//
|
||||
// @GetMapping("order_comment_info_merchant_reply")
|
||||
// @ApiOperation(value = "获取评论和商家回复")
|
||||
// public CommonResult<OrderCommentInfoAndMerchantReplyBO> 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<OrderCommentStateInfoPageBO> getOrderCommentStateInfoPage(@Validated OrderCommentStateInfoPageDTO orderCommentStateInfoPageDTO){
|
||||
// //Integer userId = UserSecurityContextHolder.getContext().getUserId();
|
||||
// //orderCommentStateInfoPageDTO.setUserId(userId);
|
||||
// return success(orderCommentService.getOrderCommentStateInfoPage(orderCommentStateInfoPageDTO));
|
||||
// }
|
||||
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -51,6 +51,11 @@ public enum ProductErrorCodeEnum implements ServiceExceptionUtil.Enumerable {
|
|||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGroup() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCode() {
|
||||
return code;
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -40,15 +40,9 @@ public interface ProductSpuConvert {
|
|||
})
|
||||
ProductSpuBO convert(ProductSpuDO spu);
|
||||
|
||||
@Named("translatePicUrlsFromString")
|
||||
default List<String> translatePicUrlsFromString(String picUrls) {
|
||||
return StringUtil.split(picUrls, ",");
|
||||
}
|
||||
|
||||
@Mappings({})
|
||||
List<ProductSpuBO> convert(List<ProductSpuDO> spus);
|
||||
|
||||
|
||||
@Mappings({
|
||||
@Mapping(source = "picUrls", target = "picUrls", ignore = true)
|
||||
})
|
||||
|
@ -131,4 +125,9 @@ public interface ProductSpuConvert {
|
|||
return spuDetailList;
|
||||
}
|
||||
|
||||
@Named("translatePicUrlsFromString")
|
||||
default List<String> translatePicUrlsFromString(String picUrls) {
|
||||
return StringUtil.split(picUrls, ",");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<ProductCategoryDO> {
|
||||
|
||||
/**
|
||||
* 查询商品分类的下一级子分类数量
|
||||
* @param productCategoryId
|
||||
* @return
|
||||
*/
|
||||
default Integer selectChildCategoryCount(Integer productCategoryId) {
|
||||
return this.selectCount(
|
||||
Wrappers.<ProductCategoryDO>lambdaQuery().eq(ProductCategoryDO::getPid, productCategoryId)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.List;
|
|||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
// TODO FROM 芋艿 to sunderui && q2118cs:貌似重复了,只要保留一个哈
|
||||
public class ProductSpuAddDTO {
|
||||
|
||||
// ========== 基本信息 =========
|
||||
|
|
|
@ -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.<ProductCategoryDO>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());
|
||||
}
|
||||
// 返回结果
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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<Integer, AdminsProductCategoryTreeNodeResponse> 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<AdminsProductCategoryTreeNodeResponse> 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);
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ public interface BannerMapper extends BaseMapper<BannerDO> {
|
|||
* @param dto
|
||||
* @return
|
||||
*/
|
||||
// TODO FROM 芋艿 to 小范:Page 方法哈
|
||||
default IPage<BannerDO> selectBannerList(BannerListDTO dto) {
|
||||
LambdaQueryWrapper<BannerDO> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (StringUtils.isEmpty(dto.getStatus())) {
|
||||
|
@ -41,4 +42,4 @@ public interface BannerMapper extends BaseMapper<BannerDO> {
|
|||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public interface BannerService {
|
|||
*/
|
||||
void updateBanner(BannerUpdateDTO adminsBannerUpdateDTO);
|
||||
|
||||
// TODO FROM 芋艿 to 小范:貌似要把 dto 搞起来,嘿嘿;
|
||||
/**
|
||||
* 更新 - banner 状态
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -13,8 +13,13 @@
|
|||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>search-application</module>
|
||||
<module>search-service-api</module>
|
||||
<module>search-service-impl</module>
|
||||
<module>search-biz</module>
|
||||
<module>search-biz-api</module>
|
||||
<!-- <module>search-service-api</module>-->
|
||||
<!-- <module>search-service-impl</module>-->
|
||||
<module>search-rpc</module>
|
||||
<module>search-rest</module>
|
||||
<module>search-rpc-api</module>
|
||||
</modules>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
|
@ -15,92 +15,15 @@
|
|||
<!-- Mall 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>common-framework</artifactId>
|
||||
<artifactId>search-rest</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>mall-spring-boot</artifactId>
|
||||
<artifactId>search-rpc</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>user-sdk</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>search-service-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>search-service-impl</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>system-service-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>swagger-bootstrap-ui</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 服务保障相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 监控 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 测试相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 提供给 mapstruct 使用 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<!-- 打包 -->
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<ProductPageBO> 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<ProductConditionBO> 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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>search</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>search-biz-api</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- Mall 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>common-framework</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>search</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>search-biz</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<!-- Mall 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>mall-spring-boot</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<artifactId>search-biz-api</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>product-rpc-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- DB 相关 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-dubbo</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Registry 和 Config 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MQ 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct</artifactId> <!-- use mapstruct-jdk8 for Java 8 or higher -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mapstruct</groupId>
|
||||
<artifactId>mapstruct-jdk8</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- test -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId> <!-- 引入该包,为了写单元测试用 -->
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 自动化配置 Spring Data Jest -->
|
||||
<dependency>
|
||||
<groupId>com.github.vanroy</groupId>
|
||||
<artifactId>spring-boot-starter-data-jest</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- 提供给 mapstruct 使用 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -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<String> 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;
|
||||
|
||||
}
|
|
@ -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<Category> categories;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Category {
|
||||
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<ProductBO> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
|
@ -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 {
|
||||
}
|
|
@ -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";
|
||||
|
||||
}
|
|
@ -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<ProductBO> convert(List<ESProductDO> list);
|
||||
|
||||
}
|
|
@ -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<ESProductDO, Integer> {
|
||||
|
||||
@Deprecated
|
||||
ESProductDO findByName(String name);
|
||||
|
||||
default Page<ESProductDO> search(Integer cid, String keyword, Integer pageNo, Integer pageSize,
|
||||
List<SortingField> 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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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<String> 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;
|
||||
|
||||
}
|
|
@ -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<String> fields;
|
||||
|
||||
}
|
|
@ -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<String> SORT_FIELDS = CollectionUtil.asSet("buyPrice");
|
||||
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer cid;
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
private String keyword;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
private Integer pageNo;
|
||||
/**
|
||||
* 分页大小
|
||||
*/
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 排序字段数组
|
||||
*/
|
||||
private List<SortingField> sorts;
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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<ProductSpuDetailBO> spus = productSpuService.getProductSpuDetailListForSync(lastId, REBUILD_FETCH_PER_SIZE);
|
||||
// rebuildCounts += spus.size();
|
||||
// // 存储到 ES 中
|
||||
// List<ESProductDO> 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<ESProductDO> 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<SortingField> 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<Integer, ProductCategoryBO> 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;
|
||||
// }
|
||||
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,7 @@
|
|||
spring:
|
||||
data:
|
||||
# Jest 配置项
|
||||
jest:
|
||||
uri: http://127.0.0.1:9200
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>search</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>search-rest</artifactId>
|
||||
<description>提供 商品搜索服务的 Rest 接口的实现,提供对外调用</description>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>search-biz</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Web 相关 -->
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>mall-spring-boot-starter-web</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>mall-spring-boot-starter-security</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>mall-spring-boot-starter-swagger</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -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<ProductPageResponse> 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<ProductConditionResponse> 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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<ProductBO> convert(List<ESProductDO> list);
|
||||
|
||||
}
|
|
@ -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<String> fields;
|
||||
|
||||
}
|
|
@ -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<String> SORT_FIELDS = CollectionUtil.asSet("buyPrice");
|
||||
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer cid;
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
private String keyword;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
private Integer pageNo;
|
||||
/**
|
||||
* 分页大小
|
||||
*/
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 排序字段数组
|
||||
*/
|
||||
private List<SortingField> sorts;
|
||||
|
||||
}
|
|
@ -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<Category> categories;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Category {
|
||||
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<ProductResponse> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
|
@ -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<String> 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;
|
||||
|
||||
}
|
|
@ -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
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>search</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>search-rpc-api</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<!--mall-->
|
||||
<dependency>
|
||||
<artifactId>search-biz-api</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>javax.validation</groupId>
|
||||
<artifactId>validation-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,21 @@
|
|||
package cn.iocoder.mall.search.biz.api.user;
|
||||
|
||||
import cn.iocoder.common.framework.vo.CommonResult;
|
||||
|
||||
public interface ProductSearchRPC {
|
||||
|
||||
CommonResult<Integer> rebuild();
|
||||
|
||||
/**
|
||||
* 构建商品的搜索索引
|
||||
*
|
||||
* @param id 商品编号
|
||||
* @return 构建结果
|
||||
*/
|
||||
CommonResult<Boolean> save(Integer id);
|
||||
|
||||
// ProductPageBO getSearchPage(ProductSearchPageDTO searchPageDTO);
|
||||
//
|
||||
// ProductConditionBO getSearchCondition(ProductConditionDTO conditionDTO);
|
||||
|
||||
}
|
|
@ -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<String> fields;
|
||||
|
||||
}
|
|
@ -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<String> SORT_FIELDS = CollectionUtil.asSet("buyPrice");
|
||||
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer cid;
|
||||
/**
|
||||
* 关键字
|
||||
*/
|
||||
private String keyword;
|
||||
|
||||
/**
|
||||
* 页码
|
||||
*/
|
||||
private Integer pageNo;
|
||||
/**
|
||||
* 分页大小
|
||||
*/
|
||||
private Integer pageSize;
|
||||
|
||||
/**
|
||||
* 排序字段数组
|
||||
*/
|
||||
private List<SortingField> sorts;
|
||||
|
||||
}
|
|
@ -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<Category> categories;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public static class Category {
|
||||
|
||||
/**
|
||||
* 分类编号
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 分类名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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<ProductResponse> list;
|
||||
/**
|
||||
* 总量
|
||||
*/
|
||||
private Integer total;
|
||||
|
||||
}
|
|
@ -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<String> 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;
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>search</artifactId>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>search-rpc</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>search-rpc-api</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.mall</groupId>
|
||||
<artifactId>search-biz</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<!-- RPC 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-dubbo</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Registry 和 Config 相关 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 自动化配置 Spring Data Jest -->
|
||||
<dependency>
|
||||
<groupId>com.github.vanroy</groupId>
|
||||
<artifactId>spring-boot-starter-data-jest</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -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<ProductBO> convert(List<ESProductDO> list);
|
||||
|
||||
}
|
|
@ -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<Integer> rebuild() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<Boolean> save(Integer id){
|
||||
// ProductSpuDetailBO productSpuDetail = productSpuService.getProductSpuDetail(spuId);
|
||||
// return ProductSpuConvert.INSTANCE.convertDetail(productSpuDetail);
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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 服务注册中心的地址
|
|
@ -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 服务注册中心的地址
|
|
@ -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
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<SystemErrorCodeEnum> {
|
||||
|
||||
// ========== 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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -85,6 +85,22 @@
|
|||
<artifactId>fastjson</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -20,11 +20,12 @@ public class ServiceExceptionConfiguration {
|
|||
|
||||
@EventListener(ApplicationReadyEvent.class) // 可参考 https://www.cnblogs.com/ssslinppp/p/7607509.html
|
||||
public void initMessages() {
|
||||
List<ErrorCodeBO> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<ErrorCodeDO> {
|
|||
default List<ErrorCodeDO> selectByGroup(Integer group) {
|
||||
return selectList(new QueryWrapperX<ErrorCodeDO>().eqIfPresent("group", group));
|
||||
}
|
||||
|
||||
|
||||
default int deleteSyStemErrorCode(int group){
|
||||
return delete(new QueryWrapper<ErrorCodeDO>().eq("group", group));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<UserDO> {
|
|||
* @return
|
||||
*/
|
||||
default IPage<UserDO> 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.<UserDO>query().lambda()
|
||||
.eq(StringUtils.isNotBlank(userPageDTO.getNickname()), UserDO::getNickname, userPageDTO.getNickname())
|
||||
.eq(null != userPageDTO.getStatus(), UserDO::getStatus, userPageDTO.getStatus())
|
||||
new QueryWrapperX<UserDO>()
|
||||
.eq(StringUtils.isNotBlank(userPageDTO.getNickname()), "nickname", userPageDTO.getNickname())
|
||||
.eq(null != userPageDTO.getStatus(), "status", userPageDTO.getStatus())
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 类哈,可以继承
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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<String, Object> 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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue