package com.upchina.common.service; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.google.common.collect.Table; import com.hazelcast.core.HazelcastInstance; import com.upchina.common.config.cache.CacheKey; import com.upchina.common.constant.AdvertPosition; import com.upchina.common.constant.ProductType; import com.upchina.common.entity.Advert; import com.upchina.common.handler.BizException; import com.upchina.common.mapper.AdvertMapper; import com.upchina.common.query.ListAdvertQuery; import com.upchina.common.query.OnlyIdQuery; import com.upchina.common.query.SaveAdvertQuery; import com.upchina.common.query.UpdateAdvertQuery; import com.upchina.common.result.Pager; import com.upchina.common.result.ResponseStatus; import com.upchina.common.vo.AdvertAppVO; import com.upchina.common.vo.AdvertVO; import com.upchina.common.vo.BackendUserVO; import com.upchina.common.vo.MergeProductInfoVO; import com.upchina.rbac.entity.UserDept; import com.upchina.rbac.service.UserService; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Service public class AdvertService { @Resource private AdvertMapper advertMapper; @Resource private UserService userService; @Resource private MergeProductService mergeProductService; @Resource private CacheService cacheService; @Resource private HazelcastInstance hazelcastInstance; @Resource private RecommendService recommendService; /** * 推荐位置和对应类型 * 首页(投顾社区首页):所有类型,包括H5 */ // 推荐位置和产品类型关系 private static final Multimap positionProductTypeMap = HashMultimap.create(); // 产品类型和推荐位置关系 private static final Multimap productTypePositionMap = HashMultimap.create(); private static void putRelation(Integer advertPosition, Collection productTypes) { productTypes.forEach(productType -> { positionProductTypeMap.put(advertPosition, productType); productTypePositionMap.put(productType, advertPosition); }); } static { putRelation(AdvertPosition.HOME_PAGE.value, Arrays.stream(ProductType.values()).map(ProductType::getValue).collect(Collectors.toSet())); } public Pager list(ListAdvertQuery query) { Integer productType = query.getProductType(); Integer productId = query.getProductId(); String name = query.getName(); Integer position = query.getPosition(); Integer createUserId = query.getCreateUserId(); QueryWrapper wrapper = Wrappers.query(); wrapper.eq(productType != null && productType != 0, "product_type", productType) .eq(productId != null && productId != 0, "product_id", productId) .like(StrUtil.isNotEmpty(name), "name", name) .eq(position != null && position != 0, "position", position) .eq(createUserId != null && createUserId != 0, "create_user_id", createUserId) .last("order by weight desc,create_time desc"); Page page = advertMapper.selectPage(query.toPage(), wrapper); Map userMap = userService.getUserMap(); List list = page.getRecords().stream().map(advert -> new AdvertVO(advert, userMap.get(advert.getCreateUserId()))).collect(Collectors.toList()); // 填充非H5类型的产品名称 List filterH5List = list.stream().filter(vo -> !ProductType.H5.value.equals(vo.getProductType())).collect(Collectors.toList()); Table productTable = mergeProductService.queryMergeProductInfo(filterH5List); filterH5List.forEach(vo -> { MergeProductInfoVO productVO = productTable.get(vo.getProductType(), vo.getProductId()); if (productVO != null) { vo.setName(productVO.getProductName()); vo.setSummary(productVO.getSummary()); } }); return new Pager<>(list, page.getTotal()); } @Transactional(rollbackFor = Exception.class) public void save(SaveAdvertQuery query, BackendUserVO backendUserVO) { validateProduct(query); ProductType productType = ProductType.fromValue(query.getProductType()); Advert advert = query.toPO(backendUserVO.getUserId()); try { advertMapper.insert(advert); } catch (DuplicateKeyException e) { throw new BizException(ResponseStatus.ADVERT_DUPLICATE); } this.clearCache(AdvertPosition.fromValue(query.getPosition())); } @Transactional(rollbackFor = Exception.class) public void update(UpdateAdvertQuery query, BackendUserVO backendUserVO) { validateProduct(query); ProductType productType = ProductType.fromValue(query.getProductType()); Advert advert = query.toPO(); int rows; try { rows = advertMapper.updateById(advert); } catch (DuplicateKeyException e) { throw new BizException(ResponseStatus.ADVERT_DUPLICATE); } if (rows == 0) { throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR); } this.clearCache(AdvertPosition.fromValue(query.getPosition())); } @Transactional(rollbackFor = Exception.class) public void delete(OnlyIdQuery query, BackendUserVO backendUserVO) { Advert advert = advertMapper.selectById(query.getId()); if (advert == null) { throw new BizException(ResponseStatus.ID_NOT_EXIST_ERROR); } advertMapper.deleteById(query.getId()); this.clearCache(AdvertPosition.fromValue(advert.getPosition())); ProductType productType = ProductType.fromValue(advert.getProductType()); } public List listForApp(Integer position) { return cacheService.get(CacheKey.ADVERT, CacheKey.AdvertKey.APP_ADVERT_LIST + position, () -> { QueryWrapper wrapper = Wrappers.query(); wrapper.eq("position", position).last("order by weight desc,create_time desc"); List list = advertMapper.selectList(wrapper); return list.stream().map(AdvertAppVO::new).collect(Collectors.toList()); }); } public void clearCache(AdvertPosition position) { Map cacheMap = hazelcastInstance.getMap(CacheKey.ADVERT); cacheMap.remove(CacheKey.AdvertKey.APP_ADVERT_LIST + position.value); } public void clearCache(ProductType productType) { Map cacheMap = hazelcastInstance.getMap(CacheKey.ADVERT); Collection positionSet = productTypePositionMap.get(productType.value); positionSet.forEach(position -> cacheMap.remove(CacheKey.AdvertKey.APP_ADVERT_LIST + position)); } private void validateProduct(SaveAdvertQuery query) { Integer position = query.getPosition(); Integer productType = query.getProductType(); Collection productTypeSet = positionProductTypeMap.get(position); if (!productTypeSet.contains(productType)) { throw new BizException(ResponseStatus.PARM_ERROR, "产品类型不符合推荐位置要求"); } if (ProductType.H5.value.equals(productType)) { if (StrUtil.isEmpty(query.getName())) { throw new BizException(ResponseStatus.PARM_ERROR, "H5链接名称不能为空"); } if (StrUtil.isEmpty(query.getUrl())) { throw new BizException(ResponseStatus.PARM_ERROR, "H5链接URL不能为空"); } } else { if (query.getProductId() == null) { throw new BizException(ResponseStatus.PARM_ERROR, "非H5类型,产品ID不能为空"); } } recommendService.validateProduct(query); } public void validateRecommendExist(ProductType productType, Integer productId) { // TODO 校验关联数据(投顾\观点\观点包\锦囊\三方产品\套餐产品) QueryWrapper advertWrapper = Wrappers.query(); advertWrapper.eq("product_type", productType.value) .eq("product_id", productId); Long advertCount = advertMapper.selectCount(advertWrapper); if (advertCount > 0) throw new BizException(ResponseStatus.ADVERT_CAN_NOT_SOLD_OUT); } }