Merge branch 'master' into qiuqiu

This commit is contained in:
pikachu 2021-06-26 10:58:57 +08:00
commit 701ea240ab
406 changed files with 7707 additions and 4720 deletions

View File

@ -26,7 +26,7 @@ Lilishop 是一款Java开发基于SpringBoot研发的B2B2C多用户商城
### 文档
**产品文档**需求、架构、使用、部署、开发https://docs.pickmall.cn
**功能清单** 功能列表https://docs.qq.com/sheet/DQ1Z2dWJKUnBRZEt5
### 项目链接(gitee)
@ -194,42 +194,23 @@ PS:单独部署的话数据库文件访问这里https://gitee.com/beijing_
#### 计划每个月发布一个版本,具体时间可能有出入
时间2021年6月15日
```
新增功能:
1.微信小程序直播
2.优惠券活动
3.新人赠券
4.准确发券
5.用户等级
6.数据导出
7.订单批量
8.APP版本升级检测
9.积分商城
功能优化:
1.优惠券有效期增加类型:设置领取后*内有效。
2.秒杀活动设置为每天开启,需设置秒杀活动开启时间。
3.店铺配送模板,配送地区如果选择省份则下方的市级地址不展示。
4.店铺配送模板支持,店铺包邮。
5.普通商品设置去除卖家承担运费。
```
时间2021年7月15日
```
新增功能:
1.会员权益
2.支持用户升级会员
3.供求单
4.IM腾讯云智服
5.服务商品
6.店铺支持订单核销
7.店铺自提点
1.积分商城
2.店铺移动端
3.店铺支持发货单
4.供求单
5.店铺自提点
6.移动端展示附近店铺
7.开屏广告
8.会员站内消息
9.移动端店铺入驻
功能优化:
1.用户分享商城、关注店铺、邀请新用户可获取积分、经验值。
2.隐私管理功能
2.移动端店铺首页优化
```
时间2021年8月16日
@ -237,15 +218,37 @@ PS:单独部署的话数据库文件访问这里https://gitee.com/beijing_
```
新增功能:
1.微淘功能
2.店铺移动端
3.店铺发货单
2.相册管理功能
3.店铺申请品牌
4.第三方商品导入淘宝、99api
5.用户等级
6.用户升级会员
7.会员权益
8.促销活动:第二件*折
9.促销活动:商品打包价
10.促销活动:商品组合购
11.促销活动:进店赠券
12.代客退单
功能优化:
1.批量上传商品分类
2.店铺维护开票项目
3.店铺展示营销中心
```
时间2021年9月15日
```
新增功能:
增加供应商功能
1.增加供应商功能
2.商品预售
3.商品预约
4.电子券码
5.企业会员
6.企业会员购
7.商品批发价
功能优化:
1.店铺运费模板支持按照体积计算
2.店铺支持自定义移动端首页
```
### 版本升级

View File

@ -1,6 +1,8 @@
package cn.lili.controller.goods;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.distribution.service.DistributionService;
@ -20,6 +22,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
@ -37,6 +40,7 @@ import java.util.Map;
* @author Chopper
* @date 2020/11/16 10:06 下午
*/
@Slf4j
@Api(tags = "买家端,商品接口")
@RestController
@RequestMapping("/buyer/goods")
@ -80,12 +84,18 @@ public class GoodsBuyerController {
@PageViewPoint(type = PageViewEnum.SKU, id = "#id")
public ResultMessage<Map<String, Object>> getSku(@NotNull(message = "商品ID不能为空") @PathVariable("goodsId") String goodsId,
@NotNull(message = "SKU ID不能为空") @PathVariable("skuId") String skuId) {
try {
// 读取选中的列表
Map<String, Object> map = goodsSkuService.getGoodsSkuDetail(goodsId, skuId);
return ResultUtil.data(map);
} catch (ServiceException se) {
log.info(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.GOODS_ERROR.message(), e);
return ResultUtil.error(ResultCode.GOODS_ERROR);
}
}
@ApiOperation(value = "获取商品分页列表")

View File

@ -1,8 +1,13 @@
package cn.lili.controller.other;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.utils.PageUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.system.entity.dos.AppVersion;
import cn.lili.modules.system.service.AppVersionService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
@ -33,4 +38,13 @@ public class AppVersionBuyerController {
public ResultMessage<Object> getAppVersion(@PathVariable String appType) {
return ResultUtil.data(appVersionService.getAppVersion(appType));
}
@ApiOperation(value = "获取版本号列表")
@ApiImplicitParam(name = "appType", value = "app类型", required = true, paramType = "path")
@GetMapping("/appVersion/{appType}")
public ResultMessage<IPage<AppVersion>> appVersion(@PathVariable String appType, PageVO pageVO) {
IPage<AppVersion> page = appVersionService.page(PageUtil.initPage(pageVO), new LambdaQueryWrapper<AppVersion>().eq(AppVersion::getType, appType));
return ResultUtil.data(page);
}
}

View File

@ -0,0 +1,48 @@
package cn.lili.controller.other.broadcast;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.broadcast.entity.dos.Studio;
import cn.lili.modules.broadcast.service.StudioService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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.RestController;
/**
* 买家端,直播间接口
*
* @author Bulbasaur
* @date: 2021/5/20 12:03 下午
*/
@RestController
@Api(tags = "买家端,直播间接口")
@RequestMapping("/buyer/broadcast/studio")
public class StudioController {
@Autowired
private StudioService studioService;
@ApiOperation(value = "获取店铺直播间列表")
@ApiImplicitParams({
@ApiImplicitParam(name = "recommend", value = "是否推荐", paramType = "query", dataType = "int"),
@ApiImplicitParam(name = "status", value = "直播间状态", paramType = "query", dataType = "String")
})
@GetMapping
public ResultMessage<IPage<Studio>> page(PageVO pageVO, Integer recommend, String status) {
return ResultUtil.data(studioService.studioList(pageVO, recommend, status));
}
@ApiOperation(value = "获取店铺直播间回放地址")
@GetMapping("/getLiveInfo/{roomId}")
public ResultMessage<Object> getLiveInfo(Integer roomId) {
return ResultUtil.data(studioService.getLiveInfo(roomId));
}
}

View File

@ -17,6 +17,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -30,6 +31,7 @@ import java.io.IOException;
* @author Chopper
* @date 2020-11-25 19:29
*/
@Slf4j
@RestController
@Api(tags = "买家端,web联合登录")
@RequestMapping("/buyer/connect")
@ -93,7 +95,7 @@ public class ConnectBuyerWebController {
try {
return ResultUtil.data(connectService.appLoginCallback(authUser, uuid));
} catch (Exception e) {
e.printStackTrace();
log.error("unionID登录错误",e);
}
return null;
}

View File

@ -2,6 +2,7 @@ package cn.lili.controller.payment;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.payment.kit.CashierSupport;
import cn.lili.modules.payment.kit.dto.PayParam;
@ -12,6 +13,7 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -25,6 +27,7 @@ import javax.servlet.http.HttpServletResponse;
* @author Chopper
* @date 2020-12-18 16:59
*/
@Slf4j
@RestController
@Api(tags = "买家端,收银台接口")
@RequestMapping("/buyer/cashier")
@ -62,8 +65,11 @@ public class CashierController {
try {
return cashierSupport.payment(paymentMethodEnum, paymentClientEnum, request, response, payParam);
} catch (ServiceException se) {
log.info("支付异常", se);
throw se;
} catch (Exception e) {
e.printStackTrace();
log.error("收银台支付错误", e);
}
return null;

View File

@ -17,29 +17,29 @@ import java.util.List;
/**
* 买家端,限时抢购接口
* 买家端,秒杀活动接口
*
* @author paulG
* @date 2020/11/17 2:30 下午
*/
@Api(tags = "买家端,限时抢购接口")
@Api(tags = "买家端,秒杀活动接口")
@RestController
@RequestMapping("/buyer/promotion/seckill")
public class SeckillBuyerController {
/**
* 限时抢购
* 秒杀活动
*/
@Autowired
private SeckillApplyService seckillApplyService;
@ApiOperation(value = "获取当天限时抢购信息")
@ApiOperation(value = "获取当天秒杀活动信息")
@GetMapping
public ResultMessage<List<SeckillTimelineVO>> getSeckillTime() {
return ResultUtil.data(seckillApplyService.getSeckillTimeline());
}
@ApiOperation(value = "获取某个时刻的限时抢购商品信息")
@ApiOperation(value = "获取某个时刻的秒杀活动商品信息")
@GetMapping("/{timeline}")
public ResultMessage<List<SeckillGoodsVO>> getSeckillGoods(@PathVariable Integer timeline) {
return ResultUtil.data(seckillApplyService.getSeckillGoods(timeline));

View File

@ -50,8 +50,17 @@ public class CartController {
public ResultMessage<Object> add(@NotNull(message = "产品id不能为空") String skuId,
@NotNull(message = "购买数量不能为空") @Min(value = 1, message = "加入购物车数量必须大于0") Integer num,
String cartType) {
try {
//读取选中的列表
cartService.add(skuId, num, cartType);
return ResultUtil.success();
} catch (ServiceException se) {
log.info(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.CART_ERROR.message(), e);
throw new ServiceException(ResultCode.CART_ERROR);
}
}
@ -150,8 +159,9 @@ public class CartController {
try {
//读取选中的列表
return ResultUtil.data(this.cartService.getCheckedTradeDTO(CartTypeEnum.valueOf(way)));
} catch (ServiceException e) {
throw e;
} catch (ServiceException se) {
log.error(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.CART_ERROR.message(), e);
throw new ServiceException(ResultCode.CART_ERROR);
@ -193,6 +203,9 @@ public class CartController {
try {
cartService.shippingMethod(selleId, shippingMethod, way);
return ResultUtil.success();
} catch (ServiceException se) {
log.error(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.CART_ERROR.message(), e);
throw new ServiceException(ResultCode.CART_ERROR);
@ -228,8 +241,9 @@ public class CartController {
try {
//读取选中的列表
return ResultUtil.data(this.cartService.createTrade(tradeParams));
} catch (ServiceException e) {
throw e;
} catch (ServiceException se) {
log.info(se.getMsg(), se);
throw se;
} catch (Exception e) {
log.error(ResultCode.ORDER_ERROR.message(), e);
throw new ServiceException(ResultCode.ORDER_ERROR);

View File

@ -4,9 +4,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
@ -153,6 +150,7 @@ ignored:
- /buyer/memberEvaluation/**/goodsEvaluation
- /buyer/memberEvaluation/**/evaluationNumber
- /buyer/appVersion/**
- /buyer/broadcast/studio/**
- /druid/**
- /swagger-ui.html
- /doc.html
@ -262,7 +260,8 @@ lili:
# account:
# username: elastic
# password: LiLiShopES
logstash:
server: 192.168.0.116:4560
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="buyer-api"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="lili-logs"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>127.0.0.1:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@ -5,6 +5,7 @@ import cn.lili.modules.file.plugin.FileManagerPlugin;
import cn.lili.modules.goods.entity.dos.Brand;
import cn.lili.modules.goods.service.BrandService;
import com.xkcoding.http.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@ -19,6 +20,7 @@ import java.util.List;
* @author paulG
* @since 2020/11/14
**/
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest
class FileTest {
@ -43,7 +45,7 @@ class FileTest {
//上传至第三方云服务或服务器
brand.setLogo(fileManagerPlugin.inputStreamUpload(inputStream, brand.getId() + ".png"));
} catch (IOException e) {
e.printStackTrace();
log.error("上传你文件出错",e);
}
}
brandService.updateBatchById(categoryList);

View File

@ -2,9 +2,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:

View File

@ -1,6 +1,7 @@
package cn.lili.controller.common;
import cn.lili.common.aop.limiter.annotation.LimitPoint;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.verification.enums.VerificationEnums;
@ -8,6 +9,7 @@ import cn.lili.common.verification.service.VerificationService;
import cn.lili.common.vo.ResultMessage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@ -17,8 +19,9 @@ import org.springframework.web.bind.annotation.*;
* @author Chopper
* @date 2020/11/26 15:41
*/
@RequestMapping("/common/slider")
@Slf4j
@RestController
@RequestMapping("/common/slider")
@Api(tags = "滑块验证码接口")
public class SliderImageController {
@ -35,8 +38,8 @@ public class SliderImageController {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
return null;
log.error("获取校验接口错误", e);
throw new ServiceException(ResultCode.VERIFICATION_EXIST);
}
}

View File

@ -4,9 +4,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="common-api"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="lili-logs"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- 配置elk日志收集 配饰的是 LOGSTASH 的地址-->
<destination>127.0.0.1:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@ -2,9 +2,6 @@ server:
servlet:
context-path: /
# 正式部署时候,解开此处配置,防止文件夹被清除导致的文件上传失败问题
# multipart:
# location: /Users/lifenlong/Desktop/ceshi
tomcat:
uri-encoding: UTF-8
threads:
@ -80,7 +77,7 @@ spring:
default-datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.0.116:3306/lilishop?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
url: jdbc:mysql://192.168.0.116:3306/Bulbasaur?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: lilishop
maxActive: 20
@ -150,6 +147,7 @@ ignored:
- /buyer/memberEvaluation/**/goodsEvaluation
- /buyer/memberEvaluation/**/evaluationNumber
- /buyer/appVersion/**
- /buyer/broadcast/studio/**
- /store/login/**
- /manager/user/login
- /manager/user/refresh/**
@ -252,7 +250,7 @@ lili:
# jwt 细节设定
jwt-setting:
# token过期时间分钟
tokenExpireTime: 60
tokenExpireTime: 30
# 使用Spring @Cacheable注解失效时间
cache:
@ -276,6 +274,8 @@ lili:
# username: elastic
# password: LiLiShopES
logstash:
server: 192.168.0.116:4560
rocketmq:
promotion-topic: lili_promotion_topic
promotion-group: lili_promotion_group

View File

@ -15,6 +15,8 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 分销订单入库
*
@ -28,7 +30,7 @@ public class DistributionOrderExecute implements OrderStatusChangeEvent, EveryDa
@Autowired
private DistributionOrderService distributionOrderService;
//分销订单持久层
@Autowired
@Resource
private DistributionOrderMapper distributionOrderMapper;

View File

@ -0,0 +1,92 @@
package cn.lili.event.impl;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.ExperienceSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.google.gson.Gson;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 会员经验值
*
* @author Bulbasaur
* @date: 2021/5/16 11:16 下午
*/
@Service
public class MemberExperienceExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent, OrderStatusChangeEvent {
//配置
@Autowired
private SettingService settingService;
//会员
@Autowired
private MemberService memberService;
//订单
@Autowired
private OrderService orderService;
/**
* 会员注册赠送经验值
* @param member 会员
*/
@Override
public void memberRegister(Member member) {
//获取经验值设置
ExperienceSetting experienceSetting = getExperienceSetting();
//赠送会员经验值
memberService.updateMemberExperience(Long.valueOf(experienceSetting.getRegister().longValue()), true, member.getId(), "会员注册,赠送经验值" + experienceSetting.getRegister());
}
/**
* 商品评价赠送经验值
* @param memberEvaluation 会员评价
*/
@Override
public void goodsComment(MemberEvaluation memberEvaluation) {
//获取经验值设置
ExperienceSetting experienceSetting = getExperienceSetting();
//赠送会员经验值
memberService.updateMemberExperience(Long.valueOf(experienceSetting.getComment().longValue()), true, memberEvaluation.getMemberId(), "会员评价,赠送经验值" + experienceSetting.getComment());
}
/**
* 完成订单赠送经验值
* @param orderMessage 订单消息
*/
@Override
public void orderChange(OrderMessage orderMessage) {
if(orderMessage.getNewStatus().equals(OrderStatusEnum.COMPLETED)){
//获取经验值设置
ExperienceSetting experienceSetting = getExperienceSetting();
//获取订单信息
Order order = orderService.getBySn(orderMessage.getOrderSn());
//计算赠送经验值数量
Double point= CurrencyUtil.mul(experienceSetting.getMoney(),order.getFlowPrice(),0);
//赠送会员经验值
memberService.updateMemberExperience(point.longValue(), true, order.getMemberId(), "会员下单,赠送经验值" + point + "");
}
}
/**
* 获取经验值设置
* @return 经验值设置
*/
private ExperienceSetting getExperienceSetting(){
Setting setting = settingService.get(SettingEnum.EXPERIENCE_SETTING.name());
return new Gson().fromJson(setting.getSettingValue(), ExperienceSetting.class);
}
}

View File

@ -1,30 +1,37 @@
package cn.lili.event.impl;
import cn.lili.common.utils.CurrencyUtil;
import cn.lili.event.AfterSaleStatusChangeEvent;
import cn.lili.event.GoodsCommentCompleteEvent;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.service.MemberService;
import cn.lili.modules.member.service.MemberWalletService;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderPromotionTypeEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.PointSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import com.google.gson.Gson;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 会员积分
*
* @author Chopper
* @author Bulbasaur
* @date 2020-07-03 11:20
*/
@Service
public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent {
public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentCompleteEvent, OrderStatusChangeEvent, AfterSaleStatusChangeEvent {
//配置
@Autowired
@ -32,22 +39,80 @@ public class MemberPointExecute implements MemberRegisterEvent, GoodsCommentComp
//会员
@Autowired
private MemberService memberService;
//订单
@Autowired
private OrderService orderService;
/**
* 会员注册赠送积分
* @param member 会员
*/
@Override
public void memberRegister(Member member) {
//获取签到积分赠送设置
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
PointSetting pointSetting = new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
//获取积分设置
PointSetting pointSetting=getPointSetting();
//赠送会员积分
memberService.updateMemberPoint(Long.valueOf(pointSetting.getRegister().longValue()), 1, member.getId(), "会员注册,赠送积分" + pointSetting.getRegister() + "");
memberService.updateMemberPoint(Long.valueOf(pointSetting.getRegister().longValue()), true, member.getId(), "会员注册,赠送积分" + pointSetting.getRegister() + "");
}
/**
* 会员评价赠送积分
* @param memberEvaluation 会员评价
*/
@Override
public void goodsComment(MemberEvaluation memberEvaluation) {
//获取签到积分赠送设置
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
PointSetting pointSetting = new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
//获取积分设置
PointSetting pointSetting=getPointSetting();
//赠送会员积分
memberService.updateMemberPoint(Long.valueOf(pointSetting.getComment().longValue()), 1, memberEvaluation.getMemberId(), "会员评价,赠送积分" + pointSetting.getComment() + "");
memberService.updateMemberPoint(Long.valueOf(pointSetting.getComment().longValue()), true, memberEvaluation.getMemberId(), "会员评价,赠送积分" + pointSetting.getComment() + "");
}
/**
* 非积分订单订单完成后赠送积分
* @param orderMessage 订单消息
*/
@Override
public void orderChange(OrderMessage orderMessage) {
if(orderMessage.getNewStatus().equals(OrderStatusEnum.COMPLETED)){
//根据订单编号获取订单数据,如果为积分订单则跳回
Order order = orderService.getBySn(orderMessage.getOrderSn());
if(order.getOrderPromotionType().equals(OrderPromotionTypeEnum.POINT.name())){
return;
}
//获取积分设置
PointSetting pointSetting=getPointSetting();
//计算赠送积分数量
Double point=CurrencyUtil.mul(pointSetting.getMoney(),order.getFlowPrice(),0);
//赠送会员积分
memberService.updateMemberPoint(point.longValue(), true, order.getMemberId(), "会员下单,赠送积分" + point + "");
}
}
/**
* 提交售后后扣除积分
* @param afterSale 售后
*/
@Override
public void afterSaleStatusChange(AfterSale afterSale) {
if (afterSale.getServiceStatus().equals(AfterSaleStatusEnum.COMPLETE.name())) {
//获取积分设置
PointSetting pointSetting=getPointSetting();
//计算扣除积分数量
Double point=CurrencyUtil.mul(pointSetting.getMoney(), afterSale.getActualRefundPrice(),0);
//扣除会员积分
memberService.updateMemberPoint(point.longValue(), false, afterSale.getMemberId(), "会员退款,扣除积分" + point + "");
}
}
/**
* 获取积分设置
* @return 积分设置
*/
private PointSetting getPointSetting(){
Setting setting = settingService.get(SettingEnum.POINT_SETTING.name());
return new Gson().fromJson(setting.getSettingValue(), PointSetting.class);
}
}

View File

@ -11,12 +11,11 @@ import cn.lili.modules.message.service.NoticeMessageService;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.order.entity.dos.AfterSale;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderTypeEnum;
import cn.lili.modules.order.order.entity.enums.OrderPromotionTypeEnum;
import cn.lili.modules.order.order.entity.vo.OrderDetailVO;
import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.order.trade.entity.enums.AfterSaleStatusEnum;
import cn.lili.modules.order.trade.entity.enums.AfterSaleTypeEnum;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -83,7 +82,7 @@ public class NoticeMessageExecute implements TradeEvent, OrderStatusChangeEvent,
break;
//如果是拼团订单发送拼团成功消息
case UNDELIVERED:
if(orderDetailVO.getOrder().getOrderType().equals(OrderTypeEnum.PINTUAN.name())){
if(orderDetailVO.getOrder().getOrderPromotionType().equals(OrderPromotionTypeEnum.PINTUAN.name())){
//拼团成功消息
noticeMessageDTO.setNoticeMessageNodeEnum(NoticeMessageNodeEnum.PINTUAN_SUCCESS);
}

View File

@ -10,8 +10,6 @@ import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.payment.entity.RefundLog;
import cn.lili.modules.payment.kit.Payment;
import cn.lili.modules.payment.kit.enums.PaymentMethodEnum;
import cn.lili.modules.payment.service.PaymentService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -24,9 +22,6 @@ import org.springframework.stereotype.Service;
@Service
public class PaymentExecute implements OrderStatusChangeEvent {
//支付日志
@Autowired
private PaymentService paymentService;
//订单
@Autowired
private OrderService orderService;

View File

@ -0,0 +1,41 @@
package cn.lili.event.impl;
import cn.lili.event.MemberRegisterEvent;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.promotion.entity.dos.CouponActivity;
import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.service.CouponActivityService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 注册赠券活动
*
* @author Bulbasaur
* @date: 2021/5/24 10:48 上午
*/
@Component
public class RegisteredCouponActivityExecute implements MemberRegisterEvent {
@Autowired
private CouponActivityService couponActivityService;
/**
* 获取进行中的注册赠券的优惠券活动
* 发送注册赠券
*
* @param member 会员
*/
@Override
public void memberRegister(Member member) {
List<CouponActivity> couponActivities = couponActivityService.list(new LambdaQueryWrapper<CouponActivity>()
.eq(CouponActivity::getCouponActivityType, CouponActivityTypeEnum.REGISTERED.name())
.eq(CouponActivity::getPromotionStatus, PromotionStatusEnum.START.name()));
couponActivityService.registered(couponActivities, member);
}
}

View File

@ -0,0 +1,72 @@
package cn.lili.event.impl;
import cn.hutool.core.util.RandomUtil;
import cn.lili.common.utils.CommonUtil;
import cn.lili.event.OrderStatusChangeEvent;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.dto.OrderMessage;
import cn.lili.modules.order.order.entity.enums.OrderComplaintStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderItemAfterSaleStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.service.OrderItemService;
import cn.lili.modules.order.order.service.OrderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 虚拟商品
*
* @author Bulbasaur
* @date: 2021/5/29 9:17 上午
*/
@Component
public class VerificationOrderExecute implements OrderStatusChangeEvent {
@Autowired
private OrderService orderService;
@Autowired
private OrderItemService orderItemService;
@Override
public void orderChange(OrderMessage orderMessage) {
//订单状态为待核验添加订单添加核验码
if (orderMessage.getNewStatus().equals(OrderStatusEnum.TAKE)) {
//获取订单信息
Order order = orderService.getBySn(orderMessage.getOrderSn());
//获取随机数判定是否存在
String code = getCode(order.getStoreId());
//设置订单验证码
orderService.update(new LambdaUpdateWrapper<Order>()
.set(Order::getVerificationCode, code)
.eq(Order::getSn, orderMessage.getOrderSn()));
//修改虚拟订单货物可以进行售后投诉
orderItemService.update(new LambdaUpdateWrapper<OrderItem>().eq(OrderItem::getOrderSn, orderMessage.getOrderSn())
.set(OrderItem::getAfterSaleStatus, OrderItemAfterSaleStatusEnum.NOT_APPLIED)
.set(OrderItem::getCommentStatus, OrderComplaintStatusEnum.NO_APPLY));
}
}
/**
* 获取随机数
* 判断当前店铺下是否使用验证码如果已使用则重新获取
*
* @param storeId 店铺ID
* @return
*/
private String getCode(String storeId) {
//获取八位验证码
String code = Long.toString(RandomUtil.randomLong(10000000, 99999999));
LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<Order>()
.eq(Order::getVerificationCode, code)
.eq(Order::getStoreId, storeId);
if (orderService.getOne(lambdaQueryWrapper) == null) {
return code;
} else {
return this.getCode(storeId);
}
}
}

View File

@ -44,6 +44,7 @@ public class OrderMessageListener implements RocketMQListener<MessageExt> {
case ORDER_CREATE:
String key = new String(messageExt.getBody());
TradeDTO tradeDTO = (TradeDTO) cache.get(key);
boolean result = true;
for (TradeEvent event : tradeEvent) {
try {
event.orderCreate(tradeDTO);
@ -52,8 +53,14 @@ public class OrderMessageListener implements RocketMQListener<MessageExt> {
tradeDTO.getSn(),
event.getClass().getName(),
e);
result = false;
}
}
//如所有步骤顺利完成
if (Boolean.TRUE.equals(result)) {
//清除记录信息的trade cache key
cache.remove(key);
}
break;
//订单状态变更
case STATUS_CHANGE:

View File

@ -44,7 +44,6 @@ public class BillExecute implements EveryDayExecute {
//获取当前时间
DateTime endTime =DateUtil.date();
//批量商家结算
for (StoreSettlementDay storeSettlementDay : storeList) {

View File

@ -0,0 +1,25 @@
package cn.lili.timetask.handler.impl.broadcast;
import cn.lili.modules.broadcast.service.CommodityService;
import cn.lili.timetask.handler.EveryHourExecute;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 小程序直播状态获取
*
* @author Bulbasaur
* @date: 2021/5/20 2:52 下午
*/
@Component
public class BroadcastExecute implements EveryHourExecute {
@Autowired
private CommodityService commodityService;
@Override
public void execute() {
//同步直播商品状态
commodityService.getGoodsWareHouse();
}
}

View File

@ -0,0 +1,80 @@
package cn.lili.timetask.handler.impl.coupon;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.lili.modules.promotion.entity.dos.CouponActivity;
import cn.lili.modules.promotion.entity.enums.CouponActivityTypeEnum;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.service.CouponActivityService;
import cn.lili.timetask.handler.EveryMinuteExecute;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* 优惠券活动状态监测
*
* @author Bulbasaur
* @date: 2021/5/24 10:08 上午
*/
@Component
public class CouponActivityExecute implements EveryMinuteExecute {
@Autowired
private CouponActivityService couponActivityService;
@Override
public void execute() {
//精确发券活动
specify();
//注册赠券的活动
registered();
}
/**
* 监测精确发券活动
* 达到活动时间发送优惠券
*/
private void specify(){
DateTime dateTime=DateUtil.date();
List<CouponActivity> couponActivities=couponActivityService.list(new LambdaQueryWrapper<CouponActivity>()
.eq(CouponActivity::getCouponActivityType, CouponActivityTypeEnum.SPECIFY.name())
.le(CouponActivity::getStartTime, dateTime)
.eq(CouponActivity::getPromotionStatus,PromotionStatusEnum.NEW.name()));
//如果有符合要求的优惠券活动发送优惠券
if(couponActivities.size()>0){
for (CouponActivity couponActivity:couponActivities) {
couponActivityService.specify(couponActivity.getId());
//修改精准发券优惠券活动状态
couponActivityService.update(new LambdaUpdateWrapper<CouponActivity>()
.eq(CouponActivity::getId,couponActivity.getId())
.set(CouponActivity::getPromotionStatus,PromotionStatusEnum.END.name()));
}
}
}
/**
* 注册赠券活动状态监测
*/
private void registered(){
//开启注册赠券优惠券活动
LambdaUpdateWrapper<CouponActivity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
lambdaUpdateWrapper.eq(CouponActivity::getCouponActivityType, CouponActivityTypeEnum.REGISTERED.name())
.eq(CouponActivity::getPromotionStatus, PromotionStatusEnum.NEW.name())
.le(CouponActivity::getStartTime, DateUtil.date())
.set(CouponActivity::getPromotionStatus,PromotionStatusEnum.START.name());
couponActivityService.update(lambdaUpdateWrapper);
//关闭注册赠券优惠券活动
LambdaUpdateWrapper<CouponActivity> endWrapper = new LambdaUpdateWrapper<>();
endWrapper.eq(CouponActivity::getCouponActivityType, CouponActivityTypeEnum.REGISTERED.name())
.eq(CouponActivity::getPromotionStatus, PromotionStatusEnum.START.name())
.le(CouponActivity::getEndTime, DateUtil.date())
.set(CouponActivity::getPromotionStatus,PromotionStatusEnum.END.name());
couponActivityService.update(endWrapper);
}
}

View File

@ -0,0 +1,38 @@
package cn.lili.timetask.handler.impl.coupon;
import cn.hutool.core.date.DateUtil;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.service.MemberCouponService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 优惠券状态监测
*
* @author Bulbasaur
* @date: 2021/5/24 10:08 上午
*/
@Component
public class CouponExecute implements EveryDayExecute {
@Autowired
private MemberCouponService memberCouponService;
/**
* 检测优惠券的使用时间超期未使用则失效
* 此方法用于领取*天后失效优惠券使用
*/
@Override
public void execute() {
LambdaUpdateWrapper<MemberCoupon> updateWrapper = new LambdaUpdateWrapper<MemberCoupon>()
.eq(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.NEW.name())
.le(MemberCoupon::getEndTime, DateUtil.date())
.set(MemberCoupon::getMemberCouponStatus, MemberCouponStatusEnum.EXPIRE.name());
this.memberCouponService.update(updateWrapper);
}
}

View File

@ -39,7 +39,6 @@ public class GoodsExecute implements EveryDayExecute {
new QueryWrapper<MemberEvaluation>()
.between("create_time", DateUtil.yesterday(), new DateTime()));
System.out.println("评论数量" + list.size());
for (Map<String, Object> map : list) {
goodsMapper.addGoodsCommentNum(Integer.parseInt(map.get("num").toString()), map.get("goods_id").toString());
}

View File

@ -3,15 +3,21 @@ package cn.lili.timetask.handler.impl.promotion;
import cn.lili.modules.order.cart.entity.vo.FullDiscountVO;
import cn.lili.modules.promotion.entity.dos.MemberCoupon;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.dos.Seckill;
import cn.lili.modules.promotion.entity.enums.MemberCouponStatusEnum;
import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum;
import cn.lili.modules.promotion.entity.vos.CouponVO;
import cn.lili.modules.promotion.entity.vos.PintuanVO;
import cn.lili.modules.promotion.service.*;
import cn.lili.modules.search.service.EsGoodsIndexService;
import cn.lili.modules.system.entity.dos.Setting;
import cn.lili.modules.system.entity.dto.SeckillSetting;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import cn.lili.timetask.handler.EveryDayExecute;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
@ -55,6 +61,13 @@ public class PromotionEverydayExecute implements EveryDayExecute {
@Autowired
private PromotionGoodsService promotionGoodsService;
//系统设置
@Autowired
private SettingService settingService;
//秒杀活动
@Autowired
private SeckillService seckillService;
/**
* 将已过期的促销活动置为结束
@ -69,53 +82,27 @@ public class PromotionEverydayExecute implements EveryDayExecute {
//结束条件 活动结束时间大于当前时间
query.addCriteria(Criteria.where("endTime").lt(new Date()));
try {
//关闭满减活动
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
if (!fullDiscountVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
//循环活动 关闭活动
for (FullDiscountVO vo : fullDiscountVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
fullDiscountService.update(this.getUpdatePromotionWrapper(ids));
}
} catch (Exception e) {
log.error("满减活动关闭错误", e);
}
try {
//结束满减活动
endFullDiscount(query);
//关闭拼团活动
List<PintuanVO> pintuanVOS = mongoTemplate.find(query, PintuanVO.class);
if (!pintuanVOS.isEmpty()) {
//准备修改活动的id
List<String> ids = new ArrayList<>();
for (PintuanVO vo : pintuanVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
pintuanService.update(this.getUpdatePromotionWrapper(ids));
//将活动商品对照表进行结束处理
promotionGoodsService.update(this.getUpdatePromotionGoodsWrapper(ids));
}
} catch (Exception e) {
log.error("拼团活动关闭错误", e);
endPintuan(query);
//结束优惠券
endCoupon(query);
//定时创建活动
addSeckill();
}
/**
* 结束优惠券活动
*
* @param query
*/
private void endCoupon(Query query) {
try {
//关闭优惠券活动
List<CouponVO> couponVOS = mongoTemplate.find(query, CouponVO.class);
@ -142,15 +129,87 @@ public class PromotionEverydayExecute implements EveryDayExecute {
} catch (Exception e) {
log.error("优惠券活动关闭错误", e);
}
}
/**
* 结束拼团活动
*
* @param query
*/
private void endPintuan(Query query) {
try {
//关闭拼团活动
List<PintuanVO> pintuanVOS = mongoTemplate.find(query, PintuanVO.class);
if (!pintuanVOS.isEmpty()) {
//准备修改活动的id
List<String> ids = new ArrayList<>();
for (PintuanVO vo : pintuanVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
pintuanService.update(this.getUpdatePromotionWrapper(ids));
//将活动商品对照表进行结束处理
promotionGoodsService.update(this.getUpdatePromotionGoodsWrapper(ids));
}
} catch (Exception e) {
log.error("拼团活动关闭错误", e);
}
}
/**
* 结束满减活动
*
* @param query
*/
private void endFullDiscount(Query query) {
try {
//关闭满减活动
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
if (!fullDiscountVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
//循环活动 关闭活动
for (FullDiscountVO vo : fullDiscountVOS) {
vo.setPromotionStatus(PromotionStatusEnum.END.name());
if (vo.getPromotionGoodsList() != null && !vo.getPromotionGoodsList().isEmpty()) {
for (PromotionGoods promotionGoods : vo.getPromotionGoodsList()) {
promotionGoods.setPromotionStatus(PromotionStatusEnum.END.name());
esGoodsIndexService.deleteEsGoodsPromotionByPromotionId(promotionGoods.getSkuId(), vo.getId());
}
}
mongoTemplate.save(vo);
ids.add(vo.getId());
}
fullDiscountService.update(this.getUpdatePromotionWrapper(ids));
}
} catch (Exception e) {
log.error("满减活动关闭错误", e);
}
}
/**
* 添加秒杀活动
* 从系统设置中获取秒杀活动的配置
* 添加30天后的秒杀活动
*/
private void addSeckill() {
Setting setting = settingService.get(SettingEnum.SECKILL_SETTING.name());
SeckillSetting seckillSetting = new Gson().fromJson(setting.getSettingValue(), SeckillSetting.class);
Seckill seckill = new Seckill(30, seckillSetting.getHours(), seckillSetting.getSeckillRule());
seckillService.saveSeckill(seckill);
}
/**
* 获取促销修改查询条件 修改活动状态
*
* @param ids
* @return
* @param ids 促销活动ID
* @return 促销活动商品查询Wrapper
*/
private UpdateWrapper getUpdatePromotionWrapper(List<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
@ -162,8 +221,8 @@ public class PromotionEverydayExecute implements EveryDayExecute {
/**
* 获取商品的促销修改查询条件 修改商品状态
*
* @param ids
* @return
* @param ids 促销活动ID
* @return 促销活动商品修改Wrapper
*/
private UpdateWrapper getUpdatePromotionGoodsWrapper(List<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();

View File

@ -186,7 +186,6 @@ class PageViewStatistics {
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);
this.date = calendar.getTime();
System.out.println(DateUtil.toString(date,DateUtil.STANDARD_FORMAT));
}
}

View File

@ -0,0 +1,36 @@
package cn.lili.trigger.executor;
import cn.hutool.json.JSONUtil;
import cn.lili.common.delayqueue.BroadcastMessage;
import cn.lili.common.trigger.model.TimeExecuteConstant;
import cn.lili.modules.broadcast.service.StudioService;
import cn.lili.trigger.TimeTriggerExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* 直播间事件触发
*
* @author Bulbasaur
* @date: 2021/6/1 5:02 下午
*/
@Slf4j
@Component(TimeExecuteConstant.BROADCAST_EXECUTOR)
public class BroadcastTimeTriggerExecutor implements TimeTriggerExecutor {
@Autowired
private StudioService studioService;
@Override
public void execute(Object object) {
//直播间订单消息
BroadcastMessage broadcastMessage = JSONUtil.toBean(JSONUtil.parseObj(object), BroadcastMessage.class);
if (broadcastMessage != null && broadcastMessage.getStudioId() != null) {
log.info("直播间消费:{}", broadcastMessage);
//修改直播间状态
studioService.updateStudioStatus(broadcastMessage);
}
}
}

View File

@ -29,6 +29,6 @@ public class PromotionDelayQueueListen extends AbstractDelayQueueListen {
@Override
public String setDelayQueueName() {
return DelayQueueEnums.PROMOTION_QUEUE.name();
return DelayQueueEnums.PROMOTION.name();
}
}

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration>
<configuration>
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
<!--应用名称-->
<property name="APP_NAME" value="consumer"/>
<!--日志文件保存路径-->
<property name="LOG_FILE_PATH" value="lili-logs"/>
<contextName>${APP_NAME}</contextName>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>30</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--输出到elk的LOGSTASH-->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<!-- 配置elk日志收集 配饰的是 LOGSTASH 的地址-->
<destination>192.168.0.116:4560</destination>
<encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
</providers>
<!--自定义字段 区分项目-->
<customFields>{"appName":"${APP_NAME}"}</customFields>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>
</configuration>

View File

@ -45,47 +45,16 @@
<de.codecentric>2.3.1</de.codecentric>
<userAgentUtils>1.21</userAgentUtils>
<interceptor-api>1.2</interceptor-api>
<poi-version>4.1.2</poi-version>
<poi-ooxml-version>4.1.2</poi-ooxml-version>
<logstash-logback-encoder>6.6</logstash-logback-encoder>
<zxing>3.4.1</zxing>
<slf4j-api>1.7.28</slf4j-api>
<xk-time>2.2.0</xk-time>
<commons-text>1.4</commons-text>
</properties>
<dependencies>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>${interceptor-api}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${de.codecentric}</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.28</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.github.xkzhangsan</groupId>
<artifactId>xk-time</artifactId>
<version>2.2.0</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-thymeleaf</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
@ -356,23 +325,11 @@
<artifactId>simple-http</artifactId>
<version>${simple-http-version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.antlr/antlr4-runtime -->
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${antlr4-runtime-version}</version>
</dependency>
<!-- http client -->
<!-- <dependency>-->
<!-- <groupId>org.apache.httpcomponents</groupId>-->
<!-- <artifactId>httpclient</artifactId>-->
<!-- <version>${httpclient-version}</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>com.squareup.okhttp3</groupId>-->
<!-- <artifactId>okhttp</artifactId>-->
<!-- <version>${okhttp-version}</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
@ -385,8 +342,54 @@
<artifactId>UserAgentUtils</artifactId>
<version>${userAgentUtils}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>${poi-version}</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>${poi-ooxml-version}</version>
</dependency>
<!--集成logstash-->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>${logstash-logback-encoder}</version>
</dependency>
<dependency>
<groupId>javax.interceptor</groupId>
<artifactId>javax.interceptor-api</artifactId>
<version>${interceptor-api}</version>
</dependency>
<dependency>
<groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId>
<version>${de.codecentric}</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${zxing}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${zxing}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api}</version>
</dependency>
<!-- 开源多维码生成工具 -->
<dependency>
<groupId>com.github.xkzhangsan</groupId>
<artifactId>xk-time</artifactId>
<version>${xk-time}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>

View File

@ -1,13 +1,12 @@
package cn.lili.common.aop.limiter;
import cn.lili.common.aop.limiter.annotation.LimitPoint;
import cn.lili.common.exception.ServiceException;
import com.google.common.collect.ImmutableList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
@ -17,10 +16,10 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.lang.reflect.Method;
/**
* 流量拦截
*
* @author Chopper
*/
@Aspect
@ -41,46 +40,44 @@ public class LimitInterceptor {
this.limitScript = limitScript;
}
@Around("execution(public * *(..)) && @annotation(cn.lili.common.aop.limiter.annotation.LimitPoint)")
public Object interceptor(ProceedingJoinPoint pjp) {
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
LimitPoint limitPointAnnotation = method.getAnnotation(LimitPoint.class);
@Before("@annotation(limitPointAnnotation)")
public void interceptor(LimitPoint limitPointAnnotation) {
LimitType limitType = limitPointAnnotation.limitType();
String name = limitPointAnnotation.name();
String key;
int limitPeriod = limitPointAnnotation.period();
int limitCount = limitPointAnnotation.limit();
switch (limitType) {
case IP:
key = limitPointAnnotation.key() + getIpAddress();
break;
case CUSTOMER:
key = limitPointAnnotation.key();
break;
default:
key = StringUtils.upperCase(method.getName());
key = limitPointAnnotation.key() + getIpAddress();
}
ImmutableList<String> keys = ImmutableList.of(StringUtils.join(limitPointAnnotation.prefix(), key));
try {
Number count = redisTemplate.execute(limitScript, keys, limitCount, limitPeriod);
log.info("Access try count is {} for name={} and key = {}", count, name, key);
if (count != null && count.intValue() <= limitCount) {
return pjp.proceed();
} else {
throw new RuntimeException("访问过于频繁,请稍后再试");
log.info("限制请求{}, 当前请求{},缓存key{}", limitCount, count.intValue(), key);
//如果缓存里没有值或者他的值小于限制频率
if (count.intValue() >= limitCount) {
throw new ServiceException("访问过于频繁,请稍后再试");
}
} catch (Throwable e) {
if (e instanceof RuntimeException) {
throw new RuntimeException(e.getLocalizedMessage());
}
//如果从redis中执行都值判定为空则这里跳过
catch (NullPointerException e) {
return;
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("服务器异常,请稍后再试");
}
}
//默认unknown常量值
private static final String UNKNOWN = "unknown";
//获取ip
public String getIpAddress() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String ip = request.getHeader("x-forwarded-for");

View File

@ -219,7 +219,7 @@ public enum CachePrefix {
STORE_ID_FULL_DISCOUNT,
/**
* 限时抢购活动缓存key前缀
* 秒杀活动活动缓存key前缀
*/
STORE_ID_SECKILL,

View File

@ -1,6 +1,7 @@
package cn.lili.common.cache.impl;
import cn.lili.common.cache.Cache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
@ -18,6 +19,7 @@ import java.util.function.Consumer;
*
* @author Chopepr
*/
@Slf4j
@Component
public class RedisCache implements Cache {
@ -158,7 +160,7 @@ public class RedisCache implements Cache {
return null;
} catch (IOException e) {
e.printStackTrace();
log.error("scan错误",e);
throw new RuntimeException(e);
}
});

View File

@ -98,7 +98,7 @@ public abstract class BaseElasticsearchService {
log.info(" Indicates whether the requisite number of shard copies were started for each shard in the index before timing out :{}", createIndexResponse.isShardsAcknowledged());
return;
} catch (Exception e) {
e.printStackTrace();
log.error("创建索引错误",e);
throw new ElasticsearchException("创建索引 {" + index + "} 失败:" + e.getMessage());
}
}
@ -420,7 +420,7 @@ public abstract class BaseElasticsearchService {
try {
searchResponse = client.search(searchRequest, COMMON_OPTIONS);
} catch (IOException e) {
e.printStackTrace();
log.error("es 搜索错误",e);
}
return searchResponse;
}

View File

@ -17,7 +17,7 @@ public enum ResultCode {
/**
* 失败返回码
*/
ERROR(400, "失败"),
ERROR(400, "服务器繁忙,请稍后重试"),
/**
* 失败返回码
@ -34,6 +34,7 @@ public enum ResultCode {
*/
WECHAT_CONNECT_NOT_EXIST(1001, "微信联合登录未配置"),
VERIFICATION_EXIST(1002, "验证码服务异常"),
/**
* 分类
*/
@ -50,135 +51,222 @@ public enum ResultCode {
/**
* 商品
*/
GOODS_ERROR(11001, "商品异常,请稍后重试"),
GOODS_NOT_EXIST(11001, "商品已下架"),
GOODS_NAME_ERROR(11002, "商品名称不正确名称应为2-50字符"),
GOODS_UNDER_ERROR(11003, "商品下架失败"),
GOODS_UPPER_ERROR(11004, "商品上架失败"),
GOODS_AUTH_ERROR(11005, "商品审核失败"),
POINT_GOODS_ERROR(11006, "积分商品业务异常,请稍后重试"),
GOODS_SKU_SN_ERROR(11007, "商品SKU编号不能为空"),
GOODS_SKU_PRICE_ERROR(11008, "商品SKU价格不能小于等于0"),
GOODS_SKU_COST_ERROR(11009, "商品SKU成本价不能小于等于0"),
GOODS_SKU_WEIGHT_ERROR(11010, "商品重量不能为负数"),
GOODS_SKU_QUANTITY_ERROR(11011, "商品库存数量不能为负数"),
GOODS_SKU_QUANTITY_NOT_ENOUGH(11011, "商品库存不足"),
/**
* 参数
*/
PARAMETER_SAVE_ERROR(12001, "参数添加失败"),
PARAMETER_UPDATE_ERROR(12002, "参数编辑失败"),
/**
* 规格
*/
SPEC_SAVE_ERROR(13001, "规格修改失败"),
SPEC_UPDATE_ERROR(13002, "规格修改失败"),
SPEC_DELETE_ERROR(13003, "此规格已绑定分类不允许删除"),
/**
* 品牌
*/
BRAND_SAVE_ERROR(14001, "品牌添加失败"),
BRAND_UPDATE_ERROR(14002, "品牌修改失败"),
BRAND_DISABLE_ERROR(14003, "品牌禁用失败"),
BRAND_DELETE_ERROR(14004, "品牌删除失败"),
/**
* 用户
*/
USER_EDIT_SUCCESS(20001, "用户修改成功"),
USER_NOT_EXIST(20002, "用户不存在"),
USER_NOT_LOGIN(20003, "用户未登录"),
USER_AUTH_EXPIRED(20004, "用户已退出,请重新登录"),
USER_AUTHORITY_ERROR(20005, "权限不足"),
USER_CONNECT_LOGIN_ERROR(20006, "未找到登录信息"),
USER_NAME_EXIST(20007, "该用户名已被注册"),
USER_PHONE_EXIST(20008, "该手机号已被注册"),
USER_PHONE_NOT_EXIST(20009, "手机号不存在"),
USER_PASSWORD_ERROR(20010, "密码不正确"),
USER_NOT_PHONE(20011, "非当前用户的手机号"),
USER_CONNECT_ERROR(20012, "联合第三方登录,授权信息错误"),
USER_RECEIPT_REPEAT_ERROR(20013, "会员发票信息重复"),
USER_RECEIPT_NOT_EXIST(20014, "会员发票信息不存在"),
USER_EDIT_ERROR(20015, "用户修改失败"),
USER_OLD_PASSWORD_ERROR(20016, "旧密码不正确"),
USER_COLLECTION_EXIST(2001, "无法重复收藏"),
USER_COLLECTION_EXIST(20017, "无法重复收藏"),
USER_GRADE_IS_DEFAULT(20018, "会员等级为默认会员等级"),
DELETE_EXIST(2001, "无法重复收藏"),
/**
* 权限
*/
PERMISSION_DEPARTMENT_ROLE_ERROR(21001, "角色已绑定部门,请逐个删除"),
PERMISSION_USER_ROLE_ERROR(21002, "角色已绑定管理员,请逐个删除"),
PERMISSION_MENU_ROLE_ERROR(21003, "菜单已绑定角色,请先删除或编辑角色"),
PERMISSION_DEPARTMENT_DELETE_ERROR(21004, "部门已经绑定管理员,请先删除或编辑管理员"),
PERMISSION_BEYOND_TEN(21005, "最多可以设置10个角色"),
/**
* 分销
*/
DISTRIBUTION_CLOSE(22000, "分销功能关闭"),
DISTRIBUTION_NOT_EXIST(22001, "分销员不存在"),
DISTRIBUTION_IS_APPLY(22002, "分销员已申请,无需重复提交"),
DISTRIBUTION_AUDIT_ERROR(22003, "审核分销员失败"),
DISTRIBUTION_RETREAT_ERROR(22004, "分销员清退失败"),
DISTRIBUTION_CASH_NOT_EXIST(22005, "分销员提现记录不存在"),
DISTRIBUTION_GOODS_DOUBLE(22006, "不能重复添加分销商品"),
/**
* 购物车
*/
CART_ERROR(30001, "读取结算页的购物车异常"),
CART_PINTUAN_NOT_EXIST_ERROR(30002, "拼团活动不存在错误"),
CART_PINTUAN_LIMIT_ERROR(30003, "购买数量超过拼团活动限制数量"),
SHIPPING_NOT_APPLY(30005, "购物商品不支持当前收货地址配送"),
/**
* 订单
*/
ORDER_ERROR(31001, "创建订单异常,请稍后重试"),
ORDER_NOT_EXIST(31002, "订单不存在"),
ORDER_DELIVERED_ERROR(31003, "订单状态错误,无法进行确认收货"),
ORDER_UPDATE_PRICE_ERROR(31004, "已支付的订单不能修改金额"),
ORDER_LOGISTICS_ERROR(31005, "物流错误"),
ORDER_DELIVER_ERROR(31006, "物流错误"),
ORDER_NOT_USER(31007, "非当前会员的订单"),
ORDER_TAKE_ERROR(31008, "当前订单无法核销"),
MEMBER_ADDRESS_NOT_EXIST(31009, "订单无收货地址,请先配置收货地址"),
ORDER_DELIVER_NUM_ERROR(31010, "没有待发货的订单"),
ORDER_NOT_SUPPORT_DISTRIBUTION(31011, "购物车中包含不支持配送的商品,请重新选择收货地址,或者重新选择商品"),
ORDER_CAN_NOT_CANCEL(31012, "当前订单状态不可取消"),
/**
* 支付
*/
PAY_UN_WANTED(32000, "当前订单不需要付款,返回订单列表等待系统订单出库即可"),
PAY_SUCCESS(32001, "支付成功"),
PAY_INCONSISTENT_ERROR(32002, "付款金额和应付金额不一致"),
PAY_DOUBLE_ERROR(32003, "订单已支付,不能再次进行支付"),
PAY_CASHIER_ERROR(32004, "收银台信息获取错误"),
PAY_ERROR(32005, "支付业务异常,请稍后重试"),
PAY_BAN(32006, "当前订单不需要付款,请返回订单列表重新操作"),
PAY_PARTIAL_ERROR(32007, "该订单已部分支付,请前往订单中心进行支付"),
PAY_NOT_SUPPORT(32008, "支付暂不支持"),
PAY_CLIENT_TYPE_ERROR(32009, "错误的客户端"),
PAY_POINT_ENOUGH(32010, "积分不足,不能兑换"),
PAY_NOT_EXIST_ORDER(32011, "支付订单不存在"),
CAN_NOT_RECHARGE_WALLET(32012, "不能使用余额进行充值"),
/**
* 售后
*/
AFTER_SALES_NOT_PAY_ERROR(33001, "当前订单未支付,不能申请售后"),
AFTER_SALES_CANCEL_ERROR(33002, "当前售后单无法取消"),
AFTER_SALES_BAN(33003, "订单状态不允许申请售后,请联系平台或商家"),
AFTER_SALES_DOUBLE_ERROR(33004, "售后已审核,无法重复操作"),
AFTER_SALES_LOGISTICS_ERROR(33005, "物流公司错误,请重新选择"),
AFTER_STATUS_ERROR(33006, "售后状态错误,请刷新页面"),
/**
* 投诉
*/
COMPLAINT_ORDER_ITEM_EMPTY_ERROR(33100, "订单不存在"),
COMPLAINT_SKU_EMPTY_ERROR(33101, "商品已下架,如需投诉请联系平台客服"),
COMPLAINT_ERROR(33102, "投诉异常,请稍后重试"),
/**
* 余额
*/
WALLET_NOT_EXIT_ERROR(34000, "钱包不存在,请联系管理员"),
WALLET_INSUFFICIENT(34001, "余额不足以支付订单,请充值!"),
WALLET_WITHDRAWAL_INSUFFICIENT(34002, "可提现金额不足!"),
WALLET_ERROR_INSUFFICIENT(34003, "零钱提现失败!"),
WALLET_REMARK_ERROR(34004, "请填写审核备注!"),
WALLET_APPLY_ERROR(34005, "提现申请异常!"),
/**
@ -195,52 +283,74 @@ public enum ResultCode {
* 优惠券
*/
COUPON_EDIT_STATUS_SUCCESS(41001, "修改状态成功!"),
COUPON_CANCELLATION_SUCCESS(41002, "会员优惠券作废成功"),
COUPON_EXPIRED(41003, "优惠券已使用/已过期,不能使用"),
COUPON_EDIT_STATUS_ERROR(41004, "优惠券修改状态失败!"),
/**
* 拼团
*/
PINTUAN_MANUAL_OPEN_SUCCESS(42001, "手动开启拼团活动成功"),
PINTUAN_MANUAL_CLOSE_SUCCESS(42002, "手动关闭拼团活动成功"),
PINTUAN_ADD_SUCCESS(42003, "添加拼团活动成功"),
PINTUAN_EDIT_SUCCESS(42004, "修改拼团活动成功"),
PINTUAN_DELETE_SUCCESS(42005, "删除拼团活动成功"),
PINTUAN_MANUAL_OPEN_ERROR(42006, "手动开启拼团活动失败"),
PINTUAN_MANUAL_CLOSE_ERROR(42007, "手动关闭拼团活动失败"),
PINTUAN_ADD_ERROR(42008, "添加拼团活动失败"),
PINTUAN_EDIT_ERROR(42009, "修改拼团活动失败"),
PINTUAN_DELETE_ERROR(42010, "删除拼团活动失败"),
/**
* 满额活动
*/
FULL_DISCOUNT_EDIT_SUCCESS(43001, "修改满优惠活动成功"),
FULL_DISCOUNT_EDIT_DELETE(43002, "删除满优惠活动成功"),
/**
* 店铺
*/
STORE_NOT_EXIST(50001, "此店铺不存在"),
STORE_NAME_EXIST_ERROR(50002, "店铺名称已存在!"),
STORE_APPLY_DOUBLE_ERROR(50003, "已有店铺,无需重复申请!"),
/**
* 结算单
*/
BILL_CHECK_ERROR(51001, "只有已出账结算单可以核对"),
BILL_COMPLETE_ERROR(51002, "只有已审核结算单可以支付"),
/**
* 文章
*/
ARTICLE_CATEGORY_NAME_EXIST(60001, "文章分类名称已存在"),
ARTICLE_CATEGORY_PARENT_NOT_EXIST(60002, "文章分类父分类不存在"),
ARTICLE_CATEGORY_BEYOND_TWO(60003, "最多为二级分类,操作失败"),
ARTICLE_CATEGORY_DELETE_ERROR(60004, "该文章分类下存在子分类,不能删除"),
ARTICLE_CATEGORY_HAS_ARTICLE(60005, "该文章分类下存在文章,不能删除"),
ARTICLE_CATEGORY_NO_DELETION(60007, "默认文章分类不能进行删除"),
ARTICLE_NO_DELETION(60008, "默认文章不能进行删除"),
@ -248,8 +358,11 @@ public enum ResultCode {
* 页面
*/
PAGE_NOT_EXIST(61001, "页面不存在"),
PAGE_OPEN_DELETE_ERROR(61002, "当前页面为开启状态,无法删除"),
PAGE_DELETE_ERROR(61003, "当前页面为唯一页面,无法删除"),
PAGE_RELEASE_ERROR(61004, "页面已发布,无需重复提交"),
/**
@ -266,39 +379,49 @@ public enum ResultCode {
* 站内信
*/
NOTICE_NOT_EXIST(80101, "当前消息模板不存在"),
NOTICE_ERROR(80102, "修改站内信异常,请稍后重试"),
/**
* OSS
*/
OSS_NOT_EXIST(80201, "OSS未配置"),
OSS_EXCEPTION(80202, "文件上传失败,请稍后重试"),
/**
* 验证码
*/
VERIFICATION_SEND_SUCCESS(80301, "短信验证码,发送成功"),
VERIFICATION_ERROR(80302, "验证失败"),
VERIFICATION_SMS_ERROR(80303, "短信验证码错误,请重新校验"),
VERIFICATION_SMS_EXPIRED_ERROR(80304, "验证码已失效,请重新校验"),
/**
* 配置错误
*/
ALIPAY_NOT_SETTING(80401, "支付宝支付未配置"),
ALIPAY_EXCEPTION(80402, "支付宝支付错误,请稍后重试"),
ALIPAY_PARAMS_EXCEPTION(80403, "支付宝参数异常"),
/**
* 微信相关异常
*/
WECHAT_CONNECT_NOT_SETTING(80500, "微信联合登陆信息未配置"),
WECHAT_PAYMENT_NOT_SETTING(80501, "微信支付信息未配置"),
WECHAT_QRCODE_ERROR(80502, "微信二维码生成异常"),
WECHAT_MP_MESSAGE_ERROR(80503, "微信小程序小消息订阅异常"),
APP_VERSION_EXIST(80600, "APP版本已存在")
;
APP_VERSION_EXIST(80600, "APP版本已存在");
private final Integer code;
private final String message;

View File

@ -44,10 +44,21 @@ public class GlobalControllerExceptionHandler {
//如果是自定义异常则获取异常返回自定义错误消息
if (e instanceof ServiceException) {
ResultCode resultCode = ((ServiceException) e).getResultCode();
ServiceException serviceException = ((ServiceException) e);
ResultCode resultCode = serviceException.getResultCode();
Integer code = null;
String message = null;
if (resultCode != null) {
return ResultUtil.error(resultCode.code(), resultCode.message());
code = resultCode.code();
message = resultCode.message();
}
//如果有扩展消息则输出异常中跟随补充异常
if (!serviceException.getMsg().equals(ServiceException.DEFAULT_MESSAGE)) {
message += ":" + serviceException.getMsg();
}
return ResultUtil.error(code, message);
}
//默认错误消息

View File

@ -4,13 +4,19 @@ import cn.lili.common.enums.ResultCode;
import lombok.Data;
/**
* 全局业务异常类
*
* @author Chopper
*/
@Data
public class ServiceException extends RuntimeException {
private String msg;
public static String DEFAULT_MESSAGE = "网络错误,请稍后重试!";
//异常消息
private String msg = DEFAULT_MESSAGE;
//错误码
private ResultCode resultCode;
public ServiceException(String msg) {
@ -19,8 +25,7 @@ public class ServiceException extends RuntimeException {
}
public ServiceException() {
super("网络错误,请稍后重试!");
this.msg = "网络错误,请稍后重试!";
super();
}
public ServiceException(ResultCode resultCode) {

View File

@ -119,7 +119,6 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
default:
return;
}
//如果是测试模式 默认验证码 6个1
if (systemSetting.getIsTestModel()) {
code = "111111";
@ -156,7 +155,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
try {
SendSmsResponse response = client.sendSms(sendSmsRequest);
} catch (Exception e) {
e.printStackTrace();
log.error("发送短信错误",e);
}
}
@ -192,7 +191,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
try {
client.sendBatchSms(sendBatchSmsRequest);
} catch (Exception e) {
e.printStackTrace();
log.error("批量发送短信错误",e);
}
}
@ -203,8 +202,6 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
public void addSmsSign(SmsSign smsSign) throws Exception {
//设置参数添加短信签名
com.aliyun.dysmsapi20170525.Client client = this.createClient();
System.out.println(smsSign.getBusinessLicense().substring(smsSign.getBusinessLicense().lastIndexOf(".") + 1));
System.out.println(smsSign.getLicense().substring(smsSign.getLicense().lastIndexOf(".")));
//营业执照
AddSmsSignRequest.AddSmsSignRequestSignFileList signFileList0 = new AddSmsSignRequest.AddSmsSignRequestSignFileList()
.setFileContents(Base64Utils.encode(smsSign.getBusinessLicense()))
@ -367,7 +364,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
config.endpoint = "dysmsapi.aliyuncs.com";
return new com.aliyun.dysmsapi20170525.Client(config);
} catch (Exception e) {
e.printStackTrace();
log.error("短信初始化错误",e);
}
return null;
}

View File

@ -2,8 +2,6 @@ package cn.lili.common.trigger.delay.queue;
import cn.lili.common.trigger.delay.AbstractDelayQueueMachineFactory;
import cn.lili.common.trigger.enums.DelayQueueEnums;
import cn.lili.common.trigger.interfaces.TimeTrigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
@ -18,11 +16,9 @@ import org.springframework.stereotype.Component;
@Component
public class PromotionDelayQueue extends AbstractDelayQueueMachineFactory {
@Autowired
private TimeTrigger timeTrigger;
@Override
public String setDelayQueueName() {
return DelayQueueEnums.PROMOTION_QUEUE.name();
return DelayQueueEnums.PROMOTION.name();
}
}

View File

@ -7,9 +7,9 @@ public enum DelayQueueEnums {
/**
* 促销任务队列
* 促销活动
*/
PROMOTION_QUEUE("促销任务队列");
PROMOTION("促销活动");
private String description;

View File

@ -6,7 +6,7 @@ package cn.lili.common.trigger.enums;
* @author paulG
* @since 2021/5/7
*/
public enum PromotionDelayTypeEnums {
public enum DelayTypeEnums {
/**
* 促销活动
@ -15,11 +15,16 @@ public enum PromotionDelayTypeEnums {
/**
* 拼团订单
*/
PINTUAN_ORDER("拼团订单");
PINTUAN_ORDER("拼团订单"),
/**
* 直播
*/
BROADCAST("直播");
private String description;
PromotionDelayTypeEnums(String description) {
DelayTypeEnums(String description) {
this.description = description;
}

View File

@ -0,0 +1,34 @@
package cn.lili.common.delayqueue;
import cn.hutool.core.date.DateTime;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
/**
* 直播消息实体
*
* @author Bulbasaur
* @date: 2021/6/1 4:48 下午
*/
@Data
@NoArgsConstructor
public class BroadcastMessage {
/**
* 直播间ID
*/
private String studioId;
/**
* 状态
*/
private String status;
public BroadcastMessage(String studioId, String status) {
this.studioId = studioId;
this.status = status;
}
}

View File

@ -13,4 +13,9 @@ public abstract class TimeExecuteConstant {
*/
public static final String PROMOTION_EXECUTOR = "promotionTimeTriggerExecutor";
/**
* 直播间延迟加载执行器
*/
public static final String BROADCAST_EXECUTOR = "broadcastTimeTriggerExecutor";
}

View File

@ -1,6 +1,6 @@
package cn.lili.common.trigger.util;
import cn.lili.common.trigger.enums.PromotionDelayTypeEnums;
import cn.lili.common.trigger.enums.DelayTypeEnums;
/**
* 延时任务工具类
@ -22,7 +22,7 @@ public class DelayQueueTools {
* @param id id
* @return 唯一键
*/
public static String wrapperUniqueKey(PromotionDelayTypeEnums type, String id) {
public static String wrapperUniqueKey(DelayTypeEnums type, String id) {
return "{TIME_TRIGGER_" + type.name() + "}_" + id;
}

View File

@ -1,5 +1,6 @@
package cn.lili.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import java.util.Base64;
@ -12,6 +13,7 @@ import java.io.*;
*
* @author Chopper
*/
@Slf4j
public class Base64DecodeMultipartFile implements MultipartFile {
private final byte[] imgContent;
@ -64,7 +66,7 @@ public class Base64DecodeMultipartFile implements MultipartFile {
stream = new FileOutputStream(dest);
stream.write(imgContent);
} catch (IOException e) {
e.printStackTrace();
log.error("transferTo错误",e);
}finally {
stream.close();
}
@ -92,7 +94,7 @@ public class Base64DecodeMultipartFile implements MultipartFile {
byte[] bytes = Base64.getDecoder().decode(base64);
stream = new ByteArrayInputStream(bytes);
} catch (Exception e) {
e.printStackTrace();
log.error("base64ToInputStream错误",e);
}
return stream;
}
@ -109,13 +111,13 @@ public class Base64DecodeMultipartFile implements MultipartFile {
}
data = swapStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
log.error("转码错误",e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
log.error("inputStreamToStream错误",e);
}
}
}

View File

@ -1,5 +1,7 @@
package cn.lili.common.utils;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -11,24 +13,9 @@ import javax.servlet.http.HttpServletResponse;
* @version v1.0
* 2020-12-14 09:32
*/
@Slf4j
public class CookieUtil {
/**
* 新增cookie
*
* @param key key值
* @param value 对应值
* @param response 响应
*/
public static void addCookie(String key, String value, HttpServletResponse response) {
try {
Cookie c = new Cookie(key, value);
c.setPath("/");
response.addCookie(c);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 新增cookie
@ -45,7 +32,7 @@ public class CookieUtil {
c.setPath("/");
response.addCookie(c);
} catch (Exception e) {
e.printStackTrace();
log.error("新增cookie错误",e);
}
}
@ -61,7 +48,7 @@ public class CookieUtil {
c.setMaxAge(0);
response.addCookie(c);
} catch (Exception e) {
e.printStackTrace();
log.error("删除cookie错误",e);
}
}
@ -83,7 +70,7 @@ public class CookieUtil {
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("获取cookie错误",e);
}
return null;
}

View File

@ -56,6 +56,24 @@ public final class CurrencyUtil {
return b1.multiply(b2).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精确的乘法运算
*
* @param v1 被乘数
* @param v2 乘数
* @param scale 表示表示需要精确到小数点以后几位
* @return 两个参数的积
*/
public static Double mul(double v1, double v2, int scale) {
if (scale < 0) {
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供相对精确的除法运算当发生除不尽的情况时 精确到小数点以后10位以后的数字四舍五入
*

View File

@ -87,6 +87,9 @@ public class DateUtil {
* @return
*/
public static Date endOfDate(Date date) {
if (date == null) {
date = new Date();
}
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, 23);
@ -200,6 +203,7 @@ public class DateUtil {
public static String toString(Date date) {
return toString(date, STANDARD_FORMAT);
}
/**
* 把日期转换成字符串型
*
@ -209,6 +213,7 @@ public class DateUtil {
public static String toString(Long date) {
return toString(date, STANDARD_FORMAT);
}
/**
* 把日期转换成字符串型
*

View File

@ -1,9 +1,12 @@
package cn.lili.common.utils;
import org.apache.http.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.NoHttpResponseException;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
@ -21,7 +24,6 @@ import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLException;
@ -30,10 +32,9 @@ import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Slf4j
public class HttpClientUtils {
//org.apache.http.impl.client.CloseableHttpClient
@ -146,11 +147,9 @@ public class HttpClientUtils {
//判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
} else {
System.out.println(response.getStatusLine().getStatusCode());
}
} catch (Exception e) {
e.printStackTrace();
log.error("get请求错误",e);
} finally {
try {
if (response != null) {
@ -158,71 +157,9 @@ public class HttpClientUtils {
}
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
log.error("Get错误",e);
}
}
return resultString;
}
public static String doPost(String url, Map<String, String> param) {
// 创建HttpClient对象
CloseableHttpClient httpClient = getHttpClient();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPostJson(String url, String json) {
// 创建HttpClient对象
CloseableHttpClient httpClient = getHttpClient();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
}

View File

@ -1,13 +1,12 @@
package cn.lili.common.utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@ -17,6 +16,7 @@ import java.util.concurrent.TimeUnit;
* @author paulG
* @since 2020/11/7
**/
@Slf4j
@Component
public class RedisUtil {
@Autowired
@ -38,51 +38,11 @@ public class RedisUtil {
}
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("指定缓存失效时间错误",e);
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 不能为null
* @return 时间() 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
@ -120,7 +80,7 @@ public class RedisUtil {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("缓存放入错误",e);
return false;
}
@ -143,215 +103,13 @@ public class RedisUtil {
}
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("普通缓存放入并设置时间错误",e);
return false;
}
}
/**
* 递增
*
* @param key
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
//================================Map=================================
/**
* HashGet
*
* @param key 不能为null
* @param item 不能为null
* @return
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key
* @param map 对应多个键值
* @param time 时间()
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key
* @param item
* @param value
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key
* @param item
* @param value
* @param time 时间() 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 不能为null
* @param item 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 不能为null
* @param item 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key
* @param item
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key
* @param item
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
//============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key
* @param value
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
@ -364,112 +122,11 @@ public class RedisUtil {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
log.error("将数据放入set缓存错误",e);
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key
* @param time 时间()
* @param values 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key
* @param values 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================listByParentId=================================
/**
* 获取list缓存的内容
*
* @param key
* @param start 开始
* @param end 结束 0 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key
* @param index 索引 index>=0时 0 表头1 第二个元素依次类推index<0时-1表尾-2倒数第二个元素依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
@ -483,7 +140,7 @@ public class RedisUtil {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("将list放入缓存错误",e);
return false;
}
}
@ -504,7 +161,7 @@ public class RedisUtil {
}
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("将list放入缓存错误",e);
return false;
}
}
@ -521,27 +178,11 @@ public class RedisUtil {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("将list放入缓存错误",e);
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* @param value
* @return
*/
public <T> boolean lPush(String key, List<T> value) {
try {
redisTemplate.opsForList().leftPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
@ -559,46 +200,12 @@ public class RedisUtil {
}
return true;
} catch (Exception e) {
e.printStackTrace();
log.error("将list放入缓存错误",e);
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key
* @param index 索引
* @param value
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
*
* @param key
* @param count 移除多少个
* @param value
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================ZSet=================================
/**

View File

@ -78,7 +78,7 @@ public class SliderImageUtil {
graphics.dispose();
//添加水印
ImageUtil.addWatermark(originalImage, "请滑动拼图");
ImageUtil.addWatermark(originalImage, "LILI-SHOP");
ByteArrayOutputStream newImageOs = new ByteArrayOutputStream();//新建流
ImageIO.write(newImage, TEMP_IMG_FILE_TYPE, newImageOs);//利用ImageIO类提供的write方法将bi以png图片的数据模式写入流
byte[] newImagery = newImageOs.toByteArray();

View File

@ -82,7 +82,7 @@ public class VerificationServiceImpl implements VerificationService {
} catch (ServiceException e) {
throw e;
} catch (Exception e) {
e.printStackTrace();
log.error("创建校验错误",e);
return null;
}
}

View File

@ -1,6 +1,7 @@
package cn.lili.config.elasticsearch;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
@ -27,6 +28,7 @@ import java.util.List;
* @author paulG
* @since 2020/10/13
**/
@Slf4j
@Configuration
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
@ -96,7 +98,7 @@ public class ElasticsearchConfig extends AbstractElasticsearchConfiguration {
try {
this.client.close();
} catch (IOException e) {
e.printStackTrace();
log.error("es clientClose错误",e);
}
}

View File

@ -61,4 +61,8 @@ public class RocketmqCustomProperties {
private String afterSaleGroup;
private String broadcastTopic;
private String broadcastGroup;
}

View File

@ -58,7 +58,7 @@ public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> impleme
//删除缓存
cache.vagueDel("{regions}");
} catch (Exception e) {
e.printStackTrace();
log.error("同步行政数据错误",e);
}
}

View File

@ -0,0 +1,64 @@
package cn.lili.modules.broadcast.entity.dos;
import cn.lili.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 小程序直播商品
* @author Bulbasaur
* @date: 2021/5/17 9:34 上午
*
*/
@Data
@Entity
@ApiModel(value = "Commodity", description = "直播商品")
@TableName("li_commodity")
@Table(name = "li_commodity")
public class Commodity extends BaseEntity {
@ApiModelProperty(value = "图片")
private String goodsImage;
@ApiModelProperty(value = "商品名称")
private String name;
//1一口价只需要传入priceprice2不传
//2价格区间price字段为左边界price2字段为右边界price和price2必传
//3显示折扣价price字段为原价price2字段为现价 price和price2必传
@ApiModelProperty(value = "价格类型")
private Integer priceType;
@ApiModelProperty(value = "价格")
private Double price;
@ApiModelProperty(value = "价格2")
private Double price2;
@ApiModelProperty(value = "商品详情页的小程序路径")
private String url;
@ApiModelProperty(value = "微信程序直播商品ID")
private Integer liveGoodsId;
@ApiModelProperty(value = "审核单ID")
private String auditId;
@ApiModelProperty(value = "审核状态")
private String auditStatus;
@ApiModelProperty(value = "店铺ID")
private String storeId;
@ApiModelProperty(value = "商品ID")
private String goodsId;
@ApiModelProperty(value = "规格ID")
private String skuId;
}

View File

@ -0,0 +1,97 @@
package cn.lili.modules.broadcast.entity.dos;
import cn.lili.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 小程序直播间
*
* @author Bulbasaur
* @date: 2021/5/17 9:47 上午
*/
@Data
@Entity
@ApiModel(value = "直播间")
@TableName("li_studio")
@Table(name = "li_studio")
public class Studio extends BaseEntity {
/**
* 直播间名字最短3个汉字最长17个汉字1个汉字相当于2个字符
*/
@ApiModelProperty(value = "直播间名字")
private String name;
/**
* 背景图填入mediaIDmediaID获取后三天内有效图片mediaID的获取请参考以下文档 https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html直播间背景图图片规则建议像素1080*1920大小不超过2M
*/
@ApiModelProperty(value = "背景图")
private String coverImg;
/**
* 直播计划开始时间开播时间需要在当前时间的10分钟后 并且 开始时间不能在 6 个月后
*/
@ApiModelProperty(value = "开始时间")
private String startTime;
/**
* 直播计划结束时间开播时间和结束时间间隔不得短于30分钟不得超过24小时
*/
@ApiModelProperty(value = "结束时间")
private String endTime;
/**
* 主播昵称最短2个汉字最长15个汉字1个汉字相当于2个字符
*/
@ApiModelProperty(value = "主播昵称")
private String anchorName;
/**
* 主播微信号如果未实名认证需要先前往小程序直播小程序进行实名验证, 小程序二维码链接https://res.wx.qq.com/op_res/9rSix1dhHfK4rR049JL0PHJ7TpOvkuZ3mE0z7Ou_Etvjf-w1J_jVX0rZqeStLfwh
*/
@ApiModelProperty(value = "主播微信号")
private String anchorWechat;
/**
* 分享图填入mediaIDmediaID获取后三天内有效图片mediaID的获取请参考以下文档 https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html直播间分享图图片规则建议像素800*640大小不超过1M
*/
@ApiModelProperty(value = "分享图")
private String shareImg;
/**
* 购物直播频道封面图填入mediaIDmediaID获取后三天内有效图片mediaID的获取请参考以下文档 https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/New_temporary_materials.html; 购物直播频道封面图图片规则建议像素800*800大小不超过100KB
*/
@ApiModelProperty(value = "封面图")
private String feedsImg;
@ApiModelProperty(value = "回放视频链接")
private String mediaUrl;
@ApiModelProperty(value = "房间ID")
private Integer roomId;
@ApiModelProperty(value = "小程序直播码")
private String qrCodeUrl;
@ApiModelProperty(value = "店铺ID")
private String storeId;
@ApiModelProperty(value = "直播间商品数量")
private Integer roomGoodsNum;
@ApiModelProperty(value = "直播间商品(最多展示两个商品name/goodsImage)")
private String roomGoodsList;
@ApiModelProperty(value = "推荐直播间")
private boolean recommend;
@ApiModelProperty(value = "直播间状态")
private String status;
}

View File

@ -0,0 +1,47 @@
package cn.lili.modules.broadcast.entity.dos;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* 直播商品
*
* @author Bulbasaur
* @date: 2021/5/18 5:42 下午
*/
@Data
@Entity
@ApiModel(value = "直播商品")
@TableName("li_studio_commodity")
@Table(name = "li_studio_commodity")
@NoArgsConstructor
public class StudioCommodity {
@Id
@TableId
@TableField
@Column(columnDefinition = "bigint(20)")
@ApiModelProperty(value = "唯一标识", hidden = true)
private String id;
@ApiModelProperty(value = "房间ID")
private Integer roomId;
@ApiModelProperty(value = "商品ID")
private Integer goodsId;
public StudioCommodity(Integer roomId, Integer goodsId) {
this.roomId = roomId;
this.goodsId = goodsId;
}
}

View File

@ -0,0 +1,22 @@
package cn.lili.modules.broadcast.entity.dto;
import lombok.Data;
/**
* 直播商品DTO
* 用于获取直播商品状态时使用
*
* @author Bulbasaur
* @date: 2021/5/25 12:12 下午
*/
@Data
public class CommodityDTO {
//商品ID
private Integer goods_id;
//商品名称
private String name;
//地址
private String url;
//审核状态
private Integer audit_status;
}

View File

@ -0,0 +1,43 @@
package cn.lili.modules.broadcast.entity.dto;
import cn.lili.common.utils.BeanUtil;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 微信小程序直播商品DTO
* @author Bulbasaur
* @date: 2021/5/17 11:03 上午
*
*/
@Data
@NoArgsConstructor
public class GoodsInfo {
@ApiModelProperty(value = "图片mediaID")
private String coverImgUrl;
@ApiModelProperty(value = "商品名称")
private String name;
//1一口价只需要传入priceprice2不传
//2价格区间price字段为左边界price2字段为右边界price和price2必传
//3显示折扣价price字段为原价price2字段为现价 price和price2必传
@ApiModelProperty(value = "价格类型")
private Integer priceType;
@ApiModelProperty(value = "价格")
private Double price;
@ApiModelProperty(value = "价格2")
private Double price2;
@ApiModelProperty(value = "商品详情页的小程序路径")
private String url;
public GoodsInfo(Commodity commodity){
BeanUtil.copyProperties(commodity, this);
}
}

View File

@ -0,0 +1,18 @@
package cn.lili.modules.broadcast.entity.dto;
import io.swagger.annotations.ApiModelProperty;
/**
* 用于直播间前台使用的直播间商品DTO
*
* @author Bulbasaur
* @date: 2021/5/20 2:34 下午
*/
public class SimpleCommodity {
@ApiModelProperty(value = "图片")
private String goodsImage;
@ApiModelProperty(value = "商品名称")
private String name;
}

View File

@ -0,0 +1,27 @@
package cn.lili.modules.broadcast.entity.enums;
/**
* 直播间状态
* @author Bulbasaur
* @date: 2021/5/31 10:32 上午
*
*/
public enum StudioStatusEnum {
NEW("新建"), START("开始"), END("结束");
private final String clientName;
StudioStatusEnum(String des) {
this.clientName = des;
}
public String clientName() {
return this.clientName;
}
public String value() {
return this.name();
}
}

View File

@ -0,0 +1,21 @@
package cn.lili.modules.broadcast.entity.vos;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 直播商品VO
*
* @author Bulbasaur
* @date: 2021/5/26 6:09 下午
*/
@Data
public class CommodityVO extends Commodity {
@ApiModelProperty(value = "SKU库存")
private Integer quantity;
@ApiModelProperty(value = "店铺名称")
private String storeName;
}

View File

@ -0,0 +1,22 @@
package cn.lili.modules.broadcast.entity.vos;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import cn.lili.modules.broadcast.entity.dos.Studio;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 直播间VO
*
* @author Bulbasaur
* @date: 2021/5/31 11:58 上午
*/
@Data
public class StudioVO extends Studio {
@ApiModelProperty(value = "直播间商品列表")
private List<Commodity> commodityList;
}

View File

@ -0,0 +1,35 @@
package cn.lili.modules.broadcast.mapper;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import cn.lili.modules.broadcast.entity.dto.SimpleCommodity;
import cn.lili.modules.broadcast.entity.vos.CommodityVO;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* 直播商品数据层
*
* @author Bulbasaur
* @date: 2021/5/17 9:56 上午
*/
public interface CommodityMapper extends BaseMapper<Commodity> {
@Select("SELECT live_goods_id FROM li_commodity WHERE audit_status='0' or audit_status='1'")
List<String> getAuditCommodity();
@Select("SELECT * FROM li_commodity c INNER JOIN li_studio_commodity sc ON sc.goods_id = c.live_goods_id WHERE sc.room_id =#{roomId}")
List<Commodity> getCommodityByRoomId(Integer roomId);
@Select("SELECT goods_image FROM li_commodity c INNER JOIN li_studio_commodity sc ON sc.goods_id = c.live_goods_id WHERE sc.room_id =#{roomId}")
List<String> getSimpleCommodityByRoomId(Integer roomId);
@Select("SELECT c.*,gs.quantity,s.store_name FROM li_commodity c INNER JOIN li_goods_sku gs ON c.sku_id = gs.id INNER JOIN li_store s ON s.id=c.store_id ${ew.customSqlSegment}")
IPage<CommodityVO> commodityVOList(IPage<CommodityVO> page, @Param(Constants.WRAPPER) Wrapper<CommodityVO> queryWrapper);
}

View File

@ -0,0 +1,13 @@
package cn.lili.modules.broadcast.mapper;
import cn.lili.modules.broadcast.entity.dos.StudioCommodity;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 直播间-商品关联持久层
* @author Bulbasaur
* @date: 2021/5/17 3:14 下午
*
*/
public interface StudioCommodityMapper extends BaseMapper<StudioCommodity> {
}

View File

@ -0,0 +1,14 @@
package cn.lili.modules.broadcast.mapper;
import cn.lili.modules.broadcast.entity.dos.Studio;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* 直播间数据层
*
* @author Bulbasaur
* @date: 2021/5/17 9:56 上午
*/
public interface StudioMapper extends BaseMapper<Studio> {
}

View File

@ -0,0 +1,45 @@
package cn.lili.modules.broadcast.service;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import cn.lili.modules.broadcast.entity.vos.CommodityVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* 直播商品业务层
*
* @author Bulbasaur
* @date: 2021/5/17 10:39 上午
*/
public interface CommodityService extends IService<Commodity> {
/**
* 添加直播商品
* @return 添加结果
*/
boolean addCommodity(List<Commodity> commodity);
/**
* 删除直播商品
* @param goodsId 直播商品ID
* @return 删除结果
*/
boolean deleteCommodity(String goodsId);
/**
* 查询微信小程序直播商品审核状态
*/
void getGoodsWareHouse();
/**
* 查看直播商品分页
* @param pageVO 分页
* @param name 商品名称
* @param auditStatus 审核状态
* @return 直播商品分页
*/
IPage<CommodityVO> commodityList(PageVO pageVO, String name, String auditStatus);
}

View File

@ -0,0 +1,13 @@
package cn.lili.modules.broadcast.service;
import cn.lili.modules.broadcast.entity.dos.StudioCommodity;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 直播间-商品关联业务层
*
* @author Bulbasaur
* @date: 2021/5/17 3:19 下午
*/
public interface StudioCommodityService extends IService<StudioCommodity> {
}

View File

@ -0,0 +1,79 @@
package cn.lili.modules.broadcast.service;
import cn.lili.common.delayqueue.BroadcastMessage;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.broadcast.entity.dos.Studio;
import cn.lili.modules.broadcast.entity.vos.StudioVO;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* 直播间业务层
*
* @author Bulbasaur
* @date: 2021/5/17 10:02 上午
*/
public interface StudioService extends IService<Studio> {
/**
* 创建直播间
* 直播间默认手机直播
* 默认开启点赞商品货架评论回放
* @param studio 直播间
* @return 开启状态
*/
Boolean create(Studio studio);
/**
* 修改直播间
* 直播间默认手机直播
* @param studio 直播间
* @return 修改状态
*/
Boolean edit(Studio studio);
/**
* 获取直播间信息
* @param id 直播间ID
* @return 直播间VO
*/
StudioVO getStudioVO(String id);
/**
* 获取直播间回放
* @param roomId 房间ID
* @return 直播间回放地址
*/
String getLiveInfo(Integer roomId);
/**
* 推送商品
* @param roomId 店铺ID
* @param goodsId 商品ID
* @return 操作结果
*/
Boolean push(Integer roomId,Integer goodsId);
/**
* 删除商品
* @param roomId 店铺ID
* @param goodsId 商品ID
* @return 操作结果
*/
Boolean goodsDeleteInRoom(Integer roomId,Integer goodsId);
/**
* 获取直播间列表
* @param pageVO 分页
* @param recommend 是否推荐
* @param status 直播间状态
* @return 直播间分页
*/
IPage<Studio> studioList(PageVO pageVO, Integer recommend, String status);
/**
* 修改直播间状态
* @param broadcastMessage 直播间消息
*/
void updateStudioStatus(BroadcastMessage broadcastMessage);
}

View File

@ -0,0 +1,112 @@
package cn.lili.modules.broadcast.serviceimpl;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.common.utils.PageUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import cn.lili.modules.broadcast.entity.dto.CommodityDTO;
import cn.lili.modules.broadcast.entity.vos.CommodityVO;
import cn.lili.modules.broadcast.mapper.CommodityMapper;
import cn.lili.modules.broadcast.service.CommodityService;
import cn.lili.modules.broadcast.util.WechatLivePlayerUtil;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.service.GoodsSkuService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 直播商品业务层实现
*
* @author Bulbasaur
* @date: 2021/5/17 11:16 上午
*/
@Service
public class CommodityServiceImpl extends ServiceImpl<CommodityMapper, Commodity> implements CommodityService {
@Autowired
private WechatLivePlayerUtil wechatLivePlayerUtil;
@Autowired
private GoodsSkuService goodsSkuService;
@Override
public boolean addCommodity(List<Commodity> commodityList) {
for (Commodity commodity : commodityList) {
//检测直播商品
checkCommodity(commodity);
//添加直播商品
JSONObject json = wechatLivePlayerUtil.addGoods(commodity);
if(!json.getStr("errcode").equals("0")){
throw new ServiceException(json.getStr("errmsg"));
}
commodity.setLiveGoodsId(Convert.toInt(json.getStr("goodsId")));
commodity.setAuditId(json.getStr("auditId"));
commodity.setStoreId(UserContext.getCurrentUser().getStoreId());
//默认为待审核状态
commodity.setAuditStatus("0");
this.save(commodity);
}
return true;
}
private void checkCommodity(Commodity commodity) {
//商品是否审核通过
GoodsSku goodsSku = goodsSkuService.getById(commodity.getSkuId());
if (!goodsSku.getIsAuth().equals(GoodsAuthEnum.PASS.name())) {
throw new ServiceException(goodsSku.getGoodsName() + " 未审核通过,不能添加直播商品");
}
//是否已添加规格商品
if (this.count(new LambdaQueryWrapper<Commodity>().eq(Commodity::getSkuId, commodity.getSkuId())) > 0) {
throw new ServiceException(goodsSku.getGoodsName() + " 已添加规格商品,无法重复增加");
}
}
@Override
public boolean deleteCommodity(String goodsId) {
JSONObject json = wechatLivePlayerUtil.deleteGoods(goodsId);
if (json.getStr("errcode").equals("0")) {
return this.remove(new LambdaQueryWrapper<Commodity>().eq(Commodity::getLiveGoodsId, goodsId));
}
return false;
}
@Override
public void getGoodsWareHouse() {
//查询审核中的商品
List<String> goodsIdList = this.baseMapper.getAuditCommodity();
if (goodsIdList.size() > 0) {
//同步状态
JSONObject json = wechatLivePlayerUtil.getGoodsWareHouse(goodsIdList);
//修改状态
List<CommodityDTO> commodityDTOList = JSONUtil.toList((JSONArray) json.get("goods"), CommodityDTO.class);
for (CommodityDTO commodityDTO : commodityDTOList) {
//修改审核状态
this.update(new LambdaUpdateWrapper<Commodity>()
.eq(Commodity::getLiveGoodsId, commodityDTO.getGoods_id())
.set(Commodity::getAuditStatus, commodityDTO.getAudit_status()));
}
}
}
@Override
public IPage<CommodityVO> commodityList(PageVO pageVO, String name, String auditStatus) {
return this.baseMapper.commodityVOList(PageUtil.initPage(pageVO),
new QueryWrapper<CommodityVO>().like(name != null, "c.name", name)
.eq(auditStatus != null, "c.audit_status", auditStatus)
.eq(UserContext.getCurrentUser().getRole().equals(UserEnums.STORE), "c.store_id", UserContext.getCurrentUser().getStoreId())
.orderByDesc("create_time"));
}
}

View File

@ -0,0 +1,17 @@
package cn.lili.modules.broadcast.serviceimpl;
import cn.lili.modules.broadcast.entity.dos.StudioCommodity;
import cn.lili.modules.broadcast.mapper.StudioCommodityMapper;
import cn.lili.modules.broadcast.service.StudioCommodityService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* 直播间-商品关联业务层实现
*
* @author Bulbasaur
* @date: 2021/5/17 3:20 下午
*/
@Service
public class StudioCommodityServiceImpl extends ServiceImpl<StudioCommodityMapper, StudioCommodity> implements StudioCommodityService {
}

View File

@ -0,0 +1,212 @@
package cn.lili.modules.broadcast.serviceimpl;
import cn.hutool.json.JSONUtil;
import cn.lili.common.delayqueue.BroadcastMessage;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.trigger.enums.DelayTypeEnums;
import cn.lili.common.trigger.interfaces.TimeTrigger;
import cn.lili.common.trigger.model.TimeExecuteConstant;
import cn.lili.common.trigger.model.TimeTriggerMsg;
import cn.lili.common.trigger.util.DelayQueueTools;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.DateUtil;
import cn.lili.common.utils.PageUtil;
import cn.lili.common.vo.PageVO;
import cn.lili.config.rocketmq.RocketmqCustomProperties;
import cn.lili.modules.broadcast.entity.dos.Studio;
import cn.lili.modules.broadcast.entity.dos.StudioCommodity;
import cn.lili.modules.broadcast.entity.enums.StudioStatusEnum;
import cn.lili.modules.broadcast.entity.vos.StudioVO;
import cn.lili.modules.broadcast.mapper.CommodityMapper;
import cn.lili.modules.broadcast.mapper.StudioMapper;
import cn.lili.modules.broadcast.service.StudioCommodityService;
import cn.lili.modules.broadcast.service.StudioService;
import cn.lili.modules.broadcast.util.WechatLivePlayerUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Map;
/**
* 小程序直播间业务层实现
*
* @author Bulbasaur
* @date: 2021/5/17 10:04 上午
*/
@Service
public class StudioServiceImpl extends ServiceImpl<StudioMapper, Studio> implements StudioService {
@Autowired
private WechatLivePlayerUtil wechatLivePlayerUtil;
@Autowired
private StudioCommodityService studioCommodityService;
@Resource
private CommodityMapper commodityMapper;
//延时任务
@Autowired
private TimeTrigger timeTrigger;
//Rocketmq
@Autowired
private RocketmqCustomProperties rocketmqCustomProperties;
@Override
public Boolean create(Studio studio) {
try {
//创建小程序直播
Map<String, String> roomMap = wechatLivePlayerUtil.create(studio);
studio.setRoomId(Integer.parseInt(roomMap.get("roomId")));
studio.setQrCodeUrl(roomMap.get("qrcodeUrl"));
studio.setStoreId(UserContext.getCurrentUser().getStoreId());
studio.setStatus(StudioStatusEnum.NEW.name());
//直播间添加成功发送直播间开启关闭延时任务
if (this.save(studio)) {
//直播开启延时任务
BroadcastMessage broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.START.name());
TimeTriggerMsg timeTriggerMsg = new TimeTriggerMsg(TimeExecuteConstant.BROADCAST_EXECUTOR,
Long.parseLong(studio.getStartTime()) * 1000L, broadcastMessage,
DelayQueueTools.wrapperUniqueKey(DelayTypeEnums.BROADCAST, studio.getId()),
rocketmqCustomProperties.getPromotionTopic());
//发送促销活动开始的延时任务
this.timeTrigger.addDelay(timeTriggerMsg);
//直播结束延时任务
broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.END.name());
timeTriggerMsg = new TimeTriggerMsg(TimeExecuteConstant.BROADCAST_EXECUTOR,
Long.parseLong(studio.getEndTime()) * 1000L, broadcastMessage,
DelayQueueTools.wrapperUniqueKey(DelayTypeEnums.BROADCAST, studio.getId()),
rocketmqCustomProperties.getPromotionTopic());
//发送促销活动开始的延时任务
this.timeTrigger.addDelay(timeTriggerMsg);
}
return true;
} catch (Exception e) {
throw new ServiceException(ResultCode.ERROR);
}
}
@Override
public Boolean edit(Studio studio) {
Studio oldStudio = this.getById(studio.getId());
wechatLivePlayerUtil.editRoom(studio);
if (this.updateById(studio)) {
//发送更新延时任务
//直播间开始
BroadcastMessage broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.START.name());
this.timeTrigger.edit(
TimeExecuteConstant.BROADCAST_EXECUTOR,
broadcastMessage,
Long.parseLong(oldStudio.getStartTime()),
Long.parseLong(studio.getStartTime()),
DelayQueueTools.wrapperUniqueKey(DelayTypeEnums.BROADCAST, studio.getId()),
DateUtil.getDelayTime(Long.parseLong(studio.getStartTime())),
rocketmqCustomProperties.getPromotionTopic());
//直播间结束
broadcastMessage = new BroadcastMessage(studio.getId(), StudioStatusEnum.START.name());
this.timeTrigger.edit(
TimeExecuteConstant.BROADCAST_EXECUTOR,
broadcastMessage,
Long.parseLong(oldStudio.getEndTime()),
Long.parseLong(studio.getEndTime()),
DelayQueueTools.wrapperUniqueKey(DelayTypeEnums.BROADCAST, studio.getId()),
DateUtil.getDelayTime(Long.parseLong(studio.getEndTime())),
rocketmqCustomProperties.getPromotionTopic());
}
return true;
}
@Override
public StudioVO getStudioVO(String id) {
StudioVO studioVO = new StudioVO();
//获取直播间信息
BeanUtil.copyProperties(this.getById(id), studioVO);
//获取直播间商品信息
studioVO.setCommodityList(commodityMapper.getCommodityByRoomId(studioVO.getRoomId()));
return studioVO;
}
@Override
public String getLiveInfo(Integer roomId) {
Studio studio = this.getByRoomId(roomId);
//获取直播间并判断回放内容是否为空如果为空则获取直播间回放并保存
if (studio.getMediaUrl() != null) {
return studio.getMediaUrl();
} else {
String mediaUrl = wechatLivePlayerUtil.getLiveInfo(roomId);
studio.setMediaUrl(mediaUrl);
this.save(studio);
return mediaUrl;
}
}
@Override
public Boolean push(Integer roomId, Integer goodsId) {
//调用微信接口添加直播间商品并进行记录
if (wechatLivePlayerUtil.pushGoods(roomId, goodsId)) {
studioCommodityService.save(new StudioCommodity(roomId, goodsId));
//添加直播间商品数量
Studio studio = this.getByRoomId(roomId);
studio.setRoomGoodsNum(studio.getRoomGoodsNum() != null ? studio.getRoomGoodsNum() + 1 : 1);
//设置直播间默认的商品前台展示只展示两个
if (studio.getRoomGoodsNum() < 3) {
studio.setRoomGoodsList(JSONUtil.toJsonStr(commodityMapper.getSimpleCommodityByRoomId(roomId)));
}
return this.updateById(studio);
}
return false;
}
@Override
public Boolean goodsDeleteInRoom(Integer roomId, Integer goodsId) {
//调用微信接口删除直播间商品并进行记录
if (wechatLivePlayerUtil.goodsDeleteInRoom(roomId, goodsId)) {
studioCommodityService.remove(new QueryWrapper<StudioCommodity>().eq("room_id", roomId).eq("goods_id", goodsId));
//减少直播间商品数量
Studio studio = this.getByRoomId(roomId);
studio.setRoomGoodsNum(studio.getRoomGoodsNum() - 1);
//设置直播间默认的商品前台展示只展示两个
if (studio.getRoomGoodsNum() < 3) {
studio.setRoomGoodsList(JSONUtil.toJsonStr(commodityMapper.getSimpleCommodityByRoomId(roomId)));
}
return this.updateById(studio);
}
return false;
}
@Override
public IPage<Studio> studioList(PageVO pageVO, Integer recommend, String status) {
return this.page(PageUtil.initPage(pageVO), new QueryWrapper<Studio>()
.eq(recommend != null, "recommend", true)
.eq(status != null, "status", status)
.orderByDesc("create_time"));
}
@Override
public void updateStudioStatus(BroadcastMessage broadcastMessage) {
this.update(new LambdaUpdateWrapper<Studio>()
.eq(Studio::getId, broadcastMessage.getStudioId())
.set(Studio::getStatus, broadcastMessage.getStatus()));
}
/**
* 根据直播间ID获取直播间
*
* @param roomId 直播间ID
* @return 直播间
*/
private Studio getByRoomId(Integer roomId) {
return this.getOne(new LambdaQueryWrapper<Studio>().eq(Studio::getRoomId, roomId));
}
}

View File

@ -0,0 +1,245 @@
package cn.lili.modules.broadcast.util;
import cn.hutool.json.JSONObject;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.base.entity.enums.ClientTypeEnum;
import cn.lili.modules.broadcast.entity.dos.Commodity;
import cn.lili.modules.broadcast.entity.dos.Studio;
import cn.lili.modules.broadcast.entity.dto.GoodsInfo;
import cn.lili.modules.message.util.WechatAccessTokenUtil;
import cn.lili.modules.system.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 微信小程序直播工具类
*
* @author Bulbasaur
* @date: 2021/5/17 10:16 上午
*/
@Slf4j
@Component
public class WechatLivePlayerUtil {
@Autowired
private WechatAccessTokenUtil wechatAccessTokenUtil;
@Autowired
private WechatMediaUtil wechatMediaUtil;
/**
* 创建小程序直播间
*
* @param studio 小程序直播
* @return 房间ID
*/
public Map<String, String> create(Studio studio) throws Exception {
//发送url
String url = "https://api.weixin.qq.com/wxaapi/broadcast/room/create?access_token=";
//添加直播间
Map<String, String> map = this.mockRoom(studio);
JSONObject json = this.doPostWithJson(url, map);
Map<String, String> roomMap = new HashMap<>();
roomMap.put("roomId", json.getStr("roomId"));
roomMap.put("qrcodeUrl", json.getStr("qrcode_url"));
return roomMap;
}
/**
* 创建小程序直播间
*
* @param studio 小程序直播
* @return 房间ID
*/
public boolean editRoom(Studio studio) {
//发送url
String url = "https://api.weixin.qq.com/wxaapi/broadcast/room/editroom?access_token=";
//修改直播间
Map<String, String> map = this.mockRoom(studio);
map.put("id", studio.getRoomId().toString());
this.doPostWithJson(url, map);
return true;
}
/**
* 获取直播间回放
*
* @param roomId 房间ID
* @return 回放地址
*/
public String getLiveInfo(Integer roomId) {
//发送url
String url = "https://api.weixin.qq.com/wxa/business/getliveinfo?access_token=";
Map<String, Object> map = new HashMap<>();
//获取回放
map.put("action", "get_replay");
//直播间ID
map.put("room_id", roomId);
//起始拉取视频0表示从第一个视频片段开始拉取
map.put("start", "0");
//每次拉取的数量建议100以内
map.put("limit", "1");
JSONObject json = this.doPostWithJson(url, map);
//TODO get media_url
return json.getStr("live_replay");
}
/**
* 推送直播间商品
*
* @param roomId 房间ID
* @param goodsId 商品ID
* @return 操作结果
*/
public Boolean pushGoods(Integer roomId, Integer goodsId) {
//发送url
String url = "https://api.weixin.qq.com/wxaapi/broadcast/room/addgoods?access_token=";
Map<String, Object> map = new HashMap<>();
//直播间回放
Integer[] ids = {goodsId};
map.put("ids", ids);
//商品ID
map.put("roomId", roomId);
this.doPostWithJson(url, map);
return true;
}
/**
* 删除直播间商品
*
* @param roomId 房间ID
* @param goodsId 商品ID
* @return 操作结果
*/
public Boolean goodsDeleteInRoom(Integer roomId, Integer goodsId) {
//发送url
String url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/deleteInRoom?access_token=";
Map<String, Integer> map = new HashMap<>();
//直播间回放
map.put("goodsId", goodsId);
//商品ID
map.put("roomId", roomId);
this.doPostWithJson(url, map);
return true;
}
/**
* 添加直播商品
*
* @param commodity 直播商品
* @return 添加结果
*/
public JSONObject addGoods(Commodity commodity) {
//发送url
String url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/add?access_token=";
//商品名称最长14个汉字
if (commodity.getName().length() > 14) {
commodity.setName(commodity.getName().substring(0, 13));
}
//新建微信商品DTO
GoodsInfo goodsInfo = new GoodsInfo(commodity);
//上传微信临时图片
goodsInfo.setCoverImgUrl(wechatMediaUtil.uploadMedia("image", commodity.getGoodsImage()));
Map<String, GoodsInfo> map = new HashMap<>();
//调用新增直播商品接口
map.put("goodsInfo", goodsInfo);
return this.doPostWithJson(url, map);
}
/**
* 删除直播商品
*
* @param goodsId 商品ID
* @return 删除结果
*/
public JSONObject deleteGoods(String goodsId) {
//发送url
String url = "https://api.weixin.qq.com/wxaapi/broadcast/goods/delete?access_token=";
Map<String, Object> map = new HashMap<>();
map.put("goodsId", goodsId);
return this.doPostWithJson(url, map);
}
/**
* 查询直播商品状态
*
* @param goodsIdList 商品ID列表
* @return 删除结果
*/
public JSONObject getGoodsWareHouse(List<String> goodsIdList) {
//发送url
String url = "https://api.weixin.qq.com/wxa/business/getgoodswarehouse?access_token=";
Map<String, Object> map = new HashMap<>();
map.put("goods_ids", goodsIdList);
return this.doPostWithJson(url, map);
}
/**
* 请求微信接口
*
* @param url 链接
* @param map 参数
* @return 返回内容
*/
private JSONObject doPostWithJson(String url, Map map) {
//获取token
String token = wechatAccessTokenUtil.cgiAccessToken(ClientTypeEnum.WECHAT_MP);
//请求链接添加token
url += token;
//发起请求
String content = HttpUtils.doPostWithJson(url, map);
//记录请求结果
log.info("微信小程序请求结果:" + content);
//获取请求内容如果token过期则重新获取如果出错则抛出错误
JSONObject jsonObject = new JSONObject(content);
if (jsonObject.get("errcode").equals("0")) {
return jsonObject;
} else if (jsonObject.get("errcode").equals("40001")) {
wechatAccessTokenUtil.removeAccessToken(ClientTypeEnum.WECHAT_MP);
return this.doPostWithJson(url, map);
} else {
throw new ServiceException(jsonObject.get("errmsg").toString());
}
}
private Map<String, String> mockRoom(Studio studio) {
Map<String, String> map = new HashMap<>();
//背景图
map.put("coverImg", wechatMediaUtil.uploadMedia("image", studio.getCoverImg()));
//分享图
map.put("shareImg", wechatMediaUtil.uploadMedia("image", studio.getShareImg()));
//购物直播频道封面图
map.put("feedsImg", wechatMediaUtil.uploadMedia("image", studio.getFeedsImg()));
//直播间名字
map.put("name", studio.getName());
//直播计划开始时间
map.put("startTime", studio.getStartTime());
//直播计划结束时间
map.put("endTime", studio.getEndTime());
//主播昵称
map.put("anchorName", studio.getAnchorName());
//主播微信号
map.put("anchorWechat", studio.getAnchorWechat());
//直播间类型
map.put("type", "0");
//是否关闭点赞
map.put("closeLike", "0");
//是否关闭货架
map.put("closeGoods", "0");
//是否关闭评论
map.put("closeComment", "0");
//直播间名字
map.put("closeReplay", "0");
return map;
}
}

View File

@ -0,0 +1,143 @@
package cn.lili.modules.broadcast.util;
import cn.hutool.json.JSONObject;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.base.entity.enums.ClientTypeEnum;
import cn.lili.modules.message.util.WechatAccessTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Date;
/**
* 微信媒体工具
*
* @author Bulbasaur
* @date: 2021/5/19 8:02 下午
*/
@Slf4j
@Component
public class WechatMediaUtil {
@Autowired
private WechatAccessTokenUtil wechatAccessTokenUtil;
/**
* 上传多媒体数据到微信服务器
*
* @param mediaFileUrl 来自网络上面的媒体文件地址
* @return
*/
public String uploadMedia(String type, String mediaFileUrl) {
//获取token
String accessToken = wechatAccessTokenUtil.cgiAccessToken(ClientTypeEnum.WECHAT_MP);
/*
* 上传媒体文件到微信服务器需要请求的地址
*/
String MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE";
StringBuffer resultStr = null;
//拼装url地址
String mediaStr = MEDIA_URL.replace("ACCESS_TOKEN", accessToken).replace("TYPE", type);
URL mediaUrl;
try {
String boundary = "----WebKitFormBoundaryOYXo8heIv9pgpGjT";
URL url = new URL(mediaStr);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//让输入输出流开启
urlConn.setDoInput(true);
urlConn.setDoOutput(true);
//使用post方式请求的时候必须关闭缓存
urlConn.setUseCaches(false);
//设置请求头的Content-Type属性
urlConn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
urlConn.setRequestMethod("POST");
//获取输出流使用输出流拼接请求体
OutputStream out = urlConn.getOutputStream();
//读取文件的数据,构建一个GET请求然后读取指定地址中的数据
mediaUrl = new URL(mediaFileUrl);
HttpURLConnection mediaConn = (HttpURLConnection) mediaUrl.openConnection();
//设置请求方式
mediaConn.setRequestMethod("GET");
//设置可以打开输入流
mediaConn.setDoInput(true);
//获取传输的数据类型
String contentType = mediaConn.getHeaderField("Content-Type");
//将获取大到的类型转换成扩展名
String fileExt = judgeType(contentType);
//获取输入流从mediaURL里面读取数据
InputStream in = mediaConn.getInputStream();
BufferedInputStream bufferedIn = new BufferedInputStream(in);
//数据读取到这个数组里面
byte[] bytes = new byte[1024];
int size = 0;
//使用outputStream流输出信息到请求体当中去
out.write(("--" + boundary + "\r\n").getBytes());
out.write(("Content-Disposition: form-data; name=\"media\";\r\n"
+ "filename=\"" + (new Date().getTime()) + fileExt + "\"\r\n"
+ "Content-Type: " + contentType + "\r\n\r\n").getBytes());
while ((size = bufferedIn.read(bytes)) != -1) {
out.write(bytes, 0, size);
}
//切记这里的换行符不能少否则将会报41005错误
out.write(("\r\n--" + boundary + "--\r\n").getBytes());
bufferedIn.close();
in.close();
mediaConn.disconnect();
InputStream resultIn = urlConn.getInputStream();
InputStreamReader reader = new InputStreamReader(resultIn);
BufferedReader bufferedReader = new BufferedReader(reader);
String tempStr = null;
resultStr = new StringBuffer();
while ((tempStr = bufferedReader.readLine()) != null) {
resultStr.append(tempStr);
}
bufferedReader.close();
reader.close();
resultIn.close();
urlConn.disconnect();
} catch (Exception e) {
log.error("微信媒体上传失败", e);
}
JSONObject jsonObject = new JSONObject(resultStr.toString());
log.info("微信媒体上传:" + jsonObject.toString());
//判断是否传递成功如果token过期则重新获取
if (jsonObject.get("errcode") != null && jsonObject.get("errcode").equals("40001")) {
wechatAccessTokenUtil.removeAccessToken(ClientTypeEnum.WECHAT_MP);
return this.uploadMedia(type, mediaFileUrl);
} else if (jsonObject.get("errcode") != null) {
throw new ServiceException(jsonObject.get("errmsg").toString());
} else {
return jsonObject.get("media_id").toString();
}
}
/**
* 通过传过来的contentType判断是哪一种类型
*
* @param contentType 获取来自连接的contentType
* @return
*/
public String judgeType(String contentType) {
String fileExt = "";
switch (contentType) {
case "image/png":
fileExt = ".png";
break;
case "image/jpeg":
fileExt = ".jpeg";
break;
case "image/jpg":
fileExt = ".jpg";
break;
}
return fileExt;
}
}

View File

@ -7,8 +7,6 @@ import cn.lili.modules.connect.mapper.ConnectConfigMapper;
import cn.lili.modules.connect.service.ConnectConfigService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -23,8 +21,6 @@ import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class ConnectConfigServiceImpl extends ServiceImpl<ConnectConfigMapper, ConnectConfig> implements ConnectConfigService {
@Autowired
private ConnectConfigMapper connectConfigMapper;
@Override
public List<ConnectConfigForm> listForms() {

View File

@ -339,7 +339,7 @@ public class ConnectServiceImpl extends ServiceImpl<ConnectMapper, Connect> impl
return JSONUtil.parseObj(result);
}
} catch (Exception e) {
e.printStackTrace();
log.error("解密,获取微信信息错误",e);
}
throw new ServiceException(ResultCode.USER_CONNECT_ERROR);
}

View File

@ -29,6 +29,7 @@ import cn.lili.modules.system.entity.dto.connect.dto.QQConnectSettingItem;
import cn.lili.modules.system.entity.dto.connect.dto.WechatConnectSettingItem;
import cn.lili.modules.system.entity.enums.SettingEnum;
import cn.lili.modules.system.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -45,6 +46,7 @@ import java.util.regex.Pattern;
* @version v1.0
* 2020-11-25 21:16
*/
@Slf4j
@Component
public class ConnectUtil {
@ -106,7 +108,7 @@ public class ConnectUtil {
try {
httpServletResponse.sendRedirect(url);
} catch (Exception e) {
e.printStackTrace();
log.error("登录回调错误",e);
}
}

View File

@ -1,5 +1,7 @@
package cn.lili.modules.connect.util;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
@ -11,6 +13,7 @@ import java.net.UnknownHostException;
* @version v1.0
* 2020-12-08 15:32
*/
@Slf4j
public class IpUtils {
/**
@ -22,7 +25,7 @@ public class IpUtils {
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
log.error("获取本机IP错误",e);
return null;
}
}

View File

@ -3,7 +3,7 @@ package cn.lili.modules.distribution.mapper;
import cn.hutool.core.date.DateTime;
import cn.lili.modules.distribution.entity.dos.DistributionOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
/**
* 分销订单数据处理层
@ -16,9 +16,8 @@ public interface DistributionOrderMapper extends BaseMapper<DistributionOrder> {
/**
* 分销提佣
*/
@Select("UPDATE li_distribution AS d " +
"SET d.can_rebate =(d.can_rebate +(SELECT SUM( dorder.rebate ) FROM li_distribution_order AS dorder WHERE dorder.distribution_id = d.id AND " +
"dorder.distribution_order_status=#{distributionOrderStatus} AND dorder.settle_cycle< #{settleCycle} ))")
@Update("UPDATE li_distribution AS d " +
"SET d.can_rebate =(d.can_rebate +(SELECT SUM( dorder.rebate ) FROM li_distribution_order AS dorder WHERE dorder.distribution_id = d.id AND dorder.distribution_order_status=#{distributionOrderStatus} AND dorder.settle_cycle< #{settleCycle} ))")
void rebate(String distributionOrderStatus, DateTime settleCycle);
}

View File

@ -34,9 +34,6 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional
public class DistributionGoodsServiceImpl extends ServiceImpl<DistributionGoodsMapper, DistributionGoods> implements DistributionGoodsService {
//分销商品
@Autowired
private DistributionGoodsMapper distributionGoodsMapper;
//分销员
@Autowired
private DistributionService distributionService;
@ -48,22 +45,22 @@ public class DistributionGoodsServiceImpl extends ServiceImpl<DistributionGoodsM
public IPage<DistributionGoodsVO> goodsPage(DistributionGoodsSearchParams searchParams) {
//获取商家的分销商品列表
if (UserContext.getCurrentUser().getRole().equals(UserEnums.STORE)) {
return distributionGoodsMapper.getDistributionGoodsVO(PageUtil.initPage(searchParams), searchParams.storeQueryWrapper());
return this.baseMapper.getDistributionGoodsVO(PageUtil.initPage(searchParams), searchParams.storeQueryWrapper());
} else if (UserContext.getCurrentUser().getRole().equals(UserEnums.MEMBER)) {
//判断当前登录用户是否为分销员
Distribution distribution = distributionService.getDistribution();
if (distribution != null) {
//判断查看已选择的分销商品列表
if (searchParams.isChecked()) {
return distributionGoodsMapper.selectGoods(PageUtil.initPage(searchParams), searchParams.distributionQueryWrapper(), distribution.getId());
return this.baseMapper.selectGoods(PageUtil.initPage(searchParams), searchParams.distributionQueryWrapper(), distribution.getId());
} else {
return distributionGoodsMapper.notSelectGoods(PageUtil.initPage(searchParams), searchParams.distributionQueryWrapper(), distribution.getId());
return this.baseMapper.notSelectGoods(PageUtil.initPage(searchParams), searchParams.distributionQueryWrapper(), distribution.getId());
}
}
throw new ServiceException(ResultCode.DISTRIBUTION_NOT_EXIST);
}
//如果是平台则直接进行查询
return distributionGoodsMapper.getDistributionGoodsVO(PageUtil.initPage(searchParams), searchParams.distributionQueryWrapper());
return this.baseMapper.getDistributionGoodsVO(PageUtil.initPage(searchParams), searchParams.distributionQueryWrapper());
}
@Override

View File

@ -11,6 +11,7 @@ import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.Date;
@ -35,18 +36,23 @@ public class Category extends BaseEntity {
@ApiModelProperty(value = "分类名称")
private String name;
@NotEmpty(message = "请选择父分类")
@ApiModelProperty(value = "父id, 根节点为0")
private String parentId;
@NotNull(message = "层级不能为空")
@ApiModelProperty(value = "层级, 从0开始")
private Integer level;
@NotNull(message = "排序值不能为空")
@ApiModelProperty(value = "排序值")
private BigDecimal sortOrder;
@NotNull(message = "请填写佣金比例")
@ApiModelProperty(value = "佣金比例")
private Double commissionRate;
@NotEmpty(message = "分类图标不能为空")
@ApiModelProperty(value = "分类图标")
private String image;

View File

@ -64,6 +64,10 @@ public class DraftGoods extends BaseEntity {
@ApiModelProperty(value = "详情")
private String intro;
@ApiModelProperty(value = "商品移动端详情")
private String mobileIntro;
@Max(value = 99999999, message = "价格不能超过99999999")
@ApiModelProperty(value = "商品价格")
private Double price;
@ -112,16 +116,8 @@ public class DraftGoods extends BaseEntity {
@ApiModelProperty(value = "运费模板id")
private String templateId;
@ApiModelProperty(value = "运费承担者")
private String freightPayer;
@ApiModelProperty(value = "是否自营")
private Boolean selfOperated;
/**
* 商品移动端详情
*/
@ApiModelProperty(value = "商品移动端详情")
private String mobileIntro;
@ApiModelProperty(value = "商品视频")
private String goodsVideo;
@ -154,4 +150,10 @@ public class DraftGoods extends BaseEntity {
@ApiModelProperty(value = "sku列表JSON")
private String skuListJson;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
*/
@ApiModelProperty(value = "商品类型", required = true)
private String goodsType;
}

View File

@ -2,11 +2,14 @@ package cn.lili.modules.goods.entity.dos;
import cn.hutool.json.JSONUtil;
import cn.lili.base.BaseEntity;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.xkcoding.http.util.StringUtil;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -16,6 +19,7 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.Max;
import java.util.Map;
/**
* 商品
@ -145,11 +149,6 @@ public class Goods extends BaseEntity {
*/
@ApiModelProperty(value = "运费模板id")
private String templateId;
/**
* 谁承担运费 BUYER买家承担STORE卖家承担
*/
@ApiModelProperty(value = " 谁承担运费 BUYER买家承担STORE卖家承担")
private String freightPayer;
/**
* 审核状态
*
@ -190,11 +189,19 @@ public class Goods extends BaseEntity {
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
*/
@ApiModelProperty(value = "商品类型", required = true)
private String goodsType;
@ApiModelProperty(value = "商品参数json", hidden = true)
@Column(columnDefinition = "TEXT")
@JsonIgnore
private String params;
public Goods() {
}
@ -206,7 +213,6 @@ public class Goods extends BaseEntity {
this.sn = goodsOperationDTO.getSn();
this.price = goodsOperationDTO.getPrice();
this.weight = goodsOperationDTO.getWeight();
this.freightPayer = goodsOperationDTO.getFreightPayer();
this.templateId = goodsOperationDTO.getTemplateId();
this.recommend = goodsOperationDTO.isRecommend();
this.sellingPoint = goodsOperationDTO.getSellingPoint();
@ -215,11 +221,35 @@ public class Goods extends BaseEntity {
this.intro = goodsOperationDTO.getIntro();
this.mobileIntro = goodsOperationDTO.getMobileIntro();
this.cost = goodsOperationDTO.getCost();
if (goodsOperationDTO.getGoodsParamsList() != null && goodsOperationDTO.getGoodsParamsList().isEmpty()) {
this.params = JSONUtil.toJsonStr(goodsOperationDTO.getGoodsParamsList());
if (goodsOperationDTO.getGoodsParamsDTOList() != null && goodsOperationDTO.getGoodsParamsDTOList().isEmpty()) {
this.params = JSONUtil.toJsonStr(goodsOperationDTO.getGoodsParamsDTOList());
}
//如果立即上架则
this.marketEnable = goodsOperationDTO.isRelease() ? GoodsStatusEnum.UPPER.name() : GoodsStatusEnum.DOWN.name();
this.goodsType = goodsOperationDTO.getGoodsType();
//循环sku判定sku是否有效
for (Map<String, Object> sku : goodsOperationDTO.getSkuList()) {
//判定参数不能为空
if (sku.get("sn") == null) {
throw new ServiceException(ResultCode.GOODS_SKU_SN_ERROR);
}
if (StringUtil.isEmpty(sku.get("price").toString()) || Integer.parseInt( sku.get("price").toString()) <= 0) {
throw new ServiceException(ResultCode.GOODS_SKU_PRICE_ERROR);
}
if (StringUtil.isEmpty(sku.get("cost").toString()) || Integer.parseInt( sku.get("cost").toString()) <= 0) {
throw new ServiceException(ResultCode.GOODS_SKU_COST_ERROR);
}
//虚拟商品没有重量字段
if(sku.containsKey("weight")) {
if (StringUtil.isEmpty(sku.get("weight").toString()) || Integer.parseInt(sku.get("weight").toString()) < 0) {
throw new ServiceException(ResultCode.GOODS_SKU_WEIGHT_ERROR);
}
}
if (StringUtil.isEmpty(sku.get("quantity").toString()) || Integer.parseInt( sku.get("quantity").toString()) < 0) {
throw new ServiceException(ResultCode.GOODS_SKU_QUANTITY_ERROR);
}
}
}
}

View File

@ -1,55 +0,0 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 商品关联参数
*
* @author pikachu
* @date 2020-02-23 9:14:33
*/
@Data
@Entity
@Table(name = "li_goods_params")
@TableName("li_goods_params")
@ApiModel(value = "商品关联参数")
public class GoodsParams extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 商品id
*/
@TableField(value = "goods_id")
@ApiModelProperty(value = "商品id", hidden = true)
private String goodsId;
/**
* 参数id
*/
@TableField(value = "param_id")
@ApiModelProperty(value = "参数id", required = true)
private String paramId;
/**
* 参数名字
*/
@TableField(value = "param_name")
@ApiModelProperty(value = "参数名字", required = true)
private String paramName;
/**
* 参数值
*/
@TableField(value = "param_value")
@ApiModelProperty(value = "参数值", required = true)
@Length(max = 100, message = "参数值字符不能大于120")
private String paramValue;
}

View File

@ -131,8 +131,6 @@ public class GoodsSku extends BaseEntity {
@ApiModelProperty(value = "运费模板id")
private String templateId;
@ApiModelProperty(value = " 谁承担运费 BUYER买家承担STORE卖家承担")
private String freightPayer;
/**
* @see GoodsAuthEnum
*/
@ -160,6 +158,18 @@ public class GoodsSku extends BaseEntity {
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
*/
@ApiModelProperty(value = "商品类型", required = true)
private String goodsType;
public Double getWeight() {
if (weight == null) {
return 0d;
}
return weight;
}
@Override
public Date getUpdateTime() {

View File

@ -1,13 +1,17 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.base.BaseEntity;
import cn.lili.base.IdEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
@ -25,7 +29,9 @@ import javax.validation.constraints.NotNull;
@Table(name = "li_parameters")
@TableName("li_parameters")
@ApiModel(value = "商品参数")
public class Parameters extends BaseEntity {
public class Parameters extends IdEntity {
private static final long serialVersionUID = -566510714456317006L;
@ -36,6 +42,7 @@ public class Parameters extends BaseEntity {
@ApiModelProperty(value = "选择值")
@NotEmpty(message = "参数选项值必填")
private String options;
@ApiModelProperty(value = "是否可索引0 不显示 1 显示", required = true)

View File

@ -1,42 +0,0 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Table;
/**
* 规格值
*
* @author pikachu
* @date 2020-02-18 15:18:56
*/
@Data
@Entity
@Table(name = "li_spec_values")
@TableName("li_spec_values")
@ApiModel(value = "规格值")
public class SpecValues extends BaseEntity {
private static final long serialVersionUID = 1L;
/**
* 规格项id
*/
@TableField(value = "spec_id")
@ApiModelProperty(value = "规格项id")
private String specId;
/**
* 规格值名字
*/
@TableField(value = "spec_value")
@ApiModelProperty(value = "规格值名字")
private String specValue;
}

View File

@ -1,11 +1,13 @@
package cn.lili.modules.goods.entity.dos;
import cn.lili.base.BaseEntity;
import cn.lili.base.IdEntity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.NotEmpty;
@ -21,7 +23,7 @@ import javax.validation.constraints.NotEmpty;
@Table(name = "li_specification")
@TableName("li_specification")
@ApiModel(value = "规格项")
public class Specification extends BaseEntity {
public class Specification extends IdEntity {
private static final long serialVersionUID = 147792597901239486L;
@ -34,9 +36,19 @@ public class Specification extends BaseEntity {
/**
* 所属卖家 0属于平台
* <p>
* 店铺自定义规格暂时废弃 2021-06-23 后续推出新配置方式
*/
@ApiModelProperty(hidden = true)
private String storeId;
/**
* 规格值名字
*/
@TableField(value = "spec_value")
@Column(columnDefinition = "TEXT")
@ApiModelProperty(value = "规格值名字, 《,》分割")
private String specValue;
}

View File

@ -1,7 +1,6 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.modules.goods.entity.dos.DraftGoods;
import cn.lili.modules.goods.entity.dos.GoodsParams;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -22,7 +21,7 @@ public class DraftGoodsDTO extends DraftGoods {
@ApiModelProperty(value = "商品参数")
@Valid
private List<GoodsParams> goodsParamsList;
private List<GoodsParamsDTO> goodsParamsDTOList;
@ApiModelProperty(value = "商品图片")
private List<String> goodsGalleryList;

View File

@ -1,6 +1,5 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.modules.goods.entity.dos.GoodsParams;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
@ -16,7 +15,7 @@ import java.util.List;
import java.util.Map;
/**
* 商品查询条件
* 商品编辑DTO
*
* @author pikachu
* @date 2020-02-24 19:27:20
@ -66,9 +65,6 @@ public class GoodsOperationDTO implements Serializable {
@Max(value = 99999999, message = "重量不能超过99999999")
private Double weight;
@ApiModelProperty(value = "谁承担运费 BUYER买家承担STORE卖家承担", required = true)
private String freightPayer;
@ApiModelProperty(value = "详情")
private String intro;
@ -86,8 +82,7 @@ public class GoodsOperationDTO implements Serializable {
private boolean recommend;
@ApiModelProperty(value = "商品参数")
@Valid
private List<GoodsParams> goodsParamsList;
private List<GoodsParamsDTO> goodsParamsDTOList;
@ApiModelProperty(value = "商品图片")
private List<String> goodsGalleryList;
@ -118,4 +113,13 @@ public class GoodsOperationDTO implements Serializable {
@ApiModelProperty(value = "是否重新生成sku数据")
private Boolean regeneratorSkuFlag = true;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
*/
@ApiModelProperty(value = "商品类型")
private String goodsType;
}

View File

@ -0,0 +1,31 @@
package cn.lili.modules.goods.entity.dto;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
* 商品关联参数
*
* @author pikachu
* @date 2020-02-23 9:14:33
*/
@Data
@ApiModel(value = "商品参数分组")
public class GoodsParamsDTO {
@TableField(value = "group_id")
@ApiModelProperty(value = "分组id")
private String groupId;
@TableField(value = "group_name")
@ApiModelProperty(value = "分组名称")
private String groupName;
@ApiModelProperty(value = "分组内的商品参数列表")
private List<GoodsParamsItemDTO> goodsParamsItemDTOList;
}

View File

@ -0,0 +1,35 @@
package cn.lili.modules.goods.entity.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
/**
* 商品参数项
*
* @author Chopper
* @version v1.0
* 2021-06-24 15:41
*/
@Data
@ApiModel(value = "商品参数列表")
public class GoodsParamsItemDTO {
@ApiModelProperty(value = "参数ID")
private String paramId;
@ApiModelProperty(value = "参数名字")
private String paramName;
@ApiModelProperty(value = "参数值")
private String paramValue;
@ApiModelProperty(value = "是否可索引0 不索引 1 索引")
private Integer isIndex = 0;
@ApiModelProperty(value = "是否必填0 不显示 1 显示")
private Integer required = 0;
}

View File

@ -67,6 +67,12 @@ public class GoodsSearchParams extends PageVO {
@ApiModelProperty(value = "是否为推荐商品")
private Boolean recommend;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
*/
@ApiModelProperty(value = "商品类型")
private String goodsType;
public <T> QueryWrapper<T> queryWrapper() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
if (StringUtils.isNotEmpty(goodsId)) {
@ -108,6 +114,10 @@ public class GoodsSearchParams extends PageVO {
if (recommend != null) {
queryWrapper.le("recommend", recommend);
}
if (goodsType != null) {
queryWrapper.eq("goods_type", goodsType);
}
queryWrapper.eq("delete_flag", false);
this.betweenWrapper(queryWrapper);
return queryWrapper;

View File

@ -1,34 +0,0 @@
package cn.lili.modules.goods.entity.dto;
import cn.lili.common.utils.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 规格搜索参数
*
* @author paulG
* @date 2020/12/19
**/
@Data
public class SpecificationSearchParams {
@ApiModelProperty(value = "规格名")
private String specName;
@ApiModelProperty(value = "绑定分类")
private String categoryPath;
@ApiModelProperty(value = "未删除 ")
private Boolean deleteFlag;
public <T> QueryWrapper<T> queryWrapper() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.like(StringUtils.isNotEmpty(specName), "spec_name", specName);
queryWrapper.eq(deleteFlag != null, "delete_flag", deleteFlag);
return queryWrapper;
}
}

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