diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertController.java index 4e03af80e..8a11fc9c4 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertController.java @@ -92,5 +92,14 @@ public class AdvertController extends XktBaseController { return R.ok(BeanUtil.copyToList(advertService.getPlatformList(), AdvertPlatformResVO.class)); } + /** + * 获取推广位示例图 + */ + @ApiOperation(value = "获取推广位示例图", httpMethod = "GET", response = R.class) + @GetMapping(value = "/demo/{advertType}") + public R getDemoPic(@PathVariable Integer advertType) { + return R.ok(advertService.getDemoPic(advertType)); + } + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java index 732af124a..c6146e991 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/AdvertRoundController.java @@ -4,10 +4,12 @@ import cn.hutool.core.bean.BeanUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.XktBaseController; import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.page.Page; import com.ruoyi.common.enums.BusinessType; -import com.ruoyi.web.controller.xkt.vo.advertRound.AdRoundStoreCreateVO; -import com.ruoyi.web.controller.xkt.vo.advertRound.AdRoundStoreResVO; +import com.ruoyi.web.controller.xkt.vo.advertRound.*; import com.ruoyi.xkt.dto.advertRound.AdRoundStoreCreateDTO; +import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageDTO; +import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageResDTO; import com.ruoyi.xkt.service.IAdvertRoundService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -15,7 +17,8 @@ import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.text.ParseException; +import javax.validation.Valid; +import java.util.List; /** * 推广营销轮次投放Controller @@ -41,34 +44,59 @@ public class AdvertRoundController extends XktBaseController { return R.ok(advertRoundService.create(BeanUtil.toBean(createVO, AdRoundStoreCreateDTO.class))); } - /** - * 根据广告ID获取推广轮次列表,并返回当前档口在这些推广轮次的数据 + * 获取推广位数据及右侧 "已订购推广位"列表 */ - @ApiOperation(value = "根据广告ID获取推广轮次列表,并返回当前档口在这些推广轮次的数据", httpMethod = "GET", response = R.class) + @ApiOperation(value = "获取推广位数据及右侧 已订购推广位 列表", httpMethod = "GET", response = R.class) @GetMapping(value = "/{advertId}/{storeId}/{showType}") public R getStoreAdInfo(@PathVariable("advertId") Long advertId, @PathVariable("storeId") Long storeId, @PathVariable("showType") Integer showType) { return R.ok(BeanUtil.toBean(advertRoundService.getStoreAdInfo(storeId, advertId, showType), AdRoundStoreResVO.class)); } - - - @GetMapping("/test") - public void test() throws ParseException { - advertRoundService.saveAdvertDeadlineToRedis(); + /** + * 位置枚举类型的推广位,获取推广商品 + */ + @ApiOperation(value = "位置枚举类型的推广位,获取推广商品", httpMethod = "GET", response = R.class) + @GetMapping(value = "/{advertRoundId}") + public R> getSetProdInfo(@PathVariable("advertRoundId") Long advertRoundId) { + return R.ok(BeanUtil.copyToList(advertRoundService.getSetProdInfo(advertRoundId), AdRoundSetProdResVO.class)); } + /** + * 获取档口已购推广列表 + */ + @ApiOperation(value = "获取档口已购推广列表", httpMethod = "POST", response = R.class) + @PostMapping("/page") + public R> page(@Valid @RequestBody AdvertRoundStorePageVO pageVO) { + return R.ok(advertRoundService.page(BeanUtil.toBean(pageVO, AdvertRoundStorePageDTO.class))); + } + /** + * 查看当前广告位推广图 + */ + @ApiOperation(value = "查看当前广告位推广图", httpMethod = "GET", response = R.class) + @GetMapping(value = "/pic/{storeId}/{advertRoundId}") + public R getAdvertStoreSetInfo(@PathVariable("storeId") Long storeId, @PathVariable("advertRoundId") Long advertRoundId) { + return R.ok(BeanUtil.toBean(advertRoundService.getAdvertStoreSetInfo(storeId, advertRoundId), AdRoundStoreSetResVO.class)); + } - // TODO 退订 - - - - // TODO 获取最受欢迎推广位8个,固定不动了 - // TODO 获取最受欢迎推广位8个,固定不动了 - - - + /** + * 退订 + */ + @ApiOperation(value = "退订", httpMethod = "POST", response = R.class) + @Log(title = "退订", businessType = BusinessType.UPDATE) + @PutMapping("/unsubscribe/{storeId}/{advertRoundId}") + public R unsubscribe(@PathVariable("storeId") Long storeId, @PathVariable("advertRoundId") Long advertRoundId) { + return R.ok(advertRoundService.unsubscribe(storeId, advertRoundId)); + } + /** + * 取最受欢迎的8个推广位 + */ + @ApiOperation(value = "取最受欢迎的8个推广位", httpMethod = "GET", response = R.class) + @GetMapping(value = "/populars") + public R> getMostPopulars() { + return R.ok(BeanUtil.copyToList(advertRoundService.getMostPopulars(), AdRoundPopularResVO.class)); + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreController.java index ad5e588bb..1b5493f2f 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/StoreController.java @@ -1,11 +1,13 @@ package com.ruoyi.web.controller.xkt; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.IdUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.XktBaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.Page; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.framework.oss.OSSClientWrapper; import com.ruoyi.web.controller.xkt.vo.store.*; import com.ruoyi.xkt.dto.store.*; import com.ruoyi.xkt.service.IStoreService; @@ -15,6 +17,9 @@ import lombok.RequiredArgsConstructor; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; /** * 档口Controller @@ -113,4 +118,35 @@ public class StoreController extends XktBaseController { } + + + + final OSSClientWrapper ossClient; + + + @GetMapping("/getKey") + public R getKey() { + return R.ok(ossClient.createStsCredentials()); + } + + @PostMapping("/upload") + public void test(@RequestParam("file") MultipartFile file) throws Exception { + final String uuid = IdUtil.randomUUID(); + ossClient.upload(uuid + ".png", file.getInputStream()); + } + + @GetMapping("/getUrl/{key}/{expireTime}") + public R getUrl(@PathVariable("key") String key, @PathVariable("expireTime") Long expireTime) throws Exception { + return R.ok(ossClient.generateUrl(key, expireTime)); + } + + @GetMapping("/download/{key}") + public void download(@PathVariable("key") String key) throws Exception { + String name = "C:\\Users\\56980\\Desktop\\test.png"; + ossClient.download(key, name); + } + + + + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundPopularResVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundPopularResVO.java new file mode 100644 index 000000000..5bdb2e06a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundPopularResVO.java @@ -0,0 +1,39 @@ +package com.ruoyi.web.controller.xkt.vo.advertRound; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("最受欢迎的8个推广位") +@Data +@Accessors(chain = true) +public class AdRoundPopularResVO { + + @ApiModelProperty(value = "广告ID") + private Long advertId; + @ApiModelProperty(value = "广告类型ID") + private Long typeId; + @ApiModelProperty(value = "广告类型名称") + private String typeName; + @ApiModelProperty(value = "推广展示类型") + private Integer showType; + @ApiModelProperty(value = "投放开始时间") + @JsonFormat(pattern = "MM月dd日", timezone = "GMT+8") + private Date startTime; + @ApiModelProperty(value = "投放结束时间") + @JsonFormat(pattern = "MM月dd日", timezone = "GMT+8") + private Date endTime; + @ApiModelProperty(value = "起拍价格") + private BigDecimal startPrice; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundSetProdResVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundSetProdResVO.java new file mode 100644 index 000000000..9d3895604 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundSetProdResVO.java @@ -0,0 +1,23 @@ +package com.ruoyi.web.controller.xkt.vo.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("当前位置枚举类型设置的商品") +@Data +@Accessors(chain = true) +public class AdRoundSetProdResVO { + + @ApiModelProperty(value = "档口商品ID") + private Long storeProdId; + @ApiModelProperty(value = "商品货号") + private String prodArtNum; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreCreateVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreCreateVO.java index 1b7675708..72c3516bf 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreCreateVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreCreateVO.java @@ -45,5 +45,8 @@ public class AdRoundStoreCreateVO { @NotBlank(message = "对象锁符号不能为空!") @ApiModelProperty(value = "对象锁符号") private String symbol; + @NotBlank(message = "交易密码不能为空!") + @ApiModelProperty(value = "交易密码") + private String transactionPassword; } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreSetResVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreSetResVO.java new file mode 100644 index 000000000..93938822d --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdRoundStoreSetResVO.java @@ -0,0 +1,37 @@ +package com.ruoyi.web.controller.xkt.vo.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("当前位置枚举类型设置的推广图") +@Data +@Accessors(chain = true) +public class AdRoundStoreSetResVO { + + @ApiModelProperty(value = "推广轮次ID") + private Long advertRoundId; + @ApiModelProperty(value = "档口的推广图") + private String fileUrl; + @ApiModelProperty(value = "档口设置的商品") + private List prodList; + + @Data + @ApiModel(value = "档口设置的商品") + @Accessors(chain = true) + public static class ARSSProdVO { + @ApiModelProperty("档口商品ID") + private Long storeProdId; + @ApiModelProperty(value = "商品货号") + private String prodArtNum; + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdvertRoundStorePageVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdvertRoundStorePageVO.java new file mode 100644 index 000000000..38d3587ac --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/advertRound/AdvertRoundStorePageVO.java @@ -0,0 +1,42 @@ +package com.ruoyi.web.controller.xkt.vo.advertRound; + +import com.ruoyi.web.controller.xkt.vo.BasePageVO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import javax.validation.constraints.NotNull; +import java.util.Date; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("档口已购推广列表入参") +@Data +public class AdvertRoundStorePageVO extends BasePageVO { + + @NotNull(message = "storeId不能为空") + @ApiModelProperty(value = "档口ID") + private Long storeId; + @ApiModelProperty(value = "推广类型") + private Integer typeId; + @ApiModelProperty(value = "投放状态") + private Integer launchStatus; + @ApiModelProperty(value = "竞价状态 只查看 已出价 或 竞价成功的状态") + private Integer biddingStatus; + @ApiModelProperty(value = "图片是否设置 1 未设置 2已设置") + private Integer picSetType; + @ApiModelProperty(value = "图片设计 1自主设计、2平台设计") + private Integer picDesignType; + @ApiModelProperty(value = "图片审核状态 1 待审核 2 审核通过 3 审核驳回") + private Integer picAuditStatus; + @ApiModelProperty(value = "投放开始时间") + private Date startTime; + @ApiModelProperty(value = "投放结束时间") + private Date endTime; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index f727a269a..8ee2da6a1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -230,22 +230,8 @@ public class Constants public static final String STORE_REDIS_PREFIX = "store_"; /** - * 枚举的广告位类型 + * 最受欢迎的8个推广位 */ -/* public final static List posEnumTypeList = new ArrayList() {{ - // 人气榜中上侧 - add(AdType.PC_HOME_POP_MID_TOP.getValue()); - // 人气榜中下侧 - add(AdType.PC_HOME_POP_MID_BOTTOM.getValue()); - // 人气榜右上侧 - add(AdType.PC_HOME_POP_RIGHT_TOP.getValue()); - // 人气榜右下侧 - add(AdType.PC_HOME_POP_RIGHT_BOTTOM.getValue()); - // 新品馆热卖榜右推广商品 - add(AdType.PC_NEW_PROD_HOT_RIGHT_PRODUCT.getValue()); - // PC下载页 - add(AdType.PC_DOWNLOAD.getValue()); - }};*/ - + public static final String ADVERT_POPULAR = "popular"; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/AdType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AdType.java index 279f01b60..b8c49ffe0 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/AdType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AdType.java @@ -56,11 +56,11 @@ public enum AdType { PC_NEW_PROD_PRODUCT_LIST(36, "新品馆商品列表", "/url"), // PC搜索结果 - PC_SEARCH_RESULT(40, "PC搜索结果", "/url"), + PC_SEARCH_RESULT(40, "电脑端搜索结果", "/url"), // PC用户中心 - PC_USER_CENTER(41, "PC用户中心", "/url"), + PC_USER_CENTER(41, "电脑端用户中心", "/url"), // PC下载页 - PC_DOWNLOAD(42, "PC下载页", "/url"), + PC_DOWNLOAD(42, "电脑端下载页", "/url"), // APP首页顶部轮播图 diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java index 481c4bb63..3f6e61363 100644 --- a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java +++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/XktTask.java @@ -334,7 +334,7 @@ public class XktTask { // 当前播放轮次id final int roundId = i + 1; updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(roundId).setLaunchStatus(launchStatus).setShowType(advert.getShowType()) - .setStartTime(java.sql.Date.valueOf(now)).setEndTime(java.sql.Date.valueOf(endDate)).setPosition(position).setStartPrice(advert.getStartPrice()) + .setStartTime(java.sql.Date.valueOf(now)).setEndTime(java.sql.Date.valueOf(endDate)).setPosition(position).setStartPrice(advert.getStartPrice()).setSysIntercept(0) .setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue()) // 如果是位置枚举的推广位,则需要精确到某一个position的推广位,反之,若是时间范围,则直接精确到播放轮次即可 ? advert.getBasicSymbol() + roundId + position : advert.getBasicSymbol() + roundId)); @@ -381,7 +381,7 @@ public class XktTask { final String position = String.valueOf((char) ('A' + j)); // 生成最新的下一轮推广位 updateList.add(new AdvertRound().setAdvertId(advert.getId()).setTypeId(advert.getTypeId()).setRoundId(maxRoundId).setShowType(advert.getShowType()) - .setLaunchStatus(AdLaunchStatus.UN_LAUNCH.getValue()).setPosition(position).setStartPrice(advert.getStartPrice()) + .setLaunchStatus(AdLaunchStatus.UN_LAUNCH.getValue()).setPosition(position).setStartPrice(advert.getStartPrice()).setSysIntercept(0) // java.sql.Date 直接转化成yyyy-MM-dd格式 .setStartTime(java.sql.Date.valueOf(startDate)).setEndTime(java.sql.Date.valueOf(endDate)) .setSymbol(Objects.equals(advert.getShowType(), AdShowType.POSITION_ENUM.getValue()) diff --git a/xkt/src/main/java/com/ruoyi/xkt/domain/AdvertRound.java b/xkt/src/main/java/com/ruoyi/xkt/domain/AdvertRound.java index 8e2b340cd..403767914 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/domain/AdvertRound.java +++ b/xkt/src/main/java/com/ruoyi/xkt/domain/AdvertRound.java @@ -28,9 +28,13 @@ public class AdvertRound extends XktBaseEntity { @TableId private Long id; /** - * 推广展示类型 时间范围 位置枚举 + * 推广展示类型 */ private Integer showType; + /** + * 展示类型 推广图、商品、推广图及商品 + */ + private Integer displayType; /** * 凭证日期 */ @@ -88,13 +92,13 @@ public class AdvertRound extends XktBaseEntity { */ private Integer biddingTempStatus; /** - * 图片审核状态 + * 图片审核状态 1 待审核 2 审核通过 3 审核驳回 */ private Integer picAuditStatus; /** * 图片是否设置 0 未设置 1已设置 */ - private Integer picSet; + private Integer picSetType; /** * 推广图ID 对应sysFile.id */ @@ -108,7 +112,7 @@ public class AdvertRound extends XktBaseEntity { */ private Integer picDesignType; /** - * 系统拦截 + * 系统拦截 0 未拦截 1拦截 */ private Integer sysIntercept; diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundPopularResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundPopularResDTO.java new file mode 100644 index 000000000..0a68e0d86 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundPopularResDTO.java @@ -0,0 +1,36 @@ +package com.ruoyi.xkt.dto.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("最受欢迎的8个推广位") +@Data +@Accessors(chain = true) +public class AdRoundPopularResDTO { + + @ApiModelProperty(value = "广告ID") + private Long advertId; + @ApiModelProperty(value = "广告类型ID") + private Integer typeId; + @ApiModelProperty(value = "广告类型名称") + private String typeName; + @ApiModelProperty(value = "推广展示类型") + private Integer showType; + @ApiModelProperty(value = "投放开始时间") + private Date startTime; + @ApiModelProperty(value = "投放结束时间") + private Date endTime; + @ApiModelProperty(value = "起拍价格") + private BigDecimal startPrice; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundSetPicResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundSetPicResDTO.java new file mode 100644 index 000000000..1a6e16e83 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundSetPicResDTO.java @@ -0,0 +1,23 @@ +package com.ruoyi.xkt.dto.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("当前位置枚举类型设置的推广图") +@Data +@Accessors(chain = true) +public class AdRoundSetPicResDTO { + + @ApiModelProperty(value = "推广轮次ID") + private Long advertRoundId; + @ApiModelProperty(value = "文件路径") + private String fileUrl; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundSetProdResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundSetProdResDTO.java new file mode 100644 index 000000000..7c84aa501 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundSetProdResDTO.java @@ -0,0 +1,23 @@ +package com.ruoyi.xkt.dto.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("当前位置枚举类型设置的商品") +@Data +@Accessors(chain = true) +public class AdRoundSetProdResDTO { + + @ApiModelProperty(value = "档口商品ID") + private Long storeProdId; + @ApiModelProperty(value = "商品货号") + private String prodArtNum; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreCreateDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreCreateDTO.java index 4de1c44ed..5d01fdd7f 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreCreateDTO.java +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreCreateDTO.java @@ -37,5 +37,7 @@ public class AdRoundStoreCreateDTO { private String prodIdStr; @ApiModelProperty(value = "对象锁符号") private String symbol; + @ApiModelProperty(value = "交易密码") + private String transactionPassword; } diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreSetResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreSetResDTO.java new file mode 100644 index 000000000..1eedaa203 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdRoundStoreSetResDTO.java @@ -0,0 +1,37 @@ +package com.ruoyi.xkt.dto.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.List; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("当前位置枚举类型设置的推广图") +@Data +@Accessors(chain = true) +public class AdRoundStoreSetResDTO { + + @ApiModelProperty(value = "推广轮次ID") + private Long advertRoundId; + @ApiModelProperty(value = "档口的推广图") + private String fileUrl; + @ApiModelProperty(value = "档口设置的商品") + private List prodList; + + @Data + @ApiModel(value = "档口设置的商品") + @Accessors(chain = true) + public static class ARSSProdDTO { + @ApiModelProperty("档口商品ID") + private Long storeProdId; + @ApiModelProperty(value = "商品货号") + private String prodArtNum; + } + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdvertRoundStorePageDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdvertRoundStorePageDTO.java new file mode 100644 index 000000000..e6ead7732 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdvertRoundStorePageDTO.java @@ -0,0 +1,40 @@ +package com.ruoyi.xkt.dto.advertRound; + +import com.ruoyi.xkt.dto.BasePageDTO; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@EqualsAndHashCode(callSuper = true) +@ApiModel("档口已购推广列表入参") +@Data +public class AdvertRoundStorePageDTO extends BasePageDTO { + + @ApiModelProperty(value = "档口ID") + private Long storeId; + @ApiModelProperty(value = "推广类型") + private Integer typeId; + @ApiModelProperty(value = "投放状态") + private Integer launchStatus; + @ApiModelProperty(value = "竞价状态 只查看 已出价 或 竞价成功的状态") + private Integer biddingStatus; + @ApiModelProperty(value = "图片是否设置 1 未设置 2已设置") + private Integer picSetType; + @ApiModelProperty(value = "图片设计 1自主设计、2平台设计") + private Integer picDesignType; + @ApiModelProperty(value = "图片审核状态 1 待审核 2 审核通过 3 审核驳回") + private Integer picAuditStatus; + @ApiModelProperty(value = "投放开始时间") + private Date startTime; + @ApiModelProperty(value = "投放结束时间") + private Date endTime; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdvertRoundStorePageResDTO.java b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdvertRoundStorePageResDTO.java new file mode 100644 index 000000000..560505ab8 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/dto/advertRound/AdvertRoundStorePageResDTO.java @@ -0,0 +1,55 @@ +package com.ruoyi.xkt.dto.advertRound; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * @author liujiang + * @version v1.0 + * @date 2025/3/27 15:12 + */ +@ApiModel("档口已订购推广返回列表") +@Data +@Accessors(chain = true) +public class AdvertRoundStorePageResDTO { + + @ApiModelProperty(value = "投放平台") + private Integer platformId; + @ApiModelProperty(value = "投放平台") + private String platformName; + @ApiModelProperty(value = "投放类型") + private Integer typeId; + @ApiModelProperty(value = "投放类型") + private String typeName; + @ApiModelProperty(value = "投放位置") + private String position; + @ApiModelProperty(value = "投放开始时间") + private String startTime; + @ApiModelProperty(value = "投放结束时间") + private String endTime; + @ApiModelProperty(value = "出价") + private String payPrice; + @ApiModelProperty(value = "投放状态") + private Integer launchStatus; + @ApiModelProperty(value = "投放状态") + private String launchStatusName; + @ApiModelProperty(value = "竞价状态") + private Integer biddingStatus; + @ApiModelProperty(value = "竞价状态") + private String biddingStatusName; + @ApiModelProperty(value = "图片设计类型") + private Integer picDesignType; + @ApiModelProperty(value = "竞价状态") + private String picDesignTypeName; + @ApiModelProperty(value = "图片是否设置") + private Integer picSetType; + @ApiModelProperty(value = "图片是否设置") + private String picSetTypeName; + @ApiModelProperty(value = "图片审核状态") + private Integer picAuditStatus; + @ApiModelProperty(value = "图片审核状态") + private String picAuditStatusName; + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java b/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java index 9aa595ed1..1f11f8335 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/AdBiddingStatus.java @@ -1,5 +1,7 @@ package com.ruoyi.xkt.enums; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -30,6 +32,6 @@ public enum AdBiddingStatus { return e; } } - return null; + throw new ServiceException("营销推广竞价状态不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/AdPicSetType.java b/xkt/src/main/java/com/ruoyi/xkt/enums/AdPicSetType.java new file mode 100644 index 000000000..14eb8178b --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/AdPicSetType.java @@ -0,0 +1,37 @@ +package com.ruoyi.xkt.enums; + +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 推广营销图片设置类型 + * + * @author liujiang + * @date 2025-04-02 23:42 + */ +@Getter +@AllArgsConstructor +public enum AdPicSetType { + + // 未设置 + UN_SET(1, "未设置"), + // 已设置 + SET(2, "已设置"), + + + ; + + private final Integer value; + private final String label; + + public static AdPicSetType of(Integer value) { + for (AdPicSetType e : AdPicSetType.values()) { + if (e.getValue().equals(value)) { + return e; + } + } + throw new ServiceException("营销推广图片是否设置不存在!", HttpStatus.ERROR); + } +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/AdShowType.java b/xkt/src/main/java/com/ruoyi/xkt/enums/AdShowType.java index 4ba4f117d..3d1d30bbc 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/AdShowType.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/AdShowType.java @@ -32,6 +32,6 @@ public enum AdShowType { return e; } } - throw new ServiceException("营销推广播放轮次不存在!", HttpStatus.ERROR); + throw new ServiceException("营销推广展示类型不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/ProdTagType.java b/xkt/src/main/java/com/ruoyi/xkt/enums/ProdTagType.java index fb5679c8c..f49f9d137 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/ProdTagType.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/ProdTagType.java @@ -1,5 +1,7 @@ package com.ruoyi.xkt.enums; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -36,6 +38,6 @@ public enum ProdTagType { return e; } } - return null; + throw new ServiceException("档口标签类型不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/ProductSizeStatus.java b/xkt/src/main/java/com/ruoyi/xkt/enums/ProductSizeStatus.java index dcda44982..c55e42700 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/ProductSizeStatus.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/ProductSizeStatus.java @@ -1,5 +1,7 @@ package com.ruoyi.xkt.enums; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -23,7 +25,7 @@ public enum ProductSizeStatus { return e; } } - return null; + throw new ServiceException("档口商品标准尺码类型不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/RegisterStatus.java b/xkt/src/main/java/com/ruoyi/xkt/enums/RegisterStatus.java index 9cc210cb8..89d8a4d07 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/RegisterStatus.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/RegisterStatus.java @@ -1,5 +1,7 @@ package com.ruoyi.xkt.enums; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -31,6 +33,6 @@ public enum RegisterStatus { return e; } } - return null; + throw new ServiceException("档口注册类型不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/SaleType.java b/xkt/src/main/java/com/ruoyi/xkt/enums/SaleType.java index 950da2263..c21da4861 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/SaleType.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/SaleType.java @@ -1,5 +1,7 @@ package com.ruoyi.xkt.enums; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -24,6 +26,6 @@ public enum SaleType { return e; } } - return null; + throw new ServiceException("档口销售出库类型不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/enums/SoleProprietorshipType.java b/xkt/src/main/java/com/ruoyi/xkt/enums/SoleProprietorshipType.java index 43ba7aa1f..6d0f6c491 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/enums/SoleProprietorshipType.java +++ b/xkt/src/main/java/com/ruoyi/xkt/enums/SoleProprietorshipType.java @@ -1,5 +1,7 @@ package com.ruoyi.xkt.enums; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.exception.ServiceException; import lombok.AllArgsConstructor; import lombok.Getter; @@ -26,6 +28,6 @@ public enum SoleProprietorshipType { return e; } } - return null; + throw new ServiceException("档口营业执照 经营类型不存在!", HttpStatus.ERROR); } } diff --git a/xkt/src/main/java/com/ruoyi/xkt/mapper/AdvertRoundMapper.java b/xkt/src/main/java/com/ruoyi/xkt/mapper/AdvertRoundMapper.java index c40545406..3a3e4353f 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/mapper/AdvertRoundMapper.java +++ b/xkt/src/main/java/com/ruoyi/xkt/mapper/AdvertRoundMapper.java @@ -2,8 +2,9 @@ package com.ruoyi.xkt.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.xkt.domain.AdvertRound; +import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageDTO; +import com.ruoyi.xkt.dto.advertRound.AdvertRoundStorePageResDTO; import org.apache.ibatis.annotations.Param; -import org.springframework.stereotype.Repository; import java.util.List; @@ -13,7 +14,6 @@ import java.util.List; * @author ruoyi * @date 2025-03-26 */ -@Repository public interface AdvertRoundMapper extends BaseMapper { /** @@ -28,4 +28,26 @@ public interface AdvertRoundMapper extends BaseMapper { boolean isStallOverBuy(@Param("advertId") Long advertId, @Param("roundId") Long roundId, @Param("storeId") Long storeId, @Param("launchStatusList") List launchStatusList); + /** + * 获取档口已订购的推广列表 + * + * @param pageDTO 列表查询入参 + * @return List + */ + List selectStoreAdvertPage(AdvertRoundStorePageDTO pageDTO); + + /** + * 将参数直接null + * @param advertRoundId advertRoundId + */ + Integer updateAttrNull(Long advertRoundId); + + /** + * 获取最受欢迎的8个推广位 + * + * @return List + */ + List selectMostPopulars(); + } + diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java index de2b1bc6d..5996436fd 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertRoundService.java @@ -1,9 +1,10 @@ package com.ruoyi.xkt.service; -import com.ruoyi.xkt.dto.advertRound.AdRoundStoreCreateDTO; -import com.ruoyi.xkt.dto.advertRound.AdRoundStoreResDTO; +import com.ruoyi.common.core.page.Page; +import com.ruoyi.xkt.dto.advertRound.*; import java.text.ParseException; +import java.util.List; /** * 推广营销Service接口 @@ -16,8 +17,8 @@ public interface IAdvertRoundService { /** * 根据广告ID获取推广轮次列表,并返回当前档口在这些推广轮次的数据 * - * @param storeId 档口ID - * @param advertId 广告ID + * @param storeId 档口ID + * @param advertId 广告ID * @param showType 时间范围 位置枚举 * @return AdRoundPlayStoreResDTO */ @@ -45,5 +46,52 @@ public interface IAdvertRoundService { void test(); + /** + * 每晚11:30更新广告位轮次状态 将biddingTempStatus赋值给biddingStatus + * + * @throws ParseException + */ void updateBiddingStatus() throws ParseException; + + /** + * 根据advertRoundId获取当前位置枚举设置的商品 + * + * @param advertRoundId advertRoundId + * @return AdRoundSetProdResDTO + */ + List getSetProdInfo(Long advertRoundId); + + /** + * 档口已订购推广列表 + * + * @param pageDTO 分页入参 + * @return Page + */ + Page page(AdvertRoundStorePageDTO pageDTO); + + /** + * 获取当前推广位的推广图 + * + * @param storeId 档口ID + * @param advertRoundId 推广位ID + * @return AdRoundSetPicResDTO + */ + AdRoundStoreSetResDTO getAdvertStoreSetInfo(Long storeId, Long advertRoundId); + + /** + * 档口退订推广位 + * + * @param storeId 档口ID + * @param advertRoundId 推广位ID + * @return + */ + Integer unsubscribe(Long storeId, Long advertRoundId); + + /** + * 获取最受欢迎8个推广位 + * + * @return List + */ + List getMostPopulars(); + } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertService.java index 084413382..7e2b5c554 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IAdvertService.java @@ -60,4 +60,11 @@ public interface IAdvertService { */ List getPlatformList(); + /** + * 查看当前推广类型 示例图 + * + * @param advertType 推广类型 + * @return String + */ + String getDemoPic(Integer advertType); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java index a447c3167..7895b7a40 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertRoundServiceImpl.java @@ -2,24 +2,24 @@ package com.ruoyi.xkt.service.impl; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.page.Page; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.enums.AdType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.xkt.domain.AdvertRound; import com.ruoyi.xkt.domain.AdvertRoundRecord; -import com.ruoyi.xkt.dto.advertRound.AdRoundStoreCreateDTO; -import com.ruoyi.xkt.dto.advertRound.AdRoundStoreResDTO; -import com.ruoyi.xkt.enums.AdBiddingStatus; -import com.ruoyi.xkt.enums.AdLaunchStatus; -import com.ruoyi.xkt.enums.AdRoundType; -import com.ruoyi.xkt.enums.AdShowType; -import com.ruoyi.xkt.mapper.AdvertRoundMapper; -import com.ruoyi.xkt.mapper.AdvertRoundRecordMapper; -import com.ruoyi.xkt.mapper.StoreMapper; +import com.ruoyi.xkt.domain.StoreProduct; +import com.ruoyi.xkt.domain.SysFile; +import com.ruoyi.xkt.dto.advertRound.*; +import com.ruoyi.xkt.enums.*; +import com.ruoyi.xkt.mapper.*; import com.ruoyi.xkt.service.IAdvertRoundService; +import com.ruoyi.xkt.service.IAssetService; import lombok.RequiredArgsConstructor; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; @@ -43,6 +43,8 @@ import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.stream.Collectors; +import static com.ruoyi.common.constant.Constants.ADVERT_POPULAR; + /** * 推广营销轮次播放Service业务层处理 * @@ -57,6 +59,9 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { final AdvertRoundRecordMapper advertRoundRecordMapper; final RedisCache redisCache; final StoreMapper storeMapper; + final StoreProductMapper storeProdMapper; + final SysFileMapper fileMapper; + final IAssetService assetService; // 推广营销位锁 key:symbol + roundId 或者 symbol + roundId + position 。value都是new Object() public static Map advertLockMap = new ConcurrentHashMap<>(); @@ -83,7 +88,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { System.err.println(advertLockMap); } - public void test() { + public void test() { System.err.println(advertLockMap); } @@ -145,6 +150,30 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { this.advertRoundMapper.updateById(updateList); } + /** + * 根据advertRoundId获取当前位置枚举设置的商品 + * + * @param advertRoundId advertRoundId + * @return AdRoundSetProdResDTO + */ + @Override + @Transactional(readOnly = true) + public List getSetProdInfo(Long advertRoundId) { + AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper() + .eq(AdvertRound::getId, advertRoundId).eq(AdvertRound::getDelFlag, Constants.UNDELETED))) + .orElseThrow(() -> new ServiceException("推广轮次不存在!")); + if (!Objects.equals(advertRound.getShowType(), AdShowType.POSITION_ENUM.getValue())) { + throw new ServiceException("当前推广位非位置枚举,不可调用该接口!", HttpStatus.ERROR); + } + if (StringUtils.isEmpty(advertRound.getProdIdStr())) { + return Collections.emptyList(); + } + List storeProdList = this.storeProdMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProduct::getDelFlag, Constants.UNDELETED).eq(StoreProduct::getStoreId, advertRound.getStoreId()) + .in(StoreProduct::getId, Arrays.stream(advertRound.getProdIdStr().split(",")).map(Long::parseLong).collect(Collectors.toList()))); + return storeProdList.stream().map(x -> new AdRoundSetProdResDTO().setStoreProdId(x.getId()).setProdArtNum(x.getProdArtNum())).collect(Collectors.toList()); + } + /** * 根据广告ID获取推广轮次列表,并返回当前档口在这些推广轮次的数据 @@ -156,7 +185,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { */ @Override @Transactional(readOnly = true) - public AdRoundStoreResDTO getStoreAdInfo(final Long storeId, final Long advertId,final Integer showType) { + public AdRoundStoreResDTO getStoreAdInfo(final Long storeId, final Long advertId, final Integer showType) { final LocalTime now = LocalTime.now(); // 当前时间 是否在 晚上22:00:01 到 晚上23:59:59之间 决定 biddingStatus 和 biddingTempStatus 用那一个字段 boolean tenClockAfter = now.isAfter(LocalTime.of(22, 0, 1)) && now.isBefore(LocalTime.of(23, 59, 59)); @@ -288,18 +317,16 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { } - - /** * 档口购买推广营销 - * 主要是两个场景:1. 某个广告位(advert_id)某个轮次(round_id)按照出价(pay_price)决定能否购买。[eg: A B C D E] - * 2. 某个广告位(advert_id)某个轮次(round_id)某个具体位置(position)按照出价(pay_price)决定能否购买。 - * 思路:每次筛选出某个类型,价格最低的推广位,然后只操作这行数据 - * (创建索引:CREATE INDEX idx_advert_round_pay_pos ON advert_round (advert_id, round_id, pay_price, position))。 - * 若:该行数据已经有其它档口先竞价了。先进行比价。如果出价低于最低价格,则抛出异常:“已经有档口出价更高了噢,请重新出价!” - * 若:新出价比原数据价格高,则:a. 给原数据档口创建转移支付单 b.新档口占据该行位置,更新数据。 + * 主要是两个场景:1. 某个广告位(advert_id)某个轮次(round_id)按照出价(pay_price)决定能否购买。[eg: A B C D E] + * 2. 某个广告位(advert_id)某个轮次(round_id)某个具体位置(position)按照出价(pay_price)决定能否购买。 + * 思路:每次筛选出某个类型,价格最低的推广位,然后只操作这行数据 + * (创建索引:CREATE INDEX idx_advert_round_pay_pos ON advert_round (advert_id, round_id, pay_price, position))。 + * 若:该行数据已经有其它档口先竞价了。先进行比价。如果出价低于最低价格,则抛出异常:“已经有档口出价更高了噢,请重新出价!” + * 若:新出价比原数据价格高,则:a. 给原数据档口创建转移支付单 b.新档口占据该行位置,更新数据。 *

- * 等到晚上10:00,所有档口购买完成。再通过定时任务(11:30),给每个类型,按照价格从高到低,进行排序。并将首页各个位置的广告数据推送到ES中。为空的广告位如何填充?? + * 等到晚上10:00,所有档口购买完成。再通过定时任务(11:30),给每个类型,按照价格从高到低,进行排序。并将首页各个位置的广告数据推送到ES中。为空的广告位如何填充?? *

* * @param createDTO 购买入参 @@ -344,38 +371,152 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { if (createDTO.getPayPrice().compareTo(ObjectUtils.defaultIfNull(minPriceAdvert.getPayPrice(), BigDecimal.ZERO)) <= 0) { throw new ServiceException("已经有档口出价更高了噢,请重新出价!", HttpStatus.ERROR); } - // storeId不为空,表明之前有其他的档口竞价 if (ObjectUtils.isNotEmpty(minPriceAdvert.getStoreId())) { - - // TODO 将推广费退至原档口余额 - // TODO 将推广费退至原档口余额 - + // 将推广费退至原档口余额 + assetService.refundAdvertFee(minPriceAdvert.getStoreId(), minPriceAdvert.getPayPrice()); // 记录竞价失败的档口推广营销 this.record(minPriceAdvert); } - - // 更新出价最低的广告位 + // 更新广告位数据 minPriceAdvert.setStoreId(createDTO.getStoreId()).setPayPrice(createDTO.getPayPrice()) + // 展示类型非商品才赋值 setType .setVoucherDate(java.sql.Date.valueOf(LocalDate.now())) .setBiddingStatus(AdBiddingStatus.BIDDING.getValue()) .setBiddingTempStatus(AdBiddingStatus.BIDDING_SUCCESS.getValue()) - .setPicDesignType(createDTO.getPicDesignType()).setProdIdStr(createDTO.getProdIdStr()); + .setPicSetType(!Objects.equals(minPriceAdvert.getDisplayType(), AdDisplayType.PRODUCT.getValue()) ? AdPicSetType.UN_SET.getValue() : null) + .setPicDesignType(!Objects.equals(minPriceAdvert.getDisplayType(), AdDisplayType.PRODUCT.getValue()) ? createDTO.getPicDesignType() : null) + .setPicAuditStatus(!Objects.equals(minPriceAdvert.getDisplayType(), AdDisplayType.PRODUCT.getValue()) ? AdPicAuditStatus.UN_AUDIT.getValue() : null) + .setProdIdStr(createDTO.getProdIdStr()); this.advertRoundMapper.updateById(minPriceAdvert); - - // TODO 新竞价成功的档口扣减余额 - // TODO 新竞价成功的档口扣减余额 - + // 扣除推广费 + assetService.payAdvertFee(createDTO.getStoreId(), createDTO.getPayPrice(), createDTO.getTransactionPassword()); } return 1; } + /** + * 档口已订购推广列表 + * + * @param pageDTO 分页入参 + * @return Page + */ + @Override + @Transactional(readOnly = true) + public Page page(AdvertRoundStorePageDTO pageDTO) { + PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize()); + List list = this.advertRoundMapper.selectStoreAdvertPage(pageDTO); + list.forEach(item -> item.setPlatformName(AdPlatformType.of(item.getPlatformId()).getLabel()) + .setLaunchStatusName(AdLaunchStatus.of(item.getLaunchStatus()).getLabel()) + .setPicAuditStatusName(ObjectUtils.isNotEmpty(item.getPicAuditStatus()) ? AdPicAuditStatus.of(item.getPicAuditStatus()).getLabel() : "") + .setPicDesignTypeName(ObjectUtils.isNotEmpty(item.getPicDesignType()) ? AdDesignType.of(item.getPicDesignType()).getLabel() : "") + .setPicAuditStatusName(ObjectUtils.isNotEmpty(item.getPicAuditStatus()) ? AdPicAuditStatus.of(item.getPicAuditStatus()).getLabel() : "") + .setPicSetTypeName(ObjectUtils.isNotEmpty(item.getPicSetType()) ? AdPicSetType.of(item.getPicSetType()).getLabel() : "") + .setTypeName(AdType.of(item.getTypeId()).getLabel()) + .setBiddingStatusName(AdBiddingStatus.of(item.getBiddingStatus()).getLabel())); + return Page.convert(new PageInfo<>(list)); + } + + /** + * 获取当前档口设置的推广位信息 + * + * @param storeId 档口ID + * @param advertRoundId 推广位ID + * @return AdRoundSetPicResDTO + */ + @Override + @Transactional(readOnly = true) + public AdRoundStoreSetResDTO getAdvertStoreSetInfo(Long storeId, Long advertRoundId) { + AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper() + .eq(AdvertRound::getId, advertRoundId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .eq(AdvertRound::getStoreId, storeId))) + .orElseThrow(() -> new ServiceException("档口购买的推广位不存在!", HttpStatus.ERROR)); + AdRoundStoreSetResDTO storeSet = new AdRoundStoreSetResDTO().setAdvertRoundId(advertRoundId); + // 获取档口设置的推广图 + if (ObjectUtils.isNotEmpty(advertRound.getPicId())) { + SysFile file = Optional.ofNullable(this.fileMapper.selectOne(new LambdaQueryWrapper() + .eq(SysFile::getId, advertRound.getPicId()).eq(SysFile::getDelFlag, Constants.UNDELETED))) + .orElseThrow(() -> new ServiceException("推广图不存在", HttpStatus.ERROR)); + storeSet.setFileUrl(file.getFileUrl()); + } + // 获取档口设置的推广商品 + if (StringUtils.isNotBlank(advertRound.getProdIdStr())) { + List storeProdList = Optional.ofNullable(this.storeProdMapper.selectList(new LambdaQueryWrapper() + .eq(StoreProduct::getStoreId, storeId).eq(StoreProduct::getDelFlag, Constants.UNDELETED) + .in(StoreProduct::getId, Arrays.stream(advertRound.getProdIdStr().split(",")).map(Long::parseLong).collect(Collectors.toList())))) + .orElseThrow(() -> new ServiceException("档口设置的推广商品不存在", HttpStatus.ERROR)); + storeSet.setProdList(storeProdList.stream().map(x -> new AdRoundStoreSetResDTO.ARSSProdDTO() + .setStoreProdId(x.getId()).setProdArtNum(x.getProdArtNum())).collect(Collectors.toList())); + } + return storeSet; + } + + /** + * 档口退订推广位 + * + * @param storeId 档口ID + * @param advertRoundId 推广位ID + * @return + */ + @Override + @Transactional + public Integer unsubscribe(Long storeId, Long advertRoundId) { + AdvertRound advertRound = Optional.ofNullable(this.advertRoundMapper.selectOne(new LambdaQueryWrapper() + .eq(AdvertRound::getId, advertRoundId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .eq(AdvertRound::getStoreId, storeId))) + .orElseThrow(() -> new ServiceException("档口购买的推广位不存在!", HttpStatus.ERROR)); + // 判断当前时间距离开播是否小于72h,若是:则不可取消 + Date threeDaysAfter = DateUtils.toDate(LocalDateTime.now().plusDays(3)); + if (threeDaysAfter.after(advertRound.getStartTime())) { + throw new ServiceException("距推广开播小于72小时,不可退订!"); + } + // 将费用退回到档口余额中 + assetService.refundAdvertFee(advertRound.getStoreId(), advertRound.getPayPrice()); + // 将推广位置为空 + return this.advertRoundMapper.updateAttrNull(advertRound.getId()); + } + + /** + * 获取最受欢迎8个推广位 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getMostPopulars() { + // 从redis中获取最受欢迎的8个推广位 + List redisList = redisCache.getCacheObject(ADVERT_POPULAR); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + // 找到有人购买的最受欢迎的advertId列表 + List advertIdList = this.advertRoundMapper.selectMostPopulars(); + if (CollectionUtils.isEmpty(advertIdList)) { + return new ArrayList<>(); + } + // 获取下一轮待投放的推广位 + List advertRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .in(AdvertRound::getAdvertId, advertIdList).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .eq(AdvertRound::getLaunchStatus, AdLaunchStatus.UN_LAUNCH.getValue())); + // 找到播放轮次最近的数据 + Map> minRoundIdMap = advertRoundList.stream().collect(Collectors + .groupingBy(AdvertRound::getAdvertId, Collectors.minBy(Comparator.comparing(AdvertRound::getRoundId)))); + // 将minRoundIdMap中的值转换为List + List list = minRoundIdMap.values().stream().map(Optional::get).map(x -> new AdRoundPopularResDTO().setAdvertId(x.getAdvertId()) + .setTypeId(x.getTypeId()).setTypeName(AdType.of(x.getTypeId()).getLabel()).setShowType(x.getShowType()).setStartTime(x.getStartTime()) + .setEndTime(x.getEndTime()).setStartPrice(x.getStartPrice())) + .collect(Collectors.toList()); + // 存到redis中 + redisCache.setCacheObject(ADVERT_POPULAR, list, 1, TimeUnit.DAYS); + return list; + } + /** * 获取已抢购推广位列表 * * @param storeId 档口ID * @param advertRoundList 播放轮次列表 - * @param recordList 未购买的播放轮次列表 + * @param recordList 未购买的播放轮次列表 * @return List */ private List getStoreBoughtList(Long storeId, List advertRoundList, List recordList) { @@ -403,9 +544,9 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 通过定时任务往redis中放当前推广位 当前播放轮 或 即将播放轮 的截止时间; * 比如:5.1 - 5.3 - * a. 现在是4.30 则截止时间是 4.30 22:00 - * b. 现在是5.2,则截止时间是 5.2 22:00:00 。 - * c. 现在是5.3,则第一轮还有请求,肯定是人为的不用管。请求第三轮 或者 第四轮 不报错。只处理第二轮请求 + * a. 现在是4.30 则截止时间是 4.30 22:00 + * b. 现在是5.2,则截止时间是 5.2 22:00:00 。 + * c. 现在是5.3,则第一轮还有请求,肯定是人为的不用管。请求第三轮 或者 第四轮 不报错。只处理第二轮请求 * * @throws ParseException */ @@ -420,7 +561,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { // 服务器当前时间 yyyy-MM-dd final Date now = DateUtils.parseDate(DateUtils.getDate(), DateUtils.YYYY_MM_DD); // 当天截止的时间 yyyy-MM-dd 22:00:00 - final String filterTime = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS) + final String filterTime = DateTimeFormatter.ofPattern(DateUtils.YYYY_MM_DD_HH_MM_SS) .format(LocalDateTime.now().withHour(22).withMinute(0).withSecond(0)); advertRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getAdvertId)) .forEach((advertId, roundList) -> { @@ -440,12 +581,6 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { return; } } - // 作用于某一轮推广的symbol(包含了播放轮次的) - /*String symbol = now.before(firstRoundEndTime) - ? roundList.stream().filter(x -> x.getRoundId().equals(AdRoundType.PLAY_ROUND.getValue())) - .map(AdvertRound::getSymbol).findAny().orElseThrow(() -> new ServiceException("获取推广第一轮symbol失败,请联系客服!", HttpStatus.ERROR)) - : roundList.stream().filter(x -> x.getRoundId().equals(AdRoundType.SECOND_ROUND.getValue())) - .map(AdvertRound::getSymbol).findAny().orElseThrow(() -> new ServiceException("获取推广第二轮symbol失败,请联系客服!", HttpStatus.ERROR));*/ // 存放到redis中 有效期1天 redisCache.setCacheObject(symbol, filterTime, 1, TimeUnit.DAYS); }); @@ -454,6 +589,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 获取当前推广轮次的过期时间 + * * @param symbol 符号 * @return */ @@ -464,6 +600,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 记录竞价失败档口推广营销 + * * @param failAdvert 竞价失败的推广营销 */ private void record(AdvertRound failAdvert) { @@ -478,6 +615,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 根据Date获取当前星期几 + * * @param date 时间yyyy-MM-dd * @return 星期几 */ @@ -489,8 +627,9 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 计算两天之间相差多少天 + * * @param startDate 开始日期 - * @param endDate 截止日期 + * @param endDate 截止日期 * @return diffDay */ public static int calculateDurationDay(Date startDate, Date endDate) { @@ -501,10 +640,11 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 获取当前档口 已抢购推广位 - * @param allRoundList 所有的推广 + * + * @param allRoundList 所有的推广 * @param allRecordList 所有竞价失败的推广 - * @param storeId 档口ID - * @param voucherDate 单据日期 + * @param storeId 档口ID + * @param voucherDate 单据日期 * @param tenClockAfter 是否是10点后 * @return */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertServiceImpl.java index 11ef33515..a56af0d15 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/AdvertServiceImpl.java @@ -1,6 +1,5 @@ package com.ruoyi.xkt.service.impl; -import java.security.SecureRandom; import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.github.pagehelper.PageHelper; @@ -9,6 +8,7 @@ import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.HttpStatus; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.page.Page; +import com.ruoyi.common.enums.AdType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.xkt.domain.Advert; @@ -17,7 +17,6 @@ import com.ruoyi.xkt.dto.advert.*; import com.ruoyi.xkt.enums.AdOnlineStatus; import com.ruoyi.xkt.enums.AdPlatformType; import com.ruoyi.xkt.enums.AdTab; -import com.ruoyi.common.enums.AdType; import com.ruoyi.xkt.mapper.AdvertMapper; import com.ruoyi.xkt.mapper.SysFileMapper; import com.ruoyi.xkt.service.IAdvertService; @@ -27,6 +26,7 @@ import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -210,6 +210,23 @@ public class AdvertServiceImpl implements IAdvertService { return platformList; } + /** + * 查看当前推广类型 示例图 + * + * @param advertType 推广类型 + * @return String + */ + @Override + @Transactional(readOnly = true) + public String getDemoPic(Integer advertType) { + Advert advert = Optional.ofNullable(this.advertMapper.selectOne(new LambdaQueryWrapper() + .eq(Advert::getTypeId, advertType).eq(Advert::getDelFlag, Constants.UNDELETED))) + .orElseThrow(() -> new ServiceException("推广类型不存在!", HttpStatus.ERROR)); + SysFile file = Optional.ofNullable(this.fileMapper.selectById(advert.getExamplePicId())) + .orElseThrow(() -> new ServiceException("示例图不存在!", HttpStatus.ERROR)); + return file.getFileUrl(); + } + /** * 校验当前是否是超级管理员操作 */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreServiceImpl.java index e24e46e7c..ca404e24e 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreServiceImpl.java @@ -19,6 +19,7 @@ import com.ruoyi.xkt.enums.StoreStatus; import com.ruoyi.xkt.mapper.DailyStoreTagMapper; import com.ruoyi.xkt.mapper.StoreMapper; import com.ruoyi.xkt.mapper.UserSubscriptionsMapper; +import com.ruoyi.xkt.service.IAssetService; import com.ruoyi.xkt.service.IStoreCertificateService; import com.ruoyi.xkt.service.IStoreService; import lombok.RequiredArgsConstructor; @@ -50,6 +51,8 @@ public class StoreServiceImpl implements IStoreService { final DailyStoreTagMapper storeTagMapper; final UserSubscriptionsMapper userSubMapper; final RedisCache redisCache; + final IAssetService assetService; + /** * 注册时新增档口数据 @@ -69,6 +72,8 @@ public class StoreServiceImpl implements IStoreService { Date oneYearAfter = Date.from(LocalDate.now().plusYears(1).atStartOfDay(ZoneId.systemDefault()).toInstant()); store.setTrialEndTime(oneYearAfter); int count = this.storeMapper.insert(store); + // 创建档口账户 + assetService.createInternalAccountIfNotExists(store.getId()); // 放到redis中 redisCache.setCacheObject(Constants.STORE_REDIS_PREFIX + store.getId(), store.getId()); return count; diff --git a/xkt/src/main/resources/mapper/AdvertRoundMapper.xml b/xkt/src/main/resources/mapper/AdvertRoundMapper.xml index 7e75224de..3ae96c90e 100644 --- a/xkt/src/main/resources/mapper/AdvertRoundMapper.xml +++ b/xkt/src/main/resources/mapper/AdvertRoundMapper.xml @@ -24,4 +24,71 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + + + + + UPDATE advert_round + SET voucher_date = NULL, + store_id = NULL, + pay_price = NULL, + bidding_status = NULL, + bidding_temp_status = NULL, + pic_audit_status = NULL, + pic_set_type = NULL, + pic_id = NULL, + prod_id_str = NULL, + pic_design_type = NULL, + sys_intercept = NULL + WHERE + id = #{advertRoundId} + + + + + + \ No newline at end of file