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