From d5cd5518fb4c9ec771dbf3d8db691fef36d18a45 Mon Sep 17 00:00:00 2001 From: mitao <2763622819@qq.com> Date: 星期五, 31 五月 2024 17:47:38 +0800 Subject: [PATCH] 提交【管理后台】-拍卖场管理相关接口 --- ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionGoodsController.java | 2 ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionSalesroomController.java | 2 ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java | 50 +++++ ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/feignClient/AuctionClient.java | 12 + ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionSalesroomServiceImpl.java | 14 + ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeckillController.java | 2 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/DelayTaskEnum.java | 2 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsInfoTitleController.java | 2 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeriesController.java | 2 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java | 12 + ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/async/AuctionAsyncMethodService.java | 126 ++++++++++++++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java | 71 ++++--- ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsGroupPurchaseController.java | 2 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/vo/GoodsSkuVO.java | 5 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/task/GoodsScheduler.java | 9 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java | 19 ++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSkuController.java | 2 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/AuctionFallbackFactory.java | 10 + ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/IAuctionGoodsService.java | 5 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsBrandController.java | 2 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java | 5 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/NotificationTypeConstant.java | 1 ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/inner/AuctionGoodsController.java | 52 +++++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSeckillServiceImpl.java | 13 + ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/task/AuctionGoodsScheduler.java | 45 +++++ ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsCategoryController.java | 2 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/DelayTaskController.java | 3 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/GoodsSku.java | 16 + ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionBrowseRecordServiceImpl.java | 7 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsFlavorTypeController.java | 2 ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/dto/GoodsSkuDTO.java | 5 31 files changed, 424 insertions(+), 78 deletions(-) diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/DelayTaskEnum.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/DelayTaskEnum.java index 5e0e3b2..ba8924e 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/DelayTaskEnum.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/DelayTaskEnum.java @@ -14,6 +14,8 @@ SECKILL_END_TASK("秒杀商品延时任务", "秒杀商品定时结束任务"), GROUP_PURCHASES_START_TASK("团购商品延时任务", "团购商品定时开始任务"), GROUP_PURCHASES_END_TASK("团购商品延时任务", "团购商品定时结束任务"), + AUCTION_GOODS_START_TASK("拍卖商品延时任务", "拍卖商品定时开始任务"), + AUCTION_GOODS_END_TASK("拍卖商品延时任务", "拍卖商品定时结束任务"), ; String name; diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/NotificationTypeConstant.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/NotificationTypeConstant.java index b5e2e23..4933c60 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/NotificationTypeConstant.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/constants/NotificationTypeConstant.java @@ -8,4 +8,5 @@ String SECKILL = "seckill"; String GROUP_PURCHASE = "group_purchase"; + String AUCTION_GOODS = "auction_goods"; } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/GoodsSku.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/GoodsSku.java index 5cd8685..9d1417d 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/GoodsSku.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/domain/GoodsSku.java @@ -1,16 +1,20 @@ package com.ruoyi.system.api.domain; -import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.enums.ListingStatusEnum; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; /** * <p> @@ -37,7 +41,7 @@ private String skuName; @ApiModelProperty(value = "商品年份") - private String years; + private LocalDateTime years; @ApiModelProperty(value = "商品分类id") private Long categoryId; diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/AuctionFallbackFactory.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/AuctionFallbackFactory.java index f6721f3..6b0bdfb 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/AuctionFallbackFactory.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/AuctionFallbackFactory.java @@ -4,7 +4,6 @@ import com.ruoyi.system.api.domain.AuctionGoods; import com.ruoyi.system.api.domain.AuctionSalesroom; import com.ruoyi.system.api.feignClient.AuctionClient; -import com.ruoyi.system.api.feignClient.OrderClient; import org.springframework.cloud.openfeign.FallbackFactory; /** @@ -27,6 +26,15 @@ return R.fail("获取普通拍卖商品失败" + cause.getMessage()); } + @Override + public R<?> endAuctionGoods(Long id, String source) { + return R.fail("结束普通拍卖商品失败" + cause.getMessage()); + } + + @Override + public R<?> startAuctionGoods(Long id, String source) { + return R.fail("开始普通拍卖商品失败" + cause.getMessage()); + } }; } } diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/feignClient/AuctionClient.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/feignClient/AuctionClient.java index a40a52a..2ff5881 100644 --- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/feignClient/AuctionClient.java +++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/feignClient/AuctionClient.java @@ -5,11 +5,11 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.system.api.domain.AuctionGoods; import com.ruoyi.system.api.domain.AuctionSalesroom; -import com.ruoyi.system.api.domain.GoodsFlavorType; -import com.ruoyi.system.api.domain.OrderAuctionBond; import com.ruoyi.system.api.factory.AuctionFallbackFactory; import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; @@ -22,4 +22,12 @@ @PostMapping("/forepart/auction-goods/getAuctionGoodsOne") R<AuctionGoods> getauctionGoodsOne(@RequestBody Long auctionGoodsId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + @PutMapping("/auction-goods/end/{id}") + R<?> endAuctionGoods(@PathVariable("id") Long id, + @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + @PutMapping("/auction-goods/start/{id}") + R<?> startAuctionGoods(@PathVariable("id") Long id, + @RequestHeader(SecurityConstants.FROM_SOURCE) String source); } diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/inner/AuctionGoodsController.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/inner/AuctionGoodsController.java new file mode 100644 index 0000000..4e67aac --- /dev/null +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/inner/AuctionGoodsController.java @@ -0,0 +1,52 @@ +package com.ruoyi.auction.controller.inner; + + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.ruoyi.auction.service.IAuctionGoodsService; +import com.ruoyi.common.core.domain.R; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * <p> + * 拍卖商品表 前端控制器 + * </p> + * + * @author mitao + * @since 2024-05-16 + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/auction-goods") +public class AuctionGoodsController { + + private final IAuctionGoodsService auctionGoodsService; + + @PutMapping("/auction-goods/end/{id}") + R<?> endAuctionGoods(@PathVariable("id") Long id) { + try { + auctionGoodsService.endAuctionGoods(id); + } catch (JsonProcessingException e) { + log.error("结束拍卖商品异常", e); + return R.fail(); + } + return R.ok(); + } + + @PutMapping("/auction-goods/start/{id}") + R<?> startAuctionGoods(@PathVariable("id") Long id) { + try { + auctionGoodsService.startAuctionGoods(id); + } catch (JsonProcessingException e) { + log.error("开始拍卖商品异常", e); + return R.fail(); + } + return R.ok(); + } + +} diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionGoodsController.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionGoodsController.java index f27ae1a..693e5ff 100644 --- a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionGoodsController.java +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionGoodsController.java @@ -27,7 +27,7 @@ * @author mitao * @since 2024-05-16 */ -@Api(value = "拍卖商品管理相关接口", tags = {"管理后台接口"}) +@Api(value = "拍卖商品管理相关接口", tags = {"管理后台-拍卖商品管理相关接口"}) @RestController @RequiredArgsConstructor @RequestMapping("/mgt/auction-goods") diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionSalesroomController.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionSalesroomController.java index 0bad556..f80f3db 100644 --- a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionSalesroomController.java +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/controller/management/MgtAuctionSalesroomController.java @@ -33,7 +33,7 @@ @RestController @RequestMapping("/mgt/auction-salesroom") @RequiredArgsConstructor -@Api(value = "拍卖场管理相关接口", tags = {"管理后台接口"}) +@Api(value = "拍卖场管理相关接口", tags = {"管理后台-拍卖场管理相关接口"}) public class MgtAuctionSalesroomController { private final IAuctionSalesroomService auctionSalesroomService; diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/IAuctionGoodsService.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/IAuctionGoodsService.java index 9837cdf..649b04a 100644 --- a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/IAuctionGoodsService.java +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/IAuctionGoodsService.java @@ -1,6 +1,7 @@ package com.ruoyi.auction.service; import com.baomidou.mybatisplus.extension.service.IService; +import com.fasterxml.jackson.core.JsonProcessingException; import com.ruoyi.auction.controller.management.dto.MgtAuctionGoodsDTO; import com.ruoyi.auction.controller.management.dto.MgtAuctionGoodsQuery; import com.ruoyi.auction.controller.management.vo.MgtAuctionGoodsVO; @@ -50,4 +51,8 @@ AuctionGoodsinfoVO getAuctionGoodsInfo(@RequestBody AuctionGoodsListDTO auctionGoodsListDTO); PageDTO<AuctionGoodsListVO> getWdAuctionSalesList(@RequestBody AuctionGoodsListDTO auctionGoodsListDTO); + + void endAuctionGoods(Long id) throws JsonProcessingException; + + void startAuctionGoods(Long id) throws JsonProcessingException; } diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/async/AuctionAsyncMethodService.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/async/AuctionAsyncMethodService.java new file mode 100644 index 0000000..2886e27 --- /dev/null +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/async/AuctionAsyncMethodService.java @@ -0,0 +1,126 @@ +package com.ruoyi.auction.service.async; + +import com.ruoyi.common.core.constant.SecurityConstants; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.redis.service.RedisService; +import com.ruoyi.system.api.constants.DelayTaskEnum; +import com.ruoyi.system.api.domain.AuctionGoods; +import com.ruoyi.system.api.domain.DelayTask; +import com.ruoyi.system.api.feignClient.SysUserClient; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.TimeUnit; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * @author mitao + * @date 2024/5/24 + */ +@Service +@Slf4j +@RequiredArgsConstructor +public class AuctionAsyncMethodService { + + private final RedisService redisService; + private final SysUserClient sysUserClient; + + @Async + @Transactional(rollbackFor = Exception.class) + public void auctionGoodsScheduleTask(List<AuctionGoods> auctionGoodsList) { + for (AuctionGoods auctionGoods : auctionGoodsList) { + LocalDateTime startTime = auctionGoods.getStartTime(); + LocalDateTime endTime = auctionGoods.getEndTime(); + // 普通拍品在一小时内开始 + if (isWithinOneHour(startTime)) { + Long id = auctionGoods.getId(); + // 普通拍品已经开始,三秒后执行 + if (LocalDateTime.now().isAfter(startTime)) { + handleStartDelayTask(id, DelayTaskEnum.AUCTION_GOODS_START_TASK, startTime, 3L); + } else { + Duration duration = Duration.between(LocalDateTime.now(), startTime); + handleStartDelayTask(id, DelayTaskEnum.AUCTION_GOODS_START_TASK, startTime, + duration.getSeconds()); + } + // 普通拍品结束延时任务 + handleEndDelayTask(id, DelayTaskEnum.AUCTION_GOODS_END_TASK, endTime); + } + } + } + + private boolean isWithinOneHour(LocalDateTime startTime) { + LocalDateTime checkTime = LocalDateTime.now().plusHours(1); + return checkTime.isAfter(startTime); + } + + private void handleEndDelayTask(Long id, DelayTaskEnum delayTaskEnum, LocalDateTime endTime) { + String endTaskKey = delayTaskEnum.getCode() + "-" + id; + DelayTask endDelayTask = sysUserClient.getDelayTask( + endTaskKey, SecurityConstants.INNER).getData(); + // 如果延时任务为空,创建延时任务控制活动定时开始和结束 + Duration duration = Duration.between(LocalDateTime.now(), endTime); + if (StringUtils.isNull(endDelayTask)) { + createEndDelayTask(endTime, endTaskKey, duration); + } else { + if (!endDelayTask.getExecuteTime().isEqual(endTime)) { + sysUserClient.deleteDelayTask(endTaskKey, + SecurityConstants.INNER); + redisService.deleteObject(endTaskKey); + createEndDelayTask(endTime, endTaskKey, duration); + } + } + log.info(">>>>>>>>>>>>>>>>>>>>延时任务{}执行了<<<<<<<<<<<<<<<<<<<<", endTaskKey); + } + + private void createEndDelayTask(LocalDateTime endTime, String seckillEndTaskKey, + Duration duration) { + DelayTask endDelayTask; + redisService.setCacheObject( + seckillEndTaskKey, + endTime, duration.getSeconds(), TimeUnit.SECONDS); + endDelayTask = new DelayTask(); + endDelayTask.setDelFlag(0); + endDelayTask.setCreateTime(LocalDateTime.now()); + endDelayTask.setExecuteTime(endTime); + endDelayTask.setRedisKey(seckillEndTaskKey); + sysUserClient.addDelayTask(endDelayTask, SecurityConstants.INNER); + } + + private void handleStartDelayTask(Long id, DelayTaskEnum delayTaskEnum, LocalDateTime startTime, + Long timeout) { + String startTaskKey = delayTaskEnum.getCode() + "-" + id; + redisService.setCacheObject( + startTaskKey, + startTime, timeout, TimeUnit.SECONDS); + // 查询延时任务 + DelayTask startDelayTask = sysUserClient.getDelayTask( + startTaskKey, SecurityConstants.INNER).getData(); + if (StringUtils.isNull(startDelayTask)) { + startDelayTask = new DelayTask(); + startDelayTask.setDelFlag(0); + startDelayTask.setCreateTime(LocalDateTime.now()); + startDelayTask.setExecuteTime(LocalDateTime.now().plusSeconds(timeout)); + startDelayTask.setRedisKey( + startTaskKey); + sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER); + } else { + if (!startDelayTask.getExecuteTime().isEqual(startTime)) { + sysUserClient.deleteDelayTask( + startTaskKey, SecurityConstants.INNER); + redisService.deleteObject( + startTaskKey); + startDelayTask.setDelFlag(0); + startDelayTask.setCreateTime(LocalDateTime.now()); + startDelayTask.setExecuteTime(LocalDateTime.now().plusSeconds(timeout)); + startDelayTask.setRedisKey( + startTaskKey); + sysUserClient.addDelayTask(startDelayTask, SecurityConstants.INNER); + } + } + log.info(">>>>>>>>>>>>>>>>>>>>延时任务{}执行了<<<<<<<<<<<<<<<<<<<<", startTaskKey); + } +} diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionBrowseRecordServiceImpl.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionBrowseRecordServiceImpl.java index 75efe65..41d7120 100644 --- a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionBrowseRecordServiceImpl.java +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionBrowseRecordServiceImpl.java @@ -3,12 +3,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.auction.domain.AuctionBrowseRecord; import com.ruoyi.auction.mapper.AuctionBrowseRecordMapper; import com.ruoyi.auction.mapper.AuctionGoodsMapper; import com.ruoyi.auction.mapper.AuctionSalesroomMapper; import com.ruoyi.auction.service.IAuctionBrowseRecordService; -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.page.PageDTO; @@ -24,15 +24,14 @@ import com.ruoyi.system.api.domain.vo.WdMemberAuctionSalesroomVO; import com.ruoyi.system.api.feignClient.GoodsSkuClient; import com.ruoyi.system.api.feignClient.OrderClient; -import org.springframework.stereotype.Service; - -import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.stream.Collectors; +import javax.annotation.Resource; +import org.springframework.stereotype.Service; /** * <p> diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java index 69c7b40..625ec40 100644 --- a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionGoodsServiceImpl.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.Lists; import com.ruoyi.auction.controller.management.dto.MgtAuctionGoodsDTO; import com.ruoyi.auction.controller.management.dto.MgtAuctionGoodsQuery; @@ -17,16 +19,19 @@ import com.ruoyi.auction.service.IAuctionBrowseRecordService; import com.ruoyi.auction.service.IAuctionGoodsService; import com.ruoyi.auction.service.IMemberAuctionCollectionService; +import com.ruoyi.auction.service.async.AuctionAsyncMethodService; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.enums.AuctionOrderTypeEnum; import com.ruoyi.common.core.enums.AuctionStartStatusEnum; import com.ruoyi.common.core.enums.BidStatusEnum; import com.ruoyi.common.core.enums.BondStatusEnum; +import com.ruoyi.common.core.enums.ListingStatusEnum; import com.ruoyi.common.core.enums.OrderFromEnum; import com.ruoyi.common.core.exception.ServiceException; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.page.BeanUtils; import com.ruoyi.common.core.utils.page.PageDTO; +import com.ruoyi.system.api.constants.NotificationTypeConstant; import com.ruoyi.system.api.domain.AuctionGoods; import com.ruoyi.system.api.domain.GoodsBrand; import com.ruoyi.system.api.domain.GoodsCategory; @@ -47,6 +52,7 @@ import com.ruoyi.system.api.feignClient.GoodsSkuClient; import com.ruoyi.system.api.feignClient.MemberClient; import com.ruoyi.system.api.feignClient.OrderClient; +import com.ruoyi.system.api.util.WebSocketUsers; import io.seata.spring.annotation.GlobalTransactional; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -55,6 +61,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import javax.annotation.Resource; import lombok.RequiredArgsConstructor; @@ -79,7 +86,9 @@ private final MemberClient memberClient; private final OrderClient orderClient; private final IAuctionBidRecordService auctionBidRecordService; - + private final AuctionAsyncMethodService auctionAsyncMethodService; + // 创建一个静态共享的ObjectMapper实例以重用 + private static final ObjectMapper objectMapper = new ObjectMapper(); @Resource private IMemberAuctionCollectionService memberAuctionCollectionService; @@ -186,6 +195,7 @@ auctionGoodsOrg.getAuctionStock() - dto.getAuctionStock()); goodsSkuClient.updGoodsStock(Lists.newArrayList(goodsStockUpdDTO), SecurityConstants.INNER); + auctionAsyncMethodService.auctionGoodsScheduleTask(Lists.newArrayList(auctionGoods)); } } @@ -516,4 +526,42 @@ page.setRecords(auctionGoodsVOS); return PageDTO.of(page); } + + @Override + public void endAuctionGoods(Long id) throws JsonProcessingException { + AuctionGoods auctionGoods = this.getById(id); + if (StringUtils.isNotNull(auctionGoods) && auctionGoods.getListingStatus().equals( + ListingStatusEnum.ON_SHELVES) && auctionGoods.getStartStatus() + .equals(AuctionStartStatusEnum.IN_PREVIEW)) { + this.lambdaUpdate().set(AuctionGoods::getStartStatus, AuctionStartStatusEnum.IN_AUCTION) + .eq(AuctionGoods::getId, id); + Map<String, Object> map = new ConcurrentHashMap<>(); + map.put("notification_type", NotificationTypeConstant.AUCTION_GOODS); + map.put("notification_time", LocalDateTime.now()); + map.put("target_id", id); + map.put("message_type", "start"); + String msg = objectMapper.writeValueAsString(map); + WebSocketUsers.sendMessageToUsersByText(msg); + log.info("===================>发送websocket通知,消息体{}", msg); + } + } + + @Override + public void startAuctionGoods(Long id) throws JsonProcessingException { + AuctionGoods auctionGoods = this.getById(id); + if (StringUtils.isNotNull(auctionGoods) && auctionGoods.getListingStatus().equals( + ListingStatusEnum.ON_SHELVES) && auctionGoods.getStartStatus() + .equals(AuctionStartStatusEnum.IN_AUCTION)) { + this.lambdaUpdate().set(AuctionGoods::getStartStatus, AuctionStartStatusEnum.ENDED) + .eq(AuctionGoods::getId, id); + Map<String, Object> map = new ConcurrentHashMap<>(); + map.put("notification_type", NotificationTypeConstant.AUCTION_GOODS); + map.put("notification_time", LocalDateTime.now()); + map.put("target_id", id); + map.put("message_type", "end"); + String msg = objectMapper.writeValueAsString(map); + WebSocketUsers.sendMessageToUsersByText(msg); + log.info("===================>发送websocket通知,消息体{}", msg); + } + } } diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionSalesroomServiceImpl.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionSalesroomServiceImpl.java index 527a996..5df7320 100644 --- a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionSalesroomServiceImpl.java +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/service/impl/AuctionSalesroomServiceImpl.java @@ -1,6 +1,5 @@ package com.ruoyi.auction.service.impl; -import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult; import com.alibaba.fastjson.JSONObject; import com.alipay.api.AlipayApiException; @@ -32,7 +31,12 @@ import com.ruoyi.auction.domain.AuctionVideo; import com.ruoyi.auction.mapper.AuctionSalesroomGoodsMapper; import com.ruoyi.auction.mapper.AuctionSalesroomMapper; -import com.ruoyi.auction.service.*; +import com.ruoyi.auction.service.IAuctionBidRecordService; +import com.ruoyi.auction.service.IAuctionBrowseRecordService; +import com.ruoyi.auction.service.IAuctionGoodsService; +import com.ruoyi.auction.service.IAuctionSalesroomGoodsService; +import com.ruoyi.auction.service.IAuctionSalesroomService; +import com.ruoyi.auction.service.IAuctionVideoService; import com.ruoyi.auction.util.CreateQrCode; import com.ruoyi.auction.util.HttpUtils; import com.ruoyi.common.core.constant.SecurityConstants; @@ -105,8 +109,8 @@ @Resource private SysUserClient sysUserClient; - @Resource - private WxMaService wxMaService; + // @Resource + // private WxMaService wxMaService; @Resource private AuctionSalesroomGoodsMapper auctionSalesroomGoodsMapper; @@ -260,7 +264,7 @@ String openid; String sessionKey = null; //获取session - session = wxMaService.getUserService().getSessionInfo(appMiniLoginDto.getCode()); + // session = wxMaService.getUserService().getSessionInfo(appMiniLoginDto.getCode()); if (session != null && StringUtils.isNotBlank(session.getOpenid())) { unionid = session.getUnionid(); openid = session.getOpenid(); diff --git a/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/task/AuctionGoodsScheduler.java b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/task/AuctionGoodsScheduler.java new file mode 100644 index 0000000..6e1d109 --- /dev/null +++ b/ruoyi-modules/ruoyi-auction/src/main/java/com/ruoyi/auction/task/AuctionGoodsScheduler.java @@ -0,0 +1,45 @@ +package com.ruoyi.auction.task; + +import com.ruoyi.auction.service.IAuctionGoodsService; +import com.ruoyi.auction.service.async.AuctionAsyncMethodService; +import com.ruoyi.common.core.enums.ListingStatusEnum; +import com.ruoyi.common.core.enums.StartStatusEnum; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.system.api.domain.AuctionGoods; +import java.time.LocalDateTime; +import java.util.List; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * @author mitao + * @date 2024/5/24 + */ +@Slf4j +@Component +@RequiredArgsConstructor +public class AuctionGoodsScheduler { + + private final AuctionAsyncMethodService asyncMethodService; + private final IAuctionGoodsService auctionGoodsService; + + @Scheduled(cron = "0 0 */1 * * ?") + private void timingTask() { + handleTaskStart(); + } + + private void handleTaskStart() { + log.info(">>>>>>>>>>>>>>>>>>>>定时任务秒杀/团购开始执行<<<<<<<<<<<<<<<<<<<<"); + LocalDateTime checkTime = LocalDateTime.now().plusHours(1); + List<AuctionGoods> list = auctionGoodsService.lambdaQuery() + .eq(AuctionGoods::getListingStatus, ListingStatusEnum.ON_SHELVES) + .eq(AuctionGoods::getStartStatus, StartStatusEnum.NOT_STARTED) + .le(AuctionGoods::getStartTime, checkTime) + .list(); + if (StringUtils.isNotEmpty(list)) { + asyncMethodService.auctionGoodsScheduleTask(list); + } + } +} diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsBrandController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsBrandController.java index 2e12dad..1c8ace4 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsBrandController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsBrandController.java @@ -31,7 +31,7 @@ @RestController @RequestMapping("/mgt/goods-brand") @RequiredArgsConstructor -@Api(value = "管理后台商品品牌相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品品牌相关接口", tags = {"管理后台-商品品牌相关接口"}) public class MgtGoodsBrandController { private final IGoodsBrandService goodsBrandService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsCategoryController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsCategoryController.java index df111a8..bc47ed0 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsCategoryController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsCategoryController.java @@ -31,7 +31,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/mgt/goods-category") -@Api(value = "管理后台商品分类相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品分类相关接口", tags = {"管理后台-商品分类相关接口"}) public class MgtGoodsCategoryController { private final IGoodsCategoryService goodsCategoryService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsFlavorTypeController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsFlavorTypeController.java index dd51aed..1d669bd 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsFlavorTypeController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsFlavorTypeController.java @@ -31,7 +31,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/mgt/goods-flavor-type") -@Api(value = "管理后台商品香型相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品香型相关接口", tags = {"管理后台-商品香型相关接口"}) public class MgtGoodsFlavorTypeController { private final IGoodsFlavorTypeService goodsFlavorTypeService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsGroupPurchaseController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsGroupPurchaseController.java index 3f9be24..6836f5b 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsGroupPurchaseController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsGroupPurchaseController.java @@ -33,7 +33,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/mgt/goods-group-purchase") -@Api(value = "管理后台商品团购相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品团购相关接口", tags = {"管理后台-商品团购相关接口"}) public class MgtGoodsGroupPurchaseController { private final IGoodsGroupPurchaseService goodsGroupPurchaseService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsInfoTitleController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsInfoTitleController.java index b0121d3..f437fac 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsInfoTitleController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsInfoTitleController.java @@ -31,7 +31,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/mgt/goods-info-title") -@Api(value = "管理后台商品信息标题相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品信息标题相关接口", tags = {"管理后台-商品信息标题相关接口"}) public class MgtGoodsInfoTitleController { private final IGoodsInfoTitleService goodsInfoTitleService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeckillController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeckillController.java index 1b619ed..07a399f 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeckillController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeckillController.java @@ -34,7 +34,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/mgt/goods-seckill") -@Api(value = "管理后台商品秒杀相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品秒杀相关接口", tags = {"管理后台-商品秒杀相关接口"}) public class MgtGoodsSeckillController { private final IGoodsSeckillService goodsSeckillService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeriesController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeriesController.java index 03c3813..d429433 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeriesController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSeriesController.java @@ -31,7 +31,7 @@ @RestController @RequiredArgsConstructor @RequestMapping("/mgt/goods-series") -@Api(value = "管理后台商品系列相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品系列相关接口", tags = {"管理后台-商品系列相关接口"}) public class MgtGoodsSeriesController { private final IGoodsSeriesService goodsSeriesService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSkuController.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSkuController.java index 3088b3d..fee2a8c 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSkuController.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/MgtGoodsSkuController.java @@ -45,7 +45,7 @@ @RestController @RequestMapping("/mgt/goods-sku") @RequiredArgsConstructor -@Api(value = "管理后台商品相关接口", tags = {"管理后台接口"}) +@Api(value = "管理后台商品相关接口", tags = {"管理后台-商品相关接口"}) public class MgtGoodsSkuController { private final IGoodsSkuService goodsSkuService; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/dto/GoodsSkuDTO.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/dto/GoodsSkuDTO.java index 99f1560..d4eeeea 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/dto/GoodsSkuDTO.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/dto/GoodsSkuDTO.java @@ -1,9 +1,11 @@ package com.ruoyi.goods.controller.management.dto; +import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.List; import javax.validation.Valid; import javax.validation.constraints.NotBlank; @@ -30,7 +32,8 @@ @ApiModelProperty(value = "商品年份") @NotBlank(message = "商品年份不能为空") - private String years; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime years; @ApiModelProperty(value = "商品分类id") @NotNull(message = "商品分类id不能为空") diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/vo/GoodsSkuVO.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/vo/GoodsSkuVO.java index 890a6df..b4d1b44 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/vo/GoodsSkuVO.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/controller/management/vo/GoodsSkuVO.java @@ -1,11 +1,13 @@ package com.ruoyi.goods.controller.management.vo; +import com.fasterxml.jackson.annotation.JsonFormat; import com.ruoyi.common.core.enums.ListingStatusEnum; import com.ruoyi.goods.controller.management.dto.GoodsInfoTitleValueDTO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; import java.math.BigDecimal; +import java.time.LocalDateTime; import java.util.List; import lombok.Data; @@ -26,7 +28,8 @@ private String skuName; @ApiModelProperty(value = "商品年份") - private String years; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime years; @ApiModelProperty(value = "商品分类id") private Long categoryId; diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java index fe612a3..b52cbe2 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/async/AsyncMethodService.java @@ -10,6 +10,7 @@ import com.ruoyi.system.api.feignClient.SysUserClient; import java.time.Duration; import java.time.LocalDateTime; +import java.util.List; import java.util.concurrent.TimeUnit; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,48 +32,52 @@ @Async @Transactional(rollbackFor = Exception.class) - public void seckillScheduleTask(GoodsSeckill goodsSeckill) { - LocalDateTime startTime = goodsSeckill.getStartTime(); - LocalDateTime endTime = goodsSeckill.getEndTime(); - //秒杀在一小时内开始 - if (isWithinOneHour(startTime)) { - Long id = goodsSeckill.getId(); - //秒杀已经开始 - if (LocalDateTime.now().isAfter(startTime)) { - handleStartDelayTask(id, DelayTaskEnum.SECKILL_START_TASK, startTime, 3L); - } else { - Duration duration = Duration.between(LocalDateTime.now(), startTime); - handleStartDelayTask(id, DelayTaskEnum.SECKILL_START_TASK, startTime, - duration.getSeconds()); + public void seckillScheduleTask(List<GoodsSeckill> goodsSeckillList) { + for (GoodsSeckill goodsSeckill : goodsSeckillList) { + LocalDateTime startTime = goodsSeckill.getStartTime(); + LocalDateTime endTime = goodsSeckill.getEndTime(); + // 秒杀在一小时内开始 + if (isWithinOneHour(startTime)) { + Long id = goodsSeckill.getId(); + // 秒杀已经开始 + if (LocalDateTime.now().isAfter(startTime)) { + handleStartDelayTask(id, DelayTaskEnum.SECKILL_START_TASK, startTime, 3L); + } else { + Duration duration = Duration.between(LocalDateTime.now(), startTime); + handleStartDelayTask(id, DelayTaskEnum.SECKILL_START_TASK, startTime, + duration.getSeconds()); + } + log.info(">>>>>>>>>>>>>>>>>>>>秒杀商品:{} 开始秒杀<<<<<<<<<<<<<<<<<<<<", id); + // 秒杀结束延时任务 + handleEndDelayTask(id, DelayTaskEnum.SECKILL_END_TASK, endTime); } - log.info(">>>>>>>>>>>>>>>>>>>>秒杀商品:{} 开始秒杀<<<<<<<<<<<<<<<<<<<<", id); - //秒杀结束延时任务 - handleEndDelayTask(id, DelayTaskEnum.SECKILL_END_TASK, endTime); - } } @Async @Transactional(rollbackFor = Exception.class) - public void groupPurchaseScheduleTask(GoodsGroupPurchase groupPurchase) { - LocalDateTime startTime = groupPurchase.getStartTime(); - LocalDateTime endTime = groupPurchase.getEndTime(); - //秒杀在一小时内开始 - if (isWithinOneHour(startTime)) { - Long id = groupPurchase.getId(); - //秒杀已经开始,三秒后执行 - if (LocalDateTime.now().isAfter(startTime)) { - handleStartDelayTask(id, DelayTaskEnum.GROUP_PURCHASES_START_TASK, startTime, 3L); - } else { - Duration duration = Duration.between(LocalDateTime.now(), startTime); - handleStartDelayTask(id, DelayTaskEnum.GROUP_PURCHASES_START_TASK, startTime, - duration.getSeconds()); + public void groupPurchaseScheduleTask(List<GoodsGroupPurchase> groupPurchaseList) { + for (GoodsGroupPurchase goodsGroupPurchase : groupPurchaseList) { + LocalDateTime startTime = goodsGroupPurchase.getStartTime(); + LocalDateTime endTime = goodsGroupPurchase.getEndTime(); + // 团购在一小时内开始 + if (isWithinOneHour(startTime)) { + Long id = goodsGroupPurchase.getId(); + // 团购已经开始,三秒后执行 + if (LocalDateTime.now().isAfter(startTime)) { + handleStartDelayTask(id, DelayTaskEnum.GROUP_PURCHASES_START_TASK, startTime, + 3L); + } else { + Duration duration = Duration.between(LocalDateTime.now(), startTime); + handleStartDelayTask(id, DelayTaskEnum.GROUP_PURCHASES_START_TASK, startTime, + duration.getSeconds()); + } + // 团购结束延时任务 + handleEndDelayTask(id, DelayTaskEnum.GROUP_PURCHASES_END_TASK, endTime); } - //秒杀结束延时任务 - handleEndDelayTask(id, DelayTaskEnum.GROUP_PURCHASES_END_TASK, endTime); } } - + private boolean isWithinOneHour(LocalDateTime startTime) { LocalDateTime checkTime = LocalDateTime.now().plusHours(1); return checkTime.isAfter(startTime); diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java index ffe3bfc..1991a32 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsGroupPurchaseServiceImpl.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.enums.GroupStatusEnum; import com.ruoyi.common.core.enums.ListingStatusEnum; @@ -119,7 +120,7 @@ .ge(GoodsSku::getStock, latestStock) .eq(GoodsSku::getId, goodsSku.getId()); this.updateById(goodsGroupPurchase); - asyncMethodService.groupPurchaseScheduleTask(goodsGroupPurchase); + asyncMethodService.groupPurchaseScheduleTask(Lists.newArrayList(goodsGroupPurchase)); } } @@ -180,12 +181,15 @@ public void startGroupPurchase(Long groupPurchaseId) throws JsonProcessingException { log.info(">>>>>>>>>>>>>>>>>>>>{}团购商品开始团购<<<<<<<<<<<<<<<<<<<<", groupPurchaseId); GoodsGroupPurchase groupPurchase = this.getById(groupPurchaseId); - if (StringUtils.isNotNull(groupPurchase)) { + if (StringUtils.isNotNull(groupPurchase) && groupPurchase.getStartStatus() + .equals(StartStatusEnum.NOT_STARTED) && groupPurchase.getListingStatus() + .equals(ListingStatusEnum.ON_SHELVES)) { this.lambdaUpdate().set(GoodsGroupPurchase::getStartStatus, StartStatusEnum.STARTED) .eq(GoodsGroupPurchase::getId, groupPurchaseId).update(); Map<String, Object> map = new ConcurrentHashMap<>(); map.put("notification_type", NotificationTypeConstant.GROUP_PURCHASE); map.put("notification_time", LocalDateTime.now()); + map.put("target_id", groupPurchaseId); map.put("message_type", "start"); String msg = objectMapper.writeValueAsString(map); WebSocketUsers.sendMessageToUsersByText(msg); @@ -202,12 +206,14 @@ public void endGroupPurchase(Long groupPurchaseId) throws JsonProcessingException { log.info(">>>>>>>>>>>>>>>>>>>>{}团购商品结束团购<<<<<<<<<<<<<<<<<<<<", groupPurchaseId); GoodsGroupPurchase groupPurchase = this.getById(groupPurchaseId); - if (StringUtils.isNotNull(groupPurchase)) { + if (StringUtils.isNotNull(groupPurchase) && groupPurchase.getStartStatus() + .equals(StartStatusEnum.STARTED)) { this.lambdaUpdate().set(GoodsGroupPurchase::getStartStatus, StartStatusEnum.ENDED) .eq(GoodsGroupPurchase::getId, groupPurchaseId).update(); Map<String, Object> map = new ConcurrentHashMap<>(); map.put("notification_type", NotificationTypeConstant.GROUP_PURCHASE); map.put("notification_time", LocalDateTime.now()); + map.put("target_id", groupPurchaseId); map.put("message_type", "end"); String msg = objectMapper.writeValueAsString(map); WebSocketUsers.sendMessageToUsersByText(msg); diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSeckillServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSeckillServiceImpl.java index eae3fa6..710ea35 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSeckillServiceImpl.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSeckillServiceImpl.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Lists; import com.ruoyi.common.core.constant.CacheConstants; import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.common.core.enums.ListingStatusEnum; @@ -83,7 +84,7 @@ .set(GoodsSku::getStock, goodsSku.getStock() - seckillStock) .ge(GoodsSku::getStock, seckillStock) .eq(GoodsSku::getId, goodsSku.getId()); - asyncMethodService.seckillScheduleTask(goodsSeckill); + asyncMethodService.seckillScheduleTask(Lists.newArrayList(goodsSeckill)); } } @@ -119,7 +120,7 @@ } GoodsSeckill goodsSeckillUpd = BeanUtils.copyBean(upd, GoodsSeckill.class); this.updateById(goodsSeckillUpd); - asyncMethodService.seckillScheduleTask(goodsSeckill); + asyncMethodService.seckillScheduleTask(Lists.newArrayList(goodsSeckill)); } /** @@ -176,9 +177,11 @@ public void startSeckill(Long seckillId) throws JsonProcessingException { log.info(">>>>>>>>>>>>>>>>>>>>{}秒杀开始<<<<<<<<<<<<<<<<<<<<", seckillId); GoodsSeckill goodsSeckill = this.getById(seckillId); - //秒杀商品不能为空且状态为未开始 + // 秒杀商品不能为空且上架状态为上架中 状态为未开始 if (StringUtils.isNotNull(goodsSeckill) - && goodsSeckill.getStartStatus().equals(StartStatusEnum.NOT_STARTED)) { + && goodsSeckill.getStartStatus().equals(StartStatusEnum.NOT_STARTED) && + goodsSeckill.getListingStatus() + .equals(ListingStatusEnum.ON_SHELVES)) { //开始秒杀 this.lambdaUpdate().set(GoodsSeckill::getStartStatus, StartStatusEnum.STARTED) .eq(GoodsSeckill::getId, seckillId).update(); @@ -191,6 +194,7 @@ Map<String, Object> map = new ConcurrentHashMap<>(); map.put("notification_type", NotificationTypeConstant.SECKILL); map.put("notification_time", LocalDateTime.now()); + map.put("target_id", seckillId); map.put("message_type", "start"); String msg = objectMapper.writeValueAsString(map); WebSocketUsers.sendMessageToUsersByText(msg); @@ -217,6 +221,7 @@ Map<String, Object> map = new ConcurrentHashMap<>(); map.put("notification_type", NotificationTypeConstant.SECKILL); map.put("notification_time", LocalDateTime.now()); + map.put("target_id", seckillId); map.put("message_type", "end"); String msg = objectMapper.writeValueAsString(map); WebSocketUsers.sendMessageToUsersByText(msg); diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java index c1ae02f..2afa2ba 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/service/impl/GoodsSkuServiceImpl.java @@ -239,7 +239,7 @@ String goodsLock = "goods_lock:" + skus.getId(); RLock redissonLock = redissonClient.getLock(goodsLock); try { - redissonLock.lock(100, TimeUnit.SECONDS); + redissonLock.lock(30, TimeUnit.SECONDS); Integer auctionStock = stockMap.get(skus.getId()); if (StringUtils.isNotNull(auctionStock) && auctionStock > 0) { // 更新商品库存,更新五次失败抛出异常 @@ -265,7 +265,8 @@ private boolean updateGoodsStock(GoodsSku skus, Integer auctionStock) { return this.lambdaUpdate() - .set(GoodsSku::getStock, skus.getStock() + auctionStock) + .set(skus.getStock() + auctionStock > 0, GoodsSku::getStock, + skus.getStock() + auctionStock) .eq(GoodsSku::getId, skus.getId()) .eq(GoodsSku::getStock, skus.getStock()) .update(); diff --git a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/task/GoodsScheduler.java b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/task/GoodsScheduler.java index 85603d1..eade347 100644 --- a/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/task/GoodsScheduler.java +++ b/ruoyi-modules/ruoyi-goods/src/main/java/com/ruoyi/goods/task/GoodsScheduler.java @@ -2,6 +2,7 @@ import com.ruoyi.common.core.enums.ListingStatusEnum; import com.ruoyi.common.core.enums.StartStatusEnum; +import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.goods.domain.GoodsGroupPurchase; import com.ruoyi.goods.service.IGoodsGroupPurchaseService; import com.ruoyi.goods.service.IGoodsSeckillService; @@ -40,15 +41,15 @@ .eq(GoodsSeckill::getStartStatus, StartStatusEnum.NOT_STARTED) .le(GoodsSeckill::getStartTime, checkTime) .list(); - for (GoodsSeckill goodsSeckill : list) { - asyncMethodService.seckillScheduleTask(goodsSeckill); + if (StringUtils.isNotEmpty(list)) { + asyncMethodService.seckillScheduleTask(list); } List<GoodsGroupPurchase> groupPurchaseList = goodsGroupPurchaseService.lambdaQuery() .eq(GoodsGroupPurchase::getListingStatus, ListingStatusEnum.ON_SHELVES) .eq(GoodsGroupPurchase::getStartStatus, StartStatusEnum.NOT_STARTED) .le(GoodsGroupPurchase::getStartTime, checkTime).list(); - for (GoodsGroupPurchase goodsGroupPurchase : groupPurchaseList) { - asyncMethodService.groupPurchaseScheduleTask(goodsGroupPurchase); + if (StringUtils.isNotEmpty(groupPurchaseList)) { + asyncMethodService.groupPurchaseScheduleTask(groupPurchaseList); } } } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/DelayTaskController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/DelayTaskController.java index a7ae62b..403c9da 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/DelayTaskController.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/DelayTaskController.java @@ -35,7 +35,8 @@ @InnerAuth @PostMapping("/addDelayTask") - public R<?> addDelayTask(@RequestBody DelayTask delayTask) { + public R<?> + addDelayTask(@RequestBody DelayTask delayTask) { delayTaskService.addDelayTask(delayTask); return R.ok(); } diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java index 8e62963..8d11737 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/listener/RedisListener.java @@ -5,6 +5,7 @@ import com.ruoyi.common.core.utils.DateUtils; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.system.api.constants.DelayTaskEnum; +import com.ruoyi.system.api.feignClient.AuctionClient; import com.ruoyi.system.api.feignClient.GoodsSkuClient; import java.util.Date; import javax.annotation.Resource; @@ -29,6 +30,8 @@ private RedisTemplate<String, Object> redisTemplate; @Resource private GoodsSkuClient goodsSkuClient; + @Resource + private AuctionClient auctionClient; public RedisListener(RedisMessageListenerContainer listenerContainer, RedisTemplate redisTemplate) { super(listenerContainer); @@ -60,6 +63,12 @@ else if(DelayTaskEnum.GROUP_PURCHASES_END_TASK.getCode().equals(operation)){ //自动结束团购任务 autoEndGroupPurchase(id); + } else if (DelayTaskEnum.AUCTION_GOODS_START_TASK.getCode().equals(operation)) { + // 自动开始团购任务 + autoStartAuctionGoods(id); + } else if (DelayTaskEnum.AUCTION_GOODS_END_TASK.getCode().equals(operation)) { + // 自动结束团购任务 + autoEndAuctionGoods(id); }else if(DelayTaskEnum.ORDER_AUTOMATIC_CANCEL.getCode().equals(operation)){ //自动取消订单 autoCancelOrder(id); @@ -73,6 +82,16 @@ } } + @Async + public void autoEndAuctionGoods(Long id) { + auctionClient.endAuctionGoods(id, SecurityConstants.INNER); + } + + @Async + public void autoStartAuctionGoods(Long id) { + auctionClient.startAuctionGoods(id, SecurityConstants.INNER); + } + public <T> T getAndSet(final String key, T value){ T oldValue=null; try { -- Gitblit v1.7.1