master:商城首页广告拆分为多个service调优;

pull/1121/head
liujiang 2025-11-09 16:20:34 +08:00
parent f6f4520e1d
commit c9003afef1
19 changed files with 1825 additions and 1453 deletions

View File

@ -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<List<PCIndexTopBannerVO>> 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<List<PCIndexTopLeftBannerVO>> 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<List<PCIndexTopRightBannerVO>> 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<List<PCIndexMidSalesVO>> 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<List<PCIndexMidStyleVO>> 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<PCIndexBottomPopularVO> 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<PCIndexFixedEarVO> 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<List<PCIndexSearchUnderlineStoreNameVO>> 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<List<PCIndexSearchRecommendProdVO>> 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<List<PCNewTopLeftBannerVO>> 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<PCNewTopRightVO> 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<List<PCNewMidBrandVO>> 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<List<PCNewMidHotLeftVO>> 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<List<PCNewMidHotRightVO>> 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<List<PCNewBottomBannerVO>> 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<List<PCStoreTopBannerVO>> 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<List<PCStoreMidBannerVO>> 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)

View File

@ -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 storeredis
* 01:00:01 storeredis
*/
public void saveStoreToRedis() {
List<Store> storeList = this.storeMapper.selectList(new LambdaQueryWrapper<Store>()
@ -181,7 +182,7 @@ public class XktTask {
}
/**
* 12:01 广
* 01:01 广
*/
@Transactional
public void dailyAdvertRound() {
@ -266,14 +267,14 @@ public class XktTask {
/**
* 00:04symbolredis
* 01:04symbolredis
*/
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 advertredis
* 01:45 advertredis
*/
public void saveAdvertToRedis() {
List<Advert> advertList = this.advertMapper.selectList(new LambdaQueryWrapper<Advert>()
@ -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<StoreMember> memberList = this.storeMemberMapper.selectList(new LambdaQueryWrapper<StoreMember>()
@ -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:00redis
* 03:00redis
*/
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<PCIndexTopBannerDTO> topBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP);
}
/**
* 5:00voucher_sequence
*/

View File

@ -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;

View File

@ -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
*

View File

@ -150,7 +150,7 @@ public interface IStoreProductService {
/**
*
*
* @param storeId ID
* @param storeId ID
* @param prodArtNum
* @return StoreProdFuzzyResDTO
*/

View File

@ -68,7 +68,7 @@ public interface IStoreProductStockService {
/**
* ID
*
* @param storeId ID
* @param storeId ID
* @param storeProdId ID
* @return String
*/

View File

@ -19,6 +19,7 @@ public interface IUserSearchHistoryService {
/**
*
*
* @return Integer
*/
Integer clearSearchHisRecord();

View File

@ -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<PCIndexTopBannerDTO> getPcIndexTop();
/**
* PC
*
* @return PCIndexTopLeftBannerDTO
*/
List<PCIndexTopLeftBannerDTO> getPcIndexTopLeftBanner();
/**
* PC
*
* @return PCIndexTopRightBannerDTO
*/
List<PCIndexTopRightBannerDTO> getPcIndexTopRightBanner();
/**
* PC
*
* @return List<PCIndexMidSalesDTO>
*/
List<PCIndexMidSalesDTO> getPcIndexMidSaleList();
/**
* PC
*
* @return List<PCIndexMidStyleDTO>
*/
List<PCIndexMidStyleDTO> getPcIndexMidStyleList();
/**
* PC
*
* @return PCIndexBottomPopularDTO
*/
PCIndexBottomPopularDTO getPcIndexBottomPopularList();
/**
* PC
*
* @return PCIndexFixedEarDTO
*/
PCIndexFixedEarDTO getPcIndexFixedEar();
/**
*
*
* @return List<PCIndexSearchUnderlineStoreNameDTO>
*/
List<PCIndexSearchUnderlineStoreNameDTO> getPcIndexSearchUnderlineStoreName();
/**
*
*
* @return List<PCIndexSearchRecommendProdDTO>
*/
List<PCIndexSearchRecommendProdDTO> getPcIndexSearchRecommendProd();
}

View File

@ -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<PCNewTopLeftBannerDTO>
*/
List<PCNewTopLeftBannerDTO> getPcNewTopLeftBanner();
/**
* PC
*
* @return PCNewTopRightDTO
*/
PCNewTopRightDTO getPcNewTopRight();
/**
* PC
*
* @return List<PCNewMidBrandDTO>
*/
List<PCNewMidBrandDTO> getPcNewMidBrandList();
/**
* PC
*
* @return List<PCNewMidHotLeftDTO>
*/
List<PCNewMidHotLeftDTO> getPcNewMidHotLeftList();
/**
* PC
*
* @return List<PCNewMidHotRightDTO>
*/
List<PCNewMidHotRightDTO> getPcNewMidHotRightList();
/**
* PC
*
* @return List<PCNewBottomBannerDTO>
*/
List<PCNewBottomBannerDTO> getPcNewBottomBannerList();
}

View File

@ -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<ESProductDTO> search(IndexSearchDTO searchDTO) throws IOException;
/**
* PC
*
* @return PCIndexTopLeftBannerDTO
*/
List<PCIndexTopLeftBannerDTO> getPcIndexTopLeftBanner();
/**
* PC
*
* @return PCIndexTopRightBannerDTO
*/
List<PCIndexTopRightBannerDTO> getPcIndexTopRightBanner();
/**
* PC
*
* @return List<PCIndexMidSalesDTO>
*/
List<PCIndexMidSalesDTO> getPcIndexMidSaleList();
/**
* PC
*
* @return List<PCIndexMidStyleDTO>
*/
List<PCIndexMidStyleDTO> getPcIndexMidStyleList();
/**
* PC
*
* @return PCIndexBottomPopularDTO
*/
PCIndexBottomPopularDTO getPcIndexBottomPopularList();
/**
* PC
*
* @return PCIndexFixedEarDTO
*/
PCIndexFixedEarDTO getPcIndexFixedEar();
/**
*
*
* @return List<PCIndexSearchUnderlineStoreNameDTO>
*/
List<PCIndexSearchUnderlineStoreNameDTO> getPcIndexSearchUnderlineStoreName();
/**
*
*
* @return List<PCIndexSearchRecommendProdDTO>
*/
List<PCIndexSearchRecommendProdDTO> getPcIndexSearchRecommendProd();
/**
* PC
*
* @return List<PCNewTopLeftBannerDTO>
*/
List<PCNewTopLeftBannerDTO> getPcNewTopLeftBanner();
/**
* PC
*
* @return PCNewTopRightDTO
*/
PCNewTopRightDTO getPcNewTopRight();
/**
* PC
*
* @return List<PCNewMidBrandDTO>
*/
List<PCNewMidBrandDTO> getPcNewMidBrandList();
/**
* PC
*
* @return List<PCNewMidHotLeftDTO>
*/
List<PCNewMidHotLeftDTO> getPcNewMidHotLeftList();
/**
* PC
*
* @return List<PCNewMidHotRightDTO>
*/
List<PCNewMidHotRightDTO> getPcNewMidHotRightList();
/**
* PC
*
* @return List<PCNewBottomBannerDTO>
*/
List<PCNewBottomBannerDTO> getPcNewBottomBannerList();
/**
* PC
*
* @return List<PCStoreTopBannerDTO>
*/
List<PCStoreTopBannerDTO> getPcStoreTopBannerList();
/**
* PC
*
* @return List<PCStoreMidBannerDTO>
*/
List<PCStoreMidBannerDTO> getPcStoreMidBannerList();
/**
* 广
*
@ -199,13 +85,6 @@ public interface IWebsitePCService {
*/
Page<PCStoreRecommendDTO> pcStoreRecommendPage(StoreSearchDTO searchDTO);
/**
* PC
*
* @return PCIndexTopBannerDTO
*/
List<PCIndexTopBannerDTO> getPcIndexTop();
/**
* PC 广
*

View File

@ -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<PCStoreTopBannerDTO>
*/
List<PCStoreTopBannerDTO> getPcStoreTopBannerList();
/**
* PC
*
* @return List<PCStoreMidBannerDTO>
*/
List<PCStoreMidBannerDTO> getPcStoreMidBannerList();
}

View File

@ -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) {

View File

@ -29,16 +29,51 @@ public class StoreColorServiceImpl implements IStoreColorService {
final StoreColorMapper storeColorMapper;
private static final Map<String, Integer> colorPriority = new HashMap<String, Integer>() {{
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<String, Integer> suffixPriority = new HashMap<String, Integer>() {{
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<String, Integer> suffixPriority = new HashMap<String, Integer>() {{
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);
}};

View File

@ -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()));
}

View File

@ -404,7 +404,7 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
List<Long> spIds = detailInfos.stream().map(StoreOrderDetailInfoDTO::getStoreProdId).distinct()
.collect(Collectors.toList());
Map<Long, String> 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<String, Date> 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<Long, String> expressNameMap = expressService.getAllExpressNameMap();
Map<String, List<StoreOrderDetail>> 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<Long> spIds = orderDetailList.stream().map(StoreOrderDetailInfoDTO::getStoreProdId).distinct()
.collect(Collectors.toList());
Map<Long, String> 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<Long, List<StoreOrderDetailInfoDTO>> orderDetailGroup = orderDetailList
@ -1139,9 +1139,9 @@ public class StoreOrderServiceImpl implements IStoreOrderService {
List<Long> afterSaleOrderIds = afterSaleOrderList.stream().map(SimpleEntity::getId)
.collect(Collectors.toList());
Map<Long, List<StoreOrderDetail>> 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<Long> storeOrderDetailIds, Long operatorId) {
StoreOrder order = getAndBaseCheck(storeOrderId);
Map<Long, StoreOrderDetail> 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<Long, StoreColor> 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<Long> spIdList = spcsMap.values().stream()

View File

@ -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<PCIndexTopBannerDTO> getPcIndexTop() {
// 从redis 中获取 PC 首页 顶部通栏
List<PCIndexTopBannerDTO> topBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP);
if (ObjectUtils.isNotEmpty(topBannerList)) {
return topBannerList;
}
// 正在播放的首页顶部通栏 必须是档口已经设置了推广图
List<AdvertRound> indexTopList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<PCIndexTopBannerDTO> 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<PCIndexTopLeftBannerDTO> getPcIndexTopLeftBanner() {
// 从redis 中获取 PC 首页顶部左侧 轮播图
List<PCIndexTopLeftBannerDTO> topLeftBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_LEFT);
if (ObjectUtils.isNotEmpty(topLeftBannerList)) {
return topLeftBannerList;
}
// 获取近一月 档口首页PC 顶部左侧轮播图推广数据
List<AdvertRound> 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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
List<PCIndexTopLeftBannerDTO> topLeftList;
// 如果顶部横向轮播图全部为空,则需要找填充的数据
if (CollectionUtils.isEmpty(launchingList)) {
List<PCIndexTopLeftBannerDTO> 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<PCIndexTopRightBannerDTO> getPcIndexTopRightBanner() {
// 从redis 中获取 PC 首页顶部右侧 轮播图
List<PCIndexTopRightBannerDTO> topRightBannerList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_TOP_RIGHT);
if (ObjectUtils.isNotEmpty(topRightBannerList)) {
return topRightBannerList;
}
List<AdvertRound> 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<StoreProdFileResDTO> mainPicList = this.prodFileMapper.selectMainPic(oneMonthList.stream().map(AdvertRound::getProdIdStr).distinct().collect(Collectors.toList()));
Map<Long, String> mainPicMap = mainPicList.stream().collect(Collectors.toMap(StoreProdFileResDTO::getStoreProdId, StoreProdFileResDTO::getFileUrl, (v1, v2) -> v2));
List<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
List<PCIndexTopRightBannerDTO> 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<PCIndexMidSalesDTO> getPcIndexMidSaleList() {
// 从redis中获取销售榜数据
List<PCIndexMidSalesDTO> 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<CateSaleRankDTO> cateSaleList = this.dailySaleProdMapper.selectSaleRankList(oneMonthAgo, now);
if (CollectionUtils.isEmpty(cateSaleList)) {
return new ArrayList<>();
}
// 销售榜榜一到榜四的推广
List<AdvertRound> saleRankList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.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<Integer, List<AdvertRound>> 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<Long> advertProdIdList = CollectionUtils.isEmpty(saleRankList) ? Collections.emptyList()
: saleRankList.stream().map(AdvertRound::getProdIdStr).map(Long::parseLong).collect(Collectors.toList());
// 销售榜推广销量等信息
List<CateSaleRankDTO> advertSaleList = cateSaleList.stream().filter(x -> advertProdIdList.contains(x.getStoreProdId())).collect(Collectors.toList());
Map<Long, CateSaleRankDTO> advertSaleMap = CollectionUtils.isEmpty(advertSaleList) ? new HashMap<>()
: advertSaleList.stream().collect(Collectors.toMap(CateSaleRankDTO::getStoreProdId, Function.identity()));
// 所有二级分类ID map
Map<Long, Long> parCateIdMap = this.getParCateIdMap();
final List<Long> storeProdIdList = cateSaleList.stream().map(CateSaleRankDTO::getStoreProdId).collect(Collectors.toList());
// 档口商品的价格及商品主图map
Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>()
: this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors
.toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity()));
Map<Long, String> cateIdMap = cateSaleList.stream().collect(Collectors.toMap(CateSaleRankDTO::getProdCateId, CateSaleRankDTO::getProdCateName, (existing, replacement) -> existing));
// Step 1: 按 prodCateId 分组并取每组销量前5的商品
Map<Long, List<CateSaleRankDTO>> 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<Long, Integer> totalSalesPerCate = cateSaleList.stream().collect(Collectors.groupingBy(CateSaleRankDTO::getProdCateId, Collectors.summingInt(CateSaleRankDTO::getSaleNum)));
// Step 3: 取总销量排名前4的 prodCateId
List<Map.Entry<Long, Integer>> top4CateEntries = totalSalesPerCate.entrySet().stream().sorted(Map.Entry.<Long, Integer>comparingByValue().reversed()).limit(4).collect(Collectors.toList());
// Step 4: 构建返回结果
List<PCIndexMidSalesDTO> retCateOrderList = new ArrayList<>();
for (int i = 0; i < top4CateEntries.size(); i++) {
// 当前销售榜推广
final List<AdvertRound> saleAdvertList = saleAdvertMap.getOrDefault(i + 1, Collections.emptyList());
final List<Long> tempAdvertProdIdList = saleAdvertList.stream().map(AdvertRound::getProdIdStr).map(Long::parseLong).collect(Collectors.toList());
Long cateId = top4CateEntries.get(i).getKey();
List<CateSaleRankDTO> 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<PCIndexMidSalesDTO.PCIMSSaleDTO> 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<PCIndexMidStyleDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCIndexMidStyleDTO> getPcIndexMidStyleList() {
// 从redis 中获取 PC 首页风格榜数据
List<PCIndexMidStyleDTO> redisStyleList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_MID_STYLE);
if (ObjectUtils.isNotEmpty(redisStyleList)) {
return redisStyleList;
}
List<AdvertRound> 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<SysFile> fileList = this.fileMapper.selectByIds(oneMonthList.stream().map(AdvertRound::getPicId)
.filter(ObjectUtils::isNotEmpty).collect(Collectors.toList()));
Map<Long, SysFile> fileMap = fileList.stream().collect(Collectors.toMap(SysFile::getId, Function.identity()));
List<Store> storeList = this.storeMapper.selectByIds(oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList()));
Map<Long, Store> storeMap = storeList.stream().collect(Collectors.toMap(Store::getId, Function.identity()));
// 获取所有的档口商品ID列表
Set<Long> 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<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdSet) ? new ConcurrentHashMap<>()
: this.storeProdMapper.selectPriceAndMainPicList(new ArrayList<>(storeProdIdSet)).stream().collect(Collectors
.toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity()));
List<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
List<PCIndexMidStyleDTO> 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<AdvertRound> 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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<Long> storeProdIdList = oneMonthList.stream()
.filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList());
// 档口商品的价格及商品主图map
Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>()
: this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors
.toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity()));
// 左侧广告
List<AdvertRound> 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<AdvertRound> 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<AdvertRound> 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<AdvertRound> 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<AdvertRound> 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<AdvertRound> 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<PCIndexBottomPopularDTO.PCIBPPopularLeftDTO> bottomLeftList;
// 处理左侧广告列表
if (CollectionUtils.isEmpty(leftLaunchingList)) {
List<PCIndexBottomPopularDTO.PCIBPPopularLeftDTO> 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<PCIndexBottomPopularDTO.PCIBPPopularMidDTO> 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<PCIndexBottomPopularDTO.PCIBPPopularRightDTO> 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<AdvertRound>()
.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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<PCIndexSearchUnderlineStoreNameDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCIndexSearchUnderlineStoreNameDTO> getPcIndexSearchUnderlineStoreName() {
List<PCIndexSearchUnderlineStoreNameDTO> searchStoreNameList;
// 从redis 中获取 PC 首页 搜索框下档口名称
List<PCIndexSearchUnderlineStoreNameDTO> redisSearchStoreNameList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_UNDERLINE_STORE_NAME);
if (ObjectUtils.isNotEmpty(redisSearchStoreNameList)) {
return redisSearchStoreNameList;
}
// 搜索框下的档口名称只有档口购买了才会显示
List<AdvertRound> searchDownStoreNameList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.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<Long, Store> storeMap = this.storeMapper.selectList(new LambdaQueryWrapper<Store>().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<PCIndexSearchRecommendProdDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCIndexSearchRecommendProdDTO> getPcIndexSearchRecommendProd() {
List<PCIndexSearchRecommendProdDTO> recommendList;
// 从redis中获取PC 搜索框中推荐商品
List<PCIndexSearchRecommendProdDTO> redisRecommendList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_INDEX_SEARCH_RECOMMEND_PROD);
if (CollectionUtils.isNotEmpty(redisRecommendList)) {
return redisRecommendList;
}
List<AdvertRound> 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<Store> storeList = this.storeMapper.selectList(new LambdaQueryWrapper<Store>().eq(Store::getDelFlag, Constants.UNDELETED)
.in(Store::getId, oneMonthList.stream().map(AdvertRound::getStoreId).collect(Collectors.toList())));
Map<Long, Store> storeMap = CollectionUtils.isEmpty(storeList) ? new HashMap<>()
: storeList.stream().collect(Collectors.toMap(Store::getId, Function.identity()));
final List<Long> storeProdIdList = oneMonthList.stream().map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList());
// 档口商品的价格及商品主图map
Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>()
: this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors
.toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity()));
// 正在播放
List<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(launchingList)) {
List<PCIndexSearchRecommendProdDTO> 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<String> existStoreProdIdList = recommendList.stream().map(PCIndexSearchRecommendProdDTO::getStoreProdId).map(String::valueOf).collect(Collectors.toList());
List<PCIndexSearchRecommendProdDTO> 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<AdvertRound> getOneMonthAdvertList(final List<Integer> 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<AdvertRound>()
.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<PCIndexTopRightBannerDTO> fillTopRightFromExpired(List<AdvertRound> expiredList, int limitCount, Map<Long, String> mainPicMap) {
List<PCIndexTopRightBannerDTO> 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 parCateIdprodCateId
*
* @return
*/
private Map<Long, Long> getParCateIdMap() {
List<SysProductCategory> prodCateList = this.prodCateMapper.selectList(new LambdaQueryWrapper<SysProductCategory>()
.eq(SysProductCategory::getDelFlag, Constants.UNDELETED)
// 排除最顶层的父级分类
.ne(SysProductCategory::getParentId, 0));
// 所有字分类
List<SysProductCategory> subCateList = prodCateList.stream().filter(x -> !Objects.equals(x.getParentId(), TOPMOST_PRODUCT_CATEGORY_ID)).collect(Collectors.toList());
Map<Long, Long> subCateMap = subCateList.stream().collect(Collectors.toMap(SysProductCategory::getId, SysProductCategory::getParentId));
// 所有的一级分类
List<Long> topCateList = prodCateList.stream().filter(x -> Objects.equals(x.getParentId(), TOPMOST_PRODUCT_CATEGORY_ID))
.map(SysProductCategory::getId).collect(Collectors.toList());
final List<Long> hasSubCateIdList = new ArrayList<>(subCateMap.keySet());
// 如果只有父类一级则父类分类ID和字类分类ID一致
Map<Long, Long> 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<PCIndexMidStyleDTO>
*/
private List<PCIndexMidStyleDTO> fillMidStyleFromExpired(List<AdvertRound> dbStyleList, Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap,
Map<Long, SysFile> fileMap, Map<Long, Store> storeMap, int limitCount) {
List<PCIndexMidStyleDTO> 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<String> prodIdStrList = StrUtil.split(advertRound.getProdIdStr(), ",");
List<PCIndexMidStyleDTO.PCIMSStyleDTO> 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<PCIndexBottomPopularDTO.PCIBPPopularMidDTO>
*/
private List<PCIndexBottomPopularDTO.PCIBPPopularMidDTO> fillPopMidFromExpired(List<AdvertRound> midExpiredList, Map<Long, SysFile> fileMap, int limitCount) {
List<PCIndexBottomPopularDTO.PCIBPPopularMidDTO> 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<PCIndexBottomPopularDTO.PCIBPPopularRightDTO>
*/
private List<PCIndexBottomPopularDTO.PCIBPPopularRightDTO> fillBottomRightFromExpired(List<AdvertRound> rightExpiredList,
Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap, int limitCount) {
List<PCIndexBottomPopularDTO.PCIBPPopularRightDTO> 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());
}
}

View File

@ -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<PCNewTopLeftBannerDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCNewTopLeftBannerDTO> getPcNewTopLeftBanner() {
List<PCNewTopLeftBannerDTO> newTopLeftList;
// 从redis 中获取 PC 首页 人气榜数据
List<PCNewTopLeftBannerDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_TOP_LEFT);
if (ObjectUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(launchingList)) {
List<PCNewTopLeftBannerDTO> 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<AdvertRound> 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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<AdvertRound> 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<AdvertRound> 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<PCNewMidBrandDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCNewMidBrandDTO> getPcNewMidBrandList() {
// 从redis中获取 新品馆 品牌榜数据
List<PCNewMidBrandDTO> newMidBrandList;
List<PCNewMidBrandDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_BRAND);
if (CollectionUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<Long, Store> storeMap = this.storeMapper.selectList(new LambdaQueryWrapper<Store>().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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<AdvertRound> 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<AdvertRound> 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<Long> 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<PCNewMidHotLeftDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCNewMidHotLeftDTO> getPcNewMidHotLeftList() {
// 从redis中获取 新品馆 热卖榜左侧数据
List<PCNewMidHotLeftDTO> newMidHotLeftList;
List<PCNewMidHotLeftDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_LEFT);
if (CollectionUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
if (CollectionUtils.isEmpty(launchingList)) {
List<PCNewMidHotLeftDTO> 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<PCNewMidHotRightDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCNewMidHotRightDTO> getPcNewMidHotRightList() {
// 从redis中获取 新品馆 热卖榜右侧数据
List<PCNewMidHotRightDTO> newMidHotRightList;
List<PCNewMidHotRightDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_MID_HOT_RIGHT);
if (CollectionUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
final List<Long> storeProdIdList = oneMonthList.stream()
.filter(x -> StringUtils.isNotBlank(x.getProdIdStr())).map(x -> Long.parseLong(x.getProdIdStr())).distinct().collect(Collectors.toList());
// 档口商品的价格及商品主图map
Map<Long, StoreProdPriceAndMainPicDTO> 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<Long> 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<PCNewBottomBannerDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCNewBottomBannerDTO> getPcNewBottomBannerList() {
// 从redis中获取 新品馆 底部横幅数据
List<PCNewBottomBannerDTO> newBottomBannerList;
List<PCNewBottomBannerDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_NEW_BOTTOM_BANNER);
if (CollectionUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
Map<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<PCNewBottomBannerDTO> 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<AdvertRound> getOneMonthAdvertList(final List<Integer> 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<AdvertRound>()
.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<PCNewMidBrandDTO>
*/
private List<PCNewMidBrandDTO> fillNewMidBrandList(List<AdvertRound> advertRoundList, Map<Long, Store> storeMap,
Map<Long, SysFile> fileMap, List<Long> existStoreIdList, int limitCount) {
List<PCNewMidBrandDTO> 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<PCNewMidHotRightDTO> fillNewMidHotRightList(List<AdvertRound> advertRoundList, Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap,
List<Long> existProdIdList, int limitCount) {
List<PCNewMidHotRightDTO> 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());
}
}

View File

@ -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<PCStoreTopBannerDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCStoreTopBannerDTO> getPcStoreTopBannerList() {
// 从redis中获取 档口馆 顶部横幅及商品数据
List<PCStoreTopBannerDTO> pcStoreTopBannerList;
List<PCStoreTopBannerDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_TOP_BANNER);
if (CollectionUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
Map<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<Long> 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<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap = CollectionUtils.isEmpty(storeProdIdList) ? new ConcurrentHashMap<>()
: this.storeProdMapper.selectPriceAndMainPicList(storeProdIdList).stream().collect(Collectors
.toMap(StoreProdPriceAndMainPicDTO::getStoreProdId, Function.identity()));
if (CollectionUtils.isEmpty(launchingList)) {
List<PCStoreTopBannerDTO> 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<PCStoreMidBannerDTO>
*/
@Override
@Transactional(readOnly = true)
public List<PCStoreMidBannerDTO> getPcStoreMidBannerList() {
// 从redis中获取 档口馆 中间横幅数据
List<PCStoreMidBannerDTO> pcStoreMidBannerList;
List<PCStoreMidBannerDTO> redisList = redisCache.getCacheObject(CacheConstants.PC_ADVERT + CacheConstants.PC_ADVERT_STORE_MID_BANNER);
if (CollectionUtils.isNotEmpty(redisList)) {
return redisList;
}
List<AdvertRound> 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<AdvertRound> 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<AdvertRound> expiredList = oneMonthList.stream().filter(x -> Objects.equals(x.getLaunchStatus(), AdLaunchStatus.EXPIRED.getValue())).collect(Collectors.toList());
Map<Long, SysFile> fileMap = fileMapper.selectList(new LambdaQueryWrapper<SysFile>().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<PCStoreMidBannerDTO> 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<AdvertRound> getOneMonthAdvertList(final List<Integer> 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<AdvertRound>()
.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<Long, SysFile> fileMap, Map<Long, StoreProdPriceAndMainPicDTO> prodPriceAndMainPicMap) {
List<PCStoreTopBannerDTO.PCSTBProdDTO> 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() : "");
}
}