master:返回各个位置营销推广数据;

pull/1121/head
liujiang 2025-05-23 23:30:40 +08:00
parent b07dff2f30
commit 47e4d57d58
16 changed files with 681 additions and 39 deletions

View File

@ -16,6 +16,8 @@ import com.ruoyi.web.controller.xkt.vo.advertRound.pc.store.PCStoreMidBannerVO;
import com.ruoyi.web.controller.xkt.vo.advertRound.pc.store.PCStoreTopBannerVO;
import com.ruoyi.web.controller.xkt.vo.advertRound.picSearch.PicSearchAdvertVO;
import com.ruoyi.web.controller.xkt.website.IndexSearchVO;
import com.ruoyi.xkt.dto.advertRound.app.index.*;
import com.ruoyi.xkt.dto.advertRound.pc.index.PCIndexRecommendDTO;
import com.ruoyi.xkt.dto.es.ESProductDTO;
import com.ruoyi.xkt.dto.website.IndexSearchDTO;
import com.ruoyi.xkt.service.IWebsiteService;
@ -52,9 +54,44 @@ public class WebsiteController extends XktBaseController {
return R.ok(websiteService.search(BeanUtil.toBean(searchVO, IndexSearchDTO.class)));
}
// PC 首页 新品馆 列表
// TODO APP 首页 热卖精选、人气爆品、新品榜 PC 首页 新品馆 列表
// TODO APP 首页 热卖精选、人气爆品、新品榜 PC 首页 新品馆 列表
// TODO APP 首页 热卖精选、人气爆品、新品榜 PC 首页 新品馆 列表
@ApiOperation(value = "PC 首页 为你推荐", httpMethod = "POST", response = R.class)
@PostMapping("/pc/index/recommend")
public R<Page<PCIndexRecommendDTO>> pcIndexRecommendPage(@Validated @RequestBody IndexSearchVO searchVO) throws IOException {
return R.ok(websiteService.pcIndexRecommendPage(BeanUtil.toBean(searchVO, IndexSearchDTO.class)));
}
@ApiOperation(value = "APP 首页 精选热卖列表", httpMethod = "POST", response = R.class)
@PostMapping("/app/index/hot-sale")
public R<Page<APPIndexHotSaleDTO>> appIndexHotSalePage(@Validated @RequestBody IndexSearchVO searchVO) throws IOException {
return R.ok(websiteService.appIndexHotSalePage(BeanUtil.toBean(searchVO, IndexSearchDTO.class)));
}
@ApiOperation(value = "APP 首页 人气爆品", httpMethod = "POST", response = R.class)
@PostMapping("/app/index/popular-sale")
public R<Page<APPIndexPopularSaleDTO>> appIndexPopularSalePage(@Validated @RequestBody IndexSearchVO searchVO) throws IOException {
return R.ok(websiteService.appIndexPopularSalePage(BeanUtil.toBean(searchVO, IndexSearchDTO.class)));
}
@ApiOperation(value = "APP 首页 新品榜", httpMethod = "POST", response = R.class)
@PostMapping("/app/index/new-prod")
public R<Page<APPIndexNewProdDTO>> appIndexNewProdPage(@Validated @RequestBody IndexSearchVO searchVO) throws IOException {
return R.ok(websiteService.appIndexNewProdPage(BeanUtil.toBean(searchVO, IndexSearchDTO.class)));
}
@ApiOperation(value = "APP 搜索", httpMethod = "POST", response = R.class)
@PostMapping("/app/index/search")
public R<Page<APPSearchDTO>> appSearchPage(@Validated @RequestBody IndexSearchVO searchVO) throws IOException {
return R.ok(websiteService.appSearchPage(BeanUtil.toBean(searchVO, IndexSearchDTO.class)));
}
@ApiOperation(value = "PC 首页 顶部横向轮播图", httpMethod = "GET", response = R.class)

View File

@ -2,11 +2,10 @@ package com.ruoyi.common.constant;
/**
* key
*
*
* @author ruoyi
*/
public class CacheConstants
{
public class CacheConstants {
/**
* redis key
*/
@ -132,7 +131,7 @@ public class CacheConstants
*/
public static final String PC_ADVERT_STORE_MID_BANNER = "pc_store_mid_banner";
/**
*
*
*/
public static final String PIC_SEARCH = "pic_search";
/**
@ -161,6 +160,22 @@ public class CacheConstants
* APP
*/
public static final String APP_INDEX_HOT_SALE_RIGHT_FIX = "app_index_hot_sale_right_fix";
/**
* APP 广
*/
public static final String APP_INDEX_HOT_SALE_ADVERT = "app_index_hot_sale_advert";
/**
* APP 广
*/
public static final String APP_INDEX_POPULAR_SALE_ADVERT = "app_index_popular_sale_advert";
/**
* APP
*/
public static final String APP_INDEX_NEW_PROD = "app_index_new_prod";
/**
* APP
*/
public static final String APP_SEARCH = "app_search";
/**
* APP
*/
@ -169,7 +184,6 @@ public class CacheConstants
* APP
*/
public static final String APP_OWN_GUESS_LIKE = "app_own_guess_like";
/**
*
*/

View File

@ -2,7 +2,10 @@ package com.ruoyi.common.constant;
import io.jsonwebtoken.Claims;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
/**
*
@ -245,5 +248,9 @@ public class Constants
*
*/
public static final int IMG_SEARCH_MAX_PAGE_NUM = 100;
/**
* APP 广 广 广广 205广 3 7 11 15 19
*/
public static final Set<Integer> insertPositions = new HashSet<>(Arrays.asList(2, 6, 10, 14, 18));
}

View File

@ -17,8 +17,8 @@ import java.util.List;
*
* @author ruoyi
*/
@NoArgsConstructor
@AllArgsConstructor
//@NoArgsConstructor
//@AllArgsConstructor
@Data
@Accessors(chain = true)
public class Page<T> implements Serializable {
@ -47,6 +47,17 @@ public class Page<T> implements Serializable {
*/
private List<T> list;
public Page() {
}
public Page(long pageNum, long pageSize, long pages, long total, List<T> list) {
this.pageNum = pageNum;
this.pageSize = pageSize;
this.pages = pages;
this.total = total;
this.list = list;
}
public static <T> Page<T> convert(PageInfo<?> pageInfo) {
return BeanUtil.toBean(pageInfo, Page.class);
}

View File

@ -960,7 +960,7 @@ public class XktTask {
// 构建部分文档更新请求
list.add(new BulkOperation.Builder().update(u -> u
.action(a -> a.doc(new HashMap<String, Object>() {{
put("tags", tags.stream().map(DailyProdTag::getTag).collect(Collectors.toList()));
put("tags", tags.stream().sorted(Comparator.comparing(x -> x.getType())).map(DailyProdTag::getTag).collect(Collectors.toList()));
}}))
.id(String.valueOf(storeProdId))
.index(Constants.ES_IDX_PRODUCT_INFO))

View File

@ -0,0 +1,40 @@
package com.ruoyi.xkt.dto.advertRound.app.index;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("APP首页热卖精选")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class APPIndexHotSaleDTO {
@ApiModelProperty(value = "档口ID")
private String storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "档口商品ID")
private String storeProdId;
@ApiModelProperty(value = "货号")
private String prodArtNum;
@ApiModelProperty(value = "主图")
private String mainPic;
@ApiModelProperty(value = "单价")
private String prodPrice;
@ApiModelProperty(value = "是否广告")
private Boolean advert;
@ApiModelProperty(value = "标签")
private List<String> tags;
}

View File

@ -0,0 +1,37 @@
package com.ruoyi.xkt.dto.advertRound.app.index;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("APP精选热卖分页")
@Data
@Accessors(chain = true)
public class APPIndexHotSalePageDTO {
@ApiModelProperty(value = "档口ID")
private String storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "档口商品ID")
private String storeProdId;
@ApiModelProperty(value = "货号")
private String prodArtNum;
@ApiModelProperty(value = "主图")
private String mainPic;
@ApiModelProperty(value = "单价")
private String prodPrice;
@ApiModelProperty(value = "是否广告")
private Boolean advert;
@ApiModelProperty(value = "标签")
private List<String> tags;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.xkt.dto.advertRound.app.index;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("APP首页新品榜列表")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class APPIndexNewProdDTO {
@ApiModelProperty(value = "档口ID")
private String storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "档口商品ID")
private String storeProdId;
@ApiModelProperty(value = "货号")
private String prodArtNum;
@ApiModelProperty(value = "主图")
private String mainPic;
@ApiModelProperty(value = "单价")
private String prodPrice;
@ApiModelProperty(value = "是否广告")
private Boolean advert;
@ApiModelProperty(value = "标签")
private List<String> tags;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.xkt.dto.advertRound.app.index;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("APP首页人气爆品列表")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class APPIndexPopularSaleDTO {
@ApiModelProperty(value = "档口ID")
private String storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "档口商品ID")
private String storeProdId;
@ApiModelProperty(value = "货号")
private String prodArtNum;
@ApiModelProperty(value = "主图")
private String mainPic;
@ApiModelProperty(value = "单价")
private String prodPrice;
@ApiModelProperty(value = "是否广告")
private Boolean advert;
@ApiModelProperty(value = "标签")
private List<String> tags;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.xkt.dto.advertRound.app.index;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("APP 搜索 列表")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class APPSearchDTO {
@ApiModelProperty(value = "档口ID")
private String storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "档口商品ID")
private String storeProdId;
@ApiModelProperty(value = "货号")
private String prodArtNum;
@ApiModelProperty(value = "主图")
private String mainPic;
@ApiModelProperty(value = "单价")
private String prodPrice;
@ApiModelProperty(value = "是否广告")
private Boolean advert;
@ApiModelProperty(value = "标签")
private List<String> tags;
}

View File

@ -0,0 +1,39 @@
package com.ruoyi.xkt.dto.advertRound.pc.index;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("PC首页为你推荐")
@Data
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PCIndexRecommendDTO {
@ApiModelProperty(value = "档口ID")
private String storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "档口商品ID")
private String storeProdId;
@ApiModelProperty(value = "货号")
private String prodArtNum;
@ApiModelProperty(value = "主图")
private String mainPic;
@ApiModelProperty(value = "单价")
private String prodPrice;
@ApiModelProperty(value = "是否广告")
private Boolean advert;
@ApiModelProperty(value = "标签")
private List<String> tags;
}

View File

@ -0,0 +1,38 @@
package com.ruoyi.xkt.dto.storeProduct;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.List;
/**
* @author liujiang
* @version v1.0
* @date 2025/3/27 15:12
*/
@ApiModel("档口商品的价格及商品主图")
@Data
public class StoreProdPriceAndMainPicAndTagDTO {
@ApiModelProperty(value = "档口商品ID")
private Long storeProdId;
@ApiModelProperty(value = "档口ID")
private Long storeId;
@ApiModelProperty(value = "档口名称")
private String storeName;
@ApiModelProperty(value = "商品标签字符串")
private String tagStr;
@ApiModelProperty(value = "商品标签")
private List<String> tags;
@ApiModelProperty(value = "商品货号")
private String prodArtNum;
@ApiModelProperty(value = "档口商品定价")
private BigDecimal minPrice;
@ApiModelProperty(value = "档口商品主图")
private String mainPicUrl;
@ApiModelProperty(value = "商品标题")
private String prodTitle;
}

View File

@ -72,5 +72,12 @@ public interface StoreProductMapper extends BaseMapper<StoreProduct> {
*/
List<StoreProdPriceAndMainPicDTO> selectPriceAndMainPicList(@Param("storeProdIdList") List<Long> storeProdIdList);
/**
*
* @param storeProdIdList ID
* @return List<StoreProdPriceAndMainPicAndTagDTO>
*/
List<StoreProdPriceAndMainPicAndTagDTO> selectPriceAndMainPicAndTagList(@Param("storeProdIdList") List<Long> storeProdIdList);
}

View File

@ -2,9 +2,7 @@ package com.ruoyi.xkt.service;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.xkt.dto.advertRound.app.category.APPCateDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.APPIndexHotSaleRightFixDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.APPIndexMidBrandDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.APPIndexTopBannerDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.*;
import com.ruoyi.xkt.dto.advertRound.app.own.APPOwnGuessLikeDTO;
import com.ruoyi.xkt.dto.advertRound.pc.PCDownloadDTO;
import com.ruoyi.xkt.dto.advertRound.pc.PCUserCenterDTO;
@ -20,7 +18,7 @@ import java.io.IOException;
import java.util.List;
/**
* Service
* 广
*
* @author ruoyi
* @date 2025-03-26
@ -201,4 +199,45 @@ public interface IWebsiteService {
* @return List<APPOwnGuessLikeDTO>
*/
List<APPOwnGuessLikeDTO> getAppOwnGuessLikeList();
/**
* APP
*
* @param searchDTO
* @return List<APPIndexHotSalePageDTO>
*/
Page<APPIndexHotSaleDTO> appIndexHotSalePage(IndexSearchDTO searchDTO) throws IOException;
/**
* APP
*
* @param searchDTO
* @return Page<APPIndexPopularSaleDTO>
*/
Page<APPIndexPopularSaleDTO> appIndexPopularSalePage(IndexSearchDTO searchDTO) throws IOException;
/**
* APP
*
* @param searchDTO
* @return Page<APPIndexNewProdDTO>
*/
Page<APPIndexNewProdDTO> appIndexNewProdPage(IndexSearchDTO searchDTO) throws IOException;
/**
* APP
*
* @param searchDTO
* @return Page<APPSearchDTO>
*/
Page<APPSearchDTO> appSearchPage(IndexSearchDTO searchDTO) throws IOException;
/**
* PC
*
* @param searchDTO
* @return List<PCIndexRecommendProdDTO>
*/
Page<PCIndexRecommendDTO> pcIndexRecommendPage(IndexSearchDTO searchDTO);
}

View File

@ -1,11 +1,11 @@
package com.ruoyi.xkt.service.impl;
import cn.hutool.core.bean.BeanUtil;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.*;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.page.Page;
@ -15,9 +15,7 @@ import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.framework.es.EsClientWrapper;
import com.ruoyi.xkt.domain.*;
import com.ruoyi.xkt.dto.advertRound.app.category.APPCateDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.APPIndexHotSaleRightFixDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.APPIndexMidBrandDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.APPIndexTopBannerDTO;
import com.ruoyi.xkt.dto.advertRound.app.index.*;
import com.ruoyi.xkt.dto.advertRound.app.own.APPOwnGuessLikeDTO;
import com.ruoyi.xkt.dto.advertRound.pc.PCDownloadDTO;
import com.ruoyi.xkt.dto.advertRound.pc.PCUserCenterDTO;
@ -28,6 +26,7 @@ import com.ruoyi.xkt.dto.advertRound.pc.store.PCStoreTopBannerDTO;
import com.ruoyi.xkt.dto.advertRound.picSearch.PicSearchAdvertDTO;
import com.ruoyi.xkt.dto.dailySale.CateSaleRankDTO;
import com.ruoyi.xkt.dto.es.ESProductDTO;
import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicAndTagDTO;
import com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicDTO;
import com.ruoyi.xkt.dto.storeProductFile.StoreProdFileResDTO;
import com.ruoyi.xkt.dto.website.IndexSearchDTO;
@ -74,6 +73,247 @@ public class WebsiteServiceImpl implements IWebsiteService {
final StoreMapper storeMapper;
final StoreProductStatisticsMapper prodStatsMapper;
/**
* APP
*
* @param searchDTO
* @return List<APPIndexHotSalePageDTO>
*/
@Override
@Transactional(readOnly = true)
public Page<APPIndexHotSaleDTO> appIndexHotSalePage(IndexSearchDTO searchDTO) throws IOException {
Page<ESProductDTO> page = this.search(searchDTO);
// 筛选出真实的数据
List<APPIndexHotSaleDTO> realDataList = page.getList().stream()
.map(esProduct -> BeanUtil.toBean(esProduct, APPIndexHotSaleDTO.class).setAdvert(Boolean.FALSE)).collect(Collectors.toList());
// APP 只有第一页 有数据 其它页暂时没有广告
if (searchDTO.getPageNum() > 1) {
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
// 从redis中获取广告
List<APPIndexHotSaleDTO> redisList = this.redisCache.getCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_HOT_SALE_ADVERT);
if (CollectionUtils.isNotEmpty(redisList)) {
// 添加广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, redisList, Constants.insertPositions));
} else {
// 从数据库查首页精选热卖推广(精准搜索是否存在推广,不存在从已过期的数据中拉数据来凑数)
List<AdvertRound> advertRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.eq(AdvertRound::getTypeId, AdType.APP_HOME_HOT_RECOMMEND_PROD.getValue())
.eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue()));
if (CollectionUtils.isNotEmpty(advertRoundList)) {
List<StoreProdPriceAndMainPicAndTagDTO> attrList = storeProdMapper.selectPriceAndMainPicAndTagList(advertRoundList.stream()
.map(x -> x.getProdIdStr()).map(Long::parseLong).collect(Collectors.toList()));
attrList = attrList.stream().peek(x -> x.setTags(StringUtils.isNotBlank(x.getTagStr()) ? Arrays.asList(x.getTagStr().split(",")) : null)).collect(Collectors.toList());
Map<Long, StoreProdPriceAndMainPicAndTagDTO> attrMap = attrList.stream().collect(Collectors.toMap(StoreProdPriceAndMainPicAndTagDTO::getStoreProdId, x -> x));
List<APPIndexHotSaleDTO> hotSaleList = advertRoundList.stream().map(x -> {
StoreProdPriceAndMainPicAndTagDTO attrDto = attrMap.get(Long.parseLong(x.getProdIdStr()));
return new APPIndexHotSaleDTO().setAdvert(Boolean.TRUE).setStoreId(x.getStoreId().toString())
.setStoreProdId(x.getProdIdStr()).setTags(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getTags() : null)
.setStoreName(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getStoreName() : "")
.setProdPrice(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMinPrice().toString() : null)
.setProdArtNum(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getProdArtNum() : "")
.setMainPic(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMainPicUrl() : "");
}).collect(Collectors.toList());
// 放到redis中 有效期1天
this.redisCache.setCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_HOT_SALE_ADVERT, hotSaleList, 1, TimeUnit.DAYS);
// 添加了广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, hotSaleList, Constants.insertPositions));
}
}
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
/**
* APP
*
* @param searchDTO
* @return Page<APPIndexPopularSaleDTO>
*/
@Override
@Transactional(readOnly = true)
public Page<APPIndexPopularSaleDTO> appIndexPopularSalePage(IndexSearchDTO searchDTO) throws IOException {
Page<ESProductDTO> page = this.search(searchDTO);
// 筛选出真实的数据
List<APPIndexPopularSaleDTO> realDataList = page.getList().stream()
.map(esProduct -> BeanUtil.toBean(esProduct, APPIndexPopularSaleDTO.class).setAdvert(Boolean.FALSE)).collect(Collectors.toList());
// APP 只有第一页 有数据 其它页暂时没有广告
if (searchDTO.getPageNum() > 1) {
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
// 从redis中获取数据
List<APPIndexPopularSaleDTO> redisList = this.redisCache.getCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_POPULAR_SALE_ADVERT);
if (CollectionUtils.isNotEmpty(redisList)) {
// 添加广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, redisList, Constants.insertPositions));
} else {
// 从数据库查首页 人气爆品 推广(精准搜索是否存在推广,不存在从已过期的数据中拉数据来凑数)
List<AdvertRound> advertRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.eq(AdvertRound::getTypeId, AdType.APP_HOME_POP_RECOMMEND_PROD.getValue())
.eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue()));
if (CollectionUtils.isNotEmpty(advertRoundList)) {
List<StoreProdPriceAndMainPicAndTagDTO> attrList = storeProdMapper.selectPriceAndMainPicAndTagList(advertRoundList.stream()
.map(x -> x.getProdIdStr()).map(Long::parseLong).collect(Collectors.toList()));
attrList = attrList.stream().peek(x -> x.setTags(StringUtils.isNotBlank(x.getTagStr()) ? Arrays.asList(x.getTagStr().split(",")) : null)).collect(Collectors.toList());
Map<Long, StoreProdPriceAndMainPicAndTagDTO> attrMap = attrList.stream().collect(Collectors.toMap(StoreProdPriceAndMainPicAndTagDTO::getStoreProdId, x -> x));
List<APPIndexPopularSaleDTO> popularSaleList = advertRoundList.stream().map(x -> {
StoreProdPriceAndMainPicAndTagDTO attrDto = attrMap.get(Long.parseLong(x.getProdIdStr()));
return new APPIndexPopularSaleDTO().setAdvert(Boolean.TRUE).setStoreId(x.getStoreId().toString())
.setStoreProdId(x.getProdIdStr()).setTags(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getTags() : null)
.setStoreName(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getStoreName() : "")
.setProdPrice(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMinPrice().toString() : null)
.setProdArtNum(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getProdArtNum() : "")
.setMainPic(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMainPicUrl() : "");
}).collect(Collectors.toList());
// 放到redis中 有效期1天
this.redisCache.setCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_POPULAR_SALE_ADVERT, popularSaleList, 1, TimeUnit.DAYS);
// 添加了广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, popularSaleList, Constants.insertPositions));
}
}
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
/**
* APP
*
* @param searchDTO
* @return Page<APPIndexNewProdDTO>
*/
@Override
@Transactional(readOnly = true)
public Page<APPIndexNewProdDTO> appIndexNewProdPage(IndexSearchDTO searchDTO) throws IOException {
Page<ESProductDTO> page = this.search(searchDTO);
// 筛选出真实的数据
List<APPIndexNewProdDTO> realDataList = page.getList().stream()
.map(esProduct -> BeanUtil.toBean(esProduct, APPIndexNewProdDTO.class).setAdvert(Boolean.FALSE)).collect(Collectors.toList());
// APP 只有第一页 有数据 其它页暂时没有广告
if (searchDTO.getPageNum() > 1) {
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
// 从redis中获取数据
List<APPIndexNewProdDTO> redisList = this.redisCache.getCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_NEW_PROD);
if (CollectionUtils.isNotEmpty(redisList)) {
// 添加广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, redisList, Constants.insertPositions));
} else {
// 从数据库查首页 新品榜 推广(精准搜索是否存在推广,不存在从已过期的数据中拉数据来凑数)
List<AdvertRound> advertRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.eq(AdvertRound::getTypeId, AdType.APP_HOME_NEW_PROD_RECOMMEND_PROD.getValue())
.eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue()));
if (CollectionUtils.isNotEmpty(advertRoundList)) {
List<StoreProdPriceAndMainPicAndTagDTO> attrList = storeProdMapper.selectPriceAndMainPicAndTagList(advertRoundList.stream()
.map(x -> x.getProdIdStr()).map(Long::parseLong).collect(Collectors.toList()));
attrList = attrList.stream().peek(x -> x.setTags(StringUtils.isNotBlank(x.getTagStr()) ? Arrays.asList(x.getTagStr().split(",")) : null)).collect(Collectors.toList());
Map<Long, StoreProdPriceAndMainPicAndTagDTO> attrMap = attrList.stream().collect(Collectors.toMap(StoreProdPriceAndMainPicAndTagDTO::getStoreProdId, x -> x));
List<APPIndexNewProdDTO> newProdList = advertRoundList.stream().map(x -> {
StoreProdPriceAndMainPicAndTagDTO attrDto = attrMap.get(Long.parseLong(x.getProdIdStr()));
return new APPIndexNewProdDTO().setAdvert(Boolean.TRUE).setStoreId(x.getStoreId().toString())
.setStoreProdId(x.getProdIdStr()).setTags(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getTags() : null)
.setStoreName(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getStoreName() : "")
.setProdPrice(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMinPrice().toString() : null)
.setProdArtNum(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getProdArtNum() : "")
.setMainPic(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMainPicUrl() : "");
}).collect(Collectors.toList());
// 放到redis中 有效期1天
this.redisCache.setCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_INDEX_NEW_PROD, newProdList, 1, TimeUnit.DAYS);
// 添加了广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, newProdList, Constants.insertPositions));
}
}
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
/**
* APP
*
* @param searchDTO
* @return Page<APPSearchDTO>
*/
@Override
@Transactional(readOnly = true)
public Page<APPSearchDTO> appSearchPage(IndexSearchDTO searchDTO) throws IOException {
Page<ESProductDTO> page = this.search(searchDTO);
// 筛选出真实的数据
List<APPSearchDTO> realDataList = page.getList().stream()
.map(esProduct -> BeanUtil.toBean(esProduct, APPSearchDTO.class).setAdvert(Boolean.FALSE)).collect(Collectors.toList());
// APP 只有第一页 有数据 其它页暂时没有广告
if (searchDTO.getPageNum() > 1) {
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
// 从redis中获取数据
List<APPSearchDTO> redisList = this.redisCache.getCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_SEARCH);
if (CollectionUtils.isNotEmpty(redisList)) {
// 添加广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, redisList, Constants.insertPositions));
} else {
// 从数据库查首页 新品榜 推广(精准搜索是否存在推广,不存在从已过期的数据中拉数据来凑数)
List<AdvertRound> advertRoundList = this.advertRoundMapper.selectList(new LambdaQueryWrapper<AdvertRound>()
.isNotNull(AdvertRound::getStoreId).eq(AdvertRound::getDelFlag, Constants.UNDELETED)
.eq(AdvertRound::getTypeId, AdType.APP_SEARCH_RESULT.getValue())
.eq(AdvertRound::getLaunchStatus, AdLaunchStatus.LAUNCHING.getValue()));
if (CollectionUtils.isNotEmpty(advertRoundList)) {
List<StoreProdPriceAndMainPicAndTagDTO> attrList = storeProdMapper.selectPriceAndMainPicAndTagList(advertRoundList.stream()
.map(x -> x.getProdIdStr()).map(Long::parseLong).collect(Collectors.toList()));
attrList = attrList.stream().peek(x -> x.setTags(StringUtils.isNotBlank(x.getTagStr()) ? Arrays.asList(x.getTagStr().split(",")) : null)).collect(Collectors.toList());
Map<Long, StoreProdPriceAndMainPicAndTagDTO> attrMap = attrList.stream().collect(Collectors.toMap(StoreProdPriceAndMainPicAndTagDTO::getStoreProdId, x -> x));
List<APPSearchDTO> newProdList = advertRoundList.stream().map(x -> {
StoreProdPriceAndMainPicAndTagDTO attrDto = attrMap.get(Long.parseLong(x.getProdIdStr()));
return new APPSearchDTO().setAdvert(Boolean.TRUE).setStoreId(x.getStoreId().toString())
.setStoreProdId(x.getProdIdStr()).setTags(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getTags() : null)
.setStoreName(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getStoreName() : "")
.setProdPrice(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMinPrice().toString() : null)
.setProdArtNum(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getProdArtNum() : "")
.setMainPic(ObjectUtils.isNotEmpty(attrDto) ? attrDto.getMainPicUrl() : "");
}).collect(Collectors.toList());
// 放到redis中 有效期1天
this.redisCache.setCacheObject(CacheConstants.APP_ADVERT + CacheConstants.APP_SEARCH, newProdList, 1, TimeUnit.DAYS);
// 添加了广告的数据
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), insertAdvertsIntoList(realDataList, newProdList, Constants.insertPositions));
}
}
return new Page<>(page.getPageNum(), page.getPageSize(), page.getPages(), page.getTotal(), realDataList);
}
/**
* PC
*
* @param searchDTO
* @return List<PCIndexRecommendProdDTO>
*/
@Override
@Transactional(readOnly = true)
public Page<PCIndexRecommendDTO> pcIndexRecommendPage(IndexSearchDTO searchDTO) {
return null;
}
/**
* 广
*
* @param dataList
* @param adverts 广
* @param positions 广
* @param <T>
* @return
*/
public static <T> List<T> insertAdvertsIntoList(List<T> dataList, List<T> adverts, Set<Integer> positions) {
List<T> mergedList = new ArrayList<>();
int dataIndex = 0;
int advertIndex = 0;
for (int i = 0; i < dataList.size() + positions.size(); i++) {
if (positions.contains(i) && advertIndex < adverts.size()) {
mergedList.add(adverts.get(advertIndex++));
} else if (dataIndex < dataList.size()) {
mergedList.add(dataList.get(dataIndex++));
}
}
return mergedList;
}
/**
*
*
@ -82,19 +322,6 @@ public class WebsiteServiceImpl implements IWebsiteService {
@Override
@Transactional(readOnly = true)
public Page<ESProductDTO> search(IndexSearchDTO searchDTO) throws IOException {
/*// 查询索引
GetIndexResponse res = esClientWrapper.getEsClient().indices().get(request -> request.index(indexName));
System.err.println(res);
System.err.println(res.result());
Set<String> all = esClientWrapper.getEsClient().indices().get(req -> req.index("*")).result().keySet();
System.out.println("all = " + all);
GetResponse<ESProductInfo> response = esClientWrapper.getEsClient().get(g -> g.index(indexName).id("1"), ESProductInfo.class);
System.err.println(response);*/
// 分页查询
// 构建 bool 查询
BoolQuery.Builder boolQuery = new BoolQuery.Builder();
// 添加 price 范围查询
@ -161,7 +388,6 @@ public class WebsiteServiceImpl implements IWebsiteService {
.build();
boolQuery.filter(f -> f.terms(t -> t.field("season.keyword").terms(termsQueryField)));
}
// 如果是按照时间过滤,则表明是“新品”,则限制 时间范围 20天前到现在
if (Objects.equals(searchDTO.getSort(), "createTime")) {
// 当前时间
@ -174,20 +400,16 @@ public class WebsiteServiceImpl implements IWebsiteService {
builder.date(DateRangeQuery.of(d -> d.field("createTime").gte(agoStr).lte(nowStr)));
boolQuery.filter(builder.build()._toQuery());
}
// 构建最终的查询
Query query = new Query.Builder().bool(boolQuery.build()).build();
// 执行搜索
SearchResponse<ESProductDTO> resList = esClientWrapper.getEsClient().search(s -> s.index(Constants.ES_IDX_PRODUCT_INFO)
.query(query).from(searchDTO.getPageNum() - 1).size(searchDTO.getPageSize())
.query(query).from((searchDTO.getPageNum() - 1) * searchDTO.getPageSize()).size(searchDTO.getPageSize())
.sort(sort -> sort.field(f -> f.field(searchDTO.getSort()).order(SortOrder.Desc))),
ESProductDTO.class);
System.err.println(resList);
return CollectionUtils.isEmpty(resList.hits().hits()) ? Page.empty(searchDTO.getPageSize(), searchDTO.getPageNum())
: Page.convert(new PageInfo<>(resList.hits().hits().stream().map(x -> x.source().setStoreProdId(x.id())).collect(Collectors.toList())));
// : Page.convert(new PageInfo<>(resList.hits().hits().stream().map(Hit::source).collect(Collectors.toList())));
final long total = resList.hits().total().value();
final List<ESProductDTO> esProdList = resList.hits().hits().stream().map(x -> x.source().setStoreProdId(x.id())).collect(Collectors.toList());
return new Page<>(searchDTO.getPageNum(), searchDTO.getPageSize(), total / searchDTO.getPageSize() + 1, total, esProdList);
}
/**
@ -1444,6 +1666,7 @@ public class WebsiteServiceImpl implements IWebsiteService {
}
/**
* PC
*

View File

@ -127,6 +127,39 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sf.file_url
</select>
<select id="selectPriceAndMainPicAndTagList" resultType="com.ruoyi.xkt.dto.storeProduct.StoreProdPriceAndMainPicAndTagDTO">
SELECT
sp.id AS storeProdId,
sp.prod_art_num AS prodArtNum,
sf.file_url AS mainPicUrl,
sp.prod_title,
MIN( spcp.price ) AS minPrice,
sp.store_id,
s.store_name,
GROUP_CONCAT(DISTINCT dpt.tag ORDER BY dpt.type ASC) AS tagStr
FROM
store_product sp
JOIN store_product_color_price spcp ON sp.id = spcp.store_prod_id
JOIN store_product_file spf ON sp.id = spf.store_prod_id
LEFT JOIN sys_file sf ON spf.file_id = sf.id
JOIN store s ON sp.store_id = s.id
LEFT JOIN daily_prod_tag dpt ON sp.id = dpt.store_prod_id
AND dpt.del_flag = 0
AND sp.id IN
<foreach item="id" collection="storeProdIdList" open="(" separator="," close=")">
#{id}
</foreach>
WHERE
sp.del_flag = 0
AND spf.file_type = 1
AND spf.order_num = 1
GROUP BY
sp.id,
sf.file_url
</select>