diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java index d1ba7ca65..f75656e4a 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/WebsiteController.java @@ -39,8 +39,7 @@ import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreRecommendDTO; import com.ruoyi.xkt.dto.website.AppStrengthSearchDTO; import com.ruoyi.xkt.dto.website.IndexSearchDTO; import com.ruoyi.xkt.dto.website.StoreSearchDTO; -import com.ruoyi.xkt.service.IWebsiteAPPService; -import com.ruoyi.xkt.service.IWebsitePCService; +import com.ruoyi.xkt.service.*; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; @@ -63,6 +62,9 @@ import java.util.List; public class WebsiteController extends XktBaseController { final IWebsitePCService websitePCService; + final IWebsitePCIndexService websitePCIndexService; + final IWebsitePCNewProdService websitePCNewProdService; + final IWebsitePCStoreService websitePCStoreService; final IWebsiteAPPService websiteAPPService; final RedisCache redisCache; @@ -93,7 +95,7 @@ public class WebsiteController extends XktBaseController { @ApiOperation(value = "PC 首页 顶部通栏", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/top") public R> getPcIndexTop() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexTop(), PCIndexTopBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexTop(), PCIndexTopBannerVO.class)); } @ApiOperation(value = "PC 搜索结果广告", httpMethod = "GET", response = R.class) @@ -105,97 +107,97 @@ public class WebsiteController extends XktBaseController { @ApiOperation(value = "PC 首页 顶部横向轮播图", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/top/left") public R> getPcIndexTopLeftBanner() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexTopLeftBanner(), PCIndexTopLeftBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexTopLeftBanner(), PCIndexTopLeftBannerVO.class)); } @ApiOperation(value = "PC 首页 顶部纵向轮播图", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/top/right") public R> getPcIndexTopRightBanner() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexTopRightBanner(), PCIndexTopRightBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexTopRightBanner(), PCIndexTopRightBannerVO.class)); } @ApiOperation(value = "PC 首页 销售榜", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/mid/sales") public R> getPcIndexMidSaleList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexMidSaleList(), PCIndexMidSalesVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexMidSaleList(), PCIndexMidSalesVO.class)); } @ApiOperation(value = "PC 首页 风格榜", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/mid/styles") public R> getPcIndexMidStyleList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexMidStyleList(), PCIndexMidStyleVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexMidStyleList(), PCIndexMidStyleVO.class)); } @ApiOperation(value = "PC 首页 人气榜", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/bottom/popular") public R getPcIndexBottomPopularList() { - return R.ok(BeanUtil.toBean(websitePCService.getPcIndexBottomPopularList(), PCIndexBottomPopularVO.class)); + return R.ok(BeanUtil.toBean(websitePCIndexService.getPcIndexBottomPopularList(), PCIndexBottomPopularVO.class)); } @ApiOperation(value = "PC 首页 两侧固定侧边栏", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/fixed-ear") public R getPcIndexFixedEar() { - return R.ok(BeanUtil.toBean(websitePCService.getPcIndexFixedEar(), PCIndexFixedEarVO.class)); + return R.ok(BeanUtil.toBean(websitePCIndexService.getPcIndexFixedEar(), PCIndexFixedEarVO.class)); } @ApiOperation(value = "PC 搜索框下方推荐档口名称", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/search-underline-store-name") public R> getPcIndexSearchUnderlineStoreName() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexSearchUnderlineStoreName(), PCIndexSearchUnderlineStoreNameVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexSearchUnderlineStoreName(), PCIndexSearchUnderlineStoreNameVO.class)); } @ApiOperation(value = "PC 首页 搜索框中推荐商品", httpMethod = "GET", response = R.class) @GetMapping("/pc/index/search-recommend-prod") public R> getPcIndexSearchRecommendProd() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcIndexSearchRecommendProd(), PCIndexSearchRecommendProdVO.class)); + return R.ok(BeanUtil.copyToList(websitePCIndexService.getPcIndexSearchRecommendProd(), PCIndexSearchRecommendProdVO.class)); } @ApiOperation(value = "PC 新品馆 顶部横向轮播图", httpMethod = "GET", response = R.class) @GetMapping("/pc/new/top/left") public R> getPcNewTopLeftBanner() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcNewTopLeftBanner(), PCNewTopLeftBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCNewProdService.getPcNewTopLeftBanner(), PCNewTopLeftBannerVO.class)); } @ApiOperation(value = "PC 新品馆 顶部纵向图", httpMethod = "GET", response = R.class) @GetMapping("/pc/new/top/right") public R getPcNewTopRight() { - return R.ok(BeanUtil.toBean(websitePCService.getPcNewTopRight(), PCNewTopRightVO.class)); + return R.ok(BeanUtil.toBean(websitePCNewProdService.getPcNewTopRight(), PCNewTopRightVO.class)); } @ApiOperation(value = "PC 新品馆 品牌榜", httpMethod = "GET", response = R.class) @GetMapping("/pc/new/mid/brand") public R> getPcNewMidBrandList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcNewMidBrandList(), PCNewMidBrandVO.class)); + return R.ok(BeanUtil.copyToList(websitePCNewProdService.getPcNewMidBrandList(), PCNewMidBrandVO.class)); } @ApiOperation(value = "PC 新品馆 热卖榜左侧轮播图", httpMethod = "GET", response = R.class) @GetMapping("/pc/new/mid/hot-left") public R> getPcNewMidHotLeftList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcNewMidHotLeftList(), PCNewMidHotLeftVO.class)); + return R.ok(BeanUtil.copyToList(websitePCNewProdService.getPcNewMidHotLeftList(), PCNewMidHotLeftVO.class)); } @ApiOperation(value = "PC 新品馆 热卖榜右侧商品图", httpMethod = "GET", response = R.class) @GetMapping("/pc/new/mid/hot-right") public R> getPcNewMidHotRightList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcNewMidHotRightList(), PCNewMidHotRightVO.class)); + return R.ok(BeanUtil.copyToList(websitePCNewProdService.getPcNewMidHotRightList(), PCNewMidHotRightVO.class)); } @ApiOperation(value = "PC 新品馆 横幅", httpMethod = "GET", response = R.class) @GetMapping("/pc/new/bottom/banner") public R> getPcNewBottomBannerList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcNewBottomBannerList(), PCNewBottomBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCNewProdService.getPcNewBottomBannerList(), PCNewBottomBannerVO.class)); } @ApiOperation(value = "PC 档口馆 顶部banner", httpMethod = "GET", response = R.class) @GetMapping("/pc/store/top/banner") public R> getPcStoreTopBannerList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcStoreTopBannerList(), PCStoreTopBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCStoreService.getPcStoreTopBannerList(), PCStoreTopBannerVO.class)); } @ApiOperation(value = "PC 档口馆 中间横幅", httpMethod = "GET", response = R.class) @GetMapping("/pc/store/mid/banner") public R> getPcStoreMidBannerList() { - return R.ok(BeanUtil.copyToList(websitePCService.getPcStoreMidBannerList(), PCStoreMidBannerVO.class)); + return R.ok(BeanUtil.copyToList(websitePCStoreService.getPcStoreMidBannerList(), PCStoreMidBannerVO.class)); } @ApiOperation(value = "PC 档口馆 档口列表", httpMethod = "POST", response = R.class) 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 e305603cf..93e2b172e 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 @@ -27,6 +27,7 @@ import com.ruoyi.framework.notice.fs.FsNotice; import com.ruoyi.system.mapper.SysDictDataMapper; import com.ruoyi.xkt.domain.*; import com.ruoyi.xkt.dto.account.WithdrawPrepareResult; +import com.ruoyi.xkt.dto.advertRound.pc.index.PCIndexTopBannerDTO; import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreRecommendDTO; import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreRecommendTempDTO; import com.ruoyi.xkt.dto.dailySale.DailySaleCusDTO; @@ -167,7 +168,7 @@ public class XktTask { } /** - * 每天凌晨12:00:01秒 更新store到redis中 + * 每天凌晨01:00:01秒 更新store到redis中 */ public void saveStoreToRedis() { List storeList = this.storeMapper.selectList(new LambdaQueryWrapper() @@ -181,7 +182,7 @@ public class XktTask { } /** - * 凌晨12:01 更新推广轮次 + * 凌晨01:01 更新推广轮次 */ @Transactional public void dailyAdvertRound() { @@ -266,14 +267,14 @@ public class XktTask { /** - * 凌晨00:04更新symbol对应的锁资源到redis中 + * 凌晨01:04更新symbol对应的锁资源到redis中 */ public void saveSymbolToRedis() { advertRoundService.initAdvertLockMap(); } /** - * 凌晨00:08更新各推广轮次结束时间 + * 凌晨01:08更新各推广轮次结束时间 */ public void saveAdvertDeadlineToRedis() { // 直接调service方法,若当时redis出了问题,也方便第一时间 通过业务流程弥补 两边都有一个补偿机制 @@ -281,7 +282,7 @@ public class XktTask { } /** - * 凌晨00:10 同步档口销售数据 + * 凌晨01:10 同步档口销售数据 */ @Transactional public void dailySale() { @@ -303,7 +304,7 @@ public class XktTask { } /** - * 凌晨00:15 同步档口客户销售数据 + * 凌晨01:15 同步档口客户销售数据 */ @Transactional public void dailySaleCustomer() { @@ -325,7 +326,7 @@ public class XktTask { } /** - * 凌晨00:20 同步档口商品销售数据 + * 凌晨01:20 同步档口商品销售数据 */ @Transactional public void dailySaleProduct() { @@ -347,7 +348,7 @@ public class XktTask { } /** - * 凌晨00:25 同步商品最新分类排序 + * 凌晨01:25 同步商品最新分类排序 */ @Transactional public void dailyCategorySort() { @@ -396,7 +397,7 @@ public class XktTask { } /** - * 凌晨00:30 更新档口的标签 + * 凌晨01:30 更新档口的标签 */ @Transactional public void dailyStoreTag() { @@ -434,7 +435,7 @@ public class XktTask { } /** - * 凌晨00:40 更新商品标签 + * 凌晨01:40 更新商品标签 */ @Transactional public void dailyProdTag() throws IOException { @@ -493,7 +494,7 @@ public class XktTask { } /** - * 凌晨12:45 将advert的数据暂存到redis中 + * 凌晨01:45 将advert的数据暂存到redis中 */ public void saveAdvertToRedis() { List advertList = this.advertMapper.selectList(new LambdaQueryWrapper() @@ -506,7 +507,7 @@ public class XktTask { } /** - * 凌晨1:00 更新档口商品的各项权重数据 + * 凌晨02:00 更新档口商品的各项权重数据 */ @Transactional public void dailyProdWeight() { @@ -547,7 +548,7 @@ public class XktTask { } /** - * 凌晨1:10 更新PC档口馆推荐列表权重数据 + * 凌晨02:10 更新PC档口馆推荐列表权重数据 */ @Transactional public void dailyStoreWeight() { @@ -598,7 +599,7 @@ public class XktTask { } /** - * 凌晨01:15 更新用户搜索历史入库 + * 凌晨02:15 更新用户搜索历史入库 */ @Transactional public void dailyUpdateUserSearchHistory() { @@ -635,7 +636,7 @@ public class XktTask { } /** - * 凌晨01:20 更新用户浏览记录入库 + * 凌晨02:20 更新用户浏览记录入库 */ @Transactional public void dailyUpdateUserBrowsingHistory() { @@ -670,7 +671,7 @@ public class XktTask { } /** - * 凌晨01:25 更新系统热搜到redis中 + * 凌晨02:25 更新系统热搜到redis中 */ @Transactional public void dailyUpdateSearchHotToRedis() { @@ -693,7 +694,7 @@ public class XktTask { } /** - * 凌晨01:30 更新统计图搜热款 + * 凌晨02:30 更新统计图搜热款 */ public void imgSearchTopProductStatistics() { log.info("-------------统计图搜热款开始-------------"); @@ -702,14 +703,14 @@ public class XktTask { } /** - * 凌晨1:35 更新试用期过期档口 + * 凌晨02:35 更新试用期过期档口 */ public void autoCloseTrialStore() { } /** - * 凌晨1:40 更新年费过期档口 + * 凌晨02:40 更新年费过期档口 */ public void autoCloseTimeoutStore() { @@ -720,7 +721,7 @@ public class XktTask { } /** - * 凌晨1:45 更新档口会员过期 + * 凌晨02:45 更新档口会员过期 */ public void autoCloseExpireStoreMember() { final Date yesterday = java.sql.Date.valueOf(LocalDate.now().minusDays(1)); @@ -737,7 +738,7 @@ public class XktTask { } /** - * 凌晨1:50 将档口会员存到redis中 + * 凌晨02:50 将档口会员存到redis中 */ public void saveStoreMemberToRedis() { List memberList = this.storeMemberMapper.selectList(new LambdaQueryWrapper() @@ -749,7 +750,7 @@ public class XktTask { } /** - * 凌晨1:55 更新APP商品销量榜、分类商品销量榜 + * 凌晨02:55 更新APP商品销量榜、分类商品销量榜 */ public void dailyProdTopSale() { final Date oneMonthAgo = java.sql.Date.valueOf(LocalDate.now().minusMonths(1)); @@ -769,7 +770,7 @@ public class XktTask { } /** - * 凌晨2:00更新档口权重到redis + * 凌晨03:00更新档口权重到redis */ public void updateStoreWeightToES() throws IOException { // 找到昨天开通会员的所有档口 @@ -823,7 +824,7 @@ public class XktTask { } /** - * 凌晨2:05更新档口访问量 + * 凌晨03:05更新档口访问量 */ @Transactional public void updateStoreVisitCount() { @@ -848,6 +849,18 @@ public class XktTask { this.storeMapper.updateById(storeList); } + /** + * 凌晨04:00更新最新的广告展示数据 + */ + @Transactional + public void clearAndUpdateAdvertShowData() { + // 1. PC 首页顶部通栏 +// redisCache.deleteObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP); +// +// List topBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP); + + } + /** * 每月第一天凌晨5:00更新voucher_sequence */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreFactoryService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreFactoryService.java index 3c2c13007..682fae5d6 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreFactoryService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreFactoryService.java @@ -1,7 +1,6 @@ package com.ruoyi.xkt.service; import com.ruoyi.common.core.page.Page; -import com.ruoyi.xkt.domain.StoreFactory; import com.ruoyi.xkt.dto.storeFactory.StoreFactoryDTO; import com.ruoyi.xkt.dto.storeFactory.StoreFactoryPageDTO; import com.ruoyi.xkt.dto.storeFactory.StoreFactoryResDTO; diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductBarcodeMatchService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductBarcodeMatchService.java index 11a7194b5..4586ab159 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductBarcodeMatchService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductBarcodeMatchService.java @@ -1,10 +1,5 @@ package com.ruoyi.xkt.service; -import com.ruoyi.xkt.domain.StoreProductBarcodeMatch; -import com.ruoyi.xkt.dto.storeProdBarcodeMatch.BarcodeMatchDTO; - -import java.util.List; - /** * 档口条形码和第三方系统条形码匹配结果Service接口 * diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductService.java index 089f7e47e..a67bfcc1c 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductService.java @@ -150,7 +150,7 @@ public interface IStoreProductService { /** * 模糊查询系统所有商品 * - * @param storeId 档口ID + * @param storeId 档口ID * @param prodArtNum 货号 * @return StoreProdFuzzyResDTO */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStockService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStockService.java index 56ae6c7ed..4fe6f5486 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStockService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IStoreProductStockService.java @@ -68,7 +68,7 @@ public interface IStoreProductStockService { /** * 根据档口ID和商品货号查询档口商品库存 * - * @param storeId 档口ID + * @param storeId 档口ID * @param storeProdId 档口商品ID * @return String */ diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IUserSearchHistoryService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IUserSearchHistoryService.java index d8acfe2db..5e8cdd35b 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IUserSearchHistoryService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IUserSearchHistoryService.java @@ -19,6 +19,7 @@ public interface IUserSearchHistoryService { /** * 清空用户的搜索历史 + * * @return Integer */ Integer clearSearchHisRecord(); diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCIndexService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCIndexService.java new file mode 100644 index 000000000..236cc8908 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCIndexService.java @@ -0,0 +1,78 @@ +package com.ruoyi.xkt.service; + +import com.ruoyi.xkt.dto.advertRound.pc.index.*; + +import java.util.List; + +/** + * 系统广告位置及搜索页 + * + * @author ruoyi + * @date 2025-03-26 + */ +public interface IWebsitePCIndexService { + + /** + * PC 首页顶部通栏 + * + * @return PCIndexTopBannerDTO + */ + List getPcIndexTop(); + + /** + * PC 首页 顶部左侧 轮播图 + * + * @return PCIndexTopLeftBannerDTO + */ + List getPcIndexTopLeftBanner(); + + /** + * PC 首页 顶部右侧 纵向轮播图 + * + * @return PCIndexTopRightBannerDTO + */ + List getPcIndexTopRightBanner(); + + /** + * PC 首页 销售榜 + * + * @return List + */ + List getPcIndexMidSaleList(); + + /** + * PC 首页 风格榜 + * + * @return List + */ + List getPcIndexMidStyleList(); + + /** + * PC 首页 人气榜 + * + * @return PCIndexBottomPopularDTO + */ + PCIndexBottomPopularDTO getPcIndexBottomPopularList(); + + /** + * PC 首页 固定侧边栏 + * + * @return PCIndexFixedEarDTO + */ + PCIndexFixedEarDTO getPcIndexFixedEar(); + + /** + * 获取搜索框下档口名称 + * + * @return List + */ + List getPcIndexSearchUnderlineStoreName(); + + /** + * 搜索框中推荐商品 + * + * @return List + */ + List getPcIndexSearchRecommendProd(); + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCNewProdService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCNewProdService.java new file mode 100644 index 000000000..cdb06a66b --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCNewProdService.java @@ -0,0 +1,57 @@ +package com.ruoyi.xkt.service; + +import com.ruoyi.xkt.dto.advertRound.pc.newProd.*; + +import java.util.List; + +/** + * 系统广告位置及搜索页 + * + * @author ruoyi + * @date 2025-03-26 + */ +public interface IWebsitePCNewProdService { + + /** + * PC 新品馆 顶部左侧 轮播图 + * + * @return List + */ + List getPcNewTopLeftBanner(); + + /** + * PC 新品馆 顶部右侧 轮播图 + * + * @return PCNewTopRightDTO + */ + PCNewTopRightDTO getPcNewTopRight(); + + /** + * PC 新品馆 品牌馆 + * + * @return List + */ + List getPcNewMidBrandList(); + + /** + * PC 新品馆 热卖榜左侧 + * + * @return List + */ + List getPcNewMidHotLeftList(); + + /** + * PC 新品馆 热卖榜右侧商品 + * + * @return List + */ + List getPcNewMidHotRightList(); + + /** + * PC 新品馆 底部横幅 + * + * @return List + */ + List getPcNewBottomBannerList(); + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java index 62b228a55..ca7ed9a87 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCService.java @@ -5,12 +5,10 @@ import com.ruoyi.xkt.dto.advertRound.pc.PCDownloadDTO; import com.ruoyi.xkt.dto.advertRound.pc.PCSearchDTO; import com.ruoyi.xkt.dto.advertRound.pc.PCSearchResultAdvertDTO; import com.ruoyi.xkt.dto.advertRound.pc.PCUserCenterDTO; -import com.ruoyi.xkt.dto.advertRound.pc.index.*; -import com.ruoyi.xkt.dto.advertRound.pc.newProd.*; -import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreMidBannerDTO; +import com.ruoyi.xkt.dto.advertRound.pc.index.PCIndexRecommendDTO; +import com.ruoyi.xkt.dto.advertRound.pc.newProd.PCNewRecommendDTO; import com.ruoyi.xkt.dto.advertRound.pc.store.PCStorePageDTO; import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreRecommendDTO; -import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreTopBannerDTO; import com.ruoyi.xkt.dto.advertRound.picSearch.PicSearchAdvertDTO; import com.ruoyi.xkt.dto.es.ESProductDTO; import com.ruoyi.xkt.dto.website.IndexSearchDTO; @@ -34,118 +32,6 @@ public interface IWebsitePCService { */ Page search(IndexSearchDTO searchDTO) throws IOException; - /** - * PC 首页 顶部左侧 轮播图 - * - * @return PCIndexTopLeftBannerDTO - */ - List getPcIndexTopLeftBanner(); - - /** - * PC 首页 顶部右侧 纵向轮播图 - * - * @return PCIndexTopRightBannerDTO - */ - List getPcIndexTopRightBanner(); - - /** - * PC 首页 销售榜 - * - * @return List - */ - List getPcIndexMidSaleList(); - - /** - * PC 首页 风格榜 - * - * @return List - */ - List getPcIndexMidStyleList(); - - /** - * PC 首页 人气榜 - * - * @return PCIndexBottomPopularDTO - */ - PCIndexBottomPopularDTO getPcIndexBottomPopularList(); - - /** - * PC 首页 固定侧边栏 - * - * @return PCIndexFixedEarDTO - */ - PCIndexFixedEarDTO getPcIndexFixedEar(); - - /** - * 获取搜索框下档口名称 - * - * @return List - */ - List getPcIndexSearchUnderlineStoreName(); - - /** - * 搜索框中推荐商品 - * - * @return List - */ - List getPcIndexSearchRecommendProd(); - - /** - * PC 新品馆 顶部左侧 轮播图 - * - * @return List - */ - List getPcNewTopLeftBanner(); - - /** - * PC 新品馆 顶部右侧 轮播图 - * - * @return PCNewTopRightDTO - */ - PCNewTopRightDTO getPcNewTopRight(); - - /** - * PC 新品馆 品牌馆 - * - * @return List - */ - List getPcNewMidBrandList(); - - /** - * PC 新品馆 热卖榜左侧 - * - * @return List - */ - List getPcNewMidHotLeftList(); - - /** - * PC 新品馆 热卖榜右侧商品 - * - * @return List - */ - List getPcNewMidHotRightList(); - - /** - * PC 新品馆 底部横幅 - * - * @return List - */ - List getPcNewBottomBannerList(); - - /** - * PC 档口馆 顶部横幅及商品 - * - * @return List - */ - List getPcStoreTopBannerList(); - - /** - * PC 档口馆 中间横幅 - * - * @return List - */ - List getPcStoreMidBannerList(); - /** * 以图搜款 广告 * @@ -199,13 +85,6 @@ public interface IWebsitePCService { */ Page pcStoreRecommendPage(StoreSearchDTO searchDTO); - /** - * PC 首页顶部通栏 - * - * @return PCIndexTopBannerDTO - */ - List getPcIndexTop(); - /** * PC 搜索结果广告列表 * diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCStoreService.java b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCStoreService.java new file mode 100644 index 000000000..8eb11fd01 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/service/IWebsitePCStoreService.java @@ -0,0 +1,30 @@ +package com.ruoyi.xkt.service; + +import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreMidBannerDTO; +import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreTopBannerDTO; + +import java.util.List; + +/** + * 系统广告位置及搜索页 + * + * @author ruoyi + * @date 2025-03-26 + */ +public interface IWebsitePCStoreService { + + /** + * PC 档口馆 顶部横幅及商品 + * + * @return List + */ + List getPcStoreTopBannerList(); + + /** + * PC 档口馆 中间横幅 + * + * @return List + */ + List getPcStoreMidBannerList(); + +} 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 9276d5565..53a8dfd17 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 @@ -535,7 +535,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { store = Optional.ofNullable(this.storeMapper.selectById(createDTO.getStoreId())).orElseThrow(() -> new ServiceException("档口不存在!", HttpStatus.ERROR)); redisCache.setCacheObject(CacheConstants.STORE_KEY + createDTO.getStoreId(), store); } - // 购买推广前置校验 + // 购买推广前置校验 this.advertPreBuyCheck(createDTO); // 当前营销推广位的锁 Object lockObj = Optional.ofNullable(advertLockMap.get(createDTO.getSymbol())).orElseThrow(() -> new ServiceException("symbol不存在!", HttpStatus.ERROR)); @@ -1125,6 +1125,7 @@ public class AdvertRoundServiceImpl implements IAdvertRoundService { /** * 购买推广前置校验 + * * @param createDTO 购买入参 */ private void advertPreBuyCheck(AdRoundStoreCreateDTO createDTO) { diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreColorServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreColorServiceImpl.java index 98022ee5e..d5dbf5111 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreColorServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreColorServiceImpl.java @@ -29,16 +29,51 @@ public class StoreColorServiceImpl implements IStoreColorService { final StoreColorMapper storeColorMapper; private static final Map colorPriority = new HashMap() {{ - put("白", 1); put("黑", 2); put("红", 3); put("棕", 4); put("灰", 5); put("卡", 6); - put("银", 7); put("金", 8); put("蓝", 9); put("绿", 10); put("黄", 11); put("粉", 12); - put("紫", 13); put("橙", 14); put("米", 15); put("杏", 16); put("香", 17); put("军", 18); - put("酒", 19); put("咖", 20); put("焦", 21); put("墨", 22); put("豹", 23); put("蛇", 24); + put("白", 1); + put("黑", 2); + put("红", 3); + put("棕", 4); + put("灰", 5); + put("卡", 6); + put("银", 7); + put("金", 8); + put("蓝", 9); + put("绿", 10); + put("黄", 11); + put("粉", 12); + put("紫", 13); + put("橙", 14); + put("米", 15); + put("杏", 16); + put("香", 17); + put("军", 18); + put("酒", 19); + put("咖", 20); + put("焦", 21); + put("墨", 22); + put("豹", 23); + put("蛇", 24); }}; - private static final Map suffixPriority = new HashMap() {{ - put("", 1); put("单里", 2); put("绒里", 3); put("毛里", 4); put("标准筒", 5); put("加宽筒", 6); - put("漆", 7); put("哑光", 8); put("亚光", 9); put("亮", 10); put("雕花", 11); put("爆裂纹", 12); - put("马毛", 13); put("豹纹", 14); put("蛇纹", 15); put("石头纹", 16); put("羊翻", 17); put("牛翻", 18); + private static final Map suffixPriority = new HashMap() {{ + put("", 1); + put("单里", 2); + put("绒里", 3); + put("毛里", 4); + put("标准筒", 5); + put("加宽筒", 6); + put("漆", 7); + put("哑光", 8); + put("亚光", 9); + put("亮", 10); + put("雕花", 11); + put("爆裂纹", 12); + put("马毛", 13); + put("豹纹", 14); + put("蛇纹", 15); + put("石头纹", 16); + put("羊翻", 17); + put("牛翻", 18); }}; diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreHomepageServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreHomepageServiceImpl.java index 72bb9ab56..46fd8bc4e 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreHomepageServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreHomepageServiceImpl.java @@ -434,7 +434,7 @@ public class StoreHomepageServiceImpl implements IStoreHomepageService { .setFileId(bigBannerMap.containsKey(x.getFileName()) ? bigBannerMap.get(x.getFileName()).getId() : null)) .collect(Collectors.toList())); } - if (CollectionUtils.isNotEmpty(homepageDTO.getDecorationList())) { + if (CollectionUtils.isNotEmpty(homepageDTO.getDecorationList())) { homePageList.addAll(homepageDTO.getDecorationList().stream().map(x -> BeanUtil.toBean(x, StoreHomepage.class).setStoreId(homepageDTO.getStoreId())) .collect(Collectors.toList())); } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java index 712ab5777..65dd31ff5 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/StoreOrderServiceImpl.java @@ -404,7 +404,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService { List spIds = detailInfos.stream().map(StoreOrderDetailInfoDTO::getStoreProdId).distinct() .collect(Collectors.toList()); Map mainPicMap = storeProductFileMapper.selectMainPicByStoreProdIdList(spIds, - FileType.MAIN_PIC.getValue(), ORDER_NUM_1).stream() + FileType.MAIN_PIC.getValue(), ORDER_NUM_1).stream() .collect(Collectors.toMap(StoreProdMainPicDTO::getStoreProdId, StoreProdMainPicDTO::getFileUrl, (o, n) -> n)); for (StoreOrderDetailInfoDTO detailInfo : detailInfos) { @@ -448,8 +448,8 @@ public class StoreOrderServiceImpl implements IStoreOrderService { return ListUtil.empty(); } Map printTimeMap = expressShippingLabelMapper.selectList(Wrappers - .lambdaQuery(ExpressShippingLabel.class) - .in(ExpressShippingLabel::getExpressWaybillNo, expressWaybillNos)) + .lambdaQuery(ExpressShippingLabel.class) + .in(ExpressShippingLabel::getExpressWaybillNo, expressWaybillNos)) .stream() .collect(Collectors.toMap(ExpressShippingLabel::getExpressWaybillNo, ExpressShippingLabel::getLastPrintTime)); @@ -488,9 +488,9 @@ public class StoreOrderServiceImpl implements IStoreOrderService { //物流信息 Map expressNameMap = expressService.getAllExpressNameMap(); Map> expressWaybillGroupMap = storeOrderDetailMapper.selectList(Wrappers - .lambdaQuery(StoreOrderDetail.class) - .eq(StoreOrderDetail::getStoreOrderId, storeOrderId) - .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)) + .lambdaQuery(StoreOrderDetail.class) + .eq(StoreOrderDetail::getStoreOrderId, storeOrderId) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)) .stream() .filter(o -> StrUtil.isNotEmpty(o.getExpressWaybillNo())) .collect(Collectors.groupingBy(StoreOrderDetail::getExpressWaybillNo)); @@ -561,7 +561,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService { List spIds = orderDetailList.stream().map(StoreOrderDetailInfoDTO::getStoreProdId).distinct() .collect(Collectors.toList()); Map mainPicMap = storeProductFileMapper.selectMainPicByStoreProdIdList(spIds, - FileType.MAIN_PIC.getValue(), ORDER_NUM_1).stream() + FileType.MAIN_PIC.getValue(), ORDER_NUM_1).stream() .collect(Collectors.toMap(StoreProdMainPicDTO::getStoreProdId, StoreProdMainPicDTO::getFileUrl, (o, n) -> n)); Map> orderDetailGroup = orderDetailList @@ -1139,9 +1139,9 @@ public class StoreOrderServiceImpl implements IStoreOrderService { List afterSaleOrderIds = afterSaleOrderList.stream().map(SimpleEntity::getId) .collect(Collectors.toList()); Map> afterSaleOrderDetailGroupMap = storeOrderDetailMapper.selectList( - Wrappers.lambdaQuery(StoreOrderDetail.class) - .in(StoreOrderDetail::getStoreOrderId, afterSaleOrderIds) - .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)) + Wrappers.lambdaQuery(StoreOrderDetail.class) + .in(StoreOrderDetail::getStoreOrderId, afterSaleOrderIds) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)) .stream() .filter(o -> { if (!EOrderStatus.AFTER_SALE_COMPLETED.getValue().equals(o.getDetailStatus())) { @@ -1512,9 +1512,9 @@ public class StoreOrderServiceImpl implements IStoreOrderService { public void refundSuccess(Long storeOrderId, List storeOrderDetailIds, Long operatorId) { StoreOrder order = getAndBaseCheck(storeOrderId); Map orderDetailMap = storeOrderDetailMapper.selectList(Wrappers - .lambdaQuery(StoreOrderDetail.class) - .eq(StoreOrderDetail::getStoreOrderId, order.getId()) - .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)) + .lambdaQuery(StoreOrderDetail.class) + .eq(StoreOrderDetail::getStoreOrderId, order.getId()) + .eq(SimpleEntity::getDelFlag, Constants.UNDELETED)) .stream() .collect(Collectors.toMap(SimpleEntity::getId, Function.identity())); for (Long storeOrderDetailId : storeOrderDetailIds) { @@ -1915,8 +1915,8 @@ public class StoreOrderServiceImpl implements IStoreOrderService { .collect(Collectors.toMap(StoreProductColorSize::getId, o -> o)); //下单商品档口颜色 Map scMap = storeColorMapper.selectByIds(spcsMap.values().stream() - .map(StoreProductColorSize::getStoreColorId) - .collect(Collectors.toSet())).stream() + .map(StoreProductColorSize::getStoreColorId) + .collect(Collectors.toSet())).stream() .collect(Collectors.toMap(StoreColor::getId, Function.identity())); //下单商品 List spIdList = spcsMap.values().stream() diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCIndexServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCIndexServiceImpl.java new file mode 100644 index 000000000..a0afdadbe --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCIndexServiceImpl.java @@ -0,0 +1,834 @@ +package com.ruoyi.xkt.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.enums.AdType; +import com.ruoyi.xkt.domain.*; +import com.ruoyi.xkt.dto.advertRound.pc.index.*; +import com.ruoyi.xkt.dto.dailySale.CateSaleRankDTO; +import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicDTO; +import com.ruoyi.xkt.dto.storeProductFile.StoreProdFileResDTO; +import com.ruoyi.xkt.enums.AdBiddingStatus; +import com.ruoyi.xkt.enums.AdDisplayType; +import com.ruoyi.xkt.enums.AdLaunchStatus; +import com.ruoyi.xkt.enums.AdStyleType; +import com.ruoyi.xkt.mapper.*; +import com.ruoyi.xkt.service.IWebsitePCIndexService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static com.ruoyi.common.constant.Constants.TOPMOST_PRODUCT_CATEGORY_ID; + +/** + * 首页搜索 + * + * @author ruoyi + * @date 2025-03-26 + */ +@Service +@RequiredArgsConstructor +public class WebsitePCIndexServiceImpl implements IWebsitePCIndexService { + + final RedisCache redisCache; + final AdvertRoundMapper advertRoundMapper; + final SysFileMapper fileMapper; + final StoreProductFileMapper prodFileMapper; + final DailySaleProductMapper dailySaleProdMapper; + final StoreProductMapper storeProdMapper; + final StoreMapper storeMapper; + final SysProductCategoryMapper prodCateMapper; + + /*** + * PC 首页 顶部通栏 + * @return + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexTop() { + // 从redis 中获取 PC 首页 顶部通栏 + List topBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP); + if (ObjectUtils.isNotEmpty(topBannerList)) { + return topBannerList; + } + // 正在播放的首页顶部通栏 必须是档口已经设置了推广图 + List indexTopList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).isNotNull(AdvertRound::getPicId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .eq(AdvertRound::getTypeId, AdType.PC_HOME_TOPMOST_BANNER.getValue()).eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue())); + if (CollectionUtils.isEmpty(indexTopList)) { + return Collections.emptyList(); + } + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, indexTopList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + // 顶部通栏数据 + List topList = indexTopList.stream().map(x -> new PCIndexTopBannerDTO().setDisplayType(x.getDisplayType()) + .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) + .sorted(Comparator.comparing(PCIndexTopBannerDTO::getPayPrice).reversed()) + .collect(Collectors.toList()); + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + for (int i = 0; i < topList.size(); i++) { + topList.get(i).setOrderNum(i + 1); + } + // 存放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP, topList, 1, TimeUnit.DAYS); + return topList; + } + + /** + * PC 首页 顶部左侧 轮播图 + * + * @return PCIndexTopLeftBannerDTO + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexTopLeftBanner() { + // 从redis 中获取 PC 首页顶部左侧 轮播图 + List topLeftBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_LEFT); + if (ObjectUtils.isNotEmpty(topLeftBannerList)) { + return topLeftBannerList; + } + // 获取近一月 档口首页PC 顶部左侧轮播图推广数据 + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_TOP_LEFT_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 必须是已经设置了推广图的数据 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + List topLeftList; + // 如果顶部横向轮播图全部为空,则需要找填充的数据 + if (CollectionUtils.isEmpty(launchingList)) { + List tempLeftList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempLeftList.add(new PCIndexTopLeftBannerDTO().setDisplayType(advertRound.getDisplayType()).setStoreId(advertRound.getStoreId()) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(advertRound.getPicId()) ? fileMap.get(advertRound.getPicId()).getFileUrl() : null)); + }); + // 只取5条数据 + topLeftList = tempLeftList.stream().limit(5).collect(Collectors.toList()); + } else { + // 顶部轮播图只要有一张即可 + topLeftList = launchingList.stream().map(x -> new PCIndexTopLeftBannerDTO().setDisplayType(x.getDisplayType()) + .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) + .collect(Collectors.toList()); + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + topLeftList.sort(Comparator.comparing(PCIndexTopLeftBannerDTO::getPayPrice).reversed()); + for (int i = 0; i < topLeftList.size(); i++) { + topLeftList.get(i).setOrderNum(i + 1); + } + // 存放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_LEFT, topLeftList, 1, TimeUnit.DAYS); + return topLeftList; + } + + /** + * PC 首页 顶部右侧 纵向轮播图 + * + * @return PCIndexTopRightBannerDTO + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexTopRightBanner() { + // 从redis 中获取 PC 首页顶部右侧 轮播图 + List topRightBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_RIGHT); + if (ObjectUtils.isNotEmpty(topRightBannerList)) { + return topRightBannerList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_TOP_RIGHT_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 必须是已经设置了prodIdStr的数据 + oneMonthList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + List mainPicList = this.prodFileMapper.selectMainPic(oneMonthList.stream().map(AdvertRound::getProdIdStr).distinct().collect(Collectors.toList())); + Map mainPicMap = mainPicList.stream().collect(Collectors.toMap(StoreProdFileResDTO::getStoreProdId, StoreProdFileResDTO::getFileUrl, (v1, v2) -> v2)); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + List topRightList; + // 顶部首页纵向轮播图 + if (CollectionUtils.isEmpty(launchingList)) { + topRightList = this.fillTopRightFromExpired(expiredList, 4, mainPicMap); + } else { + topRightList = launchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) + .map(x -> new PCIndexTopRightBannerDTO().setDisplayType(x.getDisplayType()).setStoreProdId(Long.valueOf(x.getProdIdStr())) + .setFileUrl(mainPicMap.get(Long.valueOf(x.getProdIdStr()))) + .setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId())) + .collect(Collectors.toList()); + // 如果 launchingList 只有一个则还需要补充一个推广填空 + if (topRightList.size() < 2) { + topRightList.addAll(this.fillTopRightFromExpired(expiredList, 1, mainPicMap)); + } + } + for (int i = 0; i < topRightList.size(); i++) { + topRightList.get(i).setOrderNum(i + 1); + } + // 存放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_RIGHT, topRightList, 1, TimeUnit.DAYS); + return topRightList; + } + + + /** + * PC 首页 销售榜 + * + * @return PCIndexMidSalesDTO + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexMidSaleList() { + // 从redis中获取销售榜数据 + List midSaleList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_SALE); + if (ObjectUtils.isNotEmpty(midSaleList)) { + return midSaleList; + } + final Date now = java.sql.Date.valueOf(LocalDate.now()); + final Date oneMonthAgo = java.sql.Date.valueOf(LocalDate.now().minusMonths(1)); + // 全量的销量统计数据 + List cateSaleList = this.dailySaleProdMapper.selectSaleRankList(oneMonthAgo, now); + if (CollectionUtils.isEmpty(cateSaleList)) { + return new ArrayList<>(); + } + // 销售榜榜一到榜四的推广 + List saleRankList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).isNotNull(AdvertRound::getProdIdStr) + .ne(AdvertRound::getProdIdStr, "").eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue()).in(AdvertRound::getTypeId, Arrays.asList(AdType.PC_HOME_SALE_RANK_ONE, + AdType.PC_HOME_SALE_RANK_TWO.getValue(), AdType.PC_HOME_SALE_RANK_THREE.getValue(), AdType.PC_HOME_SALE_RANK_FOUR.getValue()))); + // 销量榜一到榜四的推广 key 1 2 3 4 便于后面取数据 + Map> saleAdvertMap = saleRankList.stream().collect(Collectors.groupingBy(ad -> { + switch (ad.getTypeId()) { + case 3: + return 1; + case 4: + return 2; + case 5: + return 3; + case 6: + return 4; + default: + return ad.getTypeId(); + } + })); + // 推广商品ID列表 + final List advertProdIdList = CollectionUtils.isEmpty(saleRankList) ? Collections.emptyList() + : saleRankList.stream().map(AdvertRound::getProdIdStr).map(Long::parseLong).collect(Collectors.toList()); + // 销售榜推广销量等信息 + List advertSaleList = cateSaleList.stream().filter(x -> advertProdIdList.contains(x.getStoreProdId())).collect(Collectors.toList()); + Map advertSaleMap = CollectionUtils.isEmpty(advertSaleList) ? new HashMap<>() + : advertSaleList.stream().collect(Collectors.toMap(CateSaleRankDTO::getStoreProdId, Function.identity())); + // 所有二级分类ID map + Map parCateIdMap = this.getParCateIdMap(); + final List storeProdIdList = cateSaleList.stream().map(CateSaleRankDTO::getStoreProdId).collect(Collectors.toList()); + // 档口商品的价格及商品主图map + Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() + : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors + .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); + Map cateIdMap = cateSaleList.stream().collect(Collectors.toMap(CateSaleRankDTO::getProdCateId, CateSaleRankDTO::getProdCateName, (existing, replacement) -> existing)); + // Step 1: 按 prodCateId 分组,并取每组销量前5的商品 + Map> topSaleMap = cateSaleList.stream().collect(Collectors.groupingBy(CateSaleRankDTO::getProdCateId, Collectors.collectingAndThen( + Collectors.toList(), list -> list.stream().sorted(Comparator.comparing(CateSaleRankDTO::getSaleNum).reversed()).limit(5).collect(Collectors.toList())))); + // Step 2: 统计每个 prodCateId 的总销量 + Map totalSalesPerCate = cateSaleList.stream().collect(Collectors.groupingBy(CateSaleRankDTO::getProdCateId, Collectors.summingInt(CateSaleRankDTO::getSaleNum))); + // Step 3: 取总销量排名前4的 prodCateId + List> top4CateEntries = totalSalesPerCate.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()).limit(4).collect(Collectors.toList()); + // Step 4: 构建返回结果 + List retCateOrderList = new ArrayList<>(); + for (int i = 0; i < top4CateEntries.size(); i++) { + // 当前销售榜推广 + final List saleAdvertList = saleAdvertMap.getOrDefault(i + 1, Collections.emptyList()); + final List tempAdvertProdIdList = saleAdvertList.stream().map(AdvertRound::getProdIdStr).map(Long::parseLong).collect(Collectors.toList()); + Long cateId = top4CateEntries.get(i).getKey(); + List cateDetailList = topSaleMap.getOrDefault(cateId, Collections.emptyList()); + // 过滤掉销量为0;并且根据广告数量决定截取的商品数量 + cateDetailList = cateDetailList.stream().filter(x -> ObjectUtils.defaultIfNull(x.getSaleNum(), 0) > 0) + .filter(x -> !tempAdvertProdIdList.contains(x.getStoreProdId())).limit(5 - saleAdvertList.size()).collect(Collectors.toList()); + List saleDTOList = new ArrayList<>(); + for (int j = 0; j < cateDetailList.size(); j++) { + CateSaleRankDTO dto = cateDetailList.get(j); + // 绑定档口会员等级 + StoreMember member = this.redisCache.getCacheObject(CacheConstants.STORE_MEMBER + dto.getStoreId()); + PCIndexMidSalesDTO.PCIMSSaleDTO saleDTO = new PCIndexMidSalesDTO.PCIMSSaleDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setStoreId(dto.getStoreId()).setStoreName(dto.getStoreName()).setStoreProdId(dto.getStoreProdId()) + .setProdArtNum(dto.getProdArtNum()).setMemberLevel(ObjectUtils.isNotEmpty(member) ? member.getLevel() : null) + .setStoreProdId(dto.getStoreProdId()).setSaleNum(dto.getSaleNum()).setOrderNum(j + 1) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(dto.getStoreProdId())) + ? prodPriceAndMainPicMap.get(dto.getStoreProdId()).getMinPrice() : null) + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(dto.getStoreProdId())) + ? prodPriceAndMainPicMap.get(dto.getStoreProdId()).getMainPicUrl() : ""); + saleDTOList.add(saleDTO); + } + for (int j = 0; j < saleAdvertList.size(); j++) { + CateSaleRankDTO advertSaleDTO = advertSaleMap.get(Long.parseLong(saleAdvertList.get(j).getProdIdStr())); + // 绑定档口会员等级 + StoreMember member = this.redisCache.getCacheObject(CacheConstants.STORE_MEMBER + advertSaleDTO.getStoreId()); + PCIndexMidSalesDTO.PCIMSSaleDTO saleDTO = new PCIndexMidSalesDTO.PCIMSSaleDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setStoreId(advertSaleDTO.getStoreId()).setStoreName(advertSaleDTO.getStoreName()).setStoreProdId(advertSaleDTO.getStoreProdId()) + .setProdArtNum(advertSaleDTO.getProdArtNum()).setMemberLevel(ObjectUtils.isNotEmpty(member) ? member.getLevel() : null) + .setStoreProdId(advertSaleDTO.getStoreProdId()).setSaleNum(advertSaleDTO.getSaleNum()).setOrderNum(j + 1) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId())) + ? prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId()).getMinPrice() : null) + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId())) + ? prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId()).getMainPicUrl() : ""); + saleDTOList.add(saleDTO); + } + retCateOrderList.add(new PCIndexMidSalesDTO().setProdCateId(cateId).setProdCateName(cateIdMap.get(cateId)).setOrderNum(i + 1) + .setParCateId(parCateIdMap.get(cateId)).setSaleList(saleDTOList)); + } + // 缓存至 Redis + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_SALE, retCateOrderList, 1, TimeUnit.DAYS); + return retCateOrderList; + } + + /** + * PC 首页 风格榜 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexMidStyleList() { + // 从redis 中获取 PC 首页风格榜数据 + List redisStyleList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_STYLE); + if (ObjectUtils.isNotEmpty(redisStyleList)) { + return redisStyleList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_STYLE_RANK.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 必须是已经设置推广图和推广商品的列表 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId()) && StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 档口推广主图map + List fileList = this.fileMapper.selectByIds(oneMonthList.stream().map(AdvertRound::getPicId) + .filter(ObjectUtils::isNotEmpty).collect(Collectors.toList())); + Map fileMap = fileList.stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + List storeList = this.storeMapper.selectByIds(oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList())); + Map storeMap = storeList.stream().collect(Collectors.toMap(Store::getId, Function.identity())); + // 获取所有的档口商品ID列表 + Set storeProdIdSet = new HashSet<>(); + oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).forEach(x -> storeProdIdSet + .addAll(Arrays.stream(x.getProdIdStr().split(",")).map(Long::parseLong).collect(Collectors.toSet()))); + // 档口商品的价格及商品主图map + Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdSet) ? new ConcurrentHashMap<>() + : this.storeProdMapper.selectPriceAndMainPicList(new ArrayList<>(storeProdIdSet)).stream().collect(Collectors + .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + List midStyleList; + // 顶部 中部 风格轮播图 + if (CollectionUtils.isEmpty(launchingList)) { + midStyleList = this.fillMidStyleFromExpired(expiredList, prodPriceAndMainPicMap, fileMap, storeMap, 4); + } else { + midStyleList = this.fillMidStyleFromExpired(launchingList, prodPriceAndMainPicMap, fileMap, storeMap, 4); + // 轮播图不足4个,则从过期的广告轮播图补充 + if (midStyleList.size() < 4) { + midStyleList.addAll(this.fillMidStyleFromExpired(expiredList, prodPriceAndMainPicMap, fileMap, storeMap, 4 - launchingList.size())); + } + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + midStyleList.sort(Comparator.comparing(PCIndexMidStyleDTO::getPayPrice).reversed()); + for (int i = 0; i < midStyleList.size(); i++) { + midStyleList.get(i).setOrderNum(i + 1); + } + // 存放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_STYLE, midStyleList, 1, TimeUnit.DAYS); + return midStyleList; + } + + + /** + * PC 首页 人气榜 + * + * @return PCIndexBottomPopularDTO + */ + @Override + @Transactional(readOnly = true) + public PCIndexBottomPopularDTO getPcIndexBottomPopularList() { + PCIndexBottomPopularDTO popularDTO = new PCIndexBottomPopularDTO(); + // 从redis 中获取 PC 首页 人气榜数据 + PCIndexBottomPopularDTO redisPopular = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_BOTTOM_POPULAR); + if (ObjectUtils.isNotEmpty(redisPopular)) { + return redisPopular; + } + List oneMonthList = this.getOneMonthAdvertList(Arrays.asList( + AdType.PC_HOME_POP_LEFT_BANNER.getValue(), AdType.PC_HOME_POP_MID.getValue(), AdType.PC_HOME_POP_RIGHT.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return popularDTO; + } + // 文件map + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + final List storeProdIdList = oneMonthList.stream() + .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList()); + // 档口商品的价格及商品主图map + Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() + : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors + .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); + // 左侧广告 + List leftLaunchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_LEFT_BANNER.getValue())) + .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) + // 必须是picId不为空的,防止有的档口购买了不设置推广图 + .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + List leftExpiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_LEFT_BANNER.getValue())) + .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())) + // 必须是picId不为空的,防止有的档口购买了不设置推广图 + .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + // 中部广告 + List midLaunchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_MID.getValue())) + .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) + // 必须是picId不为空的,防止有的档口购买了不设置推广图 + .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + List midExpiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_MID.getValue())) + .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())) + // 必须是picId不为空的,防止有的档口购买了不设置推广图 + .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + // 右侧广告 + List rightLaunchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_RIGHT.getValue())) + .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) + // 必须是prodIdStr不为空的,防止有的档口购买了不设置推广商品 + .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); + List rightExpiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_RIGHT.getValue())) + .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())) + // 必须是prodIdStr不为空的,防止有的档口购买了不设置推广商品 + .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); + + List bottomLeftList; + // 处理左侧广告列表 + if (CollectionUtils.isEmpty(leftLaunchingList)) { + List tempLeftList = new ArrayList<>(); + leftExpiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempLeftList.add(new PCIndexBottomPopularDTO.PCIBPPopularLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + bottomLeftList = tempLeftList.stream().limit(5).collect(Collectors.toList()); + } else { + // 人气榜底部左侧轮播图只要有一张即可 + bottomLeftList = leftLaunchingList.stream().map(x -> new PCIndexBottomPopularDTO.PCIBPPopularLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) + .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) + .collect(Collectors.toList()); + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + bottomLeftList.sort(Comparator.comparing(PCIndexBottomPopularDTO.PCIBPPopularLeftDTO::getPayPrice).reversed()); + for (int i = 0; i < bottomLeftList.size(); i++) { + bottomLeftList.get(i).setOrderNum(i + 1); + } + popularDTO.setLeftList(bottomLeftList); + // 处理中间广告列表 + List bottomMidList; + // 处理中间广告列表 + if (CollectionUtils.isEmpty(midLaunchingList)) { + bottomMidList = this.fillPopMidFromExpired(midExpiredList, fileMap, 2); + } else { + bottomMidList = midLaunchingList.stream().map(x -> new PCIndexBottomPopularDTO.PCIBPPopularMidDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) + .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) + .collect(Collectors.toList()); + if (bottomMidList.size() < 2) { + bottomMidList.addAll(this.fillPopMidFromExpired(midExpiredList, fileMap, 1)); + } + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + bottomMidList.sort(Comparator.comparing(PCIndexBottomPopularDTO.PCIBPPopularMidDTO::getPayPrice).reversed()); + for (int i = 0; i < bottomMidList.size(); i++) { + bottomMidList.get(i).setOrderNum(i + 1); + } + popularDTO.setMidList(bottomMidList); + // 处理右侧广告商品 + List bottomRightList; + if (CollectionUtils.isEmpty(rightLaunchingList)) { + bottomRightList = this.fillBottomRightFromExpired(rightExpiredList, prodPriceAndMainPicMap, 2); + } else { + bottomRightList = rightLaunchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { + final Long storeProdId = Long.parseLong(x.getProdIdStr()); + return new PCIndexBottomPopularDTO.PCIBPPopularRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); + }).collect(Collectors.toList()); + if (bottomRightList.size() < 2) { + bottomRightList.addAll(this.fillBottomRightFromExpired(rightExpiredList, prodPriceAndMainPicMap, 1)); + } + } + for (int i = 0; i < bottomRightList.size(); i++) { + bottomRightList.get(i).setOrderNum(i + 1); + } + popularDTO.setRightList(bottomRightList); + // 存放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_BOTTOM_POPULAR, popularDTO, 1, TimeUnit.DAYS); + return popularDTO; + } + + + /** + * PC 首页 固定侧边栏 只有购买了该广告位才会显示 + * + * @return PCIndexFixedEarDTO + */ + @Override + @Transactional(readOnly = true) + public PCIndexFixedEarDTO getPcIndexFixedEar() { + PCIndexFixedEarDTO fixedEarDTO = new PCIndexFixedEarDTO(); + // 从redis 中获取 PC 首页 两侧固定挂耳 + PCIndexFixedEarDTO redisFixedEar = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_FIXED_EAR); + if (ObjectUtils.isNotEmpty(redisFixedEar)) { + return redisFixedEar; + } + // 两侧固定侧边栏必须展示正在播放的广告位,不从历史中获取 且必须已经设置推广图 + AdvertRound fixedEar = this.advertRoundMapper.selectOne(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).isNotNull(AdvertRound::getPicId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .eq(AdvertRound::getTypeId, AdType.PC_HOME_FIXED_EAR.getValue()).eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue())); + if (ObjectUtils.isEmpty(fixedEar)) { + return fixedEarDTO; + } + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, Collections.singletonList(fixedEar.getPicId()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + fixedEarDTO.setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(fixedEar.getStoreId()).setOrderNum(1) + .setFileUrl(ObjectUtils.isNotEmpty(fixedEar.getPicId()) ? fileMap.get(fixedEar.getPicId()).getFileUrl() : null); + // 存放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_FIXED_EAR, fixedEarDTO, 1, TimeUnit.DAYS); + return fixedEarDTO; + } + + + /** + * 获取搜索框下档口名称 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexSearchUnderlineStoreName() { + List searchStoreNameList; + // 从redis 中获取 PC 首页 搜索框下档口名称 + List redisSearchStoreNameList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_UNDERLINE_STORE_NAME); + if (ObjectUtils.isNotEmpty(redisSearchStoreNameList)) { + return redisSearchStoreNameList; + } + // 搜索框下的档口名称只有档口购买了才会显示 + List searchDownStoreNameList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .in(AdvertRound::getTypeId, Collections.singletonList(AdType.PC_HOME_SEARCH_DOWN_NAME.getValue())) + .eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue())); + if (CollectionUtils.isEmpty(searchDownStoreNameList)) { + return Collections.emptyList(); + } + Map storeMap = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) + .in(Store::getId, searchDownStoreNameList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(Store::getId, Function.identity())); + searchStoreNameList = searchDownStoreNameList.stream().map(advertRound -> new PCIndexSearchUnderlineStoreNameDTO() + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setStoreId(advertRound.getStoreId()).setDisplayType(AdDisplayType.STORE_NAME.getValue()) + .setStoreName(ObjectUtils.isNotEmpty(storeMap.get(advertRound.getStoreId())) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "")) + .collect(Collectors.toList()); + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + searchStoreNameList.sort(Comparator.comparing(PCIndexSearchUnderlineStoreNameDTO::getPayPrice).reversed()); + for (int i = 0; i < searchStoreNameList.size(); i++) { + searchStoreNameList.get(i).setOrderNum(i + 1); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_UNDERLINE_STORE_NAME, searchStoreNameList, 1, TimeUnit.DAYS); + return searchStoreNameList; + } + + + /** + * 搜索框中推荐商品 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcIndexSearchRecommendProd() { + List recommendList; + // 从redis中获取PC 搜索框中推荐商品 + List redisRecommendList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_RECOMMEND_PROD); + if (CollectionUtils.isNotEmpty(redisRecommendList)) { + return redisRecommendList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_SEARCH_PRODUCT.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 过滤掉prodIdStr为空的数据 + oneMonthList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + List storeList = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) + .in(Store::getId, oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()))); + Map storeMap = CollectionUtils.isEmpty(storeList) ? new HashMap<>() + : storeList.stream().collect(Collectors.toMap(Store::getId, Function.identity())); + final List storeProdIdList = oneMonthList.stream().map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList()); + // 档口商品的价格及商品主图map + Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() + : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors + .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); + // 正在播放 + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + // 已过期 + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(launchingList)) { + List tempList = new ArrayList<>(); + // 从已过期商品中随机选择5个商品 + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); + tempList.add(new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setStoreProdId(storeProdId).setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice()) + .setStoreName(storeMap.containsKey(advertRound.getStoreId()) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "") + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); + }); + recommendList = tempList.stream().limit(5).collect(Collectors.toList()); + } else { + recommendList = launchingList.stream() + // 必须是已经设置过推广商品的广告位,防止有些档口购买了广告位但没设置商品情况 + .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) + .map(advertRound -> { + final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); + return new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + .setOrderNum(this.positionToNumber(advertRound.getPosition())).setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice()) + .setStoreName(storeMap.containsKey(advertRound.getStoreId()) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "") + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); + }).collect(Collectors.toList()); + // 如果当前推广商品数量不足5个,则从已过期商品中补充 + if (recommendList.size() < 5) { + List existStoreProdIdList = recommendList.stream().map(PCIndexSearchRecommendProdDTO::getStoreProdId).map(String::valueOf).collect(Collectors.toList()); + List tempList = expiredList.stream() + .filter(x -> !existStoreProdIdList.contains(x.getProdIdStr())).limit(5 - recommendList.size()) + .map(advertRound -> { + final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); + return new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) + .setOrderNum(this.positionToNumber(advertRound.getPosition())).setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice()) + .setStoreName(storeMap.containsKey(advertRound.getStoreId()) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "") + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); + }).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(tempList)) { + recommendList.addAll(tempList); + } + } + } + // 按照出价由高到低排序 出价最高拍1 其次依次排2 3 4 5 + recommendList.sort(Comparator.comparing(PCIndexSearchRecommendProdDTO::getPayPrice).reversed()); + for (int i = 0; i < recommendList.size(); i++) { + recommendList.get(i).setOrderNum(i + 1); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_RECOMMEND_PROD, recommendList, 1, TimeUnit.DAYS); + return recommendList; + } + + + /** + * 获取近一月档口推广数据 + * + * @return 近一月档口推广数据 + */ + private List getOneMonthAdvertList(final List typeIdList) { + // 当前时间 + final Date now = java.sql.Date.valueOf(LocalDate.now()); + // 一月前 + final Date oneMonthAgo = java.sql.Date.valueOf(LocalDate.now().minusMonths(1)); + // 查询最近一个月所有的 正在播放 及 已过期的推广列表 + return this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .in(AdvertRound::getTypeId, typeIdList).between(AdvertRound::getStartTime, oneMonthAgo, now) + .in(AdvertRound::getLaunchStatus, Arrays.asList(AdLaunchStatus.LAUNCHING.getValue(), AdLaunchStatus.EXPIRED.getValue()))); + } + + /** + * 将position 的 A B C D E 转化为 1 2 3 4 5 + * + * @param position 位置 + * @return 1 2 3 4 5 + */ + private int positionToNumber(String position) { + if (position == null || position.isEmpty()) { + throw new IllegalArgumentException("Position cannot be null or empty."); + } + char firstChar = Character.toUpperCase(position.charAt(0)); + if (firstChar < 'A' || firstChar > 'Z') { + throw new IllegalArgumentException("Position must start with a letter A-Z."); + } + return firstChar - 'A' + 1; + } + + /** + * 填充首页顶部右侧纵向轮播图 + * + * @param expiredList 过期列表 + * @param limitCount 返回的数据条数 + * @param mainPicMap 商品主图map + * @return + */ + private List fillTopRightFromExpired(List expiredList, int limitCount, Map mainPicMap) { + List tempRightList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempRightList.add(new PCIndexTopRightBannerDTO().setDisplayType(advertRound.getDisplayType()).setStoreProdId(Long.valueOf(advertRound.getProdIdStr())) + .setFileUrl(mainPicMap.get(Long.valueOf(advertRound.getProdIdStr()))).setStoreId(advertRound.getStoreId())); + }); + return tempRightList.stream().limit(limitCount).collect(Collectors.toList()); + } + + + /** + * 获取父级分类ID Map,如果只有父级一级 则 parCateId和prodCateId一致 + * + * @return + */ + private Map getParCateIdMap() { + List prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper() + .eq(SysProductCategory::getDelFlag, Constants.UNDELETED) + // 排除最顶层的父级分类 + .ne(SysProductCategory::getParentId, 0)); + // 所有字分类 + List subCateList = prodCateList.stream().filter(x -> !Objects.equals(x.getParentId(), TOPMOST_PRODUCT_CATEGORY_ID)).collect(Collectors.toList()); + Map subCateMap = subCateList.stream().collect(Collectors.toMap(SysProductCategory::getId, SysProductCategory::getParentId)); + // 所有的一级分类 + List topCateList = prodCateList.stream().filter(x -> Objects.equals(x.getParentId(), TOPMOST_PRODUCT_CATEGORY_ID)) + .map(SysProductCategory::getId).collect(Collectors.toList()); + final List hasSubCateIdList = new ArrayList<>(subCateMap.keySet()); + // 如果只有父类一级,则父类分类ID和字类分类ID一致 + Map parCateAloneIdMap = topCateList.stream().filter(x -> !hasSubCateIdList.contains(x)).collect(Collectors.toMap(x -> x, x -> x)); + subCateMap.putAll(parCateAloneIdMap); + return subCateMap; + } + + + /** + * 填充首页中部风格榜数据 + * + * @param dbStyleList 风格数据 + * @param prodPriceAndMainPicMap 档口商品价格及主图map + * @param fileMap 档口推广图map + * @param storeMap 档口map + * @param limitCount 返回的数据数量 + * @return List + */ + private List fillMidStyleFromExpired(List dbStyleList, Map prodPriceAndMainPicMap, + Map fileMap, Map storeMap, int limitCount) { + List midStyleList = new ArrayList<>(); + dbStyleList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) + .collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + List prodIdStrList = StrUtil.split(advertRound.getProdIdStr(), ","); + List styleList = new ArrayList<>(); + for (int i = 0; i < prodIdStrList.size(); i++) { + Long storeProdId = Long.valueOf(prodIdStrList.get(i)); + styleList.add(new PCIndexMidStyleDTO.PCIMSStyleDTO().setStoreProdId(storeProdId).setOrderNum(i + 1).setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); + } + StoreMember storeMember = this.redisCache.getCacheObject(CacheConstants.STORE_MEMBER + storeId); + midStyleList.add(new PCIndexMidStyleDTO().setStoreId(storeId).setStoreName(storeMap.get(storeId).getStoreName()) + .setDisplayType(AdDisplayType.PICTURE.getValue()).setStyleList(styleList).setStyleType(advertRound.getStyleType()) + .setStyleTypeName(ObjectUtils.isNotEmpty(advertRound.getStyleType()) ? AdStyleType.of(advertRound.getStyleType()).getLabel() : "") + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setMemberLevel(ObjectUtils.isNotEmpty(storeMember) ? storeMember.getLevel() : null) + .setPicUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + return midStyleList.stream().limit(limitCount).collect(Collectors.toList()); + } + + + /** + * 填充首页 人气榜 中部广告 + * + * @param midExpiredList 人气榜中部过期列表 + * @param fileMap 文件map + * @param limitCount 筛选的数量 + * @return List + */ + private List fillPopMidFromExpired(List midExpiredList, Map fileMap, int limitCount) { + List tempMidList = new ArrayList<>(); + midExpiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempMidList.add(new PCIndexBottomPopularDTO.PCIBPPopularMidDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + return tempMidList.stream().limit(limitCount).collect(Collectors.toList()); + } + + + /** + * 填充PC 首页底部 人气榜右侧商品 + * + * @param rightExpiredList 右侧过期广告 + * @param prodPriceAndMainPicMap 商品价格及主图map + * @param limitCount 筛选的数量 + * @return List + */ + private List fillBottomRightFromExpired(List rightExpiredList, + Map prodPriceAndMainPicMap, int limitCount) { + List tempRightList = new ArrayList<>(); + rightExpiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); + tempRightList.add(new PCIndexBottomPopularDTO.PCIBPPopularRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setStoreProdId(Long.valueOf(advertRound.getProdIdStr())).setStoreId(advertRound.getStoreId()) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); + }); + return tempRightList.stream().limit(limitCount).collect(Collectors.toList()); + } + + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCNewProdServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCNewProdServiceImpl.java new file mode 100644 index 000000000..07e96003d --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCNewProdServiceImpl.java @@ -0,0 +1,467 @@ +package com.ruoyi.xkt.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.enums.AdType; +import com.ruoyi.xkt.domain.AdvertRound; +import com.ruoyi.xkt.domain.Store; +import com.ruoyi.xkt.domain.SysFile; +import com.ruoyi.xkt.dto.advertRound.pc.newProd.*; +import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicDTO; +import com.ruoyi.xkt.enums.AdBiddingStatus; +import com.ruoyi.xkt.enums.AdDisplayType; +import com.ruoyi.xkt.enums.AdLaunchStatus; +import com.ruoyi.xkt.mapper.AdvertRoundMapper; +import com.ruoyi.xkt.mapper.StoreMapper; +import com.ruoyi.xkt.mapper.StoreProductMapper; +import com.ruoyi.xkt.mapper.SysFileMapper; +import com.ruoyi.xkt.service.IWebsitePCNewProdService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 首页搜索 + * + * @author ruoyi + * @date 2025-03-26 + */ +@Service +@RequiredArgsConstructor +public class WebsitePCNewProdServiceImpl implements IWebsitePCNewProdService { + + final RedisCache redisCache; + final AdvertRoundMapper advertRoundMapper; + final SysFileMapper fileMapper; + final StoreProductMapper storeProdMapper; + final StoreMapper storeMapper; + + /** + * PC 新品馆 顶部左侧 轮播图 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcNewTopLeftBanner() { + List newTopLeftList; + // 从redis 中获取 PC 首页 人气榜数据 + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_LEFT); + if (ObjectUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_TOP_LEFT_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(launchingList)) { + List tempList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempList.add(new PCNewTopLeftBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(advertRound.getStoreId()) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + newTopLeftList = tempList.stream().limit(5).collect(Collectors.toList()); + } else { + newTopLeftList = launchingList.stream().map(advertRound -> new PCNewTopLeftBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) + .setStoreId(advertRound.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")) + .collect(Collectors.toList()); + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + newTopLeftList.sort(Comparator.comparing(PCNewTopLeftBannerDTO::getPayPrice).reversed()); + for (int i = 0; i < newTopLeftList.size(); i++) { + newTopLeftList.get(i).setOrderNum(i + 1); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_LEFT, newTopLeftList, 1, TimeUnit.DAYS); + return newTopLeftList; + } + + + /** + * PC 新品馆 顶部右侧 轮播图 + * + * @return PCNewTopRightDTO + */ + @Override + @Transactional(readOnly = true) + public PCNewTopRightDTO getPcNewTopRight() { + // 从redis 中获取 PC 首页 人气榜数据 + PCNewTopRightDTO newTopRight; + PCNewTopRightDTO redisNewTopRight = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_RIGHT); + if (ObjectUtils.isNotEmpty(redisNewTopRight)) { + return redisNewTopRight; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_TOP_RIGHT.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new PCNewTopRightDTO(); + } + // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new PCNewTopRightDTO(); + } + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(launchingList)) { + // 从expiredList中任意取一条数据 + newTopRight = expiredList.stream().map(x -> new PCNewTopRightDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setOrderNum(1).setStoreId(x.getStoreId()) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")).findAny().orElse(null); + } else { + newTopRight = launchingList.stream().map(x -> new PCNewTopRightDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setOrderNum(1).setStoreId(x.getStoreId()) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) + .findAny().orElse(null); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_RIGHT, newTopRight, 1, TimeUnit.DAYS); + return newTopRight; + } + + + /** + * PC 新品馆 品牌馆 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcNewMidBrandList() { + // 从redis中获取 新品馆 品牌榜数据 + List newMidBrandList; + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_BRAND); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_BRAND_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + Map storeMap = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) + .in(Store::getId, oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(Store::getId, Function.identity())); + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(launchingList)) { + newMidBrandList = this.fillNewMidBrandList(expiredList, storeMap, fileMap, new ArrayList<>(), 10); + } else { + newMidBrandList = launchingList.stream().map(x -> new PCNewMidBrandDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) + .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) + .setStoreName(ObjectUtils.isNotEmpty(storeMap.get(x.getStoreId())) ? storeMap.get(x.getStoreId()).getStoreName() : "") + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) + .collect(Collectors.toList()); + if (newMidBrandList.size() < 10) { + final List existStoreIdList = newMidBrandList.stream().map(PCNewMidBrandDTO::getStoreId).distinct().collect(Collectors.toList()); + newMidBrandList.addAll(this.fillNewMidBrandList(expiredList, storeMap, fileMap, existStoreIdList, 10 - newMidBrandList.size())); + } + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + newMidBrandList.sort(Comparator.comparing(PCNewMidBrandDTO::getPayPrice).reversed()); + for (int i = 0; i < newMidBrandList.size(); i++) { + newMidBrandList.get(i).setOrderNum(i + 1); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_BRAND, newMidBrandList, 1, TimeUnit.DAYS); + return newMidBrandList; + } + + + /** + * PC 新品馆 热卖榜左侧 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcNewMidHotLeftList() { + // 从redis中获取 新品馆 热卖榜左侧数据 + List newMidHotLeftList; + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_LEFT); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_HOT_LEFT_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(launchingList)) { + List tempList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempList.add(new PCNewMidHotLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + newMidHotLeftList = tempList.stream().limit(5).collect(Collectors.toList()); + } else { + newMidHotLeftList = launchingList.stream().map(x -> new PCNewMidHotLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) + .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) + .collect(Collectors.toList()); + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + newMidHotLeftList.sort(Comparator.comparing(PCNewMidHotLeftDTO::getPayPrice).reversed()); + for (int i = 0; i < newMidHotLeftList.size(); i++) { + newMidHotLeftList.get(i).setOrderNum(i + 1); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_LEFT, newMidHotLeftList, 1, TimeUnit.DAYS); + return newMidHotLeftList; + } + + + /** + * PC 新品馆 热卖榜右侧商品 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcNewMidHotRightList() { + // 从redis中获取 新品馆 热卖榜右侧数据 + List newMidHotRightList; + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_RIGHT); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_HOT_RIGHT_PRODUCT.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + // 必须是已经设置了推广商品的,防止有的档口购买了但没有设置推广商品 + oneMonthList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + final List storeProdIdList = oneMonthList.stream() + .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList()); + // 档口商品的价格及商品主图map + Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() + : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors + .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); + if (CollectionUtils.isEmpty(launchingList)) { + newMidHotRightList = this.fillNewMidHotRightList(expiredList, prodPriceAndMainPicMap, new ArrayList<>(), 8); + for (int i = 0; i < newMidHotRightList.size(); i++) { + newMidHotRightList.get(i).setOrderNum(i + 1); + } + } else { + newMidHotRightList = launchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { + final Long storeProdId = Long.parseLong(x.getProdIdStr()); + return new PCNewMidHotRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) + .setOrderNum(this.positionToNumber(x.getPosition())).setStoreProdId(storeProdId).setStoreId(x.getStoreId()) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); + }).collect(Collectors.toList()); + if (newMidHotRightList.size() < 8) { + final List existProdIdList = newMidHotRightList.stream().map(PCNewMidHotRightDTO::getStoreProdId).collect(Collectors.toList()); + newMidHotRightList.addAll(this.fillNewMidHotRightList(expiredList, prodPriceAndMainPicMap, existProdIdList, 8 - newMidHotRightList.size())); + for (int i = 0; i < newMidHotRightList.size(); i++) { + newMidHotRightList.get(i).setOrderNum(i + 1); + } + } + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_RIGHT, newMidHotRightList, 1, TimeUnit.DAYS); + return newMidHotRightList; + } + + + /** + * PC 新品馆 底部横幅 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcNewBottomBannerList() { + // 从redis中获取 新品馆 底部横幅数据 + List newBottomBannerList; + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_BOTTOM_BANNER); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_SINGLE_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + // 必须是已经设置了推广图的,防止有的档口购买了推广但没有设置推广图 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return Collections.emptyList(); + } + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + if (CollectionUtils.isEmpty(launchingList)) { + List tempList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempList.add(new PCNewBottomBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + newBottomBannerList = tempList.stream().limit(1).collect(Collectors.toList()); + for (int i = 0; i < newBottomBannerList.size(); i++) { + newBottomBannerList.get(i).setOrderNum(i + 1); + } + } else { + newBottomBannerList = launchingList.stream().map(x -> new PCNewBottomBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) + .setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) + .collect(Collectors.toList()); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_BOTTOM_BANNER, newBottomBannerList, 1, TimeUnit.DAYS); + return newBottomBannerList; + } + + + /** + * 获取近一月档口推广数据 + * + * @return 近一月档口推广数据 + */ + private List getOneMonthAdvertList(final List typeIdList) { + // 当前时间 + final Date now = java.sql.Date.valueOf(LocalDate.now()); + // 一月前 + final Date oneMonthAgo = java.sql.Date.valueOf(LocalDate.now().minusMonths(1)); + // 查询最近一个月所有的 正在播放 及 已过期的推广列表 + return this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .in(AdvertRound::getTypeId, typeIdList).between(AdvertRound::getStartTime, oneMonthAgo, now) + .in(AdvertRound::getLaunchStatus, Arrays.asList(AdLaunchStatus.LAUNCHING.getValue(), AdLaunchStatus.EXPIRED.getValue()))); + } + + + /** + * 将position 的 A B C D E 转化为 1 2 3 4 5 + * + * @param position 位置 + * @return 1 2 3 4 5 + */ + private int positionToNumber(String position) { + if (position == null || position.isEmpty()) { + throw new IllegalArgumentException("Position cannot be null or empty."); + } + char firstChar = Character.toUpperCase(position.charAt(0)); + if (firstChar < 'A' || firstChar > 'Z') { + throw new IllegalArgumentException("Position must start with a letter A-Z."); + } + return firstChar - 'A' + 1; + } + + + /** + * 填充 PC 首页新品馆 品牌榜 + * + * @param advertRoundList 广告 列表 + * @param storeMap 档口map + * @param fileMap 推广图map + * @param existStoreIdList 已存在的档口ID列表 + * @param limitCount 填充数量 + * @return List + */ + private List fillNewMidBrandList(List advertRoundList, Map storeMap, + Map fileMap, List existStoreIdList, int limitCount) { + List tempList = new ArrayList<>(); + advertRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + if (existStoreIdList.contains(storeId)) { + return; + } + AdvertRound advertRound = list.get(0); + tempList.add(new PCNewMidBrandDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) + .setStoreName(storeMap.get(storeId).getStoreName()) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + return tempList.stream().limit(limitCount).collect(Collectors.toList()); + } + + /** + * 填充 PC 新品馆 中间热卖榜右侧商品 + * + * @param advertRoundList 广告列表 + * @param prodPriceAndMainPicMap 商品价格和主图map + * @param existProdIdList 已存在的 商品ID列表 + * @param limitCount 返回的 数量 + * @return + */ + private List fillNewMidHotRightList(List advertRoundList, Map prodPriceAndMainPicMap, + List existProdIdList, int limitCount) { + List tempList = new ArrayList<>(); + advertRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) + .filter(x -> CollectionUtils.isEmpty(existProdIdList) || !existProdIdList.contains(Long.parseLong(x.getProdIdStr()))).findAny().orElse(null); + if (ObjectUtils.isNotEmpty(advertRound)) { + final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); + tempList.add(new PCNewMidHotRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setStoreId(storeId) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); + } + }); + return tempList.stream().limit(limitCount).collect(Collectors.toList()); + } + +} diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java index 23df71a9d..1a0ca2483 100644 --- a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCServiceImpl.java @@ -23,25 +23,24 @@ import com.ruoyi.xkt.dto.advertRound.pc.PCDownloadDTO; import com.ruoyi.xkt.dto.advertRound.pc.PCSearchDTO; import com.ruoyi.xkt.dto.advertRound.pc.PCSearchResultAdvertDTO; import com.ruoyi.xkt.dto.advertRound.pc.PCUserCenterDTO; -import com.ruoyi.xkt.dto.advertRound.pc.index.*; -import com.ruoyi.xkt.dto.advertRound.pc.newProd.*; -import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreMidBannerDTO; +import com.ruoyi.xkt.dto.advertRound.pc.index.PCIndexRecommendDTO; +import com.ruoyi.xkt.dto.advertRound.pc.newProd.PCNewRecommendDTO; import com.ruoyi.xkt.dto.advertRound.pc.store.PCStorePageDTO; import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreRecommendDTO; -import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreTopBannerDTO; import com.ruoyi.xkt.dto.advertRound.picSearch.PicSearchAdvertDTO; -import com.ruoyi.xkt.dto.dailySale.CateSaleRankDTO; import com.ruoyi.xkt.dto.es.ESProductDTO; import com.ruoyi.xkt.dto.picture.ProductMatchDTO; import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicAndTagDTO; import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicDTO; import com.ruoyi.xkt.dto.storeProduct.StoreProdViewDTO; import com.ruoyi.xkt.dto.storeProductFile.StoreProdFileLatestFourProdDTO; -import com.ruoyi.xkt.dto.storeProductFile.StoreProdFileResDTO; import com.ruoyi.xkt.dto.useSearchHistory.UserSearchHistoryDTO; import com.ruoyi.xkt.dto.website.IndexSearchDTO; import com.ruoyi.xkt.dto.website.StoreSearchDTO; -import com.ruoyi.xkt.enums.*; +import com.ruoyi.xkt.enums.AdBiddingStatus; +import com.ruoyi.xkt.enums.AdDisplayType; +import com.ruoyi.xkt.enums.AdLaunchStatus; +import com.ruoyi.xkt.enums.SearchPlatformType; import com.ruoyi.xkt.mapper.*; import com.ruoyi.xkt.service.IPictureService; import com.ruoyi.xkt.service.IWebsitePCService; @@ -63,8 +62,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; -import static com.ruoyi.common.constant.Constants.TOPMOST_PRODUCT_CATEGORY_ID; - /** * 首页搜索 * @@ -439,43 +436,6 @@ public class WebsitePCServiceImpl implements IWebsitePCService { return new Page<>(searchDTO.getPageNum(), searchDTO.getPageSize(), pages, redisList.size(), realDataList); } - /*** - * PC 首页 顶部通栏 - * @return - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexTop() { - // 从redis 中获取 PC 首页 顶部通栏 - List topBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP); - if (ObjectUtils.isNotEmpty(topBannerList)) { - return topBannerList; - } - // 正在播放的首页顶部通栏 必须是档口已经设置了推广图 - List indexTopList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() - .isNotNull(AdvertRound::getStoreId).isNotNull(AdvertRound::getPicId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) - .eq(AdvertRound::getTypeId, AdType.PC_HOME_TOPMOST_BANNER.getValue()).eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue())); - if (CollectionUtils.isEmpty(indexTopList)) { - return Collections.emptyList(); - } - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, indexTopList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - // 顶部通栏数据 - List topList = indexTopList.stream().map(x -> new PCIndexTopBannerDTO().setDisplayType(x.getDisplayType()) - .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) - .sorted(Comparator.comparing(PCIndexTopBannerDTO::getPayPrice).reversed()) - .collect(Collectors.toList()); - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - for (int i = 0; i < topList.size(); i++) { - topList.get(i).setOrderNum(i + 1); - } - // 存放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP, topList, 1, TimeUnit.DAYS); - return topList; - } - /** * PC 搜索结果右侧广告列表。 * 即使是会员 也不返回会员标识,这样布局更好看 @@ -569,1010 +529,6 @@ public class WebsitePCServiceImpl implements IWebsitePCService { return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList); } - /** - * PC 首页 顶部左侧 轮播图 - * - * @return PCIndexTopLeftBannerDTO - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexTopLeftBanner() { - // 从redis 中获取 PC 首页顶部左侧 轮播图 - List topLeftBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_LEFT); - if (ObjectUtils.isNotEmpty(topLeftBannerList)) { - return topLeftBannerList; - } - // 获取近一月 档口首页PC 顶部左侧轮播图推广数据 - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_TOP_LEFT_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 必须是已经设置了推广图的数据 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - List topLeftList; - // 如果顶部横向轮播图全部为空,则需要找填充的数据 - if (CollectionUtils.isEmpty(launchingList)) { - List tempLeftList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempLeftList.add(new PCIndexTopLeftBannerDTO().setDisplayType(advertRound.getDisplayType()).setStoreId(advertRound.getStoreId()) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(advertRound.getPicId()) ? fileMap.get(advertRound.getPicId()).getFileUrl() : null)); - }); - // 只取5条数据 - topLeftList = tempLeftList.stream().limit(5).collect(Collectors.toList()); - } else { - // 顶部轮播图只要有一张即可 - topLeftList = launchingList.stream().map(x -> new PCIndexTopLeftBannerDTO().setDisplayType(x.getDisplayType()) - .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) - .collect(Collectors.toList()); - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - topLeftList.sort(Comparator.comparing(PCIndexTopLeftBannerDTO::getPayPrice).reversed()); - for (int i = 0; i < topLeftList.size(); i++) { - topLeftList.get(i).setOrderNum(i + 1); - } - // 存放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_LEFT, topLeftList, 1, TimeUnit.DAYS); - return topLeftList; - } - - /** - * PC 首页 顶部右侧 纵向轮播图 - * - * @return PCIndexTopRightBannerDTO - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexTopRightBanner() { - // 从redis 中获取 PC 首页顶部右侧 轮播图 - List topRightBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_RIGHT); - if (ObjectUtils.isNotEmpty(topRightBannerList)) { - return topRightBannerList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_TOP_RIGHT_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 必须是已经设置了prodIdStr的数据 - oneMonthList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - List mainPicList = this.prodFileMapper.selectMainPic(oneMonthList.stream().map(AdvertRound::getProdIdStr).distinct().collect(Collectors.toList())); - Map mainPicMap = mainPicList.stream().collect(Collectors.toMap(StoreProdFileResDTO::getStoreProdId, StoreProdFileResDTO::getFileUrl, (v1, v2) -> v2)); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - List topRightList; - // 顶部首页纵向轮播图 - if (CollectionUtils.isEmpty(launchingList)) { - topRightList = this.fillTopRightFromExpired(expiredList, 4, mainPicMap); - } else { - topRightList = launchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) - .map(x -> new PCIndexTopRightBannerDTO().setDisplayType(x.getDisplayType()).setStoreProdId(Long.valueOf(x.getProdIdStr())) - .setFileUrl(mainPicMap.get(Long.valueOf(x.getProdIdStr()))) - .setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId())) - .collect(Collectors.toList()); - // 如果 launchingList 只有一个则还需要补充一个推广填空 - if (topRightList.size() < 2) { - topRightList.addAll(this.fillTopRightFromExpired(expiredList, 1, mainPicMap)); - } - } - for (int i = 0; i < topRightList.size(); i++) { - topRightList.get(i).setOrderNum(i + 1); - } - // 存放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_RIGHT, topRightList, 1, TimeUnit.DAYS); - return topRightList; - } - - /** - * PC 首页 销售榜 - * - * @return PCIndexMidSalesDTO - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexMidSaleList() { - // 从redis中获取销售榜数据 - List midSaleList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_SALE); - if (ObjectUtils.isNotEmpty(midSaleList)) { - return midSaleList; - } - final Date now = java.sql.Date.valueOf(LocalDate.now()); - final Date oneMonthAgo = java.sql.Date.valueOf(LocalDate.now().minusMonths(1)); - // 全量的销量统计数据 - List cateSaleList = this.dailySaleProdMapper.selectSaleRankList(oneMonthAgo, now); - if (CollectionUtils.isEmpty(cateSaleList)) { - return new ArrayList<>(); - } - // 销售榜榜一到榜四的推广 - List saleRankList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() - .isNotNull(AdvertRound::getStoreId).isNotNull(AdvertRound::getProdIdStr) - .ne(AdvertRound::getProdIdStr, "").eq(AdvertRound::getDelFlag, Constants.UNDELETED) - .eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue()).in(AdvertRound::getTypeId, Arrays.asList(AdType.PC_HOME_SALE_RANK_ONE, - AdType.PC_HOME_SALE_RANK_TWO.getValue(), AdType.PC_HOME_SALE_RANK_THREE.getValue(), AdType.PC_HOME_SALE_RANK_FOUR.getValue()))); - // 销量榜一到榜四的推广 key 1 2 3 4 便于后面取数据 - Map> saleAdvertMap = saleRankList.stream().collect(Collectors.groupingBy(ad -> { - switch (ad.getTypeId()) { - case 3: - return 1; - case 4: - return 2; - case 5: - return 3; - case 6: - return 4; - default: - return ad.getTypeId(); - } - })); - // 推广商品ID列表 - final List advertProdIdList = CollectionUtils.isEmpty(saleRankList) ? Collections.emptyList() - : saleRankList.stream().map(AdvertRound::getProdIdStr).map(Long::parseLong).collect(Collectors.toList()); - // 销售榜推广销量等信息 - List advertSaleList = cateSaleList.stream().filter(x -> advertProdIdList.contains(x.getStoreProdId())).collect(Collectors.toList()); - Map advertSaleMap = CollectionUtils.isEmpty(advertSaleList) ? new HashMap<>() - : advertSaleList.stream().collect(Collectors.toMap(CateSaleRankDTO::getStoreProdId, Function.identity())); - // 所有二级分类ID map - Map parCateIdMap = this.getParCateIdMap(); - final List storeProdIdList = cateSaleList.stream().map(CateSaleRankDTO::getStoreProdId).collect(Collectors.toList()); - // 档口商品的价格及商品主图map - Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() - : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors - .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); - Map cateIdMap = cateSaleList.stream().collect(Collectors.toMap(CateSaleRankDTO::getProdCateId, CateSaleRankDTO::getProdCateName, (existing, replacement) -> existing)); - // Step 1: 按 prodCateId 分组,并取每组销量前5的商品 - Map> topSaleMap = cateSaleList.stream().collect(Collectors.groupingBy(CateSaleRankDTO::getProdCateId, Collectors.collectingAndThen( - Collectors.toList(), list -> list.stream().sorted(Comparator.comparing(CateSaleRankDTO::getSaleNum).reversed()).limit(5).collect(Collectors.toList())))); - // Step 2: 统计每个 prodCateId 的总销量 - Map totalSalesPerCate = cateSaleList.stream().collect(Collectors.groupingBy(CateSaleRankDTO::getProdCateId, Collectors.summingInt(CateSaleRankDTO::getSaleNum))); - // Step 3: 取总销量排名前4的 prodCateId - List> top4CateEntries = totalSalesPerCate.entrySet().stream().sorted(Map.Entry.comparingByValue().reversed()).limit(4).collect(Collectors.toList()); - // Step 4: 构建返回结果 - List retCateOrderList = new ArrayList<>(); - for (int i = 0; i < top4CateEntries.size(); i++) { - // 当前销售榜推广 - final List saleAdvertList = saleAdvertMap.getOrDefault(i + 1, Collections.emptyList()); - final List tempAdvertProdIdList = saleAdvertList.stream().map(AdvertRound::getProdIdStr).map(Long::parseLong).collect(Collectors.toList()); - Long cateId = top4CateEntries.get(i).getKey(); - List cateDetailList = topSaleMap.getOrDefault(cateId, Collections.emptyList()); - // 过滤掉销量为0;并且根据广告数量决定截取的商品数量 - cateDetailList = cateDetailList.stream().filter(x -> ObjectUtils.defaultIfNull(x.getSaleNum(), 0) > 0) - .filter(x -> !tempAdvertProdIdList.contains(x.getStoreProdId())).limit(5 - saleAdvertList.size()).collect(Collectors.toList()); - List saleDTOList = new ArrayList<>(); - for (int j = 0; j < cateDetailList.size(); j++) { - CateSaleRankDTO dto = cateDetailList.get(j); - // 绑定档口会员等级 - StoreMember member = this.redisCache.getCacheObject(CacheConstants.STORE_MEMBER + dto.getStoreId()); - PCIndexMidSalesDTO.PCIMSSaleDTO saleDTO = new PCIndexMidSalesDTO.PCIMSSaleDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreId(dto.getStoreId()).setStoreName(dto.getStoreName()).setStoreProdId(dto.getStoreProdId()) - .setProdArtNum(dto.getProdArtNum()).setMemberLevel(ObjectUtils.isNotEmpty(member) ? member.getLevel() : null) - .setStoreProdId(dto.getStoreProdId()).setSaleNum(dto.getSaleNum()).setOrderNum(j + 1) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(dto.getStoreProdId())) - ? prodPriceAndMainPicMap.get(dto.getStoreProdId()).getMinPrice() : null) - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(dto.getStoreProdId())) - ? prodPriceAndMainPicMap.get(dto.getStoreProdId()).getMainPicUrl() : ""); - saleDTOList.add(saleDTO); - } - for (int j = 0; j < saleAdvertList.size(); j++) { - CateSaleRankDTO advertSaleDTO = advertSaleMap.get(Long.parseLong(saleAdvertList.get(j).getProdIdStr())); - // 绑定档口会员等级 - StoreMember member = this.redisCache.getCacheObject(CacheConstants.STORE_MEMBER + advertSaleDTO.getStoreId()); - PCIndexMidSalesDTO.PCIMSSaleDTO saleDTO = new PCIndexMidSalesDTO.PCIMSSaleDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreId(advertSaleDTO.getStoreId()).setStoreName(advertSaleDTO.getStoreName()).setStoreProdId(advertSaleDTO.getStoreProdId()) - .setProdArtNum(advertSaleDTO.getProdArtNum()).setMemberLevel(ObjectUtils.isNotEmpty(member) ? member.getLevel() : null) - .setStoreProdId(advertSaleDTO.getStoreProdId()).setSaleNum(advertSaleDTO.getSaleNum()).setOrderNum(j + 1) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId())) - ? prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId()).getMinPrice() : null) - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId())) - ? prodPriceAndMainPicMap.get(advertSaleDTO.getStoreProdId()).getMainPicUrl() : ""); - saleDTOList.add(saleDTO); - } - retCateOrderList.add(new PCIndexMidSalesDTO().setProdCateId(cateId).setProdCateName(cateIdMap.get(cateId)).setOrderNum(i + 1) - .setParCateId(parCateIdMap.get(cateId)).setSaleList(saleDTOList)); - } - // 缓存至 Redis - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_SALE, retCateOrderList, 1, TimeUnit.DAYS); - return retCateOrderList; - } - - - /** - * PC 首页 风格榜 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexMidStyleList() { - // 从redis 中获取 PC 首页风格榜数据 - List redisStyleList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_STYLE); - if (ObjectUtils.isNotEmpty(redisStyleList)) { - return redisStyleList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_STYLE_RANK.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 必须是已经设置推广图和推广商品的列表 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId()) && StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 档口推广主图map - List fileList = this.fileMapper.selectByIds(oneMonthList.stream().map(AdvertRound::getPicId) - .filter(ObjectUtils::isNotEmpty).collect(Collectors.toList())); - Map fileMap = fileList.stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - List storeList = this.storeMapper.selectByIds(oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList())); - Map storeMap = storeList.stream().collect(Collectors.toMap(Store::getId, Function.identity())); - // 获取所有的档口商品ID列表 - Set storeProdIdSet = new HashSet<>(); - oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).forEach(x -> storeProdIdSet - .addAll(Arrays.stream(x.getProdIdStr().split(",")).map(Long::parseLong).collect(Collectors.toSet()))); - // 档口商品的价格及商品主图map - Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdSet) ? new ConcurrentHashMap<>() - : this.storeProdMapper.selectPriceAndMainPicList(new ArrayList<>(storeProdIdSet)).stream().collect(Collectors - .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - List midStyleList; - // 顶部 中部 风格轮播图 - if (CollectionUtils.isEmpty(launchingList)) { - midStyleList = this.fillMidStyleFromExpired(expiredList, prodPriceAndMainPicMap, fileMap, storeMap, 4); - } else { - midStyleList = this.fillMidStyleFromExpired(launchingList, prodPriceAndMainPicMap, fileMap, storeMap, 4); - // 轮播图不足4个,则从过期的广告轮播图补充 - if (midStyleList.size() < 4) { - midStyleList.addAll(this.fillMidStyleFromExpired(expiredList, prodPriceAndMainPicMap, fileMap, storeMap, 4 - launchingList.size())); - } - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - midStyleList.sort(Comparator.comparing(PCIndexMidStyleDTO::getPayPrice).reversed()); - for (int i = 0; i < midStyleList.size(); i++) { - midStyleList.get(i).setOrderNum(i + 1); - } - // 存放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_STYLE, midStyleList, 1, TimeUnit.DAYS); - return midStyleList; - } - - /** - * PC 首页 人气榜 - * - * @return PCIndexBottomPopularDTO - */ - @Override - @Transactional(readOnly = true) - public PCIndexBottomPopularDTO getPcIndexBottomPopularList() { - PCIndexBottomPopularDTO popularDTO = new PCIndexBottomPopularDTO(); - // 从redis 中获取 PC 首页 人气榜数据 - PCIndexBottomPopularDTO redisPopular = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_BOTTOM_POPULAR); - if (ObjectUtils.isNotEmpty(redisPopular)) { - return redisPopular; - } - List oneMonthList = this.getOneMonthAdvertList(Arrays.asList( - AdType.PC_HOME_POP_LEFT_BANNER.getValue(), AdType.PC_HOME_POP_MID.getValue(), AdType.PC_HOME_POP_RIGHT.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return popularDTO; - } - // 文件map - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - final List storeProdIdList = oneMonthList.stream() - .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList()); - // 档口商品的价格及商品主图map - Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() - : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors - .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); - // 左侧广告 - List leftLaunchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_LEFT_BANNER.getValue())) - .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) - // 必须是picId不为空的,防止有的档口购买了不设置推广图 - .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - List leftExpiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_LEFT_BANNER.getValue())) - .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())) - // 必须是picId不为空的,防止有的档口购买了不设置推广图 - .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - // 中部广告 - List midLaunchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_MID.getValue())) - .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) - // 必须是picId不为空的,防止有的档口购买了不设置推广图 - .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - List midExpiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_MID.getValue())) - .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())) - // 必须是picId不为空的,防止有的档口购买了不设置推广图 - .filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - // 右侧广告 - List rightLaunchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_RIGHT.getValue())) - .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())) - // 必须是prodIdStr不为空的,防止有的档口购买了不设置推广商品 - .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); - List rightExpiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getTypeId(), AdType.PC_HOME_POP_RIGHT.getValue())) - .filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())) - // 必须是prodIdStr不为空的,防止有的档口购买了不设置推广商品 - .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); - - List bottomLeftList; - // 处理左侧广告列表 - if (CollectionUtils.isEmpty(leftLaunchingList)) { - List tempLeftList = new ArrayList<>(); - leftExpiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempLeftList.add(new PCIndexBottomPopularDTO.PCIBPPopularLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - bottomLeftList = tempLeftList.stream().limit(5).collect(Collectors.toList()); - } else { - // 人气榜底部左侧轮播图只要有一张即可 - bottomLeftList = leftLaunchingList.stream().map(x -> new PCIndexBottomPopularDTO.PCIBPPopularLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) - .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) - .collect(Collectors.toList()); - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - bottomLeftList.sort(Comparator.comparing(PCIndexBottomPopularDTO.PCIBPPopularLeftDTO::getPayPrice).reversed()); - for (int i = 0; i < bottomLeftList.size(); i++) { - bottomLeftList.get(i).setOrderNum(i + 1); - } - popularDTO.setLeftList(bottomLeftList); - // 处理中间广告列表 - List bottomMidList; - // 处理中间广告列表 - if (CollectionUtils.isEmpty(midLaunchingList)) { - bottomMidList = this.fillPopMidFromExpired(midExpiredList, fileMap, 2); - } else { - bottomMidList = midLaunchingList.stream().map(x -> new PCIndexBottomPopularDTO.PCIBPPopularMidDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) - .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(x.getPicId()) ? fileMap.get(x.getPicId()).getFileUrl() : null)) - .collect(Collectors.toList()); - if (bottomMidList.size() < 2) { - bottomMidList.addAll(this.fillPopMidFromExpired(midExpiredList, fileMap, 1)); - } - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - bottomMidList.sort(Comparator.comparing(PCIndexBottomPopularDTO.PCIBPPopularMidDTO::getPayPrice).reversed()); - for (int i = 0; i < bottomMidList.size(); i++) { - bottomMidList.get(i).setOrderNum(i + 1); - } - popularDTO.setMidList(bottomMidList); - // 处理右侧广告商品 - List bottomRightList; - if (CollectionUtils.isEmpty(rightLaunchingList)) { - bottomRightList = this.fillBottomRightFromExpired(rightExpiredList, prodPriceAndMainPicMap, 2); - } else { - bottomRightList = rightLaunchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { - final Long storeProdId = Long.parseLong(x.getProdIdStr()); - return new PCIndexBottomPopularDTO.PCIBPPopularRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreProdId(storeProdId).setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); - }).collect(Collectors.toList()); - if (bottomRightList.size() < 2) { - bottomRightList.addAll(this.fillBottomRightFromExpired(rightExpiredList, prodPriceAndMainPicMap, 1)); - } - } - for (int i = 0; i < bottomRightList.size(); i++) { - bottomRightList.get(i).setOrderNum(i + 1); - } - popularDTO.setRightList(bottomRightList); - // 存放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_BOTTOM_POPULAR, popularDTO, 1, TimeUnit.DAYS); - return popularDTO; - } - - /** - * PC 首页 固定侧边栏 只有购买了该广告位才会显示 - * - * @return PCIndexFixedEarDTO - */ - @Override - @Transactional(readOnly = true) - public PCIndexFixedEarDTO getPcIndexFixedEar() { - PCIndexFixedEarDTO fixedEarDTO = new PCIndexFixedEarDTO(); - // 从redis 中获取 PC 首页 两侧固定挂耳 - PCIndexFixedEarDTO redisFixedEar = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_FIXED_EAR); - if (ObjectUtils.isNotEmpty(redisFixedEar)) { - return redisFixedEar; - } - // 两侧固定侧边栏必须展示正在播放的广告位,不从历史中获取 且必须已经设置推广图 - AdvertRound fixedEar = this.advertRoundMapper.selectOne(new LambdaQueryWrapper() - .isNotNull(AdvertRound::getStoreId).isNotNull(AdvertRound::getPicId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) - .eq(AdvertRound::getTypeId, AdType.PC_HOME_FIXED_EAR.getValue()).eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue())); - if (ObjectUtils.isEmpty(fixedEar)) { - return fixedEarDTO; - } - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, Collections.singletonList(fixedEar.getPicId()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - fixedEarDTO.setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(fixedEar.getStoreId()).setOrderNum(1) - .setFileUrl(ObjectUtils.isNotEmpty(fixedEar.getPicId()) ? fileMap.get(fixedEar.getPicId()).getFileUrl() : null); - // 存放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_FIXED_EAR, fixedEarDTO, 1, TimeUnit.DAYS); - return fixedEarDTO; - } - - /** - * 获取搜索框下档口名称 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexSearchUnderlineStoreName() { - List searchStoreNameList; - // 从redis 中获取 PC 首页 搜索框下档口名称 - List redisSearchStoreNameList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_UNDERLINE_STORE_NAME); - if (ObjectUtils.isNotEmpty(redisSearchStoreNameList)) { - return redisSearchStoreNameList; - } - // 搜索框下的档口名称只有档口购买了才会显示 - List searchDownStoreNameList = this.advertRoundMapper.selectList(new LambdaQueryWrapper() - .isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) - .in(AdvertRound::getTypeId, Collections.singletonList(AdType.PC_HOME_SEARCH_DOWN_NAME.getValue())) - .eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue())); - if (CollectionUtils.isEmpty(searchDownStoreNameList)) { - return Collections.emptyList(); - } - Map storeMap = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) - .in(Store::getId, searchDownStoreNameList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(Store::getId, Function.identity())); - searchStoreNameList = searchDownStoreNameList.stream().map(advertRound -> new PCIndexSearchUnderlineStoreNameDTO() - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setStoreId(advertRound.getStoreId()).setDisplayType(AdDisplayType.STORE_NAME.getValue()) - .setStoreName(ObjectUtils.isNotEmpty(storeMap.get(advertRound.getStoreId())) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "")) - .collect(Collectors.toList()); - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - searchStoreNameList.sort(Comparator.comparing(PCIndexSearchUnderlineStoreNameDTO::getPayPrice).reversed()); - for (int i = 0; i < searchStoreNameList.size(); i++) { - searchStoreNameList.get(i).setOrderNum(i + 1); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_UNDERLINE_STORE_NAME, searchStoreNameList, 1, TimeUnit.DAYS); - return searchStoreNameList; - } - - /** - * 搜索框中推荐商品 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcIndexSearchRecommendProd() { - List recommendList; - // 从redis中获取PC 搜索框中推荐商品 - List redisRecommendList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_RECOMMEND_PROD); - if (CollectionUtils.isNotEmpty(redisRecommendList)) { - return redisRecommendList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_HOME_SEARCH_PRODUCT.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 过滤掉prodIdStr为空的数据 - oneMonthList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - List storeList = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) - .in(Store::getId, oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()))); - Map storeMap = CollectionUtils.isEmpty(storeList) ? new HashMap<>() - : storeList.stream().collect(Collectors.toMap(Store::getId, Function.identity())); - final List storeProdIdList = oneMonthList.stream().map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList()); - // 档口商品的价格及商品主图map - Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() - : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors - .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); - // 正在播放 - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - // 已过期 - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(launchingList)) { - List tempList = new ArrayList<>(); - // 从已过期商品中随机选择5个商品 - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - tempList.add(new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreProdId(storeProdId).setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice()) - .setStoreName(storeMap.containsKey(advertRound.getStoreId()) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "") - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); - }); - recommendList = tempList.stream().limit(5).collect(Collectors.toList()); - } else { - recommendList = launchingList.stream() - // 必须是已经设置过推广商品的广告位,防止有些档口购买了广告位但没设置商品情况 - .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) - .map(advertRound -> { - final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - return new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) - .setOrderNum(this.positionToNumber(advertRound.getPosition())).setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice()) - .setStoreName(storeMap.containsKey(advertRound.getStoreId()) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "") - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); - }).collect(Collectors.toList()); - // 如果当前推广商品数量不足5个,则从已过期商品中补充 - if (recommendList.size() < 5) { - List existStoreProdIdList = recommendList.stream().map(PCIndexSearchRecommendProdDTO::getStoreProdId).map(String::valueOf).collect(Collectors.toList()); - List tempList = expiredList.stream() - .filter(x -> !existStoreProdIdList.contains(x.getProdIdStr())).limit(5 - recommendList.size()) - .map(advertRound -> { - final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - return new PCIndexSearchRecommendProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId) - .setOrderNum(this.positionToNumber(advertRound.getPosition())).setStoreId(advertRound.getStoreId()).setPayPrice(advertRound.getPayPrice()) - .setStoreName(storeMap.containsKey(advertRound.getStoreId()) ? storeMap.get(advertRound.getStoreId()).getStoreName() : "") - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); - }).collect(Collectors.toList()); - if (CollectionUtils.isNotEmpty(tempList)) { - recommendList.addAll(tempList); - } - } - } - // 按照出价由高到低排序 出价最高拍1 其次依次排2 3 4 5 - recommendList.sort(Comparator.comparing(PCIndexSearchRecommendProdDTO::getPayPrice).reversed()); - for (int i = 0; i < recommendList.size(); i++) { - recommendList.get(i).setOrderNum(i + 1); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_RECOMMEND_PROD, recommendList, 1, TimeUnit.DAYS); - return recommendList; - } - - /** - * PC 新品馆 顶部左侧 轮播图 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcNewTopLeftBanner() { - List newTopLeftList; - // 从redis 中获取 PC 首页 人气榜数据 - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_LEFT); - if (ObjectUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_TOP_LEFT_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(launchingList)) { - List tempList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempList.add(new PCNewTopLeftBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(advertRound.getStoreId()) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - newTopLeftList = tempList.stream().limit(5).collect(Collectors.toList()); - } else { - newTopLeftList = launchingList.stream().map(advertRound -> new PCNewTopLeftBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) - .setStoreId(advertRound.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")) - .collect(Collectors.toList()); - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - newTopLeftList.sort(Comparator.comparing(PCNewTopLeftBannerDTO::getPayPrice).reversed()); - for (int i = 0; i < newTopLeftList.size(); i++) { - newTopLeftList.get(i).setOrderNum(i + 1); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_LEFT, newTopLeftList, 1, TimeUnit.DAYS); - return newTopLeftList; - } - - /** - * PC 新品馆 顶部右侧 轮播图 - * - * @return PCNewTopRightDTO - */ - @Override - @Transactional(readOnly = true) - public PCNewTopRightDTO getPcNewTopRight() { - // 从redis 中获取 PC 首页 人气榜数据 - PCNewTopRightDTO newTopRight; - PCNewTopRightDTO redisNewTopRight = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_RIGHT); - if (ObjectUtils.isNotEmpty(redisNewTopRight)) { - return redisNewTopRight; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_TOP_RIGHT.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new PCNewTopRightDTO(); - } - // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new PCNewTopRightDTO(); - } - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(launchingList)) { - // 从expiredList中任意取一条数据 - newTopRight = expiredList.stream().map(x -> new PCNewTopRightDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setOrderNum(1).setStoreId(x.getStoreId()) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")).findAny().orElse(null); - } else { - newTopRight = launchingList.stream().map(x -> new PCNewTopRightDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setOrderNum(1).setStoreId(x.getStoreId()) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) - .findAny().orElse(null); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_RIGHT, newTopRight, 1, TimeUnit.DAYS); - return newTopRight; - } - - /** - * PC 新品馆 品牌馆 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcNewMidBrandList() { - // 从redis中获取 新品馆 品牌榜数据 - List newMidBrandList; - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_BRAND); - if (CollectionUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_BRAND_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - Map storeMap = this.storeMapper.selectList(new LambdaQueryWrapper().eq(Store::getDelFlag, Constants.UNDELETED) - .in(Store::getId, oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(Store::getId, Function.identity())); - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(launchingList)) { - newMidBrandList = this.fillNewMidBrandList(expiredList, storeMap, fileMap, new ArrayList<>(), 10); - } else { - newMidBrandList = launchingList.stream().map(x -> new PCNewMidBrandDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) - .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) - .setStoreName(ObjectUtils.isNotEmpty(storeMap.get(x.getStoreId())) ? storeMap.get(x.getStoreId()).getStoreName() : "") - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) - .collect(Collectors.toList()); - if (newMidBrandList.size() < 10) { - final List existStoreIdList = newMidBrandList.stream().map(PCNewMidBrandDTO::getStoreId).distinct().collect(Collectors.toList()); - newMidBrandList.addAll(this.fillNewMidBrandList(expiredList, storeMap, fileMap, existStoreIdList, 10 - newMidBrandList.size())); - } - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - newMidBrandList.sort(Comparator.comparing(PCNewMidBrandDTO::getPayPrice).reversed()); - for (int i = 0; i < newMidBrandList.size(); i++) { - newMidBrandList.get(i).setOrderNum(i + 1); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_BRAND, newMidBrandList, 1, TimeUnit.DAYS); - return newMidBrandList; - } - - /** - * PC 新品馆 热卖榜左侧 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcNewMidHotLeftList() { - // 从redis中获取 新品馆 热卖榜左侧数据 - List newMidHotLeftList; - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_LEFT); - if (CollectionUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_HOT_LEFT_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 必须是已经设置了推广图的,防止有的档口购买了但没有设置图 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(launchingList)) { - List tempList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempList.add(new PCNewMidHotLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - newMidHotLeftList = tempList.stream().limit(5).collect(Collectors.toList()); - } else { - newMidHotLeftList = launchingList.stream().map(x -> new PCNewMidHotLeftDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) - .setStoreId(x.getStoreId()).setPayPrice(ObjectUtils.defaultIfNull(x.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) - .collect(Collectors.toList()); - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - newMidHotLeftList.sort(Comparator.comparing(PCNewMidHotLeftDTO::getPayPrice).reversed()); - for (int i = 0; i < newMidHotLeftList.size(); i++) { - newMidHotLeftList.get(i).setOrderNum(i + 1); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_LEFT, newMidHotLeftList, 1, TimeUnit.DAYS); - return newMidHotLeftList; - } - - /** - * PC 新品馆 热卖榜右侧商品 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcNewMidHotRightList() { - // 从redis中获取 新品馆 热卖榜右侧数据 - List newMidHotRightList; - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_RIGHT); - if (CollectionUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_HOT_RIGHT_PRODUCT.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - // 必须是已经设置了推广商品的,防止有的档口购买了但没有设置推广商品 - oneMonthList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - final List storeProdIdList = oneMonthList.stream() - .filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList()); - // 档口商品的价格及商品主图map - Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() - : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors - .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); - if (CollectionUtils.isEmpty(launchingList)) { - newMidHotRightList = this.fillNewMidHotRightList(expiredList, prodPriceAndMainPicMap, new ArrayList<>(), 8); - for (int i = 0; i < newMidHotRightList.size(); i++) { - newMidHotRightList.get(i).setOrderNum(i + 1); - } - } else { - newMidHotRightList = launchingList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> { - final Long storeProdId = Long.parseLong(x.getProdIdStr()); - return new PCNewMidHotRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setOrderNum(this.positionToNumber(x.getPosition())).setStoreProdId(storeProdId).setStoreId(x.getStoreId()) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : ""); - }).collect(Collectors.toList()); - if (newMidHotRightList.size() < 8) { - final List existProdIdList = newMidHotRightList.stream().map(PCNewMidHotRightDTO::getStoreProdId).collect(Collectors.toList()); - newMidHotRightList.addAll(this.fillNewMidHotRightList(expiredList, prodPriceAndMainPicMap, existProdIdList, 8 - newMidHotRightList.size())); - for (int i = 0; i < newMidHotRightList.size(); i++) { - newMidHotRightList.get(i).setOrderNum(i + 1); - } - } - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_RIGHT, newMidHotRightList, 1, TimeUnit.DAYS); - return newMidHotRightList; - } - - /** - * PC 新品馆 底部横幅 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcNewBottomBannerList() { - // 从redis中获取 新品馆 底部横幅数据 - List newBottomBannerList; - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_BOTTOM_BANNER); - if (CollectionUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_NEW_PROD_SINGLE_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - // 必须是已经设置了推广图的,防止有的档口购买了推广但没有设置推广图 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return Collections.emptyList(); - } - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - if (CollectionUtils.isEmpty(launchingList)) { - List tempList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempList.add(new PCNewBottomBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - newBottomBannerList = tempList.stream().limit(1).collect(Collectors.toList()); - for (int i = 0; i < newBottomBannerList.size(); i++) { - newBottomBannerList.get(i).setOrderNum(i + 1); - } - } else { - newBottomBannerList = launchingList.stream().map(x -> new PCNewBottomBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()) - .setOrderNum(this.positionToNumber(x.getPosition())).setStoreId(x.getStoreId()) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(x.getPicId())) ? fileMap.get(x.getPicId()).getFileUrl() : "")) - .collect(Collectors.toList()); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_BOTTOM_BANNER, newBottomBannerList, 1, TimeUnit.DAYS); - return newBottomBannerList; - } - - /** - * PC 档口馆 顶部横幅及商品 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcStoreTopBannerList() { - // 从redis中获取 档口馆 顶部横幅及商品数据 - List pcStoreTopBannerList; - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_TOP_BANNER); - if (CollectionUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_STORE_TOP_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - // 必须是已经设置了推广图及推广商品的,防止有的档口购买了推广位但没上传推广图及推广商品 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId()) && ObjectUtils.isNotEmpty(x.getProdIdStr())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - final List storeProdIdList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) - .flatMap(x -> Arrays.stream(x.getProdIdStr().split(",")).map(Long::parseLong)).distinct().collect(Collectors.toList()); - // 档口商品的价格及商品主图map - Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() - : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors - .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); - if (CollectionUtils.isEmpty(launchingList)) { - List tempList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempList.add(this.getStoreTopBanner(advertRound, fileMap, prodPriceAndMainPicMap)); - }); - pcStoreTopBannerList = tempList.stream().limit(1).collect(Collectors.toList()); - } else { - pcStoreTopBannerList = launchingList.stream().map(advertRound -> this - .getStoreTopBanner(advertRound, fileMap, prodPriceAndMainPicMap)).collect(Collectors.toList()); - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - pcStoreTopBannerList.sort(Comparator.comparing(PCStoreTopBannerDTO::getPayPrice).reversed()); - for (int i = 0; i < pcStoreTopBannerList.size(); i++) { - pcStoreTopBannerList.get(i).setOrderNum(i + 1); - } - // 放到redis中,过期时间为1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_TOP_BANNER, pcStoreTopBannerList, 1, TimeUnit.DAYS); - return pcStoreTopBannerList; - } - - /** - * PC 档口馆 中间横幅 - * - * @return List - */ - @Override - @Transactional(readOnly = true) - public List getPcStoreMidBannerList() { - // 从redis中获取 档口馆 中间横幅数据 - List pcStoreMidBannerList; - List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_MID_BANNER); - if (CollectionUtils.isNotEmpty(redisList)) { - return redisList; - } - List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_STORE_MID_BANNER.getValue())); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - // 必须是经设置了推广图的,防止有的档口购买了广告但没上传推广图 - oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); - if (CollectionUtils.isEmpty(oneMonthList)) { - return new ArrayList<>(); - } - List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) - .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); - List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); - Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) - .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) - .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); - if (CollectionUtils.isEmpty(launchingList)) { - List tempList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempList.add(new PCStoreMidBannerDTO().setStoreId(storeId).setDisplayType(AdDisplayType.PICTURE.getValue()) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - pcStoreMidBannerList = tempList.stream().limit(1).collect(Collectors.toList()); - } else { - pcStoreMidBannerList = launchingList.stream().map(advertRound -> new PCStoreMidBannerDTO().setStoreId(advertRound.getStoreId()) - .setDisplayType(AdDisplayType.PICTURE.getValue()).setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")) - .collect(Collectors.toList()); - } - // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 - pcStoreMidBannerList.sort(Comparator.comparing(PCStoreMidBannerDTO::getPayPrice).reversed()); - for (int i = 0; i < pcStoreMidBannerList.size(); i++) { - pcStoreMidBannerList.get(i).setOrderNum(i + 1); - } - // 放到redis 中 过期时间1天 - redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_MID_BANNER, pcStoreMidBannerList, 1, TimeUnit.DAYS); - return pcStoreMidBannerList; - } /** * 以图搜款 广告 @@ -1796,160 +752,6 @@ public class WebsitePCServiceImpl implements IWebsitePCService { }).collect(Collectors.toList()); } - /** - * 获取档口馆 顶部横幅及商品 - * - * @param advertRound 当前推广 - * @param fileMap 推广图map - * @param prodPriceAndMainPicMap 商品主图及价格map - * @return PCStoreTopBannerDTO - */ - private PCStoreTopBannerDTO getStoreTopBanner(AdvertRound advertRound, Map fileMap, Map prodPriceAndMainPicMap) { - List prodList = new ArrayList<>(); - if (StringUtils.isNotBlank(advertRound.getProdIdStr())) { - String[] prodIdStrArray = advertRound.getProdIdStr().split(","); - for (int i = 0; i < prodIdStrArray.length; i++) { - Long tempStoreProdId = Long.valueOf(prodIdStrArray[i]); - prodList.add(new PCStoreTopBannerDTO.PCSTBProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(tempStoreProdId).setOrderNum(i + 1) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(tempStoreProdId)) ? prodPriceAndMainPicMap.get(tempStoreProdId).getMinPrice() : null) - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(tempStoreProdId)) ? prodPriceAndMainPicMap.get(tempStoreProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(tempStoreProdId)) ? prodPriceAndMainPicMap.get(tempStoreProdId).getMainPicUrl() : "")); - } - } - return new PCStoreTopBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(advertRound.getStoreId()) - .setProdList(prodList).setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : ""); - } - - - /** - * 填充PC 首页底部 人气榜右侧商品 - * - * @param rightExpiredList 右侧过期广告 - * @param prodPriceAndMainPicMap 商品价格及主图map - * @param limitCount 筛选的数量 - * @return List - */ - private List fillBottomRightFromExpired(List rightExpiredList, - Map prodPriceAndMainPicMap, int limitCount) { - List tempRightList = new ArrayList<>(); - rightExpiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - tempRightList.add(new PCIndexBottomPopularDTO.PCIBPPopularRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setStoreProdId(Long.valueOf(advertRound.getProdIdStr())).setStoreId(advertRound.getStoreId()) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); - }); - return tempRightList.stream().limit(limitCount).collect(Collectors.toList()); - } - - /** - * 填充首页 人气榜 中部广告 - * - * @param midExpiredList 人气榜中部过期列表 - * @param fileMap 文件map - * @param limitCount 筛选的数量 - * @return List - */ - private List fillPopMidFromExpired(List midExpiredList, Map fileMap, int limitCount) { - List tempMidList = new ArrayList<>(); - midExpiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempMidList.add(new PCIndexBottomPopularDTO.PCIBPPopularMidDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - return tempMidList.stream().limit(limitCount).collect(Collectors.toList()); - } - - /** - * 填充首页中部风格榜数据 - * - * @param dbStyleList 风格数据 - * @param prodPriceAndMainPicMap 档口商品价格及主图map - * @param fileMap 档口推广图map - * @param storeMap 档口map - * @param limitCount 返回的数据数量 - * @return List - */ - private List fillMidStyleFromExpired(List dbStyleList, Map prodPriceAndMainPicMap, - Map fileMap, Map storeMap, int limitCount) { - List midStyleList = new ArrayList<>(); - dbStyleList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) - .collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - List prodIdStrList = StrUtil.split(advertRound.getProdIdStr(), ","); - List styleList = new ArrayList<>(); - for (int i = 0; i < prodIdStrList.size(); i++) { - Long storeProdId = Long.valueOf(prodIdStrList.get(i)); - styleList.add(new PCIndexMidStyleDTO.PCIMSStyleDTO().setStoreProdId(storeProdId).setOrderNum(i + 1).setDisplayType(AdDisplayType.PRODUCT.getValue()) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); - } - StoreMember storeMember = this.redisCache.getCacheObject(CacheConstants.STORE_MEMBER + storeId); - midStyleList.add(new PCIndexMidStyleDTO().setStoreId(storeId).setStoreName(storeMap.get(storeId).getStoreName()) - .setDisplayType(AdDisplayType.PICTURE.getValue()).setStyleList(styleList).setStyleType(advertRound.getStyleType()) - .setStyleTypeName(ObjectUtils.isNotEmpty(advertRound.getStyleType()) ? AdStyleType.of(advertRound.getStyleType()).getLabel() : "") - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setMemberLevel(ObjectUtils.isNotEmpty(storeMember) ? storeMember.getLevel() : null) - .setPicUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - return midStyleList.stream().limit(limitCount).collect(Collectors.toList()); - } - - - /** - * 填充首页顶部右侧纵向轮播图 - * - * @param expiredList 过期列表 - * @param limitCount 返回的数据条数 - * @param mainPicMap 商品主图map - * @return - */ - private List fillTopRightFromExpired(List expiredList, int limitCount, Map mainPicMap) { - List tempRightList = new ArrayList<>(); - expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.get(0); - tempRightList.add(new PCIndexTopRightBannerDTO().setDisplayType(advertRound.getDisplayType()).setStoreProdId(Long.valueOf(advertRound.getProdIdStr())) - .setFileUrl(mainPicMap.get(Long.valueOf(advertRound.getProdIdStr()))).setStoreId(advertRound.getStoreId())); - }); - return tempRightList.stream().limit(limitCount).collect(Collectors.toList()); - } - - /** - * 填充 PC 首页新品馆 品牌榜 - * - * @param advertRoundList 广告 列表 - * @param storeMap 档口map - * @param fileMap 推广图map - * @param existStoreIdList 已存在的档口ID列表 - * @param limitCount 填充数量 - * @return List - */ - private List fillNewMidBrandList(List advertRoundList, Map storeMap, - Map fileMap, List existStoreIdList, int limitCount) { - List tempList = new ArrayList<>(); - advertRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - if (existStoreIdList.contains(storeId)) { - return; - } - AdvertRound advertRound = list.get(0); - tempList.add(new PCNewMidBrandDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(storeId) - .setStoreName(storeMap.get(storeId).getStoreName()) - .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) - .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); - }); - return tempList.stream().limit(limitCount).collect(Collectors.toList()); - } - /** * 获取近一月档口推广数据 @@ -1986,32 +788,6 @@ public class WebsitePCServiceImpl implements IWebsitePCService { return firstChar - 'A' + 1; } - /** - * 填充 PC 新品馆 中间热卖榜右侧商品 - * - * @param advertRoundList 广告列表 - * @param prodPriceAndMainPicMap 商品价格和主图map - * @param existProdIdList 已存在的 商品ID列表 - * @param limitCount 返回的 数量 - * @return - */ - private List fillNewMidHotRightList(List advertRoundList, Map prodPriceAndMainPicMap, - List existProdIdList, int limitCount) { - List tempList = new ArrayList<>(); - advertRoundList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) - .forEach((storeId, list) -> { - AdvertRound advertRound = list.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) - .filter(x -> CollectionUtils.isEmpty(existProdIdList) || !existProdIdList.contains(Long.parseLong(x.getProdIdStr()))).findAny().orElse(null); - if (ObjectUtils.isNotEmpty(advertRound)) { - final Long storeProdId = Long.parseLong(advertRound.getProdIdStr()); - tempList.add(new PCNewMidHotRightDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(storeProdId).setStoreId(storeId) - .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMinPrice() : null) - .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getProdArtNum() : "") - .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(storeProdId)) ? prodPriceAndMainPicMap.get(storeProdId).getMainPicUrl() : "")); - } - }); - return tempList.stream().limit(limitCount).collect(Collectors.toList()); - } /** * @param advertRoundList 广告列表 @@ -2205,28 +981,4 @@ public class WebsitePCServiceImpl implements IWebsitePCService { redisCache.setCacheObject(CacheConstants.USER_SEARCH_HISTORY + loginUser.getUserId(), userSearchList); } - /** - * 获取父级分类ID Map,如果只有父级一级 则 parCateId和prodCateId一致 - * - * @return - */ - private Map getParCateIdMap() { - List prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper() - .eq(SysProductCategory::getDelFlag, Constants.UNDELETED) - // 排除最顶层的父级分类 - .ne(SysProductCategory::getParentId, 0)); - // 所有字分类 - List subCateList = prodCateList.stream().filter(x -> !Objects.equals(x.getParentId(), TOPMOST_PRODUCT_CATEGORY_ID)).collect(Collectors.toList()); - Map subCateMap = subCateList.stream().collect(Collectors.toMap(SysProductCategory::getId, SysProductCategory::getParentId)); - // 所有的一级分类 - List topCateList = prodCateList.stream().filter(x -> Objects.equals(x.getParentId(), TOPMOST_PRODUCT_CATEGORY_ID)) - .map(SysProductCategory::getId).collect(Collectors.toList()); - final List hasSubCateIdList = new ArrayList<>(subCateMap.keySet()); - // 如果只有父类一级,则父类分类ID和字类分类ID一致 - Map parCateAloneIdMap = topCateList.stream().filter(x -> !hasSubCateIdList.contains(x)).collect(Collectors.toMap(x -> x, x -> x)); - subCateMap.putAll(parCateAloneIdMap); - return subCateMap; - } - - } diff --git a/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCStoreServiceImpl.java b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCStoreServiceImpl.java new file mode 100644 index 000000000..ab5e1c232 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/service/impl/WebsitePCStoreServiceImpl.java @@ -0,0 +1,229 @@ +package com.ruoyi.xkt.service.impl; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.enums.AdType; +import com.ruoyi.xkt.domain.AdvertRound; +import com.ruoyi.xkt.domain.SysFile; +import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreMidBannerDTO; +import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreTopBannerDTO; +import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicDTO; +import com.ruoyi.xkt.enums.AdBiddingStatus; +import com.ruoyi.xkt.enums.AdDisplayType; +import com.ruoyi.xkt.enums.AdLaunchStatus; +import com.ruoyi.xkt.mapper.AdvertRoundMapper; +import com.ruoyi.xkt.mapper.StoreProductMapper; +import com.ruoyi.xkt.mapper.SysFileMapper; +import com.ruoyi.xkt.service.IPictureService; +import com.ruoyi.xkt.service.IWebsitePCStoreService; +import lombok.RequiredArgsConstructor; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 首页搜索 + * + * @author ruoyi + * @date 2025-03-26 + */ +@Service +@RequiredArgsConstructor +public class WebsitePCStoreServiceImpl implements IWebsitePCStoreService { + + final RedisCache redisCache; + final AdvertRoundMapper advertRoundMapper; + final SysFileMapper fileMapper; + final StoreProductMapper storeProdMapper; + final IPictureService pictureService; + + + /** + * PC 档口馆 顶部横幅及商品 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcStoreTopBannerList() { + // 从redis中获取 档口馆 顶部横幅及商品数据 + List pcStoreTopBannerList; + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_TOP_BANNER); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_STORE_TOP_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + // 必须是已经设置了推广图及推广商品的,防止有的档口购买了推广位但没上传推广图及推广商品 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId()) && ObjectUtils.isNotEmpty(x.getProdIdStr())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + final List storeProdIdList = oneMonthList.stream().filter(x -> StringUtils.isNotBlank(x.getProdIdStr())) + .flatMap(x -> Arrays.stream(x.getProdIdStr().split(",")).map(Long::parseLong)).distinct().collect(Collectors.toList()); + // 档口商品的价格及商品主图map + Map prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>() + : this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors + .toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity())); + if (CollectionUtils.isEmpty(launchingList)) { + List tempList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempList.add(this.getStoreTopBanner(advertRound, fileMap, prodPriceAndMainPicMap)); + }); + pcStoreTopBannerList = tempList.stream().limit(1).collect(Collectors.toList()); + } else { + pcStoreTopBannerList = launchingList.stream().map(advertRound -> this + .getStoreTopBanner(advertRound, fileMap, prodPriceAndMainPicMap)).collect(Collectors.toList()); + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + pcStoreTopBannerList.sort(Comparator.comparing(PCStoreTopBannerDTO::getPayPrice).reversed()); + for (int i = 0; i < pcStoreTopBannerList.size(); i++) { + pcStoreTopBannerList.get(i).setOrderNum(i + 1); + } + // 放到redis中,过期时间为1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_TOP_BANNER, pcStoreTopBannerList, 1, TimeUnit.DAYS); + return pcStoreTopBannerList; + } + + + /** + * PC 档口馆 中间横幅 + * + * @return List + */ + @Override + @Transactional(readOnly = true) + public List getPcStoreMidBannerList() { + // 从redis中获取 档口馆 中间横幅数据 + List pcStoreMidBannerList; + List redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_MID_BANNER); + if (CollectionUtils.isNotEmpty(redisList)) { + return redisList; + } + List oneMonthList = this.getOneMonthAdvertList(Collections.singletonList(AdType.PC_STORE_MID_BANNER.getValue())); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + // 必须是经设置了推广图的,防止有的档口购买了广告但没上传推广图 + oneMonthList = oneMonthList.stream().filter(x -> ObjectUtils.isNotEmpty(x.getPicId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(oneMonthList)) { + return new ArrayList<>(); + } + List launchingList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.LAUNCHING.getValue())) + .filter(x -> Objects.equals(x.getBiddingStatus(), AdBiddingStatus.BIDDING_SUCCESS.getValue())).collect(Collectors.toList()); + List expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList()); + Map fileMap = fileMapper.selectList(new LambdaQueryWrapper().eq(SysFile::getDelFlag, Constants.UNDELETED) + .in(SysFile::getId, oneMonthList.stream().map(AdvertRound::getPicId).filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()))) + .stream().collect(Collectors.toMap(SysFile::getId, Function.identity())); + if (CollectionUtils.isEmpty(launchingList)) { + List tempList = new ArrayList<>(); + expiredList.stream().collect(Collectors.groupingBy(AdvertRound::getStoreId)) + .forEach((storeId, list) -> { + AdvertRound advertRound = list.get(0); + tempList.add(new PCStoreMidBannerDTO().setStoreId(storeId).setDisplayType(AdDisplayType.PICTURE.getValue()) + .setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")); + }); + pcStoreMidBannerList = tempList.stream().limit(1).collect(Collectors.toList()); + } else { + pcStoreMidBannerList = launchingList.stream().map(advertRound -> new PCStoreMidBannerDTO().setStoreId(advertRound.getStoreId()) + .setDisplayType(AdDisplayType.PICTURE.getValue()).setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : "")) + .collect(Collectors.toList()); + } + // 按照价格由高到低进行排序,价格高的排1,其次按照价格排 2 3 4 5 + pcStoreMidBannerList.sort(Comparator.comparing(PCStoreMidBannerDTO::getPayPrice).reversed()); + for (int i = 0; i < pcStoreMidBannerList.size(); i++) { + pcStoreMidBannerList.get(i).setOrderNum(i + 1); + } + // 放到redis 中 过期时间1天 + redisCache.setCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_MID_BANNER, pcStoreMidBannerList, 1, TimeUnit.DAYS); + return pcStoreMidBannerList; + } + + + /** + * 获取近一月档口推广数据 + * + * @return 近一月档口推广数据 + */ + private List getOneMonthAdvertList(final List typeIdList) { + // 当前时间 + final Date now = java.sql.Date.valueOf(LocalDate.now()); + // 一月前 + final Date oneMonthAgo = java.sql.Date.valueOf(LocalDate.now().minusMonths(1)); + // 查询最近一个月所有的 正在播放 及 已过期的推广列表 + return this.advertRoundMapper.selectList(new LambdaQueryWrapper() + .isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED) + .in(AdvertRound::getTypeId, typeIdList).between(AdvertRound::getStartTime, oneMonthAgo, now) + .in(AdvertRound::getLaunchStatus, Arrays.asList(AdLaunchStatus.LAUNCHING.getValue(), AdLaunchStatus.EXPIRED.getValue()))); + } + + + /** + * 将position 的 A B C D E 转化为 1 2 3 4 5 + * + * @param position 位置 + * @return 1 2 3 4 5 + */ + private int positionToNumber(String position) { + if (position == null || position.isEmpty()) { + throw new IllegalArgumentException("Position cannot be null or empty."); + } + char firstChar = Character.toUpperCase(position.charAt(0)); + if (firstChar < 'A' || firstChar > 'Z') { + throw new IllegalArgumentException("Position must start with a letter A-Z."); + } + return firstChar - 'A' + 1; + } + + + /** + * 获取档口馆 顶部横幅及商品 + * + * @param advertRound 当前推广 + * @param fileMap 推广图map + * @param prodPriceAndMainPicMap 商品主图及价格map + * @return PCStoreTopBannerDTO + */ + private PCStoreTopBannerDTO getStoreTopBanner(AdvertRound advertRound, Map fileMap, Map prodPriceAndMainPicMap) { + List prodList = new ArrayList<>(); + if (StringUtils.isNotBlank(advertRound.getProdIdStr())) { + String[] prodIdStrArray = advertRound.getProdIdStr().split(","); + for (int i = 0; i < prodIdStrArray.length; i++) { + Long tempStoreProdId = Long.valueOf(prodIdStrArray[i]); + prodList.add(new PCStoreTopBannerDTO.PCSTBProdDTO().setDisplayType(AdDisplayType.PRODUCT.getValue()).setStoreProdId(tempStoreProdId).setOrderNum(i + 1) + .setPrice(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(tempStoreProdId)) ? prodPriceAndMainPicMap.get(tempStoreProdId).getMinPrice() : null) + .setProdArtNum(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(tempStoreProdId)) ? prodPriceAndMainPicMap.get(tempStoreProdId).getProdArtNum() : "") + .setMainPicUrl(ObjectUtils.isNotEmpty(prodPriceAndMainPicMap.get(tempStoreProdId)) ? prodPriceAndMainPicMap.get(tempStoreProdId).getMainPicUrl() : "")); + } + } + return new PCStoreTopBannerDTO().setDisplayType(AdDisplayType.PICTURE.getValue()).setStoreId(advertRound.getStoreId()) + .setProdList(prodList).setPayPrice(ObjectUtils.defaultIfNull(advertRound.getPayPrice(), BigDecimal.ZERO)) + .setFileUrl(ObjectUtils.isNotEmpty(fileMap.get(advertRound.getPicId())) ? fileMap.get(advertRound.getPicId()).getFileUrl() : ""); + } + + +}