Pārlūkot izejas kodu

秒杀活动: 完善 app 端获取活动分页、列表、详情接口

puhui999 1 gadu atpakaļ
vecāks
revīzija
408df683d8
12 mainītis faili ar 217 papildinājumiem un 101 dzēšanām
  1. 26 0
      yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java
  2. 1 0
      yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
  3. 66 88
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java
  4. 23 9
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java
  5. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityDetailRespVO.java
  6. 0 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java
  7. 57 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java
  8. 4 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java
  9. 1 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java
  10. 8 1
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java
  11. 17 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java
  12. 13 0
      yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java

+ 26 - 0
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java

@@ -43,6 +43,16 @@ public class LocalDateTimeUtils {
         return LocalDateTime.of(year, mouth, day, 0, 0, 0);
     }
 
+    /**
+     * 创建指定时间
+     *
+     * @param timeStr 时间字符串
+     * @return 指定时间
+     */
+    public static LocalDateTime buildTime(String timeStr) {
+        return LocalDateTime.of(LocalDate.now(), LocalTime.parse(timeStr));
+    }
+
     public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1,
                                                    int year2, int mouth2, int day2) {
         return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)};
@@ -62,6 +72,22 @@ public class LocalDateTimeUtils {
         return LocalDateTimeUtil.isIn(LocalDateTime.now(), startTime, endTime);
     }
 
+    /**
+     * 判断当前时间是否在该时间范围内
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return 是否
+     */
+    public static boolean isBetween(String startTime, String endTime) {
+        if (startTime == null || endTime == null) {
+            return false;
+        }
+        LocalDate nowDate = LocalDate.now();
+        return LocalDateTimeUtil.isIn(LocalDateTime.now(), LocalDateTime.of(nowDate, LocalTime.parse(startTime)),
+                LocalDateTime.of(nowDate, LocalTime.parse(endTime)));
+    }
+
     /**
      * 判断时间段是否重叠
      *

+ 1 - 0
yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java

@@ -56,6 +56,7 @@ public interface ErrorCodeConstants {
     ErrorCode SECKILL_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED_OR_END = new ErrorCode(1013008004, "秒杀活动未关闭或未结束,不能删除");
     ErrorCode SECKILL_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1013008005, "秒杀活动已关闭,不能重复关闭");
     ErrorCode SECKILL_ACTIVITY_UPDATE_STOCK_FAIL = new ErrorCode(1013008006, "秒杀失败,原因秒杀库存不足");
+    ErrorCode SECKILL_ACTIVITY_FAIL_STATUS_CLOSED = new ErrorCode(1013008007, "秒杀活动已关闭");
 
     // ========== 秒杀时段 1013009000 ==========
     ErrorCode SECKILL_CONFIG_NOT_EXISTS = new ErrorCode(1013009000, "秒杀时段不存在");

+ 66 - 88
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillActivityController.java

@@ -1,136 +1,114 @@
 package cn.iocoder.yudao.module.promotion.controller.app.seckill;
 
+import cn.hutool.core.util.ObjectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityDetailRespVO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityRespVO;
-import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillActivityService;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.time.LocalDateTime;
-import java.util.ArrayList;
+import javax.annotation.Resource;
+import java.util.Arrays;
 import java.util.List;
 
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.findFirst;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.isBetween;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.SECKILL_ACTIVITY_FAIL_STATUS_CLOSED;
 
 @Tag(name = "用户 App - 秒杀活动")
 @RestController
 @RequestMapping("/promotion/seckill-activity")
 @Validated
 public class AppSeckillActivityController {
+    @Resource
+    private SeckillActivityService activityService;
+    @Resource
+    @Lazy
+    private SeckillConfigService configService;
+
+    @Resource
+    private ProductSpuApi spuApi;
 
     @GetMapping("/get-now")
     @Operation(summary = "获得当前秒杀活动") // 提供给首页使用
     // TODO 芋艿:需要增加 spring cache
     public CommonResult<AppSeckillActivityNowRespVO> getNowSeckillActivity() {
-        AppSeckillActivityNowRespVO respVO = new AppSeckillActivityNowRespVO();
-        respVO.setConfig(new AppSeckillConfigRespVO().setId(10L).setStartTime("01:00").setEndTime("09:59"));
-        List<AppSeckillActivityRespVO> activityList = new ArrayList<>();
-        AppSeckillActivityRespVO activity1 = new AppSeckillActivityRespVO();
-        activity1.setId(1L);
-        activity1.setName("618 大秒杀");
-        activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity1.setMarketPrice(50);
-        activity1.setSeckillPrice(100);
-        activityList.add(activity1);
+        // 1、获取当前时间处在哪个秒杀阶段
+        List<SeckillConfigDO> configList = configService.getSeckillConfigList();
+        SeckillConfigDO filteredConfig = findFirst(configList, config -> ObjectUtil.equal(config.getStatus(),
+                CommonStatusEnum.ENABLE.getStatus()) && isBetween(config.getStartTime(), config.getEndTime()));
+        // 1、1 时段不存在直接返回 null
+        if (filteredConfig == null) {
+            return success(null);
+        }
 
-        AppSeckillActivityRespVO activity2 = new AppSeckillActivityRespVO();
-        activity2.setId(2L);
-        activity2.setName("双十一大秒杀");
-        activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
-        activity2.setMarketPrice(100);
-        activity2.setSeckillPrice(200);
-        activityList.add(activity2);
-        respVO.setActivities(activityList);
-        return success(respVO);
+        // 2、查询满足当前阶段的活动
+        List<SeckillActivityDO> activityList = activityService.getSeckillActivityListByConfigIds(Arrays.asList(filteredConfig.getId()));
+        List<SeckillActivityDO> filteredList = filterList(activityList, item -> ObjectUtil.equal(item.getStatus(), CommonStatusEnum.ENABLE.getStatus()));
+        // 2、1 获取 spu 信息
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(filteredList, SeckillActivityDO::getSpuId));
+        return success(SeckillActivityConvert.INSTANCE.convert(filteredConfig, filteredList, spuList));
     }
 
     @GetMapping("/page")
     @Operation(summary = "获得秒杀活动分页")
-    // TODO @芋艿:分页参数
     public CommonResult<PageResult<AppSeckillActivityRespVO>> getSeckillActivityPage(AppSeckillActivityPageReqVO pageReqVO) {
-        List<AppSeckillActivityRespVO> activityList = new ArrayList<>();
-        AppSeckillActivityRespVO activity1 = new AppSeckillActivityRespVO();
-        activity1.setId(1L);
-        activity1.setName("618 大秒杀");
-        activity1.setSpuId(2048L);
-        activity1.setPicUrl("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg");
-        activity1.setMarketPrice(50);
-        activity1.setSeckillPrice(100);
-        activity1.setUnitName("个");
-        activity1.setStock(1);
-        activity1.setTotalStock(2);
-        activityList.add(activity1);
-
-        AppSeckillActivityRespVO activity2 = new AppSeckillActivityRespVO();
-        activity2.setId(2L);
-        activity2.setName("双十一大秒杀");
-        activity2.setSpuId(4096L);
-        activity2.setPicUrl("https://static.iocoder.cn/mall/132.jpeg");
-        activity2.setMarketPrice(100);
-        activity2.setSeckillPrice(200);
-        activity2.setUnitName("套");
-        activity2.setStock(2);
-        activity2.setTotalStock(3);
-        activityList.add(activity2);
-        return success(new PageResult<>(activityList, 100L));
+        // 1、查询满足当前阶段的活动
+        PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
+        // 1、1 获取 spu 信息
+        List<ProductSpuRespDTO> spuList = spuApi.getSpuList(CollectionUtils.convertList(pageResult.getList(), SeckillActivityDO::getSpuId));
+        return success(SeckillActivityConvert.INSTANCE.convertPage(pageResult, spuList));
     }
 
     @GetMapping("/get-detail")
     @Operation(summary = "获得秒杀活动明细")
     @Parameter(name = "id", description = "活动编号", required = true, example = "1024")
     public CommonResult<AppSeckillActivityDetailRespVO> getSeckillActivity(@RequestParam("id") Long id) {
+        // 1、获取当前时间处在哪个秒杀阶段
+        List<SeckillConfigDO> configList = configService.getSeckillConfigList();
+        SeckillConfigDO filteredConfig = findFirst(configList, config -> ObjectUtil.equal(config.getStatus(),
+                CommonStatusEnum.ENABLE.getStatus()) && isBetween(config.getStartTime(), config.getEndTime()));
+        // 1、1 时段不存在直接返回 null
+        if (filteredConfig == null) {
+            return success(null);
+        }
+
+        // 2、获取活动
+        SeckillActivityDO seckillActivity = activityService.getSeckillActivity(id);
+        if (seckillActivity == null) {
+            return success(null);
+        }
         // TODO 芋艿:如果禁用的时候,需要抛出异常;
-        AppSeckillActivityDetailRespVO obj = new AppSeckillActivityDetailRespVO();
-        // 设置其属性的值
-        obj.setId(id);
-        obj.setName("晚九点限时秒杀");
-        obj.setStatus(1);
-        obj.setStartTime(LocalDateTime.of(2023, 6, 16, 0, 0, 0));
-        obj.setEndTime(LocalDateTime.of(2023, 6, 20, 23, 59, 0));
-        obj.setSpuId(633L);
-        obj.setSingleLimitCount(2);
-        obj.setTotalLimitCount(3);
-        obj.setStock(100);
-        obj.setTotalStock(200);
+        if (ObjectUtil.equal(seckillActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus())) {
+            throw exception(SECKILL_ACTIVITY_FAIL_STATUS_CLOSED);
+        }
 
-        // 创建一个Product对象的列表
-        List<AppSeckillActivityDetailRespVO.Product> productList = new ArrayList<>();
-        // 创建三个新的Product对象并设置其属性的值
-        AppSeckillActivityDetailRespVO.Product product1 = new AppSeckillActivityDetailRespVO.Product();
-        product1.setSkuId(1L);
-        product1.setSeckillPrice(100);
-        product1.setStock(50);
-        // 将第一个Product对象添加到列表中
-        productList.add(product1);
-        // 创建第二个Product对象并设置其属性的值
-        AppSeckillActivityDetailRespVO.Product product2 = new AppSeckillActivityDetailRespVO.Product();
-        product2.setSkuId(2L);
-        product2.setSeckillPrice(200);
-        product2.setStock(100);
-        // 将第二个Product对象添加到列表中
-        productList.add(product2);
-        // 创建第三个Product对象并设置其属性的值
-        AppSeckillActivityDetailRespVO.Product product3 = new AppSeckillActivityDetailRespVO.Product();
-        product3.setSkuId(3L);
-        product3.setSeckillPrice(300);
-        product3.setStock(150);
-        // 将第三个Product对象添加到列表中
-        productList.add(product3);
-        // 将Product列表设置为对象的属性值
-        obj.setProducts(productList);
-        return success(obj);
+        // 3、获取活动商品
+        List<SeckillProductDO> products = activityService.getSeckillProductListByActivityId(seckillActivity.getId());
+        return success(SeckillActivityConvert.INSTANCE.convert3(seckillActivity, products, filteredConfig));
     }
 
 }

+ 23 - 9
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/AppSeckillConfigController.java

@@ -1,7 +1,12 @@
 package cn.iocoder.yudao.module.promotion.controller.app.seckill;
 
+import cn.hutool.core.collection.CollectionUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
+import cn.iocoder.yudao.module.promotion.service.seckill.SeckillConfigService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.validation.annotation.Validated;
@@ -9,7 +14,8 @@ import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import java.util.Arrays;
+import javax.annotation.Resource;
+import java.util.Collections;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -19,18 +25,26 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 @RequestMapping("/promotion/seckill-config")
 @Validated
 public class AppSeckillConfigController {
+    @Resource
+    private SeckillConfigService configService;
 
     @GetMapping("/list")
     @Operation(summary = "获得秒杀时间段列表")
     public CommonResult<List<AppSeckillConfigRespVO>> getSeckillConfigList() {
-        return success(Arrays.asList(
-                new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59")
-                        .setSliderPicUrls(Arrays.asList("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
-                                "https://static.iocoder.cn/mall/132.jpeg")),
-                new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"),
-                new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"),
-                new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59")
-        ));
+        List<SeckillConfigDO> list = configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
+        if (CollectionUtil.isEmpty(list)) {
+            return success(Collections.emptyList());
+        }
+
+        return success(SeckillConfigConvert.INSTANCE.convertList2(list));
+        //return success(Arrays.asList(
+        //        new AppSeckillConfigRespVO().setId(1L).setStartTime("00:00").setEndTime("09:59")
+        //                .setSliderPicUrls(Arrays.asList("https://static.iocoder.cn/mall/a79f5d2ea6bf0c3c11b2127332dfe2df.jpg",
+        //                        "https://static.iocoder.cn/mall/132.jpeg")),
+        //        new AppSeckillConfigRespVO().setId(2L).setStartTime("10:00").setEndTime("12:59"),
+        //        new AppSeckillConfigRespVO().setId(2L).setStartTime("13:00").setEndTime("22:59"),
+        //        new AppSeckillConfigRespVO().setId(2L).setStartTime("23:00").setEndTime("23:59")
+        //));
     }
 
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityDetailRespVO.java

@@ -19,7 +19,7 @@ public class AppSeckillActivityDetailRespVO {
     @Schema(description = "活动状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     private Integer status;
 
-    // TODO @芋艿:开始时间、结束时间,要和场次结合起来;就是要算到当前场次,是几点哈
+    // TODO @芋艿:开始时间、结束时间,要和场次结合起来;就是要算到当前场次,是几点哈;
 
     @Schema(description = "活动开始时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime startTime;

+ 0 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/seckill/vo/activity/AppSeckillActivityRespVO.java

@@ -31,7 +31,6 @@ public class AppSeckillActivityRespVO {
     private Integer totalStock;
 
     @Schema(description = "秒杀金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100")
-    // 从秒杀商品里取最低价
     private Integer seckillPrice;
 
 }

+ 57 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillactivity/SeckillActivityConvert.java

@@ -3,15 +3,22 @@ package cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
+import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
 import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
+import cn.iocoder.yudao.module.product.enums.DictTypeConstants;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityDetailRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityDetailRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityNowRespVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityRespVO;
+import cn.iocoder.yudao.module.promotion.convert.seckill.seckillconfig.SeckillConfigConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.Mapping;
 import org.mapstruct.Mappings;
@@ -20,6 +27,10 @@ import org.mapstruct.factory.Mappers;
 import java.util.List;
 import java.util.Map;
 
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
+import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
+
 /**
  * 秒杀活动 Convert
  *
@@ -79,4 +90,50 @@ public interface SeckillActivityConvert {
 
     List<SeckillProductRespVO> convertList2(List<SeckillProductDO> list);
 
+    List<AppSeckillActivityRespVO> convertList3(List<SeckillActivityDO> activityList);
+
+    default AppSeckillActivityNowRespVO convert(SeckillConfigDO filteredConfig, List<SeckillActivityDO> activityList, List<ProductSpuRespDTO> spuList) {
+        AppSeckillActivityNowRespVO respVO = new AppSeckillActivityNowRespVO();
+        respVO.setConfig(SeckillConfigConvert.INSTANCE.convert1(filteredConfig));
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        respVO.setActivities(CollectionUtils.convertList(convertList3(activityList), item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setMarketPrice(spu.getMarketPrice());
+                item.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
+            });
+            return item;
+        }));
+        return respVO;
+    }
+
+    PageResult<AppSeckillActivityRespVO> convertPage1(PageResult<SeckillActivityDO> pageResult);
+
+    default PageResult<AppSeckillActivityRespVO> convertPage(PageResult<SeckillActivityDO> pageResult, List<ProductSpuRespDTO> spuList) {
+        PageResult<AppSeckillActivityRespVO> result = convertPage1(pageResult);
+        Map<Long, ProductSpuRespDTO> spuMap = convertMap(spuList, ProductSpuRespDTO::getId);
+        List<AppSeckillActivityRespVO> list = CollectionUtils.convertList(result.getList(), item -> {
+            findAndThen(spuMap, item.getSpuId(), spu -> {
+                item.setPicUrl(spu.getPicUrl());
+                item.setMarketPrice(spu.getMarketPrice());
+                item.setUnitName(DictFrameworkUtils.getDictDataLabel(DictTypeConstants.PRODUCT_UNIT, spu.getUnit()));
+            });
+            return item;
+        });
+        result.setList(list);
+        return result;
+    }
+
+    AppSeckillActivityDetailRespVO convert2(SeckillActivityDO seckillActivity);
+
+    List<AppSeckillActivityDetailRespVO.Product> convertList1(List<SeckillProductDO> products);
+
+    default AppSeckillActivityDetailRespVO convert3(SeckillActivityDO seckillActivity, List<SeckillProductDO> products, SeckillConfigDO filteredConfig) {
+        AppSeckillActivityDetailRespVO respVO = convert2(seckillActivity);
+        respVO.setProducts(convertList1(products));
+        respVO.setStartTime(buildTime(filteredConfig.getStartTime()));
+        respVO.setEndTime(buildTime(filteredConfig.getEndTime()));
+        return respVO;
+    }
+
 }

+ 4 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/seckill/seckillconfig/SeckillConfigConvert.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.Seck
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigSimpleRespVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.config.SeckillConfigUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.config.AppSeckillConfigRespVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillconfig.SeckillConfigDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
@@ -33,4 +34,7 @@ public interface SeckillConfigConvert {
 
     PageResult<SeckillConfigRespVO> convertPage(PageResult<SeckillConfigDO> page);
 
+    List<AppSeckillConfigRespVO> convertList2(List<SeckillConfigDO> list);
+
+    AppSeckillConfigRespVO convert1(SeckillConfigDO filteredConfig);
 }

+ 1 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/seckill/seckillactivity/SeckillActivityDO.java

@@ -87,7 +87,7 @@ public class SeckillActivityDO extends BaseDO {
      */
     private Integer singleLimitCount;
     /**
-     * 秒杀库存
+     * 秒杀库存(剩余库存秒杀时扣减)
      */
     private Integer stock;
     /**

+ 8 - 1
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/seckill/seckillactivity/SeckillActivityMapper.java

@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
@@ -24,7 +25,7 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
                 .likeIfPresent(SeckillActivityDO::getName, reqVO.getName())
                 .eqIfPresent(SeckillActivityDO::getStatus, reqVO.getStatus())
                 .betweenIfPresent(SeckillActivityDO::getCreateTime, reqVO.getCreateTime())
-                .apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ",time_ids) > 0")
+                .apply(ObjectUtil.isNotNull(reqVO.getConfigId()), "FIND_IN_SET(" + reqVO.getConfigId() + ", config_ids) > 0")
                 .orderByDesc(SeckillActivityDO::getId));
     }
 
@@ -48,4 +49,10 @@ public interface SeckillActivityMapper extends BaseMapperX<SeckillActivityDO> {
                 .setSql("totalStock = totalStock - " + count));
     }
 
+    default PageResult<SeckillActivityDO> selectPage(AppSeckillActivityPageReqVO pageReqVO, Integer status) {
+        return selectPage(pageReqVO, new LambdaQueryWrapperX<SeckillActivityDO>()
+                .eqIfPresent(SeckillActivityDO::getStatus, status)
+                .apply(ObjectUtil.isNotNull(pageReqVO.getConfigId()), "FIND_IN_SET(" + pageReqVO.getConfigId() + ",config_ids) > 0"));
+    }
+
 }

+ 17 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityService.java

@@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityCreateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
 
@@ -88,4 +89,20 @@ public interface SeckillActivityService {
      */
     List<SeckillProductDO> getSeckillProductListByActivityId(Collection<Long> activityIds);
 
+    /**
+     * 通过活动时段获取秒杀活动
+     *
+     * @param ids 时段配置编号
+     * @return 秒杀活动列表
+     */
+    List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids);
+
+    /**
+     * 通过活动时段获取秒杀活动
+     *
+     * @param pageReqVO 请求
+     * @return 秒杀活动列表
+     */
+    PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO);
+
 }

+ 13 - 0
yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.service.seckill;
 import cn.hutool.core.util.ObjectUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
 import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
 import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
@@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.Se
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.activity.SeckillActivityUpdateReqVO;
 import cn.iocoder.yudao.module.promotion.controller.admin.seckill.vo.product.SeckillProductBaseVO;
+import cn.iocoder.yudao.module.promotion.controller.app.seckill.vo.activity.AppSeckillActivityPageReqVO;
 import cn.iocoder.yudao.module.promotion.convert.seckill.seckillactivity.SeckillActivityConvert;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillActivityDO;
 import cn.iocoder.yudao.module.promotion.dal.dataobject.seckill.seckillactivity.SeckillProductDO;
@@ -264,4 +266,15 @@ public class SeckillActivityServiceImpl implements SeckillActivityService {
         return seckillProductMapper.selectListByActivityId(activityIds);
     }
 
+    @Override
+    public List<SeckillActivityDO> getSeckillActivityListByConfigIds(Collection<Long> ids) {
+        return CollectionUtils.filterList(seckillActivityMapper.selectList(),
+                item -> CollectionUtils.anyMatch(item.getConfigIds(), ids::contains));
+    }
+
+    @Override
+    public PageResult<SeckillActivityDO> getSeckillActivityAppPageByConfigId(AppSeckillActivityPageReqVO pageReqVO) {
+        return seckillActivityMapper.selectPage(pageReqVO, CommonStatusEnum.ENABLE.getStatus());
+    }
+
 }