package com.pcloud.book.group.biz.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import com.alibaba.fastjson.JSONObject;
import com.pcloud.analysisengine.browse.dto.GroupBrowseStatisticVO;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.appcenter.app.dto.AppRaysDTO;
import com.pcloud.appcenter.app.dto.AppTypeDto;
import com.pcloud.appcenter.assist.dto.AssistTempletDTO;
import com.pcloud.appcenter.base.dto.AppPriceCacheDTO;
import com.pcloud.appcenter.cache.service.AppPriceCacheService;
import com.pcloud.audioapp.audioLesson.service.AudioLessonService;
import com.pcloud.book.applet.biz.AppletGroupSearchRecordBiz;
import com.pcloud.book.applet.biz.AppletRecordBiz;
import com.pcloud.book.applet.biz.AppletUserBookcaseBiz;
import com.pcloud.book.applet.biz.ServeCollectBiz;
import com.pcloud.book.applet.dto.AppletTaskDTO;
import com.pcloud.book.applet.entity.AppletGroupSearchRecord;
import com.pcloud.book.applet.entity.AppletRecord;
import com.pcloud.book.applet.entity.AppletUserBookcase;
import com.pcloud.book.applet.entity.ServeCollect;
import com.pcloud.book.applet.enums.AppletRecordTypeEnum;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookBiz;
import com.pcloud.book.book.constant.BookConstant;
import com.pcloud.book.book.dao.BookAdviserDao;
import com.pcloud.book.book.dao.BookDao;
import com.pcloud.book.book.dao.BookLabelDao;
import com.pcloud.book.book.dao.BookRaysClassifyDao;
import com.pcloud.book.book.dto.BookAdviserDto;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.entity.Book;
import com.pcloud.book.book.entity.BookLabel;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.book.book.vo.SearchBookVO;
import com.pcloud.book.consumer.analysisengine.BrowseRecordConsr;
import com.pcloud.book.consumer.app.AppConsr;
import com.pcloud.book.consumer.app.AssistTempletConsr;
import com.pcloud.book.consumer.channel.QrcodeSceneConsr;
import com.pcloud.book.consumer.common.ExportConsr;
import com.pcloud.book.consumer.content.ResourceConsr;
import com.pcloud.book.consumer.exercisebook.ExerciseBookConsr;
import com.pcloud.book.consumer.message.MessageConsr;
import com.pcloud.book.consumer.raystask.AdviserTaskConsr;
import com.pcloud.book.consumer.raystask.MainLineConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
import com.pcloud.book.consumer.settlement.BookConsr;
import com.pcloud.book.consumer.settlement.SettlementConsr;
import com.pcloud.book.consumer.trade.TradeConsr;
import com.pcloud.book.consumer.user.AdviserConsr;
import com.pcloud.book.consumer.user.AgentConsr;
import com.pcloud.book.consumer.user.ChannelConsr;
import com.pcloud.book.consumer.wechat.WechatConsr;
import com.pcloud.book.consumer.wechatgroup.WechatGroupConsr;
import com.pcloud.book.consumer.wodapp.WordappConsr;
import com.pcloud.book.group.biz.BookGroupAppBiz;
import com.pcloud.book.group.biz.BookGroupBiz;
import com.pcloud.book.group.biz.BookGroupClassifyBiz;
import com.pcloud.book.group.biz.GroupMaterialAccountBiz;
import com.pcloud.book.group.biz.GroupQrcodeBiz;
import com.pcloud.book.group.biz.ResourcePageBiz;
import com.pcloud.book.group.constant.BookBusinessConstants;
import com.pcloud.book.group.dao.AppClickRecordDao;
import com.pcloud.book.group.dao.AppTouchRecordDao;
import com.pcloud.book.group.dao.BookAppletSceneDao;
import com.pcloud.book.group.dao.BookGroupAgentRecordDao;
import com.pcloud.book.group.dao.BookGroupAppDao;
import com.pcloud.book.group.dao.BookGroupCipherUserDao;
import com.pcloud.book.group.dao.BookGroupClassifyDao;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dao.BookGroupFriendGuideDao;
import com.pcloud.book.group.dao.BookGroupServeDao;
import com.pcloud.book.group.dao.CopyCipherRecordDao;
import com.pcloud.book.group.dao.GroupQrcodeDao;
import com.pcloud.book.group.dao.GroupQrcodeStyleDao;
import com.pcloud.book.group.dao.JoinGroupCipherDao;
import com.pcloud.book.group.dao.PushBookGroupUpdateDao;
import com.pcloud.book.group.dao.TempletRelevanceDao;
import com.pcloud.book.group.dao.WeixinQrcodeDao;
import com.pcloud.book.group.dao.WeixinQrcodeGenerationDao;
import com.pcloud.book.group.dao.WxUserWechatRelevanceDao;
import com.pcloud.book.group.dao.WxWechatUserCorrelationDao;
import com.pcloud.book.group.dto.AgentStatisticsInfoDTO;
import com.pcloud.book.group.dto.AltAndCountDTO;
import com.pcloud.book.group.dto.AltIdAndNameDTO;
import com.pcloud.book.group.dto.AppStatisticsDTO;
import com.pcloud.book.group.dto.BackgroundGroupQrcodeDTO;
import com.pcloud.book.group.dto.BookAppletSceneDTO;
import com.pcloud.book.group.dto.BookGroup4CatalogDTO;
import com.pcloud.book.group.dto.BookGroupClassifyDTO;
import com.pcloud.book.group.dto.BookGroupCountDTO;
import com.pcloud.book.group.dto.BookGroupCreateDTO;
import com.pcloud.book.group.dto.BookGroupDTO;
import com.pcloud.book.group.dto.BookGroupIdAndCountDTO;
import com.pcloud.book.group.dto.BookGroupKeywordResourceDTO;
import com.pcloud.book.group.dto.BookGroupScanStatisticsRequestDTO;
import com.pcloud.book.group.dto.BookGroupScanStatisticsRespDTO;
import com.pcloud.book.group.dto.BookGroupSceneDTO;
import com.pcloud.book.group.dto.BookGroupServeCountDTO;
import com.pcloud.book.group.dto.BookGroupServeDTO;
import com.pcloud.book.group.dto.BookGroupStatistic4AgentDTO;
import com.pcloud.book.group.dto.BookGroupStatisticDTO;
import com.pcloud.book.group.dto.BookGroupStatisticsDTO;
import com.pcloud.book.group.dto.BookServeDTO;
import com.pcloud.book.group.dto.BookServeQueryDTO;
import com.pcloud.book.group.dto.BookServeResourceDTO;
import com.pcloud.book.group.dto.ChangeQrCodeTypeDto;
import com.pcloud.book.group.dto.ClassifyDTO;
import com.pcloud.book.group.dto.ClassifyKeywordDTO;
import com.pcloud.book.group.dto.ClickClassifyDTO;
import com.pcloud.book.group.dto.CountAndTimeDTO;
import com.pcloud.book.group.dto.DayCountDTO;
import com.pcloud.book.group.dto.ErpBookGroupDTO;
import com.pcloud.book.group.dto.ErpGroupQrcodeDTO;
import com.pcloud.book.group.dto.GroupCipherDTO;
import com.pcloud.book.group.dto.GroupQrcodeDTO;
import com.pcloud.book.group.dto.GroupStoreMyPayDto;
import com.pcloud.book.group.dto.GroupUseDTO;
import com.pcloud.book.group.dto.HotAppDTO;
import com.pcloud.book.group.dto.JoinGroupCipherDTO;
import com.pcloud.book.group.dto.LabelUserCountDTO;
import com.pcloud.book.group.dto.LargeTempletDTO;
import com.pcloud.book.group.dto.OwnAltQrcodeInfoDTO;
import com.pcloud.book.group.dto.PersonalQrcodeDTO;
import com.pcloud.book.group.dto.QrcodeNameAndProIdDTO;
import com.pcloud.book.group.dto.ResourceBrowseParamDto;
import com.pcloud.book.group.dto.SelfBookGroupStDTO;
import com.pcloud.book.group.dto.SelfBookGroupStParamDTO;
import com.pcloud.book.group.dto.SelfRobotBookGroupDTO;
import com.pcloud.book.group.dto.SelfRobotUserDTO;
import com.pcloud.book.group.dto.SelfRobtParamDTO;
import com.pcloud.book.group.dto.StatisticsIncomeDto;
import com.pcloud.book.group.dto.TopAgentBookGroupDTO;
import com.pcloud.book.group.dto.UserBookBaseInfoDTO;
import com.pcloud.book.group.dto.UserSelectParamDTO;
import com.pcloud.book.group.dto.WechatMessageDTO;
import com.pcloud.book.group.entity.BizMaterial;
import com.pcloud.book.group.entity.BookAppletScene;
import com.pcloud.book.group.entity.BookGroup;
import com.pcloud.book.group.entity.BookGroupAgentRecord;
import com.pcloud.book.group.entity.BookGroupCipherUser;
import com.pcloud.book.group.entity.BookGroupFriendGuide;
import com.pcloud.book.group.entity.BookGroupServe;
import com.pcloud.book.group.entity.GroupMaterialAccount;
import com.pcloud.book.group.entity.GroupQrcode;
import com.pcloud.book.group.entity.GroupQrcodeStyle;
import com.pcloud.book.group.entity.JoinGroupCipher;
import com.pcloud.book.group.entity.PushBookGroupUpdate;
import com.pcloud.book.group.entity.QrChangeRecord;
import com.pcloud.book.group.entity.ResourcePage;
import com.pcloud.book.group.entity.TempletRelevance;
import com.pcloud.book.group.entity.WeixinQrcodeGeneration;
import com.pcloud.book.group.entity.WxUserWechatRelevance;
import com.pcloud.book.group.entity.WxWechatUserCorrelation;
import com.pcloud.book.group.enums.AppAndProductTypeEnum;
import com.pcloud.book.group.enums.ChangeOriginTypeEnum;
import com.pcloud.book.group.enums.CipherTypeEnum;
import com.pcloud.book.group.enums.JoinGroupTypeEnum;
import com.pcloud.book.group.enums.LargeTempletEnum;
import com.pcloud.book.group.enums.QrcodeJumpType;
import com.pcloud.book.group.enums.UseTypeEnum;
import com.pcloud.book.group.mapper.BizMaterialMapper;
import com.pcloud.book.group.mapper.MpServiceMappingMapper;
import com.pcloud.book.group.set.GroupSet;
import com.pcloud.book.group.tools.BookExcelReader;
import com.pcloud.book.group.tools.SendWeixinRequestTools;
import com.pcloud.book.group.vo.BookGroupAnalysisParam;
import com.pcloud.book.group.vo.BookGroupAnalysisVO;
import com.pcloud.book.group.vo.BookGroupServeCountVO;
import com.pcloud.book.group.vo.ClassifyAndGroupCountVO;
import com.pcloud.book.group.vo.ClassifyQrcodeVO;
import com.pcloud.book.group.vo.ExcelDataVO;
import com.pcloud.book.group.vo.ExerciseBookCourseVO;
import com.pcloud.book.group.vo.FriendsVO;
import com.pcloud.book.group.vo.GroupIncomeStaticParamVO;
import com.pcloud.book.group.vo.GroupQrcodeBaseInfoVO;
import com.pcloud.book.group.vo.GroupScanTrendParamVO;
import com.pcloud.book.group.vo.GroupScanTrendVO;
import com.pcloud.book.group.vo.GroupStatisticVO;
import com.pcloud.book.group.vo.ListBook4ChannelVO;
import com.pcloud.book.group.vo.ListBookGroup4ChannelParamVO;
import com.pcloud.book.group.vo.ResourceClickVO;
import com.pcloud.book.group.vo.ResourcesStatisticVO;
import com.pcloud.book.group.vo.StatisticVO;
import com.pcloud.book.group.vo.TotalRescourceDataVO;
import com.pcloud.book.group.vo.UserBookInfoItemVO;
import com.pcloud.book.group.vo.UserBookInfoVO;
import com.pcloud.book.group.vo.WxGroupStatisticVO;
import com.pcloud.book.keywords.biz.BookKeywordBiz;
import com.pcloud.book.keywords.biz.SelfRobotKeywordBiz;
import com.pcloud.book.keywords.dao.BookKeywordDao;
import com.pcloud.book.keywords.dto.KeywordDTO;
import com.pcloud.book.keywords.enums.ReplyTypeEnum;
import com.pcloud.book.keywords.vo.ListKeywordVO;
import com.pcloud.book.mapper.clickhouse.BookMapper;
import com.pcloud.book.mq.producer.UpdateSuperSearchProducer;
import com.pcloud.book.pcloudkeyword.biz.PcloudRobotBiz;
import com.pcloud.book.pcloudkeyword.entity.PcloudRobot;
import com.pcloud.book.push.enums.AltTypeEnum;
import com.pcloud.book.reading.dao.ReadingUserDao;
import com.pcloud.book.record.biz.BookBrowseRecordBiz;
import com.pcloud.book.record.entity.BookBrowseRecord;
import com.pcloud.book.rightsSetting.biz.RightsSettingBiz;
import com.pcloud.book.rightsSetting.constants.RightsSettingConstant;
import com.pcloud.book.rightsSetting.dto.RightsSettingDto;
import com.pcloud.book.skill.biz.PcloudGroupActivityBiz;
import com.pcloud.book.skill.entity.PcloudGroupActivity;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.book.util.properties.BookProps;
import com.pcloud.channelcenter.base.constants.ChannelConstants;
import com.pcloud.channelcenter.base.constants.ChannelEnum;
import com.pcloud.channelcenter.base.constants.MessageFromTypeEnum;
import com.pcloud.channelcenter.base.exceptions.ChannelBizException;
import com.pcloud.channelcenter.qrcode.dto.AppTypeUseCount;
import com.pcloud.channelcenter.qrcode.dto.GroupQrcodeVO;
import com.pcloud.channelcenter.qrcode.dto.QrcodeSceneDto;
import com.pcloud.channelcenter.wechat.dto.AccountSettingDto;
import com.pcloud.channelcenter.wechat.dto.BookServeParamVO;
import com.pcloud.channelcenter.wechat.dto.MessageDto;
import com.pcloud.channelcenter.wechat.entity.AccountSetting;
import com.pcloud.channelcenter.wechat.vo.BookServeVO;
import com.pcloud.common.constant.CacheConstant;
import com.pcloud.common.constant.QrcodeStyleConstant;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.core.constant.AdviserTaskConstants;
import com.pcloud.common.core.constant.ProductTypeConstant;
import com.pcloud.common.core.constant.SystemCode;
import com.pcloud.common.core.enums.NotifyOriginTypeEnum;
import com.pcloud.common.dto.ResponseDto;
import com.pcloud.common.dto.StoreFlowInfoDto;
import com.pcloud.common.entity.UploadResultInfo;
import com.pcloud.common.enums.AppTypeEnum;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.page.PageBean;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.BeanUtils;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.NumberUtil;
import com.pcloud.common.utils.QrcodeUtils;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.UUIDUitl;
import com.pcloud.common.utils.aliyun.OssUtils;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.export.excel.ExcelExportor;
import com.pcloud.common.utils.httpclient.UrlUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.common.utils.zip.CompressUtils;
import com.pcloud.contentcenter.resource.dto.ResourceDTO;
import com.pcloud.exercisebook.dto.CourseModuleDTO;
import com.pcloud.facade.tradecenter.dto.ClassifyPayDetailDto;
import com.pcloud.facade.tradecenter.dto.GroupIncomeSearchDto;
import com.pcloud.facade.tradecenter.dto.GroupMoneyDto;
import com.pcloud.facade.tradecenter.dto.ProductSaleDetailDto;
import com.pcloud.facade.tradecenter.dto.SpeWechatGroupDto;
import com.pcloud.facade.tradecenter.dto.WechatGroupDto;
import com.pcloud.facade.wechat.material.dto.GroupNewsMaterialAddDTO;
import com.pcloud.facade.wechat.material.service.MaterialService;
import com.pcloud.labelcenter.label.service.LabelService;
import com.pcloud.liveapp.live.dto.ProductIdSearchDto;
import com.pcloud.liveapp.live.service.TimeTableService;
import com.pcloud.resourcecenter.product.dto.AddAppProductParamDTO;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.ProductTypeDto;
import com.pcloud.resourcecenter.product.dto.ProductVideoScheduleDTO;
import com.pcloud.resourcecenter.product.dto.ProductVideoScheduleQueryDTO;
import com.pcloud.resourcecenter.product.dto.SpecificationDto;
import com.pcloud.resourcecenter.product.dto.UpdateAppProductParamDTO;
import com.pcloud.resourcecenter.product.entity.Product;
import com.pcloud.resourcecenter.product.service.ProductService;
import com.pcloud.resourcecenter.store.constants.StoreCons;
import com.pcloud.settlementcenter.record.dto.GetGroupClassifyIncomeDTO;
import com.pcloud.settlementcenter.record.dto.GetGroupQrcodeIncomeDTO;
import com.pcloud.settlementcenter.record.dto.GroupRescourceIncomeParamDTO;
import com.pcloud.settlementcenter.record.dto.ProductStaticUnderAppMapDTO;
import com.pcloud.settlementcenter.record.service.SettlementService;
import com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;
import com.pcloud.videolesson.schedule.service.ScheduleService;
import com.pcloud.wechatgroup.group.dto.BookGroupScanStatisticsDTO;
import com.pcloud.wechatgroup.group.dto.BookGroupScanStatisticsReqDTO;
import com.pcloud.wechatgroup.group.dto.GroupMemberStatisDTO;
import com.pcloud.wechatgroup.group.dto.GroupRobotDTO;
import com.pcloud.wechatgroup.group.dto.GroupUserCountDTO;
import com.pcloud.wechatgroup.group.service.GroupMemberService;
import com.pcloud.wechatgroup.message.dto.GroupMsgCountDTO;
import com.pcloud.wechatgroup.message.dto.SendTextDTO;
import com.pcloud.wechatgroup.message.dto.UserChatCountDTO;
import com.pcloud.wechatgroup.selfrobot.dto.AltAndUserDTO;
import com.pcloud.wechatgroup.selfrobot.dto.AltAndUserResultDTO;
import com.pcloud.wechatgroup.selfrobot.dto.AvailableRobotParamDTO;
import com.pcloud.wechatgroup.selfrobot.dto.RobotBaseInfoDTO;
import com.pcloud.wechatgroup.selfrobot.dto.SelfRobotDTO;
import com.pcloud.wechatgroup.selfrobot.dto.UserRobotDTO;
import com.pcloud.wechatgroup.selfrobot.enums.SelfRobotTypeEnum;
import com.sdk.wxgroup.SendMessageTypeEnum;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.awt.*;
import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import lombok.SneakyThrows;

import static com.pcloud.book.book.constant.BookConstant.READER_COUNT_MAP;

/**
 * Description 社群书群二维码业务逻辑层接口实现类 Created by PENG on 2019/4/17.
 */
@Component("bookGroupBiz")
public class BookGroupBizImpl implements BookGroupBiz {
    private static final Logger LOGGER = LoggerFactory.getLogger(BookGroupBizImpl.class);

    private final static String DEFAULT_PRODUCT_COVER_IMG = "https://oss.5rs.me/oss/uploadfe/png/1c5da08d2c9598a5f0b0252acb84d8b8.png";

    @Value("${book.group.qrcode.domain}")
    private String bookGroupQrcodeDomain;

    @Autowired
    private BookGroupDao bookGroupDao;
    @Autowired
    private LabelService labelService;
    @Autowired
    private ProductService productService;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private BookBiz bookBiz;
    @Autowired
    private BookSet bookSet;
    @Autowired
    private BookDao bookDao;
    @Autowired
    private SettlementService settlementService;
    @Autowired
    private BookGroupClassifyBiz bookGroupClassifyBiz;
    @Autowired
    private GroupMemberService groupMemberService;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private AppTouchRecordDao appTouchRecordDao;
    @Autowired
    private AppClickRecordDao appClickRecordDao;
    @Autowired
    private SettlementConsr settlementConsr;
    @Autowired
    private TradeConsr tradeConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private MainLineConsr mainLineConsr;
    @Autowired
    private BookGroupClassifyDao bookGroupClassifyDao;
    @Autowired
    private BookKeywordDao bookKeywordDao;
    @Autowired
    private AudioLessonService audioLessonService;
    @Autowired
    private ScheduleService scheduleService;
    @Autowired
    private TimeTableService timeTableService;
    @Autowired
    private AppPriceCacheService appPriceCacheService;
    @Autowired
    private TempletRelevanceDao templetRelevanceDao;
    @Autowired
    private JoinGroupCipherDao joinGroupCipherDao;
    @Autowired
    private WechatGroupConsr wechatGroupConsr;
    @Autowired
    private WeixinQrcodeDao weixinQrcodeDao;
    @Autowired
    private BookConsr bookConsr;
    @Autowired
    private GroupQrcodeBiz groupQrcodeBiz;
    @Autowired
    private BookGroupServeDao bookGroupServeDao;
    @Autowired
    private GroupQrcodeDao groupQrcodeDao;
    @Autowired
    private BookGroupCipherUserDao bookGroupCipherUserDao;
    @Autowired
    private GroupSet groupSet;
    @Autowired
    private MessageConsr messageConsr;
    @Autowired
    private PushBookGroupUpdateDao pushBookGroupUpdateDao;
    @Autowired
    private BookKeywordBiz bookKeywordBiz;
    @Autowired
    private WeixinQrcodeGenerationDao weixinQrcodeGenerationDao;
    @Autowired
    private AgentConsr agentConsr;
    @Autowired
    private BookGroupAppBiz bookGroupAppBiz;
    @Autowired
    private BookGroupAgentRecordDao bookGroupAgentRecordDao;
    @Autowired
    private BookGroupAppDao bookGroupAppDao;
    @Autowired
    private CopyCipherRecordDao copyCipherRecordDao;
    @Autowired
    private BrowseRecordConsr browseRecordConsr;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private WxUserWechatRelevanceDao wxUserWechatRelevanceDao;
    @Autowired
    private WxWechatUserCorrelationDao wxWechatUserCorrelationDao;
    @Autowired
    private BookLabelDao bookLabelDao;
    @Autowired
    private BookGroupFriendGuideDao bookGroupFriendGuideDao;
    @Autowired
    private ResourceConsr resourceConsr;
    @Autowired
    private ReadingUserDao readingUserDao;
    @Autowired
    private SelfRobotKeywordBiz selfRobotKeywordBiz;
    @Autowired
    private PcloudRobotBiz pcloudRobotBiz;
    @Autowired
    private BookAdviserDao bookAdviserDao;
    @Autowired
    private BookRaysClassifyDao bookRaysClassifyDao;
    @Autowired
    private WechatConsr wechatConsr;
    @Autowired
    private BookAppletSceneDao bookAppletSceneDao;
    @Autowired
    private RightsSettingBiz rightsSettingBiz;
    @Autowired
    private AppletUserBookcaseBiz appletUserBookcaseBiz;
    @Autowired
    private AppletGroupSearchRecordBiz appletGroupSearchRecordBiz;
    @Autowired
    private BookBrowseRecordBiz bookBrowseRecordBiz;
    @Value("${system.env}")
    private String envStr;
    @Autowired
    private MaterialService materialService;
    @Autowired
    private GroupMaterialAccountBiz groupMaterialAccountBiz;
    @Autowired
    private BizMaterialMapper bizMaterialMapper;
    @Autowired
    private PcloudGroupActivityBiz pcloudGroupActivityBiz;
    @Autowired
    private AppletRecordBiz appletRecordBiz;
    @Autowired
    private ChannelConsr channelConsr;
    @Autowired
    private ServeCollectBiz serveCollectBiz;
    @Autowired
    private GroupQrcodeStyleDao groupQrcodeStyleDao;
    @Autowired
    private MpServiceMappingMapper mpServiceMappingMapper;
    @Autowired
    private AssistTempletConsr assistTempletConsr;
    @Autowired
    private WordappConsr wordappConsr;
    @Autowired
    private ExerciseBookConsr exerciseBookConsr;
    @Autowired
    private BookMapper bookMapper;
    @Autowired
    private ResourcePageBiz resourcePageBiz;
    @Autowired
    private UpdateSuperSearchProducer searchProducer;
    @Autowired
    private AdviserTaskConsr adviserTaskConsr;

    private static final ThreadPoolExecutor PLATFORM_STATISTICS_EXPORT_THREAD = new ThreadPoolExecutor(2, 2,
            0, TimeUnit.SECONDS, new LinkedBlockingQueue<>(),
            new BasicThreadFactory.Builder().namingPattern("platform_statistics_export_thread-%d").build());

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public String updateNoISBNBookGeneratorQrcode(MultipartFile file) {
        // 全局锁
        String key = CacheConstant.BOOK + "updateNoISBNBookGeneratorQrcode";
        boolean setnx = JedisClusterUtils.setnx(key, "1");
        if (!setnx) {
            return "导入中，请稍后重试";
        }
        JedisClusterUtils.expire(key, 5 * 60);
        File zip = null;
        File path = null;
        try {
            List<ExcelDataVO> excelDataVOS = BookExcelReader.readExcel(file);
            if (CollectionUtils.isEmpty(excelDataVOS)) {
                return StringUtils.EMPTY;
            }
            String strFile =
                    new File(".").getCanonicalFile() + File.separator + "temp" + File.separator + "noisbn" + File.separator + "qrcode" + File.separator;
            String date = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss");
            path = new File(strFile + date);
            if (!path.exists()) {
                boolean mkdir = path.mkdirs();
                if (!mkdir) {
                    LOGGER.error("创建临时文件夹:{} 失败", mkdir);
                    return StringUtils.EMPTY;
                }
            }
            // 获取当前最大id
            Long oldDataMax = bookGroupDao.getOldDataMax();
            for (ExcelDataVO vo : excelDataVOS) {
                String name = vo.getBookName();
                Long num = ++oldDataMax;
                String url = BookProps.getWechatDomain() + BookBusinessConstants.NO_ISBN_QRCODE_URI + num;
                String shortUrl4Own = UrlUtils.getShortUrl4Own(url);
                String qrcode = QrcodeUtils.create(shortUrl4Own);
                LOGGER.info("===序号:{}, name:{}, url:{}, shortUrl:{}, qrcode:{}  ", num, name, url, shortUrl4Own, qrcode);
                // 下载二维码到日期目录
                String outFilePath = strFile + date + File.separator + name + ".png";
                OssUtils.downloadFile(qrcode, outFilePath);
                // 新增数据
                bookGroupDao.insertOldData(num);
            }
            // 将日期目录下的二维码打包成zip上传至oss
            zip = ZipUtil.zip(strFile + date);
            UploadResultInfo uploadResultInfo = OssUtils.uploadLocalFile(zip.getPath(), zip.getName());
            return uploadResultInfo.getUrl();
        } catch (Exception e) {
            LOGGER.error("生成无书号二维码失败:{}", e);
        } finally {
            JedisClusterUtils.del(key);
            // 处理完成删除目录和压缩包
            if (!Objects.isNull(path)) {
                boolean delete = path.delete();
                if (!delete) {
                    LOGGER.error("生成无书号二维码，删除path失败");
                }
            }
            if (!Objects.isNull(zip)) {
                boolean delete = zip.delete();
                if (!delete) {
                    LOGGER.error("生成无书号二维码，删除path失败");
                }
            }
        }
        return StringUtils.EMPTY;
    }

    @Override
    public BookGroupDTO getDTOByBookId( Long bookId, Long channelId, Long adviserId ) {
        return bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
    }

    /**
     * 创建社群书时生成群二维码
     */
    @Override
    @ParamLog("创建社群书时生成群二维码")
    @Transactional(rollbackFor = Exception.class)
    public BookGroup createBookGroupAfterCreateBook( Long bookId, Long channelId, Long adviserId, Integer addType, Long sceneId, Integer joinGroupType,
                                                     Integer jumpType, String jumpUrl) throws BizException {
        if (QrcodeJumpType.H5_SELF_URL.getCode().equals(jumpType) && StringUtil.isEmpty(jumpUrl)){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"请配置自定义链接");
        }
        BookGroup bookGroup = new BookGroup();
        bookGroup.setBookId(bookId);
        bookGroup.setChannelId(channelId);
        bookGroup.setCreateUser(adviserId);
        //填充出版社id
        Long agentId = adviserConsr.getAgentIdByAdviser(bookGroup.getCreateUser());
        bookGroup.setAgentId(agentId);
        Boolean isShowBookName = bookGroupDao.getIsShowBookName(adviserId);
        if (isShowBookName != null) {
            bookGroup.setIsShowBookName(isShowBookName);
        }
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(joinGroupType)) {
            bookGroup.setBookGroupCipher(getBookGroupCipher());
        }
        if (JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType)){
            jumpType = null == jumpType ? QrcodeJumpType.APPLET_XIAORUI.getCode():jumpType;
            bookGroup.setJumpType(jumpType);
            bookGroup.setJumpUrl(jumpUrl);
        }
        if ((addType != null && addType == 1)) {
            GroupQrcodeVO groupQrcodeVO;
            if (sceneId != null) {
                //将图书下某个二维码替换成社群码
                groupQrcodeVO = qrcodeSceneConsr.setQrcodeToGroup(sceneId);
            } else {
                //创建公众号二维码
                groupQrcodeVO = qrcodeSceneConsr.createWxGroupQrcode(bookId, channelId, adviserId);
            }
            if (groupQrcodeVO == null) {
                throw new BookBizException(BookBizException.ERROR, "二维码生成失败！");
            }
            bookGroup.setGroupQrcodeUrl(groupQrcodeVO.getQrcodeUrl());
            bookGroup.setSceneId(groupQrcodeVO.getSceneId());
            bookGroupDao.insert(bookGroup);
            BookGroup group = new BookGroup();
            group.setId(bookGroup.getId());
            group.setGroupQrcodeLink(this.getGroupQrcodeLink(bookGroup.getId(), adviserId, joinGroupType, jumpType, jumpUrl));
            if (joinGroupType != null) {
                group.setJoinGroupType(joinGroupType);
            }
            bookGroupDao.update(group);
            bookGroup.setGroupQrcodeLink(group.getGroupQrcodeLink());
        } else {
            //小睿码创建公众号二维码
            Boolean bookGroupAccountsQrcode = JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType) && QrcodeJumpType.H5_OFFICIAL_ACCOUNTS.getCode().equals(jumpType);
            if (bookGroupAccountsQrcode){
                GroupQrcodeVO  groupQrcodeVO = qrcodeSceneConsr.createWxGroupQrcode(bookId, channelId, adviserId);
                if (groupQrcodeVO == null) {
                    throw new BookBizException(BookBizException.ERROR, "二维码生成失败！");
                }
                bookGroup.setSceneId(groupQrcodeVO.getSceneId());
            }
            bookGroupDao.insert(bookGroup);
            String groupQrcodeLink = this.getGroupQrcodeLink(bookGroup.getId(), adviserId, joinGroupType, jumpType, jumpUrl);
            String uuid = getUUID16();
            String preLink = groupQrcodeLink;
            if (!QrcodeJumpType.H5_SELF_URL.getCode().equals(jumpType)) {
                groupQrcodeLink = bookGroupQrcodeDomain+"/"+uuid;
            }
            String groupQrcodeUrl = QrcodeUtils.createWithMargin(groupQrcodeLink, 1);
            BookGroup group = new BookGroup();
            group.setId(bookGroup.getId());
            group.setGroupQrcodeUrl(groupQrcodeUrl);
            group.setGroupQrcodeLink(groupQrcodeLink);
            if (joinGroupType != null) {
                group.setJoinGroupType(joinGroupType);
            }
            bookGroupDao.update(group);
            bookGroup.setGroupQrcodeUrl(groupQrcodeUrl);
            bookGroup.setGroupQrcodeLink(groupQrcodeLink);
            bookGroup.setPreLink(preLink);
            bookGroup.setUuid(uuid);
        }
        if (null != bookId && !bookId.equals(0L)) {
            mainLineConsr.sendAddBookGroupTask(bookId, adviserId);
        }
        //小睿机器人生成小程序码
        if (JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType)) {
            this.createBookGroupAppletUrl(bookGroup.getId(), bookId, channelId, adviserId);
        }
        return bookGroup;
    }


    public static String getUUID16() {
        StringBuffer shortBuffer = new StringBuffer();
        String uuid = UUID.randomUUID().toString().replace("-", "");
        for (int i = 0; i < 16; i++) {
            String str = uuid.substring(i * 2, i * 2 + 2);
            int x = Integer.parseInt(str, 16);
            shortBuffer.append(chars[x % 0x3E]);
        }
        return shortBuffer.toString();

    }
    public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
            "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8",
            "9", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
            "U", "V", "W", "X", "Y", "Z" };


    /**
     * 获取社群书群二维码信息
     */
    @Override
    public BookGroupDTO getBookGroupInfo( Long bookGroupId ) throws BizException {
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (null == bookGroupDTO) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "群二维码不存在！");
        }
        List<Long> labelIds = new ArrayList<>();
        if (null != bookGroupDTO.getProLabelId()) {
            labelIds.add(bookGroupDTO.getProLabelId());
        }
        if (null != bookGroupDTO.getDepLabelId()) {
            labelIds.add(bookGroupDTO.getDepLabelId());
        }
        if (null != bookGroupDTO.getPurLabelId()) {
            labelIds.add(bookGroupDTO.getPurLabelId());
        }
        if (!ListUtils.isEmpty(labelIds)) {
            Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            if (!MapUtils.isEmpty(labelMap)) {
                if (null != bookGroupDTO.getProLabelId() && labelMap.containsKey(bookGroupDTO.getProLabelId())) {
                    bookGroupDTO.setProLabelName(labelMap.get(bookGroupDTO.getProLabelId()));
                }
                if (null != bookGroupDTO.getDepLabelId() && labelMap.containsKey(bookGroupDTO.getDepLabelId())) {
                    bookGroupDTO.setDepLabelName(labelMap.get(bookGroupDTO.getDepLabelId()));
                }
                if (null != bookGroupDTO.getPurLabelId() && labelMap.containsKey(bookGroupDTO.getPurLabelId())) {
                    bookGroupDTO.setPurLabelName(labelMap.get(bookGroupDTO.getPurLabelId()));
                }
            }
        }
        BookDto bookDto = bookBiz.getBaseById(bookGroupDTO.getBookId());
        if (null != bookDto) {
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            bookGroupDTO.setBookInfo(bookDto);
        }
        //好友引导语
        List<BookGroupFriendGuide> friendGuides = this.getFriendGuideList(bookGroupDTO.getId());
        if (!ListUtils.isEmpty(friendGuides)) {
            bookGroupDTO.setFriendGuideList(friendGuides);
        }
        //设置样式
        GroupQrcodeStyle groupQrcodeStyle = groupQrcodeStyleDao.getQrcodeStyleByBookGroupId(bookGroupDTO.getId());
        bookGroupDTO.setGroupQrcodeStyle(groupQrcodeStyle);
        return bookGroupDTO;
    }


    public BookGroupDTO getBookInfo( Long bookGroupId ) throws BizException {
        BookGroupDTO bookGroupDTO = bookGroupDao.getBookInfo(bookGroupId);
        return bookGroupDTO;
    }

    @Override
    public Map<Long, BookGroupDTO> getBookGroupInfoByIds( List<Long> bookGroupIds ) throws BizException {
        if (ListUtils.isEmpty(bookGroupIds)) {
            return null;
        }
        List<BookGroupDTO> list = bookGroupDao.getDTOByIds(bookGroupIds);
        if (ListUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        List<Long> bookIds = list.stream().map(BookGroupDTO::getBookId).collect(Collectors.toList());
        if (ListUtils.isEmpty(bookIds)) {
            return new HashMap<>();
        }
        Map<Long, BookDto> mapByIds = bookDao.getMapByIds(bookIds);
        if (ListUtils.isEmpty(list)) {
            return null;
        }
        list.forEach(e -> {
            if (!MapUtils.isEmpty(mapByIds) && mapByIds.get(e.getBookId()) != null) {
                e.setBookName(mapByIds.get(e.getBookId()).getBookName());
                e.setIsbn(mapByIds.get(e.getBookId()).getIsbn());
                e.setBookNumber("BK" + e.getBookId());
            }
        });
        return list.stream().collect(Collectors.toMap(BookGroupDTO::getId, dto -> dto));
    }

    @Override
    public List<BookGroupDTO> getBookGroupInfoByBookIdAndAdviserId( List<Long> bookIds, List<Long> adviserIds ) {
        if (ListUtils.isEmpty(bookIds) || ListUtils.isEmpty(adviserIds)) {
            return null;
        }

        return bookGroupDao.getDTOByBookIdsAnsAdviserIds(bookIds, adviserIds);
    }

    /**
     * 获取社群书群二维码信息
     */
    @Override
    public BookGroupDTO getBookGroupInfo4Wechat( Long bookGroupId ) throws BizException {
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO != null) {
            Long adviserId = bookGroupDTO.getCreateUser();
            if (adviserId != null) {
                Map<Long, AdviserBaseInfoDto> adviserInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(Arrays.asList(adviserId));
                if (adviserInfoDtoMap != null) {
                    AdviserBaseInfoDto adviserBaseInfoDto = adviserInfoDtoMap.get(adviserId);
                    if (adviserBaseInfoDto != null) {
                        bookGroupDTO.setAgentId(adviserBaseInfoDto.getAgentId());
                        bookGroupDTO.setAgentName(adviserBaseInfoDto.getAgentName());
                    }
                }
            }
            if (bookGroupDTO.getBookId() != null) {
                Map<String, Object> paramMap = Maps.newHashMap();
                paramMap.put("bookId", bookGroupDTO.getBookId());
                paramMap.put("adviserId", adviserId);
                paramMap.put("channelId", bookGroupDTO.getChannelId());
                BookDto bookDto = bookDao.getById(paramMap);
                if (bookDto != null) {
                    bookGroupDTO.setBookName(bookDto.getBookName());
                    bookGroupDTO.setBookImg(bookDto.getCoverImg());
                    bookGroupDTO.setPublish(bookDto.getPublish());
                    bookGroupDTO.setAreaLabelId(bookDto.getAreaLabelId());
                    bookGroupDTO.setVerLabelId(bookDto.getVerLabelId());
                    bookGroupDTO.setGraLabelId(bookDto.getGraLabelId());
                    bookGroupDTO.setSubLabelId(bookDto.getSubLabelId());
                    List<Long> bookLabelIds = new ArrayList<>();
                    bookLabelIds.add(bookDto.getAreaLabelId());
                    bookLabelIds.add(bookDto.getVerLabelId());
                    bookLabelIds.add(bookDto.getGraLabelId());
                    bookLabelIds.add(bookDto.getSubLabelId());
                    Map<Long, BookLabel> bookLabelMap = bookLabelDao.getMapByIds(bookLabelIds);
                    if (bookLabelMap.get(bookDto.getAreaLabelId()) != null) {
                        bookGroupDTO.setAreaLabelName(bookLabelMap.get(bookDto.getAreaLabelId()).getName());
                    }
                    if (bookLabelMap.get(bookDto.getVerLabelId()) != null) {
                        bookGroupDTO.setVerLabelName(bookLabelMap.get(bookDto.getVerLabelId()).getName());
                    }
                    if (bookLabelMap.get(bookDto.getGraLabelId()) != null) {
                        bookGroupDTO.setGraLabelName(bookLabelMap.get(bookDto.getGraLabelId()).getName());
                    }
                    if (bookLabelMap.get(bookDto.getSubLabelId()) != null) {
                        bookGroupDTO.setSubLabelName(bookLabelMap.get(bookDto.getSubLabelId()).getName());
                    }
                }
            }
        }
        //好友引导语
        List<BookGroupFriendGuide> friendGuides = this.getFriendGuideList(bookGroupId);
        if (!ListUtils.isEmpty(friendGuides)) {
            bookGroupDTO.setFriendGuideList(friendGuides);
        }
        return bookGroupDTO;
    }

    /**
     * 获取社群书群二维码信息
     */
    @Override
    public BookGroupDTO getBookGroupInfoByBookId( Long bookId, Long channelId, Long adviserId, Integer addType, Long sceneId, Integer joinGroupType,
                                                  Integer jumpType, String jumpUrl) throws BizException {
        BookGroupDTO bookGroupDTO = null;
        if (!bookId.equals(0L)) {
            bookGroupDTO = bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
        }
        if (null == bookGroupDTO) {
            BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookId, channelId, adviserId, addType, sceneId, joinGroupType, jumpType, jumpUrl);
            bookGroupDTO = new BookGroupDTO();
            bookGroupDTO.setId(bookGroup.getId());
            bookGroupDTO.setBookId(bookId);
            bookGroupDTO.setChannelId(channelId);
            bookGroupDTO.setGroupQrcodeUrl(bookGroup.getGroupQrcodeUrl());
            bookGroupDTO.setCreateUser(adviserId);
        } else {
            // 当书籍存在时根据前端传的addType来决定用什么码替换addType=1公众号码，其他为自建码
            BookGroup group = new BookGroup();
            group.setId(bookGroupDTO.getId());
            // 更新为微信码
            if (addType != null && addType == 1) {
                //创建公众号二维码
                GroupQrcodeVO groupQrcodeVO = qrcodeSceneConsr.createWxGroupQrcode(bookId, channelId, adviserId);
                if (groupQrcodeVO == null) {
                    throw new BookBizException(BookBizException.ERROR, "二维码生成失败！");
                }
                group.setSceneId(groupQrcodeVO.getSceneId());
                group.setGroupQrcodeUrl(groupQrcodeVO.getQrcodeUrl());
                group.setGroupQrcodeLink(this.getGroupQrcodeLink(bookGroupDTO.getId(), adviserId, joinGroupType, jumpType, jumpUrl));
                bookGroupDao.update(group);
                // 展示返回最新生成的
                bookGroupDTO.setGroupQrcodeUrl(groupQrcodeVO.getQrcodeUrl());
            }
            // 更新为自建码
            if (addType != null && addType == 2) {
                // 如果是恢复书籍，且选择自建码则清空sceneId
                if (null != bookGroupDTO.getSceneId() && bookGroupDTO.getSceneId() > 0) {
                    group.setSceneId(0L);
                    final Boolean haveQrcode = this.isHaveQrcode(bookId, channelId, adviserId);
                    // 如果之前是公众号二维码则要重新生成自有码
                    if (!haveQrcode) {
                        String groupQrcodeLink = this.getGroupQrcodeLink(bookGroupDTO.getId(), adviserId, joinGroupType, jumpType, jumpUrl);
                        String groupQrcodeUrl = QrcodeUtils.createWithMargin(groupQrcodeLink, 1);
                        group.setGroupQrcodeUrl(groupQrcodeUrl);
                        group.setGroupQrcodeLink(groupQrcodeLink);
                        // 展示返回最新生成的
                        bookGroupDTO.setGroupQrcodeUrl(groupQrcodeUrl);
                    }
                    bookGroupDao.update(group);
                }
            }
        }
        List<Long> labelIds = new ArrayList<>();
        if (null != bookGroupDTO.getProLabelId()) {
            labelIds.add(bookGroupDTO.getProLabelId());
        }
        if (null != bookGroupDTO.getDepLabelId()) {
            labelIds.add(bookGroupDTO.getDepLabelId());
        }
        if (null != bookGroupDTO.getPurLabelId()) {
            labelIds.add(bookGroupDTO.getPurLabelId());
        }
        if (!ListUtils.isEmpty(labelIds)) {
            Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            if (!MapUtils.isEmpty(labelMap)) {
                if (null != bookGroupDTO.getProLabelId() && labelMap.containsKey(bookGroupDTO.getProLabelId())) {
                    bookGroupDTO.setProLabelName(labelMap.get(bookGroupDTO.getProLabelId()));
                }
                if (null != bookGroupDTO.getDepLabelId() && labelMap.containsKey(bookGroupDTO.getDepLabelId())) {
                    bookGroupDTO.setDepLabelName(labelMap.get(bookGroupDTO.getDepLabelId()));
                }
                if (null != bookGroupDTO.getPurLabelId() && labelMap.containsKey(bookGroupDTO.getPurLabelId())) {
                    bookGroupDTO.setPurLabelName(labelMap.get(bookGroupDTO.getPurLabelId()));
                }
            }
        }
        BookDto bookDto = bookBiz.getBaseById(bookId);
        if (null != bookDto) {
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            bookGroupDTO.setBookInfo(bookDto);
        }
        //好友引导语
        List<BookGroupFriendGuide> friendGuides = this.getFriendGuideList(bookGroupDTO.getId());
        if (!ListUtils.isEmpty(friendGuides)) {
            bookGroupDTO.setFriendGuideList(friendGuides);
        }
        //设置样式
        GroupQrcodeStyle groupQrcodeStyle = groupQrcodeStyleDao.getQrcodeStyleByBookGroupId(bookGroupDTO.getId());
        bookGroupDTO.setGroupQrcodeStyle(groupQrcodeStyle);
        return bookGroupDTO;
    }

    /**
     * 社群码链接
     * @author：zhuyajie
     * @date：2020/10/12 14:26
        自建码规则更新
        https://qrcode.5rs.me/t-1/agentId/[sceneId|bookGroupId]
        t-1，自建码，sceneId
        t-2，社群码，bookGroupId
     */
    private String getGroupQrcodeLink(Long bookGroupId, Long adviserId, Integer joinGroupType, Integer jumpType, String jumpUrl) {
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        String url;
        if (JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType)){
            if (QrcodeJumpType.APPLET_SHUXIAO.getCode().equals(jumpType)) {
                //进小程序-书晓t-4
                url = bookGroupQrcodeDomain + "/t-4/" + agentId + "/" + bookGroupId;
            } else if (QrcodeJumpType.H5_SELF_URL.getCode().equals(jumpType)) {
                //进h5-自定义链接
                url = UrlUtils.getShortUrl4Own(jumpUrl);
            } else if (QrcodeJumpType.H5_XIAORUI.getCode().equals(jumpType)) {
                //进h5-书僮小睿小程序码/跳转按钮
                url = bookGroupQrcodeDomain + "/t-5/" + agentId + "/" + bookGroupId;
            } else if (QrcodeJumpType.H5_OFFICIAL_ACCOUNTS.getCode().equals(jumpType)) {
                //进h5-出版社公众号二维码
                url = bookGroupQrcodeDomain + "/t-6/" + agentId + "/" + bookGroupId;
            } else if (QrcodeJumpType.H5_RESOURCE.getCode().equals(jumpType)) {
                //进h5-资源页
                url = bookGroupQrcodeDomain + "/t-7/" + agentId + "/" + bookGroupId;
            } else {
                //小睿码t-3
                url = bookGroupQrcodeDomain + "/t-3/" + agentId + "/" + bookGroupId;
            }
        } else {
            url = bookGroupQrcodeDomain + "/t-2/" + agentId + "/" + bookGroupId;
        }
        return url;
    }

    @ParamLog("获取好友引导语信息")
    public List<BookGroupFriendGuide> getFriendGuideList( Long bookGroupId ) {
        List<BookGroupFriendGuide> friendGuides = bookGroupFriendGuideDao.getListByBookGroupId(bookGroupId);
        if (ListUtils.isEmpty(friendGuides)) {
            return new ArrayList<>();
        }
        List<Long> resourceIds = friendGuides.stream().filter(s -> s.getType().equals(ReplyTypeEnum.RESOURCE.value)).map(BookGroupFriendGuide::getResourceId).distinct().collect(Collectors.toList());
        Map<Long, ResourceDTO> resourceDTOMap = new HashMap<>();
        if (!ListUtils.isEmpty(resourceIds)) {
            resourceDTOMap = resourceConsr.mapByIds(resourceIds);
        }
        for (BookGroupFriendGuide friendGuide : friendGuides) {
            if (ReplyTypeEnum.RESOURCE.value.equals(friendGuide.getType()) && !MapUtils.isEmpty(resourceDTOMap)) {
                ResourceDTO resourceDTO = resourceDTOMap.get(friendGuide.getResourceId());
                if (resourceDTO != null) {
                    friendGuide.setResourceName(resourceDTO.getResourceName());
                    friendGuide.setResourceUrl(resourceDTO.getFileUrl());
                    friendGuide.setResourceTypeCode(resourceDTO.getTypeCode());
                    friendGuide.setResourceTypeName(resourceDTO.getTypeName());
                    friendGuide.setFileType(resourceDTO.getFileType());
                    friendGuide.setResourcePdfItems(resourceDTO.getResourcePdfItems());
                    friendGuide.setResourceOfficeItemDTOs(resourceDTO.getResourceOfficeItemDTOs());
                    friendGuide.setFileSize(resourceDTO.getFileSize());
                }
            }
        }
        return friendGuides;
    }

    /**
     * 更新群二维码信息
     */
    @Override
    @ParamLog(value = "更新群二维码信息", isAfterReturn = false)
    @Transactional(rollbackFor = Exception.class)
    public void updateBookGroup( BookGroup bookGroup ) throws BizException {
        if (null == bookGroup.getId()
                || StringUtil.isEmpty(bookGroup.getGroupQrcodeName())
                || bookGroup.getJoinGroupType() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.GROUP_QRCODE.getCode().equals(bookGroup.getJoinGroupType())
                && (StringUtil.isEmpty(bookGroup.getJoinTitle())
                || StringUtil.isEmpty(bookGroup.getJoinSlogan())
                || null == bookGroup.getProLabelId()
                || null == bookGroup.getDepLabelId()
                || null == bookGroup.getPurLabelId())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroup.getJoinGroupType())
                && (bookGroup.getIsInviteGroup() == null
                || StringUtil.isEmpty(bookGroup.getAddFriendGuide())
                || StringUtil.isEmpty(bookGroup.getCustomerServiceName())
                || null == bookGroup.getProLabelId()
                || null == bookGroup.getDepLabelId()
                || null == bookGroup.getPurLabelId())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroup.getJoinGroupType())
                && (ListUtils.isEmpty(bookGroup.getFriendGuideList())
                || StringUtil.isEmpty(bookGroup.getShortBookName()))) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroup.getJoinGroupType())) {
            checkShortBookName(bookGroup);
        }
        if (bookGroup.getGroupQrcodeName().contains("#")) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "名称不能包含#！");
        }
        BookGroup group = bookGroupDao.getById(bookGroup.getId());
        if (null == group) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "群二维码不存在！");
        }
        if (!bookGroup.getJoinGroupType().equals(group.getJoinGroupType())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码前后类型不一致！！");
        }
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroup.getJoinGroupType())) {
            this.updateFriendGuide(bookGroup.getId(), bookGroup.getFriendGuideList(), group.getCreateUser());
        }
        if (JoinGroupTypeEnum.GROUP_QRCODE.getCode().equals(bookGroup.getJoinGroupType())) {
            Long productId = group.getProductId();
            if (null == group.getProductId()) {
                AddAppProductParamDTO addAppProductParamDTO = new AddAppProductParamDTO();
                addAppProductParamDTO.setAppProCode(ProductTypeConstant.BOOK_GROUP);
                addAppProductParamDTO.setAppProName(bookGroup.getGroupQrcodeName());
                addAppProductParamDTO.setCoverImg(DEFAULT_PRODUCT_COVER_IMG);
                addAppProductParamDTO.setPartyId(group.getCreateUser());
                addAppProductParamDTO.setChannelId(group.getChannelId());
                Long agentId = adviserConsr.getAgentIdByAdviser(group.getCreateUser());
                addAppProductParamDTO.setAgentId(agentId);
                Product product = ResponseHandleUtil.parseResponse(productService.postAddBookGroupProduct(addAppProductParamDTO), Product.class);
                if (null == product) {
                    throw new BookBizException(BookBizException.DB_DML_FAIL, "操作失败！");
                }
                bookGroup.setProductId(product.getProductId());
                productId = product.getProductId();
            } else {
                UpdateAppProductParamDTO updateAppProductParamDTO = new UpdateAppProductParamDTO();
                updateAppProductParamDTO.setProductId(group.getProductId());
                updateAppProductParamDTO.setChannelId(group.getChannelId());
                updateAppProductParamDTO.setAppProName(bookGroup.getGroupQrcodeName());
                ResponseHandleUtil.parseResponse(productService.postUpdateBookGroupProduct(updateAppProductParamDTO), Product.class);
            }
            //上架
            if (null != productId) {
                Long channelId = bookGroup.getChannelId() == null ? group.getChannelId() : bookGroup.getChannelId();
                productConsr.productAutoOnShelves(channelId, Arrays.asList(productId));
            }
        }
        //二维码跳转链接
        String groupQrcodeLink = group.getGroupQrcodeLink();
        //设置社群码样式
        //每次更新之前都重新生成
        String qrcode = QrcodeUtils.createWithMargin(groupQrcodeLink, 1);
        groupQrcodeStyleDao.delQrcodeStyle(bookGroup.getId());
        if(null!=bookGroup.getGroupQrcodeStyle()){
            GroupQrcodeStyle groupQrcodeStyle = bookGroup.getGroupQrcodeStyle();
            groupQrcodeStyle.setBookGroupId(bookGroup.getId());
            groupQrcodeStyleDao.insert(groupQrcodeStyle);
            //如果有颜色样式
            qrcode = createQrcode(groupQrcodeStyle, groupQrcodeLink);
        }
        bookGroup.setOriginUrl(qrcode);
        //如果有图片样式
        if(null!=bookGroup.getBackgroundType() && bookGroup.getBackgroundType()>0){
            qrcode= QrcodeUtils.getStyleQr(qrcode, bookGroup.getBackgroundType(), null);
        }
        bookGroup.setGroupQrcodeUrl(qrcode);
        bookGroup.setBackgroundType(bookGroup.getBackgroundType());
        bookGroupDao.update(bookGroup);
        //更新至超级搜索
        searchProducer.update(bookGroup.getId());
    }

    /**
     * 根据二维码样式生成二维码
     *
     * @param qrcodeStyle
     * @param qrUrl
     * @return
     */
    public String createQrcode(GroupQrcodeStyle qrcodeStyle, String qrUrl) {
        String qrcodeUrl = "";
        // 调用common 生成带图案的二维码
        if (qrcodeStyle == null) {// 若未设置样式类型 ，则使用默认二维码
            qrcodeUrl = QrcodeUtils.createWithMargin(qrUrl,1);
        } else if (QrcodeStyleConstant.COLOR_QR.equals(qrcodeStyle.getStyleType())) {// 若为纯色二维码
            qrcodeUrl = QrcodeUtils.createColorWithMargin(qrUrl, Integer.parseInt(qrcodeStyle.getOnColor().replaceAll("#", ""), 16),1);
        } else if (QrcodeStyleConstant.GRADIENT_LOGO_QR.equals(qrcodeStyle.getStyleType())) {// 渐变色带logo
            Color newColor = new Color(qrcodeStyle.getNewRedColor(), qrcodeStyle.getNewGreenColor(),
                    qrcodeStyle.getNewBlueColor());
            Color oldColor = new Color(qrcodeStyle.getOldRedColor(), qrcodeStyle.getOldGreenColor(),
                    qrcodeStyle.getOldBlueColor());
            qrcodeUrl = QrcodeUtils.createGradientColorLogoQr(qrUrl, qrcodeStyle.getLogoUrl(), newColor, oldColor,1);
        } else if (QrcodeStyleConstant.COLOR_LOGO_QR.equals(qrcodeStyle.getStyleType())) {// 纯色logo
            qrcodeUrl = QrcodeUtils.createLogoQr(qrUrl, qrcodeStyle.getLogoUrl(),
                    Integer.parseInt(qrcodeStyle.getOnColor().replaceAll("#", ""), 16),1);
        } else if (QrcodeStyleConstant.GRADIENT_QR.equals(qrcodeStyle.getStyleType())) {// 渐变色二维码
            Color newColor = new Color(qrcodeStyle.getNewRedColor(), qrcodeStyle.getNewGreenColor(),
                    qrcodeStyle.getNewBlueColor());
            Color oldColor = new Color(qrcodeStyle.getOldRedColor(), qrcodeStyle.getOldGreenColor(),
                    qrcodeStyle.getOldBlueColor());
            qrcodeUrl = QrcodeUtils.createGradientColorQr(qrUrl, newColor, oldColor,1);
        } else if (QrcodeStyleConstant.LOGO_QR.equals(qrcodeStyle.getStyleType())) {// 黑白logo
            qrcodeUrl = QrcodeUtils.createLogoQr(qrUrl, qrcodeStyle.getLogoUrl(), 0xFF000000,1);
        } else {
            qrcodeUrl = QrcodeUtils.createWithMargin(qrUrl,1);
        }
        return qrcodeUrl;
    }

    /**
     * 更新群引导语
     *
     * @param bookGroupId
     * @param friendGuideList
     */
    private void updateFriendGuide( Long bookGroupId, List<BookGroupFriendGuide> friendGuideList, Long createUser ) {
        if (null == bookGroupId || ListUtils.isEmpty(friendGuideList)) {
            return;
        }
        bookGroupFriendGuideDao.deleteByBookGroupId(bookGroupId);
        friendGuideList.forEach(e -> {
            e.setBookGroupId(bookGroupId);
            e.setCreateUser(createUser);
        });
        bookGroupFriendGuideDao.insert(friendGuideList);
    }

    @ParamLog("判断书籍简称是否重复")
    private void checkShortBookName( BookGroup bookGroup ) {
        if (!StringUtil.isEmpty(bookGroup.getShortBookName())) {
            //判断是否为纯数字，不能为纯数字
            if (!StringUtil.isEmpty(bookGroup.getShortBookName())) {
                String shortBookName = bookGroup.getShortBookName();
                Boolean allNum = true;
                for (int i = 0; i < shortBookName.length(); i++) {
                    int chr = shortBookName.charAt(i);
                    if (chr < 48 || chr > 57) {
                        allNum = false;
                    }
                }
                if (allNum) {
                    throw new BookBizException(BookBizException.PARAM_IS_ERROR, "请填写符合规范的书刊简称！");
                }
            }
            BookGroup byShortBookName = bookGroupDao.getByShortBookName(bookGroup.getShortBookName());
            if (byShortBookName != null && !byShortBookName.getId().equals(bookGroup.getId())) {
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍简称已存在，请重新设置");
            }
        }
    }

    /**
     * 根据书刊ID删除
     */
    @Override
    @ParamLog(value = "根据书刊ID删除", isAfterReturn = false)
    @Transactional(rollbackFor = Exception.class)
    public void deleteByBookId( Long bookId, Long channelId, Long adviserId ) throws BizException {
        bookGroupDao.deleteByBookId(bookId, channelId, adviserId);
    }

    /**
     * 根据书刊ID恢复
     */
    @Override
    @ParamLog(value = "根据书刊ID恢复", isAfterReturn = false)
    @Transactional(rollbackFor = Exception.class)
    public void recoverByBookId( Long bookId, Long channelId, Long adviserId ) throws BizException {
        bookGroupDao.recoverByBookId(bookId, channelId, adviserId);
    }

    /**
     * 关联社群码和社群书
     */
    @Override
    @ParamLog("关联社群码和社群书")
    @Transactional(rollbackFor = Exception.class)
    public void linkBookGroup( Long bookId, Long bookGroupId, Long adviserId ) throws BizException {
        BookGroupDTO bookGroupDTO = getBookGroupInfo4Wechat(bookGroupId);
        if (null == bookGroupDTO || bookGroupDTO.getIsDelete() || !bookGroupDTO.getCreateUser().equals(adviserId)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码不存在或已删除！");
        }
        if (null != bookGroupDTO.getBookId() && !bookGroupDTO.getBookId().equals(0L)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "社群码已关联其他社群书！");
        }
        BookGroupDTO dto = bookGroupDao.getDTOByBookId(bookId, bookGroupDTO.getChannelId(), adviserId);
        if (null != dto) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "该社群书已经添加过其他社群码！");
        }
        BookGroup bookGroup = new BookGroup();
        bookGroup.setBookId(bookId);
        bookGroup.setId(bookGroupId);
        long result = bookGroupDao.linkBookGroup(bookGroup);
        if (result <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "关联社群书失败！");
        }
    }

    /**
     * 根据社群码ID获取书名
     */
    @Override
    public Map<String, Object> getBookNameByBookGroupId( Long bookGroupId ) throws BizException {
        Map<String, Object> result = new HashMap<>();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO != null) {
            result.put("joinGroupType", bookGroupDTO.getJoinGroupType());
            if (JoinGroupTypeEnum.XIAORUI.getCode().equals(bookGroupDTO.getJoinGroupType())) {
                result.put("jumpType", bookGroupDTO.getJumpType());
                result.put("jumpUrl", bookGroupDTO.getJumpUrl());
            }
        }
        if (null != bookGroupDTO && null != bookGroupDTO.getBookId()) {
            BookDto bookDto = bookBiz.getBaseById(bookGroupDTO.getBookId());
            if (null != bookDto) {
                result.put("bookName", StringUtil.addBracket(bookDto.getBookName()));
            }
            result.put("isDelete", bookGroupDTO.getIsDelete());
        } else {
            result.put("isDelete", true);
        }
        return result;
    }

    /**
     * 获取社群书列表(编辑)
     */
    @Override
    public PageBean listBookGroup4Adviser( Map<String, Object> paramMap, PageParam pageParam, Long adviserId ) throws BizException {
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listBookGroup4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        // 设置是否被冻结
        bookSet.setFreezeStatus(pageBean.getRecordList());
        // 填充社群书数据
        List<Long> bookGroupIds = new ArrayList<>();
        List<Long> relatedGroupIds = new ArrayList<>();
        pageBean.getRecordList().forEach(obj -> {
            BookDto bookDto = (BookDto) obj;
            bookGroupIds.add(bookDto.getBookGroupId());
            if (null != bookDto.getRelatedBookGroupId()) {
                relatedGroupIds.add(bookDto.getRelatedBookGroupId());
            }
        });
        ResponseEntity<ResponseDto<Map<Long, BigDecimal>>> responseEntity = settlementService.getWXGroupIncomeByAdviser(bookGroupIds, adviserId);
        Map<Long, BigDecimal> incomeMap = ResponseHandleUtil.parseMap(responseEntity, Long.class, BigDecimal.class);
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyDao.getClassifyCountAbout(bookGroupIds);
        Map<Long, Integer> scanMap = ResponseHandleUtil.parseMap(groupMemberService.getScanUserCountByGroup(bookGroupIds), Long.class, Integer.class);
        Map<Long, BookGroupDTO> relatedBookGroupMap = new HashMap<>();
        if (!ListUtils.isEmpty(relatedGroupIds)){
            relatedBookGroupMap = bookGroupDao.mapDTOByIds(relatedGroupIds);
        }
        for (Object object : pageBean.getRecordList()) {
            BookDto bookDto = (BookDto) object;
            Long bookGroupId = bookDto.getBookGroupId();
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(bookGroupId)) {
                BookGroupStatisticDTO dto = statisMap.get(bookGroupId);
                bookDto.setClassifyCount(null != dto.getClassifyCount() ? dto.getClassifyCount().longValue() : 0L);
                bookDto.setGroupCount(null != dto.getGroupNumber() ? dto.getGroupNumber().longValue() : 0L);
                bookDto.setGroupPersonCount(null != dto.getUserNumber() ? dto.getUserNumber().longValue() : 0L);
            } else {
                bookDto.setClassifyCount(0L);
                bookDto.setGroupPersonCount(0L);
                bookDto.setGroupCount(0L);
            }
            if (!MapUtils.isEmpty(scanMap) && scanMap.containsKey(bookGroupId)) {
                bookDto.setScanCount(null != scanMap.get(bookGroupId) ? scanMap.get(bookGroupId).longValue() : 0L);
            } else {
                bookDto.setScanCount(0L);
            }
            if (!MapUtils.isEmpty(incomeMap) && incomeMap.containsKey(bookGroupId)) {
                BigDecimal income = incomeMap.get(bookGroupId);
                bookDto.setTotalIncome(null != income ? income.setScale(2, BigDecimal.ROUND_HALF_UP) : BigDecimal.ZERO);
            } else {
                bookDto.setTotalIncome(BigDecimal.ZERO);
            }
            if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookDto.getJoinGroupType())
                    || JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookDto.getJoinGroupType())){
                //好友数量
                Integer friendsCount = bookGroupCipherUserDao.getFriendsCountByBookGroup(bookGroupId);
                bookDto.setFriendsCount(friendsCount);
            }
            Boolean hasRobotKeyword = selfRobotKeywordBiz.hasKeyword(bookGroupId);
            bookDto.setHasRobotKeyword(hasRobotKeyword);
            if (!MapUtils.isEmpty(relatedBookGroupMap) && relatedBookGroupMap.containsKey(bookDto.getRelatedBookGroupId())) {
                BookGroupDTO relatedBookGroup = relatedBookGroupMap.get(bookDto.getRelatedBookGroupId());
                bookDto.setRelatedBookGroup(relatedBookGroup);
            }
        }
        return pageBean;
    }

    @Override
    public PageBeanNew<ListBook4ChannelVO> listBookGroup4Channel(Long channelId, ListBookGroup4ChannelParamVO listBookGroup4ChannelParamVO) {
        Integer currentPage = listBookGroup4ChannelParamVO.getCurrentPage();
        Integer numPerPage = listBookGroup4ChannelParamVO.getNumPerPage();
        if (currentPage == null || numPerPage == null || currentPage < 0 || numPerPage < 0) {
            throw BookBizException.PAGE_PARAM_DELETION;
        }
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        paramMap.put("keywords", listBookGroup4ChannelParamVO.getKeywords());
        paramMap.put("isFundBook", listBookGroup4ChannelParamVO.getIsFundBook());
        String startTime = listBookGroup4ChannelParamVO.getStartTime();
        String endTime = listBookGroup4ChannelParamVO.getEndTime();
        if (startTime != null) {
            paramMap.put("startTime", startTime + " 00:00:00");
        }
        if (endTime != null) {
            paramMap.put("endTime", endTime + " 23:59:59");
        }
        paramMap.put("offset", currentPage * numPerPage);
        paramMap.put("limit", numPerPage);

        Integer totalCount = bookMapper.countBookGroup4Channel(paramMap);
        if (totalCount < 1) {
            return new PageBeanNew(currentPage, numPerPage, new ArrayList<>());
        }

        List<ListBook4ChannelVO> recordList = bookMapper.listBookGroup4Channel(paramMap);
        List<Long> bookGroupIds = recordList.stream().filter(x -> ObjectUtil.isAllNotEmpty(x, x.getBookGroupId())).map(ListBook4ChannelVO::getBookGroupId).distinct().collect(Collectors.toList());

        if (ListUtils.isEmpty(bookGroupIds)) {
            return new PageBeanNew(currentPage, numPerPage, new ArrayList<>());
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyDao.getClassifyCountAbout(bookGroupIds);
        recordList.forEach(e -> {
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(e.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(e.getBookGroupId());
                e.setClassifyNum(null != dto.getClassifyCount() ? dto.getClassifyCount().longValue() : 0L);
                e.setTotalNum(null != dto.getUserNumber() ? dto.getUserNumber().longValue() : 0L);
            } else {
                e.setClassifyNum(0L);
                e.setTotalNum(0L);
            }
        });
        return new PageBeanNew<>(currentPage, numPerPage, totalCount, recordList);
    }

    /**
     * 获取社群书列表(编辑)
     */
    @Override
    public List<BookDto> listSimpleBookGroup4Adviser( Map<String, Object> paramMap ) throws BizException {
        return bookDao.listSimpleBookGroup4Adviser(paramMap);
    }

    /**
     * 获取社群书列表(编辑)
     */
    @Override
    public PageBean listSimpleBookGroup4Adviser( Map<String, Object> paramMap, PageParam pageParam ) throws BizException {
        return bookDao.listPage(pageParam, paramMap, "listSimpleBookGroup4Adviser");
    }

    /**
     * 获取未创建社群码的书刊列表
     */
    @Override
    public PageBean listBook4CreateBookGroup( Map<String, Object> paramMap, PageParam pageParam, Long adviserId ) throws BizException {
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listBook4CreateBookGroup");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        return pageBean;
    }

    @Override
    @ParamLog("获取社群码名称以及商品标识")
    public QrcodeNameAndProIdDTO getQrcodeNameAndProId( Long bookGroupId ) throws BizException {
        return bookGroupDao.getQrcodeNameAndProId(bookGroupId);
    }

    @Override
    @ParamLog("获取排序类型")
    public Integer getRankType( Long bookGroupId ) throws BizException {
        return bookGroupDao.getRankType(bookGroupId);
    }

    @Override
    @ParamLog("更新排序类型")
    public void updateRankType( Long bookGroupId, Integer rankType ) throws BizException {
        bookGroupDao.updateRankType(bookGroupId, rankType);
    }

    /**
     * 编辑获取社群码总数量
     */
    @Override
    public Map<String, Object> getTotalBookGroupCount( Long adviserId ) throws BizException {
        Map<String, Object> result = new HashMap<>();
        Integer bookGroupCount = bookGroupDao.getBookGroupCount(adviserId);
        result.put("bookGroupCount", bookGroupCount);
        Integer friendsCount = bookGroupDao.getBookGroupFriendsCountByAdviser(adviserId);
        result.put("friendsCount", friendsCount);
        return result;
    }

    @Override
    public String getSpareQr( Long bookGroupId ) {
        return bookGroupDao.getSpareQr(bookGroupId);
    }

    @Override
    public BookGroupDTO getBaseInfoBySceneId(Long sceneId) {
        BookGroupDTO bookGroupDTO = new BookGroupDTO();
        //自有码H5落地页配置公众号
        ResourcePage resourcePage = resourcePageBiz.getPageByOfficialScene(sceneId);
        if (null != resourcePage) {
            if (null != resourcePage.getBookGroupId()) {
                BookAppletScene appletScene = bookAppletSceneDao.getByBookGroupId(resourcePage.getBookGroupId());
                bookGroupDTO.setAppletId(null == appletScene ? null : appletScene.getAppletId());
                BookGroupDTO groupDTO = bookGroupDao.getDTOById(resourcePage.getBookGroupId());
                bookGroupDTO.setUrl(null == groupDTO ? null : groupDTO.getGroupQrcodeLink());
                bookGroupDTO.setEntranceTitle(null == groupDTO ? null :groupDTO.getEntranceTitle());
                bookGroupDTO.setEntranceContent(null == groupDTO ? null :groupDTO.getEntranceContent());
                bookGroupDTO.setBookId(null == groupDTO ? null :groupDTO.getBookId());
                bookGroupDTO.setId(resourcePage.getBookGroupId());

            } else if (null != resourcePage.getSceneId()) {
                BookAppletScene appletScene = bookAppletSceneDao.getBySceneId(resourcePage.getSceneId());
                bookGroupDTO.setAppletId(null == appletScene ? null : appletScene.getAppletId());
                QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(resourcePage.getSceneId());
                bookGroupDTO.setUrl(null == qrcodeSceneDto ? null : qrcodeSceneDto.getUrl());
                bookGroupDTO.setBookId(null == qrcodeSceneDto ? null : qrcodeSceneDto.getAdviserBookId());
                bookGroupDTO.setSceneId(resourcePage.getSceneId());
            }
            //H5资源页均设为小睿类型
            bookGroupDTO.setJoinGroupType(JoinGroupTypeEnum.XIAORUI.getCode());
            bookGroupDTO.setResourcePageOpenRays(resourcePage.getOpenRays());
            //关注公众号后小睿入口默认文案
            bookGroupDTO.setEntranceTitle(StringUtil.isEmpty(bookGroupDTO.getEntranceTitle()) ?
                    "进入本书专属书友社区" : bookGroupDTO.getEntranceTitle());
            bookGroupDTO.setEntranceContent(StringUtil.isEmpty(bookGroupDTO.getEntranceContent()) ?
                    "我是书童小睿，你的专属伴读助手，我不仅提供本书配套服务，还将带你体验书友社区" : bookGroupDTO.getEntranceContent());

        } else {
            //群码、1v1码
            BookGroupDTO groupDTO = bookGroupDao.getBaseInfoBySceneId(sceneId);
            if (null != groupDTO) {
                bookGroupDTO.setJoinGroupType(groupDTO.getJoinGroupType());
                bookGroupDTO.setUrl(groupDTO.getGroupQrcodeLink());
                bookGroupDTO.setId(groupDTO.getId());
                BookAppletScene appletScene = bookAppletSceneDao.getByBookGroupId(groupDTO.getId());
                bookGroupDTO.setAppletUrl(null == appletScene ? null : appletScene.getAppletUrl());
                bookGroupDTO.setAppletId(null == appletScene ? null : appletScene.getAppletId());
            }
        }
        return bookGroupDTO;
    }

    @Override
    public void updatePersonQrcode( PersonalQrcodeDTO personalQrcodeDTO ) {
        if (personalQrcodeDTO == null || personalQrcodeDTO.getNewQrcodeUrl() == null ||
                personalQrcodeDTO.getOldQrcodeUrl() == null) {
            throw new BookBizException(BookBizException.ERROR, "参数缺失");
        }
        bookGroupDao.updatePersonQrcode(personalQrcodeDTO);
    }

    @Override
    @ParamLog("是否是特殊的出版社")
    public Boolean isSpecialAgent( Long agentId ) {
        return bookGroupDao.isSpecialAgent(agentId);
    }

    @Override
    public Boolean isHaveQrcode( Long bookId, Long channelId, Long adviserId ) {
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
        return bookGroupDTO != null && null == bookGroupDTO.getSceneId();
    }

    @ParamLog("获取应用统计")
    @Override
    public PageBeanNew<AppStatisticsDTO> getAppStatistics( Integer currentPage, Integer numPerPage, Long bookGroupId, Long qrcodeId, Long partyId ) {
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        map.put("qrcodeId", qrcodeId);
        PageBeanNew<AppStatisticsDTO> pageBeanNew;
        if (qrcodeId != null) {
            pageBeanNew = appTouchRecordDao.listPageNew(pageParam, map, "getAppTouchStatistics");
        } else {
            pageBeanNew = bookGroupAppDao.listPageNew(pageParam, map, "getAppServeStatistics");
            List<AppStatisticsDTO> list = pageBeanNew.getRecordList();
            if (!ListUtils.isEmpty(list)) {
                List<AppStatisticsDTO> touchStatistics = appTouchRecordDao.getAppTouchStatistics(map);
                if (!ListUtils.isEmpty(touchStatistics)) {
                    for (AppStatisticsDTO appStatisticsDTO : list) {
                        for (AppStatisticsDTO in : touchStatistics) {
                            if (appStatisticsDTO.getServeId().equals(in.getServeId()) && appStatisticsDTO.getServeType().equalsIgnoreCase(in.getServeType())) {
                                appStatisticsDTO.setPushCount(in.getPushCount());
                            }
                        }
                    }
                }
                for (AppStatisticsDTO appStatisticsDTO : list) {
                    if (appStatisticsDTO.getPushCount() == null) {
                        appStatisticsDTO.setPushCount(0);
                    }
                }
            }
        }
        List<AppStatisticsDTO> appStatisticsDTOS = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(appStatisticsDTOS)) {
            return pageBeanNew;
        }
        List<Long> serveIds = appStatisticsDTOS.stream().filter(s -> s.getServeId() != null).map(AppStatisticsDTO::getServeId).collect(Collectors.toList());
        //获取点击次数
        List<AppStatisticsDTO> appClickStatisticsDTOS = appClickRecordDao.getClickStatisticsByServeIds(serveIds, qrcodeId, bookGroupId);
        Map<Long, Integer> clickCountMap = new HashMap<>();
        if (!ListUtils.isEmpty(appClickStatisticsDTOS)) {
            for (AppStatisticsDTO in : appClickStatisticsDTOS) {
                clickCountMap.put(in.getServeId(), in.getClickCount());
            }
        }
        List<Long> productIds = appStatisticsDTOS.stream().filter(s -> s.getServeId() != null && "PRODUCT".equalsIgnoreCase(s.getServeType())).map(AppStatisticsDTO::getServeId).collect(Collectors.toList());
        List<Long> appIds = appStatisticsDTOS.stream().filter(s -> s.getServeId() != null && "APP".equalsIgnoreCase(s.getServeType())).map(AppStatisticsDTO::getServeId).collect(Collectors.toList());
        //获取详情
        Map<Long, AppDto> appDtoMap = appConsr.mapByIds(appIds);
        Map<Long, ProductDto> productDtoMap = productConsr.getProBasesByIds(productIds);


        List<AppPriceCacheDTO> appPriceCacheDTOS = new ArrayList<>();
        for (Long appId : appIds) {
            if (appDtoMap.get(appId) != null) {
                AppPriceCacheDTO appPriceCacheDTO = new AppPriceCacheDTO();
                appPriceCacheDTO.setAppTypeEnum(AppTypeEnum.APP_TYPE_MAP.get(appDtoMap.get(appId).getTypeCode()));
                appPriceCacheDTO.setAppId(appId);
                appPriceCacheDTOS.add(appPriceCacheDTO);
            }
        }
        Map<Long, BigDecimal> appPriceMap = ResponseHandleUtil.parseMapResponse(appPriceCacheService.getCaches(appPriceCacheDTOS), Long.class, BigDecimal.class);
        //结算接口
        Map<Long, BigDecimal> productIncomeMap = settlementConsr.getAdviserIncomeByCondition(productIds, "PRODUCT", partyId, qrcodeId, bookGroupId);
        Map<Long, BigDecimal> appIncomeMap = settlementConsr.getAdviserIncomeByCondition(appIds, "APP", partyId, qrcodeId, bookGroupId);
        //交易接口
        WechatGroupDto wechatGroupDtoP = new WechatGroupDto();
        wechatGroupDtoP.setBookGroupId(bookGroupId);
        wechatGroupDtoP.setIds(productIds);
        wechatGroupDtoP.setPartyId(partyId);
        wechatGroupDtoP.setType("PRODUCT");
        wechatGroupDtoP.setQrcodeId(qrcodeId);
        WechatGroupDto wechatGroupDtoA = new WechatGroupDto();
        wechatGroupDtoA.setBookGroupId(bookGroupId);
        wechatGroupDtoA.setIds(appIds);
        wechatGroupDtoA.setPartyId(partyId);
        wechatGroupDtoA.setType("APP");
        wechatGroupDtoA.setQrcodeId(qrcodeId);
        Map<Long, GroupMoneyDto> productSaleMap = tradeConsr.getQrGroupSaleMoney(wechatGroupDtoP);
        Map<Long, GroupMoneyDto> appSaleMap = tradeConsr.getQrGroupSaleMoney(wechatGroupDtoA);
        for (AppStatisticsDTO appStatisticsDTO : appStatisticsDTOS) {
            Long id = appStatisticsDTO.getServeId();
            String type = appStatisticsDTO.getServeType();
            Integer clickCount = clickCountMap.get(id);
            if (clickCount == null) {
                clickCount = 0;
            }
            appStatisticsDTO.setClickCount(clickCount);
            Integer buyCount = 0;
            Double incomeAmount = 0D;
            Double saleAmount = 0D;
            if ("PRODUCT".equalsIgnoreCase(type)) {
                if (productIncomeMap.get(id) != null) {
                    incomeAmount = productIncomeMap.get(id).doubleValue();
                }
                appStatisticsDTO.setIncomeAmount(incomeAmount);
                if (productSaleMap.get(id) != null) {
                    saleAmount = productSaleMap.get(id).getSaleMoney();
                    buyCount = productSaleMap.get(id).getSaleCount().intValue();
                }
                appStatisticsDTO.setSaleAmount(saleAmount);
                appStatisticsDTO.setBuyCount(buyCount);
                if (productDtoMap != null && productDtoMap.get(id) != null) {
                    ProductDto productDto = productDtoMap.get(id);
                    appStatisticsDTO.setServeName(productDto.getProductName());
                    appStatisticsDTO.setImage(productDto.getCoverImg());
                    ProductTypeDto productTypeDto = productDto.getProductTypeDto();
                    if (productTypeDto != null) {
                        appStatisticsDTO.setTypeName(productTypeDto.getTypeName());
                    }
                    List<SpecificationDto> specificationDtos = productDto.getSpecification();
                    if (!ListUtils.isEmpty(specificationDtos)) {
                        SpecificationDto specificationDto = specificationDtos.get(0);
                        if (specificationDto != null) {
                            appStatisticsDTO.setDealPrice(specificationDto.getDealPrice());
                            appStatisticsDTO.setRetailPrice(specificationDto.getAdvisePrice());
                        }
                    }
                }
            }
            if ("APP".equalsIgnoreCase(type)) {
                if (appIncomeMap.get(id) != null) {
                    incomeAmount = appIncomeMap.get(id).doubleValue();
                }
                appStatisticsDTO.setIncomeAmount(incomeAmount);
                GroupMoneyDto groupMoneyDtoApp = appSaleMap.get(id);
                if (groupMoneyDtoApp != null) {
                    saleAmount = groupMoneyDtoApp.getSaleMoney();
                    buyCount = groupMoneyDtoApp.getSaleCount().intValue();
                }
                appStatisticsDTO.setSaleAmount(saleAmount);
                appStatisticsDTO.setBuyCount(buyCount);
                if (appDtoMap != null && appDtoMap.get(id) != null) {
                    AppDto appDto = appDtoMap.get(id);
                    appStatisticsDTO.setTypeName(appDto.getTypeName());
                    appStatisticsDTO.setServeName(appDto.getTitle());
                    appStatisticsDTO.setImage(appDto.getSquareImg());
                }
                if (appPriceMap != null) {
                    if (appPriceMap.get(id) != null) {
                        appStatisticsDTO.setRetailPrice(appPriceMap.get(id).doubleValue());
                        appStatisticsDTO.setDealPrice(0D);
                    }
                }
            }
            if (buyCount == null || buyCount == 0 || clickCount == null || clickCount == 0) {
                appStatisticsDTO.setBuyRate(0D);
            } else {
                appStatisticsDTO.setBuyRate(new BigDecimal(buyCount.doubleValue() / clickCount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            }
        }
        //处理音频、视频、直播课的逻辑
        dealOtherSale(appStatisticsDTOS, productDtoMap, bookGroupId, qrcodeId, partyId);
        return pageBeanNew;
    }

    @ParamLog("处理音频、视频、直播课的逻辑")
    private void dealOtherSale( List<AppStatisticsDTO> appStatisticsDTOS, Map<Long, ProductDto> productDtoMap, Long bookGroupId, Long qrcodeId, Long partyId ) {
        if (productDtoMap == null || productDtoMap.values() == null || productDtoMap.values().isEmpty()) {
            return;
        }
        //视频课，音频课，直播课特殊处理
        List<Long> videoProductIds = new ArrayList<>();
        List<Long> audioProductIds = new ArrayList<>();
        List<Long> liveProductIds = new ArrayList<>();
        List<ProductDto> productDtos = new ArrayList<>(productDtoMap.values());
        if (!ListUtils.isEmpty(productDtos)) {
            for (ProductDto productDto : productDtos) {
                ProductTypeDto productTypeDto = productDto.getProductTypeDto();
                String productTypeCode = "";
                if (productTypeDto != null) {
                    productTypeCode = productTypeDto.getTypeCode();
                }
                String[] videoTypes = {"VIDEO_COURSE", "VIDEO_SCHEDULE"};
                if (Arrays.asList(videoTypes).contains(productTypeCode)) {
                    videoProductIds.add(productDto.getProductId());
                }
                String[] audioTypes = {"AUDIOAPP", "AUDIO_RESOURCE", "AUDIO_SCHEDULE", "AUDIO_COURSE"};
                if (Arrays.asList(audioTypes).contains(productTypeCode)) {
                    audioProductIds.add(productDto.getProductId());
                }
                String[] liveTypes = {"LIVE", "SCHEDULE"};
                if (Arrays.asList(liveTypes).contains(productTypeCode)) {
                    liveProductIds.add(productDto.getProductId());
                }
            }
        }
        Map<Long, List<Long>> videoPProductMapIds = new HashMap<>();
        Map<Long, List<Long>> audioPProductMapIds = new HashMap<>();
        Map<Long, List<Long>> livePProductMapIds = new HashMap<>();
        //视频课
        if (!ListUtils.isEmpty(videoProductIds)) {
            videoPProductMapIds = ResponseHandleUtil.parseMapList(scheduleService.getCourseProductIdByIds(videoProductIds, "PRODUCT"), Long.class, Long.class);
        }
        //音频课
        if (!ListUtils.isEmpty(audioProductIds)) {
            audioPProductMapIds = ResponseHandleUtil.parseMapList(audioLessonService.getProIdsByIds(audioProductIds, "PRODUCT"), Long.class, Long.class);
        }
        //直播课
        if (!ListUtils.isEmpty(liveProductIds)) {
            ProductIdSearchDto productIdSearchDto = new ProductIdSearchDto();
            productIdSearchDto.setIds(liveProductIds);
            productIdSearchDto.setType("PRODUCT");
            livePProductMapIds = ResponseHandleUtil.parseMapList(timeTableService.getCoursePidsUnderTable(productIdSearchDto), Long.class, Long.class);
        }
        List<Long> valProductIds = new ArrayList<>();
        fillProductIdsFromLL(valProductIds, videoPProductMapIds);
        fillProductIdsFromLL(valProductIds, audioPProductMapIds);
        fillProductIdsFromLL(valProductIds, livePProductMapIds);
        if (!ListUtils.isEmpty(valProductIds)) {
            //调交易中心获取交易额信息
            WechatGroupDto wechatGroupDtoP = new WechatGroupDto();
            wechatGroupDtoP.setBookGroupId(bookGroupId);
            wechatGroupDtoP.setIds(valProductIds);
            wechatGroupDtoP.setPartyId(partyId);
            wechatGroupDtoP.setType("PRODUCT");
            wechatGroupDtoP.setQrcodeId(qrcodeId);
            Map<Long, GroupMoneyDto> productSaleMap = tradeConsr.getQrGroupSaleMoney(wechatGroupDtoP);
            Map<Long, BigDecimal> productIncomeMap = settlementConsr.getAdviserIncomeByCondition(valProductIds, "PRODUCT", partyId, qrcodeId, bookGroupId);
            SpeWechatGroupDto speWechatGroupDto = new SpeWechatGroupDto();
            speWechatGroupDto.setBookGroupId(bookGroupId);
            speWechatGroupDto.setPartyId(partyId);
            speWechatGroupDto.setQrcodeId(qrcodeId);
            Map<Long, List<Long>> map = new HashMap<>();
            map.putAll(videoPProductMapIds);
            map.putAll(audioPProductMapIds);
            map.putAll(livePProductMapIds);
            speWechatGroupDto.setProductIdMap(map);
            Map<Long, GroupMoneyDto> forBuyCountMap = tradeConsr.getSpeQrGroupSaleMoney(speWechatGroupDto);
            Map<Long, Double> proSaleMap = new HashMap<>();
            Map<Long, Double> proIncomeMap = new HashMap<>();
            if (productSaleMap.values() != null && !productSaleMap.values().isEmpty()) {
                dealSale(videoProductIds, videoPProductMapIds, productSaleMap, proSaleMap, productIncomeMap, proIncomeMap);
                dealSale(audioProductIds, audioPProductMapIds, productSaleMap, proSaleMap, productIncomeMap, proIncomeMap);
                dealSale(liveProductIds, livePProductMapIds, productSaleMap, proSaleMap, productIncomeMap, proIncomeMap);
                for (AppStatisticsDTO appStatisticsDTO : appStatisticsDTOS) {
                    Long id = appStatisticsDTO.getServeId();
                    String type = appStatisticsDTO.getServeType();
                    if ("PRODUCT".equalsIgnoreCase(type)) {
                        Integer toAddCount = 0;
                        GroupMoneyDto groupMoneyDto = forBuyCountMap.get(id);
                        if (groupMoneyDto != null && groupMoneyDto.getSaleCount() != null) {
                            toAddCount = groupMoneyDto.getSaleCount().intValue();
                        }
                        addProductSale(id, productDtoMap, proSaleMap, proIncomeMap, toAddCount, appStatisticsDTO);
                    }
                }
            }
        }
    }

    private void addProductSale( Long id, Map<Long, ProductDto> productDtoMap, Map<Long, Double> proSaleMap, Map<Long, Double> proIncomeMap, Integer toAddCount, AppStatisticsDTO appStatisticsDTO ) {
        ProductDto productDto = productDtoMap.get(id);
        String[] videoTypes = {"VIDEO_COURSE", "VIDEO_SCHEDULE"};
        String[] audioTypes = {"AUDIOAPP", "AUDIO_RESOURCE", "AUDIO_SCHEDULE", "AUDIO_COURSE"};
        String[] liveTypes = {"LIVE", "SCHEDULE"};
        String typeCode = "";
        if (productDto != null && productDto.getProductTypeDto() != null) {
            typeCode = productDto.getProductTypeDto().getTypeCode();
        }
        if (productDto != null && (Arrays.asList(videoTypes).contains(typeCode)
                || Arrays.asList(audioTypes).contains(typeCode)
                || Arrays.asList(liveTypes).contains(typeCode))) {
            Double toAdd = proSaleMap.get(id);
            Double incomeToAdd = proIncomeMap.get(id);
            if (toAdd != null) {
                Double oldSale = appStatisticsDTO.getSaleAmount();
                if (oldSale == null) {
                    oldSale = 0D;
                }
                appStatisticsDTO.setSaleAmount(oldSale + toAdd);
            }
            if (incomeToAdd != null) {
                Double oldIncome = appStatisticsDTO.getIncomeAmount();
                if (oldIncome == null) {
                    oldIncome = 0D;
                }
                appStatisticsDTO.setIncomeAmount(oldIncome + incomeToAdd);
            }
            if (toAddCount != null) {
                Integer oldBuy = appStatisticsDTO.getBuyCount();
                if (oldBuy == null) {
                    oldBuy = 0;
                }
                appStatisticsDTO.setBuyCount(oldBuy + toAddCount);
                Integer buyCount = appStatisticsDTO.getBuyCount();
                Integer clickCount = appStatisticsDTO.getClickCount();
                //重新设置购买率
                if (buyCount == null || buyCount == 0 || clickCount == null || clickCount == 0) {
                    appStatisticsDTO.setBuyRate(0D);
                } else {
                    appStatisticsDTO.setBuyRate(new BigDecimal(buyCount.doubleValue() / clickCount).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                }
            }
        }
    }

    private void dealSale( List<Long> ids, Map<Long, List<Long>> productMapIds, Map<Long, GroupMoneyDto> productSaleMap, Map<Long, Double> saleMap, Map<Long, BigDecimal> productIncomeMap, Map<Long, Double> incomeMap ) {
        if (!ListUtils.isEmpty(ids)) {
            for (Long id : ids) {
                List<Long> productIds = productMapIds.get(id);
                if (!ListUtils.isEmpty(productIds)) {
                    Double saleMoney = 0D;
                    Long saleCount = 0L;
                    Double incomeMoney = 0D;
                    for (Long productId : productIds) {
                        GroupMoneyDto groupMoneyDto = productSaleMap.get(productId);
                        if (groupMoneyDto != null) {
                            if (groupMoneyDto.getSaleMoney() != null) {
                                saleMoney = saleMoney + groupMoneyDto.getSaleMoney();
                            }
                            if (groupMoneyDto.getSaleCount() != null) {
                                saleCount = saleCount + groupMoneyDto.getSaleCount();
                            }
                        }
                        if (productIncomeMap != null && productIncomeMap.get(productId) != null) {
                            incomeMoney = incomeMoney + productIncomeMap.get(productId).doubleValue();
                        }
                    }
                    saleMap.put(id, saleMoney);
                    incomeMap.put(id, incomeMoney);
                }
            }
        }
    }

    private void fillProductIdsFromLL( List<Long> productIds, Map<Long, List<Long>> map ) {
        if (map != null && !map.values().isEmpty()) {
            List<List<Long>> ll = new ArrayList<>(map.values());
            for (List<Long> l : ll) {
                if (!ListUtils.isEmpty(l)) {
                    productIds.addAll(l);
                }
            }
        }
    }

    @Override
    public void exportGroupQrcode4Adviser( Map<String, Object> paramMap, Long adviserId ) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            // 生成文件名
            String fileName = "社群码导出_" + DateUtils.getShortDateStr();
            Boolean isSuccess = true;
            String zipUrl = "";
            Long oneBookGroupId= null;
            try {
                Map<String, List<String[]>> zipFileMap = new HashMap<>();
                List<String[]> qrcodePicUrls = new ArrayList<String[]>();
                // 设置查询参数
                List<BookDto> bookDtos = bookDao.listBookGroup4Adviser(paramMap);
                if (ListUtils.isEmpty(bookDtos)) {
                    return;
                }
                oneBookGroupId = bookDtos.get(0).getBookGroupId();
                Integer noName = 0;
                for (BookDto bookDto : bookDtos) {
                    String bookName = null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null;
                    String groupQrcodeName = bookDto.getGroupQrcodeName();
                    if (StringUtil.isEmpty(bookDto.getGroupQrcodeUrl())) {
                        continue;
                    }
                    String qrcodeUrl = bookDto.getGroupQrcodeUrl().replace("//oss", "//file");
                    String qrcodeName;
                    if (!StringUtil.isEmpty(bookName)) {
                        qrcodeName = bookName;
                        if (!StringUtil.isEmpty(groupQrcodeName)) {
                            qrcodeName = qrcodeName + groupQrcodeName;
                        }
                    } else {
                        if (!StringUtil.isEmpty(groupQrcodeName)) {
                            qrcodeName = groupQrcodeName;
                        } else {
                            noName = noName + 1;
                            qrcodeName = "未命名" + noName;
                        }
                    }
                    if (Integer.valueOf(2).equals(bookDto.getJoinGroupType()) && !StringUtil.isEmpty(bookDto.getBookGroupCipher())) {
                        qrcodeName = qrcodeName + "（" + bookDto.getBookGroupCipher() + "）";
                    }
                    // 加入二维码图片
                    String[] qrcodePicurl = {qrcodeName, qrcodeUrl};
                    qrcodePicUrls.add(qrcodePicurl);
                }
                zipFileMap.put(fileName, qrcodePicUrls);
                UploadResultInfo zipUrlInfo = CompressUtils.zipByCatalog(zipFileMap, fileName);
                zipUrl = zipUrlInfo != null ? zipUrlInfo.getUrl() : null;

            } catch (Exception e) {
                LOGGER.error("生成导出文件失败" + e.getMessage(), e);
                isSuccess = false;
            }
            // 发送消息
            if (isSuccess) {
                JSONObject content = new JSONObject();
                content.put("commitTime", DateUtils.formatDate(new Date()));
                content.put("type", "社群码导出");
                messageConsr.sendLetter(adviserId, adviserId, content.toJSONString(), SystemCode.adviser.code, "qrcode_download", zipUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
                //编辑任务queue
                adviserTaskConsr.sendAdviserTaskQueue(adviserId, AdviserTaskConstants.TargetTypeEnum.QRCODE.getValue(),
                        oneBookGroupId, AdviserTaskConstants.OperateTypeEnum.DOWNLOAD_QRCODE.getValue());
            }
        });
    }

    @ParamLog("根据bookId获取社群书分类等统计")
    @Override
    public StatisticVO getBookGroupStatistics( Long bookId ) {
        StatisticVO statisticVO = bookGroupClassifyDao.getBookGroupStatistics(bookId);
        if (null == statisticVO || null == statisticVO.getBookGroupId()) {
            return new StatisticVO();
        }
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(statisticVO.getJoinGroupType())) {
            Long bookGroupId = statisticVO.getBookGroupId();
            //个人号数、好友数
            Integer robotCount = bookGroupCipherUserDao.getAltCountByBookGroup(bookGroupId);
            statisticVO.setRobotCount(robotCount);
            Integer friendCount = bookGroupCipherUserDao.getFriendsCountByBookGroup(bookGroupId);
            statisticVO.setFriendCount(friendCount);
        }
        return statisticVO;
    }

    @ParamLog("根据bookId获取社群书分类和关键词等统计信息")
    @Override
    public List<ClassifyKeywordDTO> getBookGroupKeywordStatistics( Long bookId ) {
        List<ClassifyKeywordDTO> classifyKeywordDTOS = bookGroupClassifyDao.getClassifyStatistics(bookId);
        return classifyKeywordDTOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新是否显示书名")
    @Override
    public void updateIsShowBookName( Boolean isShowBookName, Long partyId ) {
        bookGroupDao.updateIsShowBookName(isShowBookName, partyId);
    }

    @ParamLog("获取是否显示书名")
    @Override
    public Boolean getIsShowBookName( Long partyId ) {
        return bookGroupDao.getIsShowBookName(partyId);
    }


    @Transactional(rollbackFor = Exception.class)
    @ParamLog("删除社群码")
    @Override
    public void deleteBookGroup( Long bookGroupId ) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空");
        }
        BookGroupDTO dto = bookGroupDao.getDTOById(bookGroupId);
        if (dto == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该数据！");
        }
        if (dto.getBookId() != null && !new Long(0L).equals(dto.getBookId())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码已经绑定图书！");
        }
        ClassifyAndGroupCountVO classifyAndGroupCount = bookGroupClassifyBiz.getClassifyAndGroupCount(bookGroupId);
        if (classifyAndGroupCount != null
                && ((classifyAndGroupCount.getClassifyCount() != null && classifyAndGroupCount.getClassifyCount() > 0)
                || (classifyAndGroupCount.getGroupCount() != null && classifyAndGroupCount.getGroupCount() > 0))) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码下已有分类！");
        }
        bookGroupDao.deleteByBookGroupId(bookGroupId);
    }

    @Override
    public void deleteBookGroup4Adviser( Long bookGroupId ) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空");
        }
        BookGroupDTO dto = bookGroupDao.getDTOById(bookGroupId);
        if (dto == null || dto.getIsDelete()) {
            throw new BookBizException(BookBizException.ID_NOT_EXIST, "没有该数据！");
        }
        bookGroupDao.deleteByBookGroupId(bookGroupId);
        bookAppletSceneDao.deleteByBookGroupId(bookGroupId);
        //更新至超级搜索中
        searchProducer.delete(bookGroupId);
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("根据社群码id获取个人二维码信息")
    @Override
    public OwnAltQrcodeInfoDTO getOwnAltQrcodeInfoDTOByBookGroupId( Long wechatUserId, Long bookGroupId ) {
        OwnAltQrcodeInfoDTO ownAltQrcodeInfoDTO = new OwnAltQrcodeInfoDTO();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该社群码");
        }
        ownAltQrcodeInfoDTO.setCustomerServiceName(bookGroupDTO.getCustomerServiceName());
        //这里的暗号从社群书获取
        ownAltQrcodeInfoDTO.setCipher(bookGroupDTO.getBookGroupCipher());
        ownAltQrcodeInfoDTO.setAddFriendGuide(bookGroupDTO.getAddFriendGuide());
        Long bookId = bookGroupDTO.getBookId();
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", bookGroupDTO.getCreateUser());
        paramMap.put("channelId", bookGroupDTO.getChannelId());
        BookDto bookDto = bookDao.getById(paramMap);
        Long templetId = bookDto.getTempletId();
        //根据分类id获取大类
        TempletRelevance templetRelevance = templetRelevanceDao.getByTempletId(templetId);
        LOGGER.info("根据分类id获取大类templetRelevance" + templetRelevance.toString());
        Integer largeTemplet = templetRelevance.getLargeTemplet();
        Long agentId = bookGroupDTO.getAgentId();
        //根据bookGroupId获取机器人
        AvailableRobotParamDTO availableRobotParamDTO = new AvailableRobotParamDTO();
        availableRobotParamDTO.setAgentId(agentId);
        availableRobotParamDTO.setBookGroupId(bookGroupId);
        availableRobotParamDTO.setWechatUserId(wechatUserId);
        availableRobotParamDTO.setLargeTemplet(largeTemplet);
        availableRobotParamDTO.setSpecialAgent(bookGroupDTO.getBelongSpecialAgent());
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            List<Long> labelIds = new ArrayList<>();
            if (null != bookGroupDTO.getProLabelId()) {
                labelIds.add(bookGroupDTO.getProLabelId());
            }
            if (null != bookGroupDTO.getDepLabelId()) {
                labelIds.add(bookGroupDTO.getDepLabelId());
            }
            if (!ListUtils.isEmpty(labelIds)) {
                Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
                if (!MapUtils.isEmpty(labelMap)) {
                    if (null != bookGroupDTO.getProLabelId() && labelMap.containsKey(bookGroupDTO.getProLabelId())) {
                        availableRobotParamDTO.setSubject(labelMap.get(bookGroupDTO.getProLabelId()));
                    }
                    if (null != bookGroupDTO.getDepLabelId() && labelMap.containsKey(bookGroupDTO.getDepLabelId())) {
                        availableRobotParamDTO.setGrade(labelMap.get(bookGroupDTO.getDepLabelId()));
                    }
                }
            }
            availableRobotParamDTO.setRobotType(SelfRobotTypeEnum.version_origin.getCode());
        }
        if (JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            Long subLabelId = bookDto.getSubLabelId();
            Long graLabelId = bookDto.getGraLabelId();
            if (subLabelId != null && graLabelId != null) {
                Map<Long, BookLabel> bookLabelMap = bookLabelDao.getMapByIds(Arrays.asList(subLabelId, graLabelId));
                if (bookLabelMap.get(graLabelId) != null) {
                    availableRobotParamDTO.setGrade(bookLabelMap.get(graLabelId).getName());
                }
                if (bookLabelMap.get(subLabelId) != null) {
                    availableRobotParamDTO.setSubject(bookLabelMap.get(subLabelId).getName());
                }
            }
            availableRobotParamDTO.setRobotType(SelfRobotTypeEnum.version1.getCode());
        }
        SelfRobotDTO selfRobotDTO = wechatGroupConsr.getAvailableRobotByBookGroup(availableRobotParamDTO);
        if (selfRobotDTO == null) {
            //没有可用机器人返回没有可用机器人
            ownAltQrcodeInfoDTO.setHasUsedRobot(false);
            return ownAltQrcodeInfoDTO;
        }
        ownAltQrcodeInfoDTO.setHasUsedRobot(true);
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setAltId(selfRobotDTO.getWxId());
        ownAltQrcodeInfoDTO.setAltNickName(selfRobotDTO.getNickName());
        ownAltQrcodeInfoDTO.setAltQrcodeUrl(selfRobotDTO.getQrcodeUrl());
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setResourceOpen(selfRobotDTO.getResourceOpen());
        if (selfRobotDTO.getAgentRobot() != null && selfRobotDTO.getAgentRobot()) {
            //先查询有没有重复的
            BookGroupAgentRecord old = bookGroupAgentRecordDao.getByAltIdAndBookGroupId(selfRobotDTO.getWxId(), bookGroupId);
            if (old == null) {
                //没有重复的就插入
                BookGroupAgentRecord bookGroupAgentRecord = new BookGroupAgentRecord();
                bookGroupAgentRecord.setBookGroupId(bookGroupId);
                bookGroupAgentRecord.setAgentId(agentId);
                bookGroupAgentRecord.setAdviserId(bookGroupDTO.getCreateUser());
                bookGroupAgentRecord.setAgentName(selfRobotDTO.getAgentName());
                bookGroupAgentRecord.setGrade(selfRobotDTO.getGrade());
                bookGroupAgentRecord.setSubject(selfRobotDTO.getSubject());
                bookGroupAgentRecord.setTarget(selfRobotDTO.getTarget());
                bookGroupAgentRecord.setAltId(selfRobotDTO.getWxId());
                bookGroupAgentRecordDao.insert(bookGroupAgentRecord);
            }
        }
        return ownAltQrcodeInfoDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("根据分类id获取个人二维码信息")
    @Override
    public OwnAltQrcodeInfoDTO getOwnAltQrcodeInfoDTOByClassifyId( Long wechatUserId, Long classifyId ) {
        OwnAltQrcodeInfoDTO ownAltQrcodeInfoDTO = new OwnAltQrcodeInfoDTO();
        //根据分类id查询社群码信息
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (classifyDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该分类");
        }
        Long bookId = classifyDTO.getBookId();
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", classifyDTO.getCreateUser());
        paramMap.put("channelId", classifyDTO.getChannelId());
        BookDto bookDto = bookDao.getById(paramMap);
        Long templetId = bookDto.getTempletId();
        //根据分类id获取大类
        TempletRelevance templetRelevance = templetRelevanceDao.getByTempletId(templetId);
        LOGGER.info("根据分类id获取大类templetRelevance" + templetRelevance.toString());
        Integer largeTemplet = templetRelevance.getLargeTemplet();
        SelfRobotDTO selfRobotDTO = wechatGroupConsr.getAvailableRobot(wechatUserId, largeTemplet, classifyId);
        if (selfRobotDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "未找到机器人!");
        }
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setAltId(selfRobotDTO.getWxId());
        ownAltQrcodeInfoDTO.setAltNickName(selfRobotDTO.getNickName());
        ownAltQrcodeInfoDTO.setAltQrcodeUrl(selfRobotDTO.getQrcodeUrl());
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        //获取之前是否有没有使用的暗号
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByWechatUserId(wechatUserId, classifyId);
        String cipher;
        if (joinGroupCipher != null) {
            cipher = joinGroupCipher.getCipher();
        } else {
            //新增暗号
            cipher = UUIDUitl.generateShort();
            //查重，如果有重复，再次生成
            JoinGroupCipher joinGroupCipherHas = joinGroupCipherDao.getByCipher(cipher);
            if (joinGroupCipherHas != null) {
                cipher = UUIDUitl.generateShort();
            }
            cipher = "RAYS_" + cipher;
            JoinGroupCipher joinGroupCipherNew = new JoinGroupCipher();
            joinGroupCipherNew.setCipher(cipher);
            joinGroupCipherNew.setWechatUserId(wechatUserId);
            joinGroupCipherNew.setClassifyId(classifyId);
            joinGroupCipherNew.setAltId(selfRobotDTO.getWxId());
            joinGroupCipherNew.setType(CipherTypeEnum.CLASSIFY_CIPHER.code);
            joinGroupCipherDao.insert(joinGroupCipherNew);
        }
        ownAltQrcodeInfoDTO.setCipher(cipher);
        return ownAltQrcodeInfoDTO;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("根据分类id获取个人二维码信息")
    @Override
    public OwnAltQrcodeInfoDTO getOwnAltQrcodeInfoDTOByQrcodeId( Long wechatUserId, Long qrcodeId ) {
        OwnAltQrcodeInfoDTO ownAltQrcodeInfoDTO = new OwnAltQrcodeInfoDTO();
        GroupQrcode groupQrcode = groupQrcodeDao.getById(qrcodeId);
        Long classifyId = groupQrcode.getClassifyId();

        //根据分类id查询社群码信息
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (classifyDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该分类");
        }
        Long bookId = classifyDTO.getBookId();
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", classifyDTO.getCreateUser());
        paramMap.put("channelId", classifyDTO.getChannelId());
        BookDto bookDto = bookDao.getById(paramMap);
        Long templetId = bookDto.getTempletId();
        //根据分类id获取大类
        TempletRelevance templetRelevance = templetRelevanceDao.getByTempletId(templetId);
        LOGGER.info("根据分类id获取大类templetRelevance" + templetRelevance.toString());
        Integer largeTemplet = templetRelevance.getLargeTemplet();
        SelfRobotDTO selfRobotDTO = wechatGroupConsr.getAvailableRobot(wechatUserId, largeTemplet, classifyId);
        if (selfRobotDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "未找到机器人!");
        }
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        ownAltQrcodeInfoDTO.setAltId(selfRobotDTO.getWxId());
        ownAltQrcodeInfoDTO.setAltNickName(selfRobotDTO.getNickName());
        ownAltQrcodeInfoDTO.setAltQrcodeUrl(selfRobotDTO.getQrcodeUrl());
        ownAltQrcodeInfoDTO.setAltHeadUrl(selfRobotDTO.getHeadPic());
        //获取之前是否有没有使用的暗号
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByWechatUserIdAndQrcodeId(wechatUserId, qrcodeId, CipherTypeEnum.QRCODE_CIPHER.code);
        String cipher;
        if (joinGroupCipher != null) {
            cipher = joinGroupCipher.getCipher();
        } else {
            //新增暗号
            cipher = UUIDUitl.generateShort();
            //查重，如果有重复，再次生成
            JoinGroupCipher joinGroupCipherHas = joinGroupCipherDao.getByCipher(cipher);
            if (joinGroupCipherHas != null) {
                cipher = UUIDUitl.generateShort();
            }
            cipher = "RAYS_" + cipher;
            JoinGroupCipher joinGroupCipherNew = new JoinGroupCipher();
            joinGroupCipherNew.setCipher(cipher);
            joinGroupCipherNew.setWechatUserId(wechatUserId);
            joinGroupCipherNew.setClassifyId(classifyId);
            joinGroupCipherNew.setAltId(selfRobotDTO.getWxId());
            joinGroupCipherNew.setQrcodeId(qrcodeId);
            joinGroupCipherNew.setType(CipherTypeEnum.QRCODE_CIPHER.code);
            joinGroupCipherDao.insert(joinGroupCipherNew);
        }
        ownAltQrcodeInfoDTO.setCipher(cipher);
        return ownAltQrcodeInfoDTO;
    }

    @ParamLog("获取暗号状态")
    @Override
    public Integer getCipherState( String cipher ) {
        Integer state;
        if (StringUtil.isEmpty(cipher)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByCipher(cipher);
        if (joinGroupCipher == null) {
            //暗号错误
            state = 2;
        } else if (joinGroupCipher.getHasUsed() != null && joinGroupCipher.getHasUsed()) {
            //已使用
            state = 1;
        } else {
            //未使用
            state = 0;
        }
        return state;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("获取暗号状态为已使用")
    @Override
    public void updateCipherStateToUsed( String cipher, String wxId ) {
        if (StringUtil.isEmpty(cipher) || StringUtil.isEmpty(wxId)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        joinGroupCipherDao.updateCipherStateToUsed(cipher, wxId);
    }

    @ParamLog("获取个人二维码方式群已使用和未使用数量")
    @Override
    public GroupUseDTO getGroupUse( List<String> altIds ) {
        if (ListUtils.isEmpty(altIds)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        GroupUseDTO groupUseDTO = new GroupUseDTO();
        Integer notUsed = weixinQrcodeDao.countByState(0, altIds);
        Integer hasUsed = weixinQrcodeDao.countByState(1, altIds);
        Integer full = weixinQrcodeDao.countByState(2, altIds);
        groupUseDTO.setHasUsed(hasUsed + full);
        groupUseDTO.setNotUsed(notUsed);
        return groupUseDTO;
    }

    @ParamLog("获取所有的大类分类")
    @Override
    public List<LargeTempletDTO> getAllLargTemplet() {
        List<LargeTempletDTO> list = new ArrayList<>();
        for (LargeTempletEnum largeTempletEnum : LargeTempletEnum.values()) {
            LargeTempletDTO largeTempletDTO = new LargeTempletDTO();
            largeTempletDTO.setLargeTemplet(largeTempletEnum.code);
            largeTempletDTO.setName(largeTempletEnum.name);
            list.add(largeTempletDTO);
        }
        return list;
    }

    @ParamLog("根据微信id和机器人id获取分类集合")
    @Override
    public List<JoinGroupCipherDTO> getClassifyIdsByWxIdAndAltId( String wxId, String altId ) {
        if (StringUtil.isEmpty(wxId) || StringUtil.isEmpty(altId)) {
            return new ArrayList<>();
        }
        List<JoinGroupCipherDTO> list = joinGroupCipherDao.getClassifyIdsByWxIdAndAltId(wxId, altId);
        return CollectionUtils.isEmpty(list) ? Lists.newArrayList() : list;
    }

    @ParamLog("获取暗号基本信息")
    @Override
    public GroupCipherDTO getJoinGroupCipher( String cipher ) {
        if (StringUtil.isEmpty(cipher)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        JoinGroupCipher joinGroupCipher = joinGroupCipherDao.getByCipher(cipher);
        if (joinGroupCipher != null) {
            GroupCipherDTO groupCipherDTO = new GroupCipherDTO();
            BeanUtils.copyProperties(joinGroupCipher, groupCipherDTO);
            return groupCipherDTO;
        }
        return null;
    }

    @ParamLog("为信息流批量获取社群书基本信息")
    @Override
    public Map<Long, StoreFlowInfoDto> getFlowInfoByBookGroupIds( List<Long> bookGroupIds ) {
        Map<Long, StoreFlowInfoDto> result = new HashMap<>();
        if (ListUtils.isEmpty(bookGroupIds)) {
            return null;
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupIds", bookGroupIds);
        List<Object> listBook4ChannelVOS = bookDao.listBy(paramMap, "getBookGroupInfo4Channel");
        if (ListUtils.isEmpty(bookGroupIds)) {
            return new HashMap<>();
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyBiz.getBookGroupStatistic(bookGroupIds);
        listBook4ChannelVOS.forEach(e -> {
            ListBook4ChannelVO listBook4ChannelVO = (ListBook4ChannelVO) e;
            StoreFlowInfoDto storeFlowInfoDto = new StoreFlowInfoDto();
            storeFlowInfoDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            storeFlowInfoDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            storeFlowInfoDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            storeFlowInfoDto.setTitle(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                storeFlowInfoDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                storeFlowInfoDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            } else {
                storeFlowInfoDto.setResourceNum(0);
                storeFlowInfoDto.setResourceItemNum(0);
            }
            result.put(listBook4ChannelVO.getBookGroupId(), storeFlowInfoDto);
        });
        return result;
    }

    @ParamLog("获取指定条数社群书基本信息")
    @Override
    public Map<Long, StoreFlowInfoDto> getBookGroupInfoByChannelId( Long channelId, Integer itemNum ) {
        Map<Long, StoreFlowInfoDto> result = new HashMap<>();
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        paramMap.put("offset", 0);
        paramMap.put("limit", itemNum);

        Integer totalCount = bookMapper.countBookGroup4Channel(paramMap);
        if (totalCount < 1) {
            return new HashMap<>();
        }
        List<ListBook4ChannelVO> recordList = bookMapper.listBookGroup4Channel(paramMap);
        List<Long> bookGroupIds = recordList.stream().filter(x -> ObjectUtil.isAllNotEmpty(x, x.getBookGroupId())).map(ListBook4ChannelVO::getBookGroupId).distinct().collect(Collectors.toList());
        if (ListUtils.isEmpty(bookGroupIds)) {
            return new HashMap<>();
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyBiz.getBookGroupStatistic(bookGroupIds);
        recordList.forEach(listBook4ChannelVO -> {
            StoreFlowInfoDto storeFlowInfoDto = new StoreFlowInfoDto();
            storeFlowInfoDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            storeFlowInfoDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            storeFlowInfoDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            storeFlowInfoDto.setTitle(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                storeFlowInfoDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                storeFlowInfoDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            } else {
                storeFlowInfoDto.setResourceNum(0);
                storeFlowInfoDto.setResourceItemNum(0);
            }
            result.put(listBook4ChannelVO.getBookGroupId(), storeFlowInfoDto);
        });
        return result;
    }


    @Override
    @ParamLog("知识商城获取社群书信息")
    public PageBeanNew<StoreFlowInfoDto> listBookGroup4KnowledgeMall( Long channelId, int currentPage, int numPerPage ) {
        List<StoreFlowInfoDto> results = new ArrayList<>();
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        paramMap.put("offset", currentPage * numPerPage);
        paramMap.put("limit", numPerPage);

        Integer totalCount = bookMapper.countBookGroup4Channel(paramMap);
        if (totalCount < 1) {
            return new PageBeanNew(currentPage, numPerPage, new ArrayList<>());
        }
        List<ListBook4ChannelVO> recordList = bookMapper.listBookGroup4Channel(paramMap);
        List<Long> bookGroupIds = recordList.stream().map(ListBook4ChannelVO::getBookGroupId).collect(Collectors.toList());
        if (ListUtils.isEmpty(bookGroupIds)) {
            return new PageBeanNew(currentPage, numPerPage, 0, new ArrayList<>());
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyBiz.getBookGroupStatistic(bookGroupIds);
        for (ListBook4ChannelVO listBook4ChannelVO : recordList) {
            StoreFlowInfoDto storeFlowInfoDto = new StoreFlowInfoDto();
            storeFlowInfoDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            storeFlowInfoDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            storeFlowInfoDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            storeFlowInfoDto.setTitle(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                storeFlowInfoDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                storeFlowInfoDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            } else {
                storeFlowInfoDto.setResourceNum(0);
                storeFlowInfoDto.setResourceItemNum(0);
            }
            results.add(storeFlowInfoDto);
        }
        return new PageBeanNew<>(currentPage, numPerPage, totalCount, results);
    }

    @ParamLog("获取用户购买或者参与过的社群书信息")
    @Override
    public PageBeanNew<GroupStoreMyPayDto> getUserBrowseGroup4KnowLedgeMall( Long channelId, Long wechatUserId, Integer currentPage, Integer numPerPage ) {
        List<GroupStoreMyPayDto> results = new ArrayList<>();
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        List<Long> bookGroupIds = Lists.newArrayList();
        bookGroupIds = tradeConsr.getBuyBookGroupIdList(channelId, wechatUserId);
        Map<String, Object> paramMap = new HashMap<>();
        if (ListUtils.isEmpty(bookGroupIds)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        paramMap.put("bookGroupIds", bookGroupIds);
        PageBeanNew<ListBook4ChannelVO> resultInfos = bookDao.listPageNew(pageParam, paramMap, "getBookGroupInfo4Channel");
        List<Long> groupIds = resultInfos.getRecordList().stream().map(ListBook4ChannelVO::getBookGroupId).collect(Collectors.toList());
        if (ListUtils.isEmpty(bookGroupIds)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        Map<Long, BookGroupStatisticDTO> statisMap = bookGroupClassifyDao.getClassifyCountAbout(groupIds);
        for (ListBook4ChannelVO listBook4ChannelVO : resultInfos.getRecordList()) {
            GroupStoreMyPayDto groupStoreMyPayDto = new GroupStoreMyPayDto();
            groupStoreMyPayDto.setOriginId(listBook4ChannelVO.getBookGroupId());
            groupStoreMyPayDto.setOriginType(StoreCons.OriginTypeEnum.BOOK_GROUP.getCode());
            groupStoreMyPayDto.setCoverImg(listBook4ChannelVO.getCoverImg());
            groupStoreMyPayDto.setOriginName(listBook4ChannelVO.getBookName());
            if (!MapUtils.isEmpty(statisMap) && statisMap.containsKey(listBook4ChannelVO.getBookGroupId())) {
                BookGroupStatisticDTO dto = statisMap.get(listBook4ChannelVO.getBookGroupId());
                groupStoreMyPayDto.setResourceNum(null != dto.getClassifyCount() ? dto.getClassifyCount() : 0);
                groupStoreMyPayDto.setResourceItemNum(null != dto.getUserNumber() ? dto.getUserNumber() : 0);
            } else {
                groupStoreMyPayDto.setResourceNum(0);
                groupStoreMyPayDto.setResourceItemNum(0);
            }
            results.add(groupStoreMyPayDto);
        }
        return new PageBeanNew<>(currentPage, numPerPage, resultInfos.getTotalCount(), results);
    }


    @Override
    public BookGroupStatisticsDTO getBookGroupStatisByBookGroupId( Long bookGroupId ) {
        Map<Long, BookGroupStatisticDTO> bookGroupStatisticMap = bookGroupClassifyDao.getClassifyCountAbout(Arrays.asList(bookGroupId));
        BookGroupStatisticsDTO bookGroupStatisticsDTO = new BookGroupStatisticsDTO();
        Long appCount = appTouchRecordDao.getCountByBokkGroupId(bookGroupId, "APP");
        Long productCount = appTouchRecordDao.getCountByBokkGroupId(bookGroupId, "PRODUCT");
        if (MapUtils.isEmpty(bookGroupStatisticMap)) {
            bookGroupStatisticsDTO.setClassifyCount(0L);
            bookGroupStatisticsDTO.setGroupPersonNum(0L);
            bookGroupStatisticsDTO.setWxGroupCount(0L);
            bookGroupStatisticsDTO.setPromAppCount(appCount);
            bookGroupStatisticsDTO.setPromProductCount(productCount);
            return bookGroupStatisticsDTO;
        }
        bookGroupStatisticsDTO.setClassifyCount(bookGroupStatisticMap.get(bookGroupId).getClassifyCount().longValue());
        bookGroupStatisticsDTO.setGroupPersonNum(bookGroupStatisticMap.get(bookGroupId).getUserNumber().longValue());
        bookGroupStatisticsDTO.setWxGroupCount(bookGroupStatisticMap.get(bookGroupId).getGroupNumber().longValue());
        bookGroupStatisticsDTO.setPromAppCount(appCount);
        bookGroupStatisticsDTO.setPromProductCount(productCount);
        return bookGroupStatisticsDTO;
    }

    @Override
    public PageBeanNew<ResourcesStatisticVO> getGroupIncomeStatic( GroupIncomeStaticParamVO groupIncomeStaticParamVO, Long adviserId ) {
        Long bookGroupId = groupIncomeStaticParamVO.getBookGroupId();
        Integer currentPage = groupIncomeStaticParamVO.getCurrentPage();
        Integer numPerPage = groupIncomeStaticParamVO.getNumPerPage();
        String type = groupIncomeStaticParamVO.getType();
        Long classifyId = groupIncomeStaticParamVO.getClassifyId();
        Long wxGroupId = groupIncomeStaticParamVO.getWxGroupId();
        if (currentPage == null || currentPage < 0 || numPerPage == null || numPerPage <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "分页参数错误！");
        }
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "社群码id不能为空！");
        }
        if (type == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "类型不能为空");
        }
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        map.put("type", type);
        if (null != classifyId) {
            map.put("classifyId", classifyId);
        }
        if (null != wxGroupId) {
            map.put("qrcodeId", wxGroupId);
        }
        PageBeanNew<ResourcesStatisticVO> pageBeanNew = appClickRecordDao.listPageNew(pageParam, map, "getClickStatistics");
        List<ResourcesStatisticVO> recordList = pageBeanNew.getRecordList();
        if (ListUtils.isEmpty(recordList)) {
            return pageBeanNew;
        }
        //填充数据
        setInfo(recordList, bookGroupId, classifyId, wxGroupId, type, adviserId);
        return pageBeanNew;
    }

    void setInfo( List<ResourcesStatisticVO> recordList, Long bookGroupId, Long classifyId, Long qrcodeId, String type, Long partyId ) {
        List<Long> rescourceIds = recordList.stream().map(ResourcesStatisticVO::getRescourceId).collect(Collectors.toList());
//        map.put("rescourceIds",rescourceIds);
        GroupRescourceIncomeParamDTO groupRescourceIncomeParamDTO = new GroupRescourceIncomeParamDTO();
        groupRescourceIncomeParamDTO.setBookGroupId(bookGroupId);
        groupRescourceIncomeParamDTO.setClassifyId(classifyId);
        groupRescourceIncomeParamDTO.setQrcodeId(qrcodeId);
        groupRescourceIncomeParamDTO.setType(type);
        groupRescourceIncomeParamDTO.setRescourceIds(rescourceIds);
        groupRescourceIncomeParamDTO.setRoleId(5L);
        groupRescourceIncomeParamDTO.setPartyId(partyId);
        Map<Long, BigDecimal> rescourceIncome = bookConsr.getRescourceIncome(groupRescourceIncomeParamDTO);
        GroupIncomeSearchDto groupIncomeSearchDto = new GroupIncomeSearchDto();
        groupIncomeSearchDto.setBookGroupId(bookGroupId);
        groupIncomeSearchDto.setClassifyId(classifyId);
        groupIncomeSearchDto.setIds(rescourceIds);
        groupIncomeSearchDto.setQrcodeId(qrcodeId);
        groupIncomeSearchDto.setTypeCode(type);
        Map<Long, GroupMoneyDto> saleDetail4Group = tradeConsr.getSaleDetail4Group(groupIncomeSearchDto);
        Map<Long, AppDto> appDtoMap;
        Map<Long, ProductDto> productDtoMap;
        if ("APP".equals(type)) {
            appDtoMap = appConsr.mapByIds(rescourceIds);
            recordList.forEach(e -> {
                if (!MapUtils.isEmpty(appDtoMap) && null != appDtoMap.get(e.getRescourceId())) {
                    e.setRescourceName(appDtoMap.get(e.getRescourceId()).getTitle());
                }
                if (!MapUtils.isEmpty(saleDetail4Group) && null != saleDetail4Group.get(e.getRescourceId())) {
                    e.setSaleCount(saleDetail4Group.get(e.getRescourceId()).getSaleCount());
                    e.setTotalSale(new BigDecimal(saleDetail4Group.get(e.getRescourceId()).getSaleMoney()));
                } else {
                    e.setSaleCount(0L);
                    e.setTotalSale(BigDecimal.ZERO);
                }
                e.setType("APP");
                if (null == rescourceIncome.get(e.getRescourceId())) {
                    e.setTotalIncome(BigDecimal.ZERO);
                } else {
                    e.setTotalIncome(rescourceIncome.get(e.getRescourceId()));
                }
            });
        } else {
            productDtoMap = productConsr.getProBasesByIds(rescourceIds);
            recordList.forEach(e -> {
                if (!MapUtils.isEmpty(productDtoMap) && null != productDtoMap.get(e.getRescourceId())) {
                    e.setRescourceName(productDtoMap.get(e.getRescourceId()).getProductName());
                }
                e.setType("PRODUCT");
                if (null == rescourceIncome.get(e.getRescourceId())) {
                    e.setTotalIncome(BigDecimal.ZERO);
                } else {
                    e.setTotalIncome(rescourceIncome.get(e.getRescourceId()));
                }
                if (!MapUtils.isEmpty(saleDetail4Group) && null != saleDetail4Group.get(e.getRescourceId())) {
                    e.setSaleCount(saleDetail4Group.get(e.getRescourceId()).getSaleCount());
                    e.setTotalSale(new BigDecimal(saleDetail4Group.get(e.getRescourceId()).getSaleMoney()));
                } else {
                    e.setSaleCount(0L);
                    e.setTotalSale(BigDecimal.ZERO);
                }
            });
        }
    }

    @Override
    public List<GroupScanTrendVO> getGroupScanTrend( GroupScanTrendParamVO groupScanTrendParamVO, Long adviserId ) {
        Integer dayNum = groupScanTrendParamVO.getDayNum();
        if (dayNum == null) {
            groupScanTrendParamVO.setDayNum(30);
            dayNum = 30;
        }
        Date startDate = groupScanTrendParamVO.getStartDate();
        Date endDate = groupScanTrendParamVO.getEndDate();
        Long bookGroupId = groupScanTrendParamVO.getBookGroupId();
        Long classifyId = groupScanTrendParamVO.getClassifyId();
        Long wxGroupId = groupScanTrendParamVO.getWxGroupId();
        List<Date> dateList = settlementConsr.getDateList(dayNum, startDate, endDate);
        List<GroupScanTrendVO> groupScanTrendVOS = appClickRecordDao.getClickTrend(groupScanTrendParamVO);
        List<Date> collect = groupScanTrendVOS.stream().map(GroupScanTrendVO::getDate).collect(Collectors.toList());
        List<ClassifyPayDetailDto> groupBuyCount = tradeConsr.getGroupBuyCount(bookGroupId, classifyId, wxGroupId, startDate, endDate);
        List<String> tradeDate = groupBuyCount.stream().map(ClassifyPayDetailDto::getDivideDate).collect(Collectors.toList());
        if (dateList.size() > groupScanTrendVOS.size()) {
            dateList.forEach(e -> {
                if (!collect.contains(e)) {
                    GroupScanTrendVO groupScanTrendVO = new GroupScanTrendVO();
                    groupScanTrendVO.setDate(e);
                    groupScanTrendVO.setScanCount(0L);
                    groupScanTrendVOS.add(groupScanTrendVO);
                }
            });
        }
        if (ListUtils.isEmpty(groupBuyCount)) {
            groupScanTrendVOS.forEach(e -> e.setBuyCount(0L));
        } else {
            groupScanTrendVOS.forEach(e -> {
                for (ClassifyPayDetailDto classifyPayDetailDto : groupBuyCount) {
                    if (DateUtils.formatDate(e.getDate()).equals(classifyPayDetailDto.getDivideDate())) {
                        e.setBuyCount(classifyPayDetailDto.getBuyCount());
                    } else {
                        e.setBuyCount(0L);
                    }
                }
            });
        }

        return groupScanTrendVOS;
    }

    @Override
    public PageBeanNew<GroupStatisticVO> getClassifyStatistic( Long bookGroupId, Long adviserId, Integer currentPage, Integer numPerPage ) {
        PageParam pageParam = new PageParam(currentPage, numPerPage);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupId", bookGroupId);
        PageBeanNew<GroupStatisticVO> pageClassify = bookGroupClassifyDao.listPageNew(pageParam, paramMap, "pageClassify");
        List<GroupStatisticVO> recordList = pageClassify.getRecordList();
        if (ListUtils.isEmpty(recordList)) {
            return new PageBeanNew<>();
        }
        List<Long> classifyIds = recordList.stream().map(GroupStatisticVO::getClassifyId).collect(Collectors.toList());
        if (ListUtils.isEmpty(classifyIds)) {
            return new PageBeanNew<>();
        }
        Map<Long, ClickClassifyDTO> longClickClassifyDTOMap = bookGroupClassifyDao.mapClickClassify(classifyIds);
        GetGroupClassifyIncomeDTO getGroupClassifyIncomeDTO = new GetGroupClassifyIncomeDTO();
        getGroupClassifyIncomeDTO.setClassifyIds(classifyIds);
        getGroupClassifyIncomeDTO.setPartyId(adviserId);
        getGroupClassifyIncomeDTO.setRoleId(5L);
        Map<Long, BigDecimal> classifyIncome = bookConsr.getClassifyIncome(getGroupClassifyIncomeDTO);
        Map<Long, Long> mapMemberCount = wechatGroupConsr.getclassifyMemberCount(classifyIds);
        recordList.forEach(e -> {

            if (longClickClassifyDTOMap.get(e.getClassifyId()) != null) {
                Long count = longClickClassifyDTOMap.get(e.getClassifyId()).getCount() == null ? 0L : longClickClassifyDTOMap.get(e.getClassifyId()).getCount();
                e.setClickCount(count);
            }
            if (BigDecimal.ZERO.compareTo(e.getPrice()) == 0) {
                e.setIsFree(1);
            } else {
                e.setIsFree(0);
            }
            if (!MapUtils.isEmpty(classifyIncome)) {
                e.setIncome(classifyIncome.get(e.getClassifyId()));
            } else {
                e.setIncome(BigDecimal.ZERO);
            }
            if (!MapUtils.isEmpty(mapMemberCount)) {
                e.setInGroupPersonCount(mapMemberCount.get(e.getClassifyId()));
            } else {
                e.setInGroupPersonCount(0L);
            }
        });
        return pageClassify;
    }

    @Override
    public List<WxGroupStatisticVO> getQrcodeStatistic( Long bookGroupId, Long classifyId, Long adviserId ) {
        List<ClassifyQrcodeVO> qrcodeByClassify = groupQrcodeBiz.getQrcodeByClassify(bookGroupId, classifyId);
        if (ListUtils.isEmpty(qrcodeByClassify)) {
            return new ArrayList<>();
        }
        List<Long> qrcodeIds = qrcodeByClassify.stream().map(ClassifyQrcodeVO::getId).collect(Collectors.toList());
        List<String> wxGroupIds = qrcodeByClassify.stream().map(ClassifyQrcodeVO::getWeixinGroupId).collect(Collectors.toList());
        GetGroupQrcodeIncomeDTO getGroupQrcodeIncomeDTO = new GetGroupQrcodeIncomeDTO();
        getGroupQrcodeIncomeDTO.setRoleId(5L);
        getGroupQrcodeIncomeDTO.setQrcodeIds(qrcodeIds);
        getGroupQrcodeIncomeDTO.setPartyId(adviserId);
        Map<Long, BigDecimal> qrcodeIncome = bookConsr.getQrcodeIncome(getGroupQrcodeIncomeDTO);
        Map<String, GroupMemberStatisDTO> groupMemberStatisDTOMap = wechatGroupConsr.listGroupMemberStatisInfo(wxGroupIds);
        List<WxGroupStatisticVO> wxGroupStatisticVOS = new ArrayList<>();
        qrcodeByClassify.forEach(e -> {
            WxGroupStatisticVO wxGroupStatisticVO = new WxGroupStatisticVO();
            wxGroupStatisticVO.setCreatedTime(e.getCreatedTime());
            wxGroupStatisticVO.setGroupPersonCount(e.getUserNumber().longValue());
            if (MapUtils.isEmpty(qrcodeIncome)) {
                wxGroupStatisticVO.setIncome(BigDecimal.ZERO);
            } else {
                wxGroupStatisticVO.setIncome(qrcodeIncome.get(e.getId()));
            }
            if (MapUtils.isEmpty(groupMemberStatisDTOMap)) {
                wxGroupStatisticVO.setInGroupPersonCount(0L);
            } else {
                wxGroupStatisticVO.setInGroupPersonCount(groupMemberStatisDTOMap.get(e.getWeixinGroupId()).getJoinCount().longValue());
            }
            wxGroupStatisticVO.setQrcodeId(e.getId());
            wxGroupStatisticVO.setWxGroupName(e.getGroupName());
            wxGroupStatisticVOS.add(wxGroupStatisticVO);
        });

        return wxGroupStatisticVOS;
    }

    @Override
    public TotalRescourceDataVO getTotalRescourceData( Long bookGroupId, Long adviserId, Long classifyId, Long qrcodeId, String type ) {
        TotalRescourceDataVO totalRescourceDataVO = new TotalRescourceDataVO();
        List<Long> rescourceIds = appClickRecordDao.getRescourceIds(bookGroupId, classifyId, qrcodeId, type);
        Long rescourceTotalClick = appClickRecordDao.getRescourceTotalClick(bookGroupId, classifyId, qrcodeId, type);
        totalRescourceDataVO.setClickCount(rescourceTotalClick == null ? 0L : rescourceTotalClick);
        GroupRescourceIncomeParamDTO groupRescourceIncomeParamDTO = new GroupRescourceIncomeParamDTO();
        groupRescourceIncomeParamDTO.setBookGroupId(bookGroupId);
        groupRescourceIncomeParamDTO.setClassifyId(classifyId);
        groupRescourceIncomeParamDTO.setQrcodeId(qrcodeId);
        groupRescourceIncomeParamDTO.setType(type);
        groupRescourceIncomeParamDTO.setRescourceIds(rescourceIds);
        groupRescourceIncomeParamDTO.setPartyId(adviserId);
        groupRescourceIncomeParamDTO.setRoleId(5L);
        BigDecimal rescourceTotalIncome = bookConsr.getRescourceTotalIncome(groupRescourceIncomeParamDTO);
        totalRescourceDataVO.setTotalIncome(rescourceTotalIncome == null ? BigDecimal.ZERO : rescourceTotalIncome);
        BigDecimal totalSale = tradeConsr.getTotalSale(bookGroupId, classifyId, qrcodeId, type);
        totalRescourceDataVO.setTotalSale(totalSale);
        return totalRescourceDataVO;
    }

    @Override
    public Map<String, String> exportRescourceIncomeData( Long bookGroupId, Long adviserId ) {
        List<StatisticsIncomeDto> appStatisticsIncomeDtos = new ArrayList<>();
        List<StatisticsIncomeDto> productStatisticsIncomeDtos = new ArrayList<>();
        List<ResourcesStatisticVO> appClickStatistics = appClickRecordDao.getClickStatistics(bookGroupId, null, null, "APP");
        List<ResourcesStatisticVO> productClickStatistics = appClickRecordDao.getClickStatistics(bookGroupId, null, null, "PRODUCT");
        if (!ListUtils.isEmpty(appClickStatistics)) {
            setInfo(appClickStatistics, bookGroupId, null, null, "APP", adviserId);
            //获取挂在应用下的商品信息
            ProductStaticUnderAppMapDTO productStaticUnderAppMapDTO = new ProductStaticUnderAppMapDTO();
            productStaticUnderAppMapDTO.setBookGroupId(bookGroupId);
            productStaticUnderAppMapDTO.setAppIds(appClickStatistics.stream().map(ResourcesStatisticVO::getRescourceId).collect(Collectors.toList()));
            productStaticUnderAppMapDTO.setPartyId(adviserId);
            productStaticUnderAppMapDTO.setRoleId(5L);
//            Map<Long, List<com.pcloud.settlementcenter.record.dto.ResourcesStatisticVO>> productStaticUnderApp = settlementConsr.getProductStaticUnderApp(productStaticUnderAppMapDTO);
//            Map<Long, List<StatisticsIncomeDto>> productStaticUnderAppMap = copy(productStaticUnderApp,bookGroupId);
            appClickStatistics.forEach(e -> {
                StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
                statisticsIncomeDto.setAppId(e.getRescourceId());
                statisticsIncomeDto.setBookGroupId(bookGroupId);
                statisticsIncomeDto.setIncome(e.getTotalIncome());
                statisticsIncomeDto.setAppName(e.getRescourceName());
                statisticsIncomeDto.setSaleCounts(e.getSaleCount().intValue());
                statisticsIncomeDto.setSaleMoney(e.getTotalSale());
                statisticsIncomeDto.setScanCounts(e.getBrowseCount().intValue());
//                statisticsIncomeDto.setItemList(productStaticUnderAppMap.get(e.getRescourceId()));
                appStatisticsIncomeDtos.add(statisticsIncomeDto);
            });

        }
        if (!ListUtils.isEmpty(productClickStatistics)) {
            setInfo(productClickStatistics, bookGroupId, null, null, "PRODUCT", adviserId);
            productClickStatistics.forEach(e -> {
                StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
                statisticsIncomeDto.setProductId(e.getRescourceId());
                statisticsIncomeDto.setBookGroupId(bookGroupId);
                statisticsIncomeDto.setIncome(e.getTotalIncome());
                statisticsIncomeDto.setProductName(e.getRescourceName());
                statisticsIncomeDto.setSaleCounts(e.getSaleCount().intValue());
                statisticsIncomeDto.setSaleMoney(e.getTotalSale());
                statisticsIncomeDto.setScanCounts(e.getBrowseCount().intValue());
                productStatisticsIncomeDtos.add(statisticsIncomeDto);
            });
        }

        TotalRescourceDataVO appTotalRescourceData = getTotalRescourceData(bookGroupId, null, null, null, "APP");
        StatisticsIncomeDto appSumStatistics = setResourceSumStatistics(appTotalRescourceData);
        TotalRescourceDataVO productTotalRescourceData = getTotalRescourceData(bookGroupId, null, null, null, "PRODUCT");
        StatisticsIncomeDto productSumStatistics = setResourceSumStatistics(productTotalRescourceData);
        Map<String, Object> dataMap = new HashMap<>();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            bookGroupDTO = new BookGroupDTO();
        }
        String groupQrcodeName = bookGroupDTO.getGroupQrcodeName() == null ? " " : bookGroupDTO.getGroupQrcodeName();
        String title = "社群码" + groupQrcodeName + "的收益列表";
        dataMap.put("appIncomeList", appStatisticsIncomeDtos);
        dataMap.put("productIncomeList", productStatisticsIncomeDtos);
        dataMap.put("title", title);
        dataMap.put("appSumStatistics", appSumStatistics);
        dataMap.put("productSumStatistics", productSumStatistics);
        String today = DateUtils.formatDate(DateUtils.nowTimeStamp(), DateUtils.DATE_FORMAT_DATEONLY);
        String fileName = title + "-" + today;
        String filePath;
        try {
            filePath = ExcelExportor.uploadExcel(this.getClass(), dataMap, "template_bookGroupStatistics.ftl");
            LOGGER.info("生成Excel【END】" + filePath);
        } catch (Exception e) {
            LOGGER.error("生成Excel异常+++" + e.getMessage(), e);
            throw new BookBizException(BookBizException.ERROR, "导出失败，请联系管理员");
        }
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("fileName", fileName);
        resultMap.put("fileUrl", filePath);

        return resultMap;
    }

    private StatisticsIncomeDto setResourceSumStatistics( TotalRescourceDataVO totalRescourceDataVO ) {
        if (totalRescourceDataVO == null) {
            return new StatisticsIncomeDto();
        }
        Long clickCount = totalRescourceDataVO.getClickCount();
        BigDecimal totalIncome = totalRescourceDataVO.getTotalIncome();
        BigDecimal totalSale = totalRescourceDataVO.getTotalSale();
        StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
        statisticsIncomeDto.setScanCounts(clickCount.intValue());
        statisticsIncomeDto.setIncome(totalIncome);
        statisticsIncomeDto.setSaleMoney(totalSale);
        return statisticsIncomeDto;
    }

    private Map<Long, List<StatisticsIncomeDto>> copy( Map<Long, List<com.pcloud.settlementcenter.record.dto.ResourcesStatisticVO>> productStaticUnderApp, Long bookGroupId ) {
        Map<Long, List<StatisticsIncomeDto>> productStaticUnderAppMap = new HashMap<>();
        if (MapUtils.isEmpty(productStaticUnderApp)) {
            return productStaticUnderAppMap;
        }
        List<StatisticsIncomeDto> productStatisticsIncomeDtos = new ArrayList<>();
        productStaticUnderApp.forEach(( k, v ) -> {
            v.forEach(e -> {
                StatisticsIncomeDto statisticsIncomeDto = new StatisticsIncomeDto();
                statisticsIncomeDto.setProductId(e.getRescourceId());
                statisticsIncomeDto.setIncome(e.getTotalIncome());
                statisticsIncomeDto.setProductName(e.getRescourceName());
                statisticsIncomeDto.setSaleCounts(e.getSaleCount() == null ? 0 : e.getSaleCount().intValue());
                statisticsIncomeDto.setSaleMoney(e.getTotalSale());
                statisticsIncomeDto.setScanCounts(e.getBrowseCount() == null ? 0 : e.getBrowseCount().intValue());
                productStatisticsIncomeDtos.add(statisticsIncomeDto);
            });
            productStaticUnderAppMap.put(k, productStatisticsIncomeDtos);
        });
        return productStaticUnderAppMap;
    }

    @Override
    public Map<Long, Long> getResourcesBrowseCount( ResourceBrowseParamDto resourceBrowseParamDto ) {
        Map<Long, Long> resultMap = new HashMap<>();
        Long bookGroupId = resourceBrowseParamDto.getBookGroupId();
        Long classifyId = resourceBrowseParamDto.getClassifyId();
        Long qrcodeId = resourceBrowseParamDto.getQrcodeId();
        String typeCode = resourceBrowseParamDto.getTypeCode();
        List<Long> ids = resourceBrowseParamDto.getIds();
        if (ListUtils.isEmpty(ids)) {
            return resultMap;
        }
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        map.put("classifyId", classifyId);
        map.put("qrcodeId", qrcodeId);
        map.put("type", typeCode);
        map.put("rescourceIds", ids);
        Map<Long, ResourceClickVO> resourceClick = appClickRecordDao.getResourceClick(map);
        if (MapUtils.isEmpty(resourceClick)) {
            return resultMap;
        }
        resourceClick.forEach(( k, v ) -> {
            resultMap.put(k, v.getClickCount());
        });
        return resultMap;
    }

    @Override
    public Map<String, Integer> getBookGroupFriendsCountByDay( Long bookGroupId, String startDate, String endDate ) {
        String startTime = DateUtils.formatDate(DateUtils.getDayStart(DateUtils.getDateByStr(startDate)), DateUtils.DATE_FORMAT_DATETIME);
        String endTime = DateUtils.formatDate(DateUtils.getDayEnd(DateUtils.getDateByStr(endDate)), DateUtils.DATE_FORMAT_DATETIME);
        List<DayCountDTO> countDTOS = bookGroupCipherUserDao.getBookGroupFriendsCountByDay(bookGroupId, startTime, endTime);
        Map<String, Integer> map = new HashMap<>();
        if (ListUtils.isEmpty(countDTOS)) {
            return map;
        }
        for (DayCountDTO dayCountDTO : countDTOS) {
            map.put(dayCountDTO.getDate(), dayCountDTO.getCount());
        }
        return map;
    }

    @Override
    public PageBeanNew<FriendsVO> listPageFriendsStatistic( Long bookGroupId, Integer currentPage, Integer numPerPage ) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupId", bookGroupId);
        PageBeanNew<FriendsVO> pageBeanNew = bookGroupCipherUserDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "listPageFriendsStatistic");
        List<FriendsVO> recordList = pageBeanNew.getRecordList();
        if (null == pageBeanNew || ListUtils.isEmpty(recordList)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        List<UserRobotDTO> paramList = new ArrayList<>();
        recordList.forEach(friendsVO -> {
            UserRobotDTO robotDTO = new UserRobotDTO();
            robotDTO.setWxUserId(friendsVO.getWxUserId());
            robotDTO.setRobotId(friendsVO.getRobotId());
            paramList.add(robotDTO);
        });
        Map<String, UserChatCountDTO> dtoMap = wechatGroupConsr.getUserChatInfoByUserIdRobotId(paramList);
        for (FriendsVO friendsVO : recordList) {
            friendsVO.setState("正常");
            if (!MapUtils.isEmpty(dtoMap)) {
                UserChatCountDTO countDTO = dtoMap.get(friendsVO.getWxUserId());
                friendsVO.setNickName(countDTO.getNickName());
                friendsVO.setHeadPic(countDTO.getHeadPic());
                friendsVO.setSex(countDTO.getSex());
                friendsVO.setCountry(countDTO.getCountry());
                friendsVO.setProvince(countDTO.getProvince());
                friendsVO.setCity(countDTO.getCity());
                friendsVO.setSpeakCount(countDTO.getChatCount());
                friendsVO.setSpeakCountLast7(countDTO.getSevenDayChatCount());
                friendsVO.setLastSpeakTime(countDTO.getLastChatTime());
                if (null != countDTO.getFriendState() && countDTO.getFriendState() == 2) {
                    friendsVO.setState("已删除");
                }
            }
        }
        return pageBeanNew;
    }

    @ParamLog("批量新增资源配置")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchAddBookGroupServe( Long partyId, List<BookGroupServe> bookGroupServes ) {
        checkBookGroupServe(bookGroupServes);
        List<Long> bookGroupIds = bookGroupServes.stream().filter(s -> s.getBookGroupId() != null).map(BookGroupServe::getBookGroupId).distinct().collect(Collectors.toList());
        List<BookGroupServe> bookGroupServeLists = bookGroupServeDao.getListByBookGroupIds(bookGroupIds);
        //校验之前是否已存在
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            Long bookGroupId = bookGroupServe.getBookGroupId();
            Long serveId = bookGroupServe.getServeId();
            String ServeType = bookGroupServe.getServeType();
            for (BookGroupServe bookGroupServeList : bookGroupServeLists) {
                if (bookGroupId.equals(bookGroupServeList.getBookGroupId())
                        && serveId.equals(bookGroupServeList.getServeId())
                        && ServeType.equals(bookGroupServeList.getServeType())) {
                    throw new BookBizException(BookBizException.PARAM_IS_EXIST, "该资源已存在！");
                }
            }
        }
        List<BookGroupDTO> dtos = bookGroupDao.getDTOByIds(bookGroupIds);
        Map<Long, BookGroupDTO> dtoMap = new HashMap<>();
        List<Long> channelIds = new ArrayList<>();
        for (BookGroupDTO bookGroupDTO : dtos) {
            dtoMap.put(bookGroupDTO.getId(), bookGroupDTO);
            if (!channelIds.contains(bookGroupDTO.getChannelId())) {
                channelIds.add(bookGroupDTO.getChannelId());
            }
        }
        Map<Long, AccountSettingDto> accountSettingDtoMap = new HashMap<>();
        for (Long channelId : channelIds) {
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
            accountSettingDtoMap.put(channelId, accountSettingDto);
        }
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            Long bookGroupId = bookGroupServe.getBookGroupId();
            BookGroupDTO bookGroupDTO = dtoMap.get(bookGroupId);
            AccountSettingDto accountSettingDto = accountSettingDtoMap.get(bookGroupDTO.getChannelId());
            if (AppAndProductTypeEnum.APP.value.equalsIgnoreCase(bookGroupServe.getServeType())) {
                AppDto appDto = appConsr.getBaseById(bookGroupServe.getServeId());
                if (appDto != null) {
                    accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                    bookGroupServe.setTypeCode(appDto.getTypeCode());
                }
            } else if (AppAndProductTypeEnum.PRODUCT.value.equalsIgnoreCase(bookGroupServe.getServeType())){
                ProductDto productDto = productConsr.getProBaseById(bookGroupServe.getServeId());
                if (null != productDto){
                    bookGroupServe.setTypeCode(productDto.getProductTypeDto()==null?null:productDto.getProductTypeDto().getTypeCode());
                }
            }
            // 处理链接地址
            String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupId;
            String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
            //转短链
            String resultUrl = UrlUtils.getShortUrl4Own(linkUrl);
            bookGroupServe.setShortUrl(resultUrl);
            bookGroupServe.setCreateUser(partyId);
        }
        bookGroupServeDao.batchInsert(bookGroupServes);
        //将作品应用关键词加到社群书应用
        bookGroupAppBiz.addServeToBookGroupApp(bookGroupServes);
        Map<Long, List<BookGroupServe>> listMap = bookGroupServes.stream().filter(s -> AppAndProductTypeEnum.PRODUCT.value.equalsIgnoreCase(s.getServeType())).collect(Collectors.groupingBy(s -> s.getBookGroupId()));
        for (Long bookGroupId : bookGroupIds) {
            List<BookGroupServe> list = listMap.get(bookGroupId);
            if (!ListUtils.isEmpty(list)) {
                BookGroupDTO dto = dtoMap.get(bookGroupId);
                List<Long> productIds = list.stream().filter(s -> s.getServeId() != null).map(BookGroupServe::getServeId).collect(Collectors.toList());
                //自动上架
                productConsr.productAutoOnShelves(dto.getChannelId(), productIds);
            }
        }
    }

    @ParamLog("删除资源配置")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBookGroupServe( Long id ) {
        if (id == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
        }
        bookGroupServeDao.deleteById(id);
    }

    @ParamLog("获取资源配置集合")
    @Override
    public List<BookGroupServe> getBookGroupServeList( Long bookGroupId ) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        List<BookGroupServe> list = bookGroupServeDao.getListByBookGroupId(bookGroupId);
        if (ListUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        fillServeInfo(list);
        return list;
    }

    @ParamLog("客户端获取资源配置集合")
    @Override
    public PageBeanNew<BookGroupServe> getBookGroupServeList4Wechat( Long bookGroupId, Integer currentPage, Integer numPerPage ) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        if (currentPage == null || numPerPage == null || currentPage < 0 || numPerPage <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "分页参数有误！");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("bookGroupId", bookGroupId);
        PageBeanNew<BookGroupServe> pageBeanNew = bookGroupServeDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getListByBookGroupId");
        fillServeInfo(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    @ParamLog("客户端获取资源配置集合")
    @Override
    public BookServeResourceDTO getBookGroupServeListByBookGroupId( Long bookGroupId ) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        BookServeResourceDTO bookResourceDTO = new BookServeResourceDTO();

        SearchBookVO bookInfo = bookBiz.getBookInfoByBookGroupId(bookGroupId);
        bookResourceDTO.setAgentName(bookInfo.getAgentName());
        bookResourceDTO.setAuthor(bookInfo.getAuthor());
        bookResourceDTO.setBookCoverImg(bookInfo.getCoverImg());
        bookResourceDTO.setBookId(bookInfo.getBookId());
        bookResourceDTO.setBookName(bookInfo.getBookName());
        bookResourceDTO.setAdviserId(bookInfo.getAdviserId());
        bookResourceDTO.setChannelId(bookInfo.getChannelId());

        List<BookGroupServe> bookGroupServes = resourcePageBiz.getServeListByBookGroupId(bookGroupId);
        bookResourceDTO.setMessages(fillMessages(bookGroupServes, bookInfo.getChannelId(), bookGroupId));
        bookResourceDTO.setOriginalCost(setQrMessagePrice(bookResourceDTO.getMessages(), bookInfo.getChannelId()));
        return bookResourceDTO;
    }

    private List<WechatMessageDTO> fillMessages( List<BookGroupServe> list, Long channelId, Long bookGroupId) {
        if (ListUtils.isEmpty(list)) {
            return Lists.newArrayList();
        }
        AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
        List<Long> productIds = new ArrayList<>();
        List<Long> appIds = new ArrayList<>();
        for (BookGroupServe bookGroupServe : list) {
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                productIds.add(bookGroupServe.getServeId());
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                appIds.add(bookGroupServe.getServeId());
            }
        }

        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMap = productConsr.getProBasesByIds(productIds);
        }
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMap = appConsr.mapByIds(appIds);
        }
        List<WechatMessageDTO> messages = Lists.newArrayList();
        WechatMessageDTO wechatMessageDTO;
        for (BookGroupServe bookGroupServe : list) {
            wechatMessageDTO = new WechatMessageDTO();
            // 处理链接地址
            String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupId;
            String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                ProductDto productDto = productDtoMap.get(bookGroupServe.getServeId());
                if (productDto != null) {
                    wechatMessageDTO.setPosterPicUrl(productDto.getPicture1());
                    wechatMessageDTO.setCoverImg(productDto.getCoverImg());
                    wechatMessageDTO.setFromId(productDto.getProductId());
                    wechatMessageDTO.setFromType(productDto.getProductTypeDto().getTypeCode());
                    wechatMessageDTO.setPrice(productDto.getRetailPrice());
                    wechatMessageDTO.setShortName(productDto.getShortName());
                    wechatMessageDTO.setTitle(productDto.getProductName());
                    wechatMessageDTO.setTypeCode(bookGroupServe.getServeType());
                    wechatMessageDTO.setUrl(linkUrl);
                    messages.add(wechatMessageDTO);
                }
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
                if (appDto != null) {
                    wechatMessageDTO.setPosterPicUrl(appDto.getTransverseImg());
                    wechatMessageDTO.setCoverImg(appDto.getSquareImg());
                    wechatMessageDTO.setFromId(appDto.getAppId());
                    wechatMessageDTO.setFromType(appDto.getTypeCode());
                    wechatMessageDTO.setPrice(appDto.getRetailPrice());
                    wechatMessageDTO.setShortName(appDto.getShortTitle());
                    wechatMessageDTO.setTitle(appDto.getTitle());
                    wechatMessageDTO.setTypeCode(bookGroupServe.getServeType());
                    wechatMessageDTO.setUrl(linkUrl);
                    messages.add(wechatMessageDTO);
                }
            }
        }
        return messages;
    }


    private BigDecimal setQrMessagePrice( List<WechatMessageDTO> wechatMessages, Long chennelId ) {
        if (CollectionUtils.isEmpty(wechatMessages)) {
            return BigDecimal.ZERO;
        }
        final List<Long> productIds = Lists.newArrayList();
        final List<AppPriceCacheDTO> appPriceCacheDTOS = Lists.newArrayList();
        for (WechatMessageDTO message : wechatMessages) {
            if (ChannelEnum.PRODUCT.value.equals(message.getTypeCode())) {
                productIds.add(message.getFromId());
            }
            if (ChannelEnum.APP.value.equals(message.getTypeCode())) {
                AppPriceCacheDTO dto = new AppPriceCacheDTO();
                dto.setAppId(message.getFromId());
                dto.setAppTypeEnum(AppTypeEnum.APP_TYPE_MAP.get(message.getFromType()));
                appPriceCacheDTOS.add(dto);
            }

        }
        final Map<Long, BigDecimal> appPrice = this.appConsr.getAppPrice(appPriceCacheDTOS);
        final Map<Long, ProductDto> priceInfo = this.productConsr.getProPriceInfo(productIds, chennelId);
        BigDecimal originalCost = BigDecimal.ZERO;
        for (WechatMessageDTO message : wechatMessages) {
            if (ChannelEnum.PRODUCT.value.equals(message.getTypeCode()) && !CollectionUtils.isEmpty(priceInfo)) {
                final ProductDto productDto = priceInfo.get(message.getFromId());
                if (null == productDto || CollectionUtils.isEmpty(productDto.getSpecification())) {
                    continue;
                }
                final Double retailPrice = productDto.getSpecification().get(0).getRetailPrice();
                message.setPrice(new BigDecimal(null == retailPrice ? 0 : retailPrice));
            }
            if (ChannelEnum.APP.value.equals(message.getTypeCode()) && !CollectionUtils.isEmpty(appPrice)) {
                final BigDecimal price = appPrice.get(message.getFromId());
                if (null == price) {
                    continue;
                }
                message.setPrice(price);
            }
            if (null != message.getPrice()) {
                originalCost = originalCost.add(message.getPrice());
            }
        }
        return originalCost;
    }

    @ParamLog("填充资源信息")
    private void fillServeInfo( List<BookGroupServe> list ) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Long> productIds = new ArrayList<>();
        List<Long> appIds = new ArrayList<>();
        for (BookGroupServe bookGroupServe : list) {
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                productIds.add(bookGroupServe.getServeId());
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                appIds.add(bookGroupServe.getServeId());
            }
        }
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        Map<Long, Boolean> isSuperMap = new HashMap<>();
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMap = productConsr.getProBasesByIds(productIds);
            isSuperMap = productConsr.getIsSuperByProductIdList(productIds);
        }
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMap = appConsr.mapByIds(appIds);
        }
        for (BookGroupServe bookGroupServe : list) {
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                ProductDto productDto = productDtoMap.get(bookGroupServe.getServeId());
                if (productDto != null) {
                    bookGroupServe.setServeName(productDto.getProductName());
                    bookGroupServe.setPicUrl(productDto.getCoverImg());
                    if (productDto.getProductTypeDto() != null) {
                        bookGroupServe.setTypeCode(productDto.getProductTypeDto().getTypeCode());
                        bookGroupServe.setFromType(productDto.getProductTypeDto().getTypeName());
                    }
                    bookGroupServe.setIsSuper(isSuperMap.get(bookGroupServe.getServeId()));
                    bookGroupServe.setMerchantId(productDto.getAuthor());
                }
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
                if (appDto != null) {
                    bookGroupServe.setServeName(appDto.getTitle());
                    bookGroupServe.setTypeCode(appDto.getTypeCode());
                    bookGroupServe.setPicUrl(appDto.getSquareImg());
                    bookGroupServe.setFromType(appDto.getTypeName());
                }
            }
        }
    }

    @ParamLog("获取社群码暗号")
    @Override
    public String getBookGroupCipher() {
        String bookGroupCipher = createBookGroupCipher();
        //判断是否为库里面没有的
        BookGroup bookGroup = bookGroupDao.getByBookGroupCipher(bookGroupCipher);
        if (bookGroup != null) {
            //重新生成
            bookGroupCipher = createBookGroupCipher();
        }
        return bookGroupCipher;
    }

    @ParamLog("校验字段")
    private void checkBookGroupServe( List<BookGroupServe> bookGroupServes ) {
        if (ListUtils.isEmpty(bookGroupServes)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
        }
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            if (bookGroupServe == null) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数不能为空！");
            }
            if (bookGroupServe.getBookGroupId() == null) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数社群书id不能为空！");
            }
            if (bookGroupServe.getServeId() == null) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数应用或作品id不能为空！");
            }
            if (StringUtil.isEmpty(bookGroupServe.getServeUrl())) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "链接不能为空！");
            }
            if (!("PRODUCT".equals(bookGroupServe.getServeType()) || "APP".equals(bookGroupServe.getServeType()))) {
                throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数应用或作品类型有误（APP或PRODUCT）！");
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("批量更新资源配置")
    @Override
    public void batchUpdateBookGroupServe( Long partyId, List<BookGroupServe> bookGroupServes ) {
        checkBookGroupServe(bookGroupServes);
        List<Long> bookGroupIds = bookGroupServes.stream().filter(s -> s.getBookGroupId() != null).map(BookGroupServe::getBookGroupId).distinct().collect(Collectors.toList());
        //删除之前旧的
        bookGroupServeDao.deleteByBookGroupIds(bookGroupIds);
        //批量新增新的
        batchAddBookGroupServe(partyId, bookGroupServes);
    }

    @ParamLog("将1v1旧数据的关键词全部都干掉，有应用或作品的挂在社群书配置资源里面")
    @Override
    public void dealSelfBookGroupKeywordToServer() {
        List<BookGroup> bookGroups = bookGroupDao.getBookGroupByJoinGroupType(JoinGroupTypeEnum.ROBOT.getCode());
        if (ListUtils.isEmpty(bookGroups)) {
            return;
        }
        List<Long> bookGroupIds = bookGroups.stream().filter(s -> s.getId() != null).map(BookGroup::getId).collect(Collectors.toList());
        //查询关键词
        List<KeywordDTO> keywordDTOS = bookKeywordDao.getListByBookGroupIdsAndType(bookGroupIds, ReplyTypeEnum.APP.value);
        if (ListUtils.isEmpty(keywordDTOS)) {
            return;
        }
        Map<Long, List<KeywordDTO>> map = keywordDTOS.stream().filter(s -> s.getBookGroupId() != null).collect(Collectors.groupingBy(KeywordDTO::getBookGroupId));
        for (BookGroup bookGroup : bookGroups) {
            Long bookGroupId = bookGroup.getId();
            List<KeywordDTO> list = map.get(bookGroupId);
            if (ListUtils.isEmpty(list)) {
                continue;
            }
            //查询有没有配置资源，如果没有则新增加入
            List<BookGroupServe> bookGroupServes = bookGroupServeDao.getListByBookGroupId(bookGroupId);
            if (!ListUtils.isEmpty(bookGroupServes)) {
                continue;
            }
            List<BookGroupServe> bookGroupServesNew = new ArrayList<>();
            for (KeywordDTO keywordDTO : list) {
                BookGroupServe bookGroupServe = new BookGroupServe();
                bookGroupServe.setBookGroupId(bookGroupId);
                bookGroupServe.setServeId(keywordDTO.getServeId());
                bookGroupServe.setServeType(keywordDTO.getServeType());
                bookGroupServe.setCreateUser(bookGroup.getCreateUser());
                bookGroupServe.setServeUrl(keywordDTO.getLinkUrl());
                // 处理链接地址
                String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupId;
                AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(bookGroup.getChannelId());
                if ("APP".equalsIgnoreCase(bookGroupServe.getServeType())) {
                    AppDto appDto = appConsr.getBaseById(bookGroupServe.getServeId());
                    if (appDto != null) {
                        accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                    }
                }
                String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
                //转短链
                String resultUrl = UrlUtils.getShortUrl4Own(linkUrl);
                bookGroupServe.setShortUrl(resultUrl);
                bookGroupServesNew.add(bookGroupServe);
            }
            if (!ListUtils.isEmpty(bookGroupServesNew)) {
                bookGroupServeDao.batchInsert(bookGroupServesNew);
            }
        }
        //按照社群码id集合把关键词逻辑删除
        bookKeywordDao.deleteByBookGroupIds(bookGroupIds);
    }

    @ParamLog("补充1v1旧数据的暗号")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void fillSelfBookGroupCipher() {
        List<BookGroup> bookGroups = bookGroupDao.getNoCipherSelfBookGroups();
        if (ListUtils.isEmpty(bookGroups)) {
            return;
        }
        for (BookGroup bookGroup : bookGroups) {
            String groupCipher = getBookGroupCipher();
            bookGroupDao.updateCipher(bookGroup.getId(), groupCipher);
        }
    }

    @ParamLog("将之前的配置资源取的社群码运营更新为应用本身的运营")
    @Override
    public void dealBookGroupServerChannel() {
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getListByServerType("APP");
        if (ListUtils.isEmpty(bookGroupServes)) {
            return;
        }
        List<Long> appIds = new ArrayList<>();
        List<Long> bookGroupIds = new ArrayList<>();
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            if (!appIds.contains(bookGroupServe.getServeId())) {
                appIds.add(bookGroupServe.getServeId());
            }
            if (!bookGroupIds.contains(bookGroupServe.getBookGroupId())) {
                bookGroupIds.add(bookGroupServe.getBookGroupId());
            }
        }
        Map<Long, AppDto> appDtoMap = appConsr.getBaseByIds(appIds);
        List<BookGroupDTO> bookGroupDTOList = bookGroupDao.getDTOByIds(bookGroupIds);
        Map<Long, BookGroupDTO> bookGroupMap = new HashMap<>();
        for (BookGroupDTO bookGroupDTO : bookGroupDTOList) {
            bookGroupMap.put(bookGroupDTO.getId(), bookGroupDTO);
        }
        for (BookGroupServe bookGroupServe : bookGroupServes) {
            AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
            BookGroupDTO bookGroupDTO = bookGroupMap.get(bookGroupServe.getBookGroupId());
            if (appDto != null && bookGroupDTO != null && !appDto.getChannelId().equals(bookGroupDTO.getChannelId())) {
                //换链接
                String endUrl = bookGroupServe.getServeUrl() + "&book_group_id=" + bookGroupServe.getBookGroupId();
                AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                String linkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, endUrl);
                //转短链
                String resultUrl = UrlUtils.getShortUrl4Own(linkUrl);
                bookGroupServeDao.updateShortUrl(bookGroupServe.getId(), resultUrl);
            }
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新是否邀请入群")
    @Override
    public void updateIsInviteGroup( BookGroup bookGroup ) {
        if (bookGroup == null || bookGroup.getId() == null || bookGroup.getIsInviteGroup() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        BookGroupDTO oldBookGroup = bookGroupDao.getDTOById(bookGroup.getId());
        if (oldBookGroup == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码不存在！");
        }
        bookGroupDao.updateIsInviteGroup(bookGroup.getId(), bookGroup.getIsInviteGroup());
        //如果从不邀请进群修改为邀请进群则视为更新
        if (oldBookGroup.getIsInviteGroup() != null && !oldBookGroup.getIsInviteGroup() && bookGroup.getIsInviteGroup()) {
            bookGroupDao.updateIsSomeUpdate(bookGroup.getId(), true);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("更新1v1是否有更新")
    @Override
    public void updateIsSomeUpdate( BookGroup bookGroup ) {
        if (bookGroup == null || bookGroup.getId() == null || bookGroup.getIsSomeUpdate() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        Long bookGroupId = bookGroup.getId();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO != null && JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            bookGroupDao.updateIsSomeUpdate(bookGroupId, bookGroup.getIsSomeUpdate());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("新增推送更新")
    @Override
    public void addPushBookGroupUpdate( BookGroup bookGroup ) {
        if (bookGroup == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        Long bookGroupId = bookGroup.getId();
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该社群码！");
        }
        if (!JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "该社群码不是1v1模式！");
        }
        if (bookGroupDTO.getIsSomeUpdate() == null || !bookGroupDTO.getIsSomeUpdate()) {
            LOGGER.info("没有更新！bookGroupId=" + bookGroupId);
            return;
        }
        if (bookGroupDTO.getLastPushUpdateTime() != null && (new Date().getTime() - bookGroupDTO.getLastPushUpdateTime().getTime() < 7 * 24 * 60 * 60 * 1000)) {
            LOGGER.info("距离上次更新不到7天！bookGroupId=" + bookGroupId);
            return;
        }
        //查询已经关联的用户wxUserIds
        List<BookGroupCipherUser> bookGroupCipherUsers = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupId(bookGroupId);
        if (ListUtils.isEmpty(bookGroupCipherUsers)) {
            LOGGER.info("该社群书没有用户bookGroupId=" + bookGroupId);
            return;
        }
        if (bookGroupCipherUsers.size() > 100) {
            LOGGER.info("该社群书用户数量超过100，不处理bookGroupId=" + bookGroupId);
            return;
        }
        List<PushBookGroupUpdate> pushBookGroupUpdates = new ArrayList<>();
        for (BookGroupCipherUser bookGroupCipherUser : bookGroupCipherUsers) {
            PushBookGroupUpdate pushBookGroupUpdate = new PushBookGroupUpdate();
            pushBookGroupUpdate.setBookGroupId(bookGroupId);
            pushBookGroupUpdate.setWxUserId(bookGroupCipherUser.getWxUserId());
            pushBookGroupUpdate.setAltId(bookGroupCipherUser.getAltId());
            pushBookGroupUpdate.setIsPush(false);
            pushBookGroupUpdates.add(pushBookGroupUpdate);
        }
        pushBookGroupUpdateDao.batchInsert(pushBookGroupUpdates);
        bookGroupDao.updateLastPushUpdateTime(bookGroupId);
        bookGroupDao.updateIsSomeUpdate(bookGroupId, false);
    }

    @ParamLog("推送更新")
    @Override
    public void pushBookGroupUpdate() {
        PushBookGroupUpdate pushBookGroupUpdate = pushBookGroupUpdateDao.getEarliestPushBookGroupUpdate();
        if (pushBookGroupUpdate != null) {
            Integer count = pushBookGroupUpdateDao.updateIsPushTrue(pushBookGroupUpdate.getId());
            if (count == 0) {
                LOGGER.info("此条已更新pushBookGroupUpdate=" + pushBookGroupUpdate.toString());
                return;
            }
            try {
                LOGGER.info("开始推送pushBookGroupUpdate=" + pushBookGroupUpdate.toString());
                SendTextDTO sendTextDTO = new SendTextDTO();
                sendTextDTO.setWxId(pushBookGroupUpdate.getAltId());
                sendTextDTO.setCode(SendMessageTypeEnum.SELF.getCode());
                //获取小号基本信息，获取ip
                GroupRobotDTO groupRobotDTO = wechatGroupConsr.getGroupRobotByWxId(pushBookGroupUpdate.getAltId());
                if (groupRobotDTO != null) {
                    Integer version = groupRobotDTO.getVersion();
                    WeixinQrcodeGeneration weixinQrcodeGeneration = weixinQrcodeGenerationDao.getByGeneration(version);
                    if (weixinQrcodeGeneration != null) {
                        sendTextDTO.setIp(weixinQrcodeGeneration.getWechatGroupIp());
                    }
                }
                sendTextDTO.setWechatUserId(pushBookGroupUpdate.getWxUserId());
                bookKeywordBiz.dealByBookGroup(sendTextDTO, pushBookGroupUpdate.getBookGroupId(), true);
            } catch (Exception e) {
                LOGGER.error("推送更新出错pushBookGroupUpdate=" + pushBookGroupUpdate.toString() + e.getMessage());
            } finally {
                pushBookGroupUpdateDao.updateIsPushTrue(pushBookGroupUpdate.getId());
            }
        }
    }

    @ParamLog("获取是否能推送更新的各个状态")
    @Override
    public Map<String, Boolean> getStatesForPushUpdate( Long bookGroupId ) {
        if (bookGroupId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数有误！");
        }
        Map<String, Boolean> map = new HashMap<>();
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
        if (bookGroupDTO == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "没有该社群码！");
        }
        if (bookGroupDTO.getIsSomeUpdate() != null && bookGroupDTO.getIsSomeUpdate()) {
            map.put("isSomeUpdate", true);
        } else {
            map.put("isSomeUpdate", false);
        }
        if (bookGroupDTO.getLastPushUpdateTime() != null && (new Date().getTime() - bookGroupDTO.getLastPushUpdateTime().getTime() < 7 * 24 * 60 * 60 * 1000)) {
            map.put("isMoreThan7days", false);
        } else {
            map.put("isMoreThan7days", true);
        }
        //查询已经关联的用户wxUserIds
        List<BookGroupCipherUser> bookGroupCipherUsers = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupId(bookGroupId);
        if (!ListUtils.isEmpty(bookGroupCipherUsers) && bookGroupCipherUsers.size() < 100) {
            map.put("isPersonSizeSuitable", true);
        } else {
            map.put("isPersonSizeSuitable", false);
        }
        return map;
    }

    @ParamLog("上架所有的个人号配置资源")
    @Override
    public void dealBookGroupServeOldOnShelves() {
        //查询所有的配置资源作品
        List<BookGroupServe> list = bookGroupServeDao.getProductServeList();
        if (!ListUtils.isEmpty(list)) {
            List<Long> bookGroupIds = list.stream().map(BookGroupServe::getBookGroupId).distinct().collect(Collectors.toList());
            List<BookGroupDTO> dtos = bookGroupDao.getDTOByIds(bookGroupIds);
            Map<Long, Long> channelMap = new HashMap<>();
            for (BookGroupDTO bookGroupDTO : dtos) {
                channelMap.put(bookGroupDTO.getId(), bookGroupDTO.getChannelId());
            }
            Map<Long, List<BookGroupServe>> map = list.stream().collect(Collectors.groupingBy(BookGroupServe::getBookGroupId));
            for (Long bookGroupId : bookGroupIds) {
                List<BookGroupServe> bookGroupServes = map.get(bookGroupId);
                Long channelId = channelMap.get(bookGroupId);
                if (!ListUtils.isEmpty(bookGroupServes) && channelId != null) {
                    List<Long> productIds = bookGroupServes.stream().filter(s -> s.getServeId() != null).map(BookGroupServe::getServeId).collect(Collectors.toList());
                    //上架
                    productConsr.productAutoOnShelves(channelId, productIds);
                }
            }
        }
    }

    @ParamLog("生成暗号")
    private String createBookGroupCipher() {
        //生成暗号规则：abc1234，前三位小写字母，后四位数字
        Random random = new Random();
        String s = "";
        for (int i = 0; i < 3; i++) {
            int result = 97 + random.nextInt(26);
            s = s + String.valueOf((char) result);
        }
        for (int i = 0; i < 4; i++) {
            int result = random.nextInt(10);
            s = s + String.valueOf(result);
        }
        return s;
    }

    @Override
    public PageBeanNew<BookGroupAnalysisVO> listPageBookGroupAnalysis( BookGroupAnalysisParam bookGroupAnalysisParam ) {
        Map<String, Object> paramMap = new HashMap<>();
        if (!ListUtils.isEmpty(bookGroupAnalysisParam.getBookIds())) {
            paramMap.put("bookIds", bookGroupAnalysisParam.getBookIds());
        }
        if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAdviserIds())) {
            paramMap.put("adviserIds", bookGroupAnalysisParam.getAdviserIds());
        }
        if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAgentIds())) {
            paramMap.put("agentIds", bookGroupAnalysisParam.getAgentIds());
        }
        if (null != bookGroupAnalysisParam.getIsFundSupport()){
            paramMap.put("isFundSupport", bookGroupAnalysisParam.getIsFundSupport());
        }
        if (null != bookGroupAnalysisParam.getIsCopyright()){
            paramMap.put("isCopyright", bookGroupAnalysisParam.getIsCopyright());
        }
        String monthDate = bookGroupAnalysisParam.getMonthDate();
        String monthKey = monthDate == null?"all":monthDate;
        String key = BookBusinessConstants.AGENT_STATISTIC;
        String field = bookGroupAnalysisParam.getCurrentPage()+"_"+bookGroupAnalysisParam.getNumPerPage()+"_"+monthKey;
        String countKey = BookBusinessConstants.AGENT_STATISTIC_COUNT;
        if (MapUtils.isEmpty(paramMap)){
            List<BookGroupAnalysisVO> list = JedisClusterUtils.hgetJson2List(key,field,BookGroupAnalysisVO.class);
            Integer count= 0;
            if (!StringUtil.isEmpty(JedisClusterUtils.get(countKey))){
                count = Integer.valueOf(JedisClusterUtils.get(countKey));
            }
            if (!ListUtils.isEmpty(list) && count>0){
                return new PageBeanNew<>(bookGroupAnalysisParam.getCurrentPage(),bookGroupAnalysisParam.getNumPerPage(),count,list);
            }
        }
        PageBeanNew<BookGroupAnalysisVO> pageBeanNew = bookGroupDao.listPageNew(
                new PageParam(bookGroupAnalysisParam.getCurrentPage(), bookGroupAnalysisParam.getNumPerPage()), paramMap, "listPageBookGroupAnalysis");
        if (null == pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())) {
            return new PageBeanNew<>(bookGroupAnalysisParam.getCurrentPage(), bookGroupAnalysisParam.getNumPerPage(), 0, new ArrayList<>());
        }
        //设置书刊分类名称
        groupSet.setTempletName(pageBeanNew.getRecordList());
        //设置出版运营编辑名称
        groupSet.setPartyInfo(pageBeanNew.getRecordList());
        //设置社群码扫码量
        groupSet.setGroupScanCount(pageBeanNew.getRecordList(), monthDate);
        //设置微信群数据（分类数，群数，群人数，好友数，资源数）
        groupSet.setGroupStatistic(pageBeanNew.getRecordList(), monthDate);
        //设置资源数据(浏览量，读者量，销售额，支付率，客单价)
        groupSet.setResourceStatistic(pageBeanNew.getRecordList(), monthDate);
        if (MapUtils.isEmpty(paramMap)){
            JedisClusterUtils.hset2Json(key,field,pageBeanNew.getRecordList());
            JedisClusterUtils.expire(key,60);
            JedisClusterUtils.set(countKey,String.valueOf(pageBeanNew.getTotalCount()),60);
        }
        return pageBeanNew;
    }

    @Override
    public void exportBookGroupAnalysis( BookGroupAnalysisParam bookGroupAnalysisParam, Long partyId ) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            Map<String, Object> paramMap = new HashMap<>();
            if (!ListUtils.isEmpty(bookGroupAnalysisParam.getBookIds())) {
                paramMap.put("bookIds", bookGroupAnalysisParam.getBookIds());
            }
            if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAdviserIds())) {
                paramMap.put("adviserIds", bookGroupAnalysisParam.getAdviserIds());
            }
            if (!ListUtils.isEmpty(bookGroupAnalysisParam.getAgentIds())) {
                paramMap.put("agentIds", bookGroupAnalysisParam.getAgentIds());
            }
            paramMap.put("isFundSupport", bookGroupAnalysisParam.getIsFundSupport());
            paramMap.put("isCopyright", bookGroupAnalysisParam.getIsCopyright());
            List<BookGroupAnalysisVO> list = bookGroupDao.listPageBookGroupAnalysis(paramMap);
            if (ListUtils.isEmpty(list)) {
                return;
            }
            String monthDate = bookGroupAnalysisParam.getMonthDate();
            //设置书刊分类名称
            groupSet.setTempletName(list);
            //设置出版运营编辑名称
            groupSet.setPartyInfo(list);
            //设置社群码扫码量
            groupSet.setGroupScanCount(list, monthDate);
            //设置微信群数据（分类数，群数，群人数，好友数，资源数）
            groupSet.setGroupStatistic(list, monthDate);
            //设置资源数据(浏览量，读者量，销售额，支付率，客单价)
            groupSet.setResourceStatistic(list, monthDate);

            Boolean isSuccess = true;
            String fileUrl = "";
            String fileName = "社群书分析";
            if (!StringUtil.isEmpty(monthDate)) {
                String[] dateStr = monthDate.split("-");
                fileName = dateStr[0] + "年" + Integer.parseInt(dateStr[1]) + "月" + fileName;
            }
            try {
                fileUrl = groupSet.fillBookGroupExcel(list, fileName);
            } catch (Exception e) {
                isSuccess = false;
                LOGGER.error("导出文件失败" + e.getMessage(), e);
            }
            if (isSuccess) {
                JSONObject content = new JSONObject();
                content.put("commitTime", DateUtils.formatDate(new Date()));
                content.put("type", "社群书分析导出");
                messageConsr.sendLetter(partyId, partyId, content.toJSONString(), SystemCode.pcloud.code, "book_download", fileUrl, fileName);
            }
        });
    }

    @Override
    public List<BookGroupKeywordResourceDTO> getKeyWordResourceByBookGroup( Long bookGroupId ) {
        List<BookGroupKeywordResourceDTO> list = bookKeywordDao.getBookGroupResourceList(bookGroupId);
        return list;
    }

    @Override
    public List<Long> getQrcodeIdsByBookGroupId( Long bookGroupId ) {
        List<Long> ids = groupQrcodeDao.getIdsByBookGroupId(bookGroupId);
        return ids;
    }

    @Override
    public List<String> getFriendIdsByBookGroupId( Long bookGroupId ) {
        return bookGroupCipherUserDao.getFriendIdsByBookGroupId(bookGroupId);
    }

    @Override
    public PageBeanNew<SelfRobotUserDTO> listPageFriendInfo( SelfRobtParamDTO selfRobtParamDTO ) {
        Map<String, Object> paramMap = new HashMap<>();
        if (!ListUtils.isEmpty(selfRobtParamDTO.getUserIds())) {
            paramMap.put("userIds", selfRobtParamDTO.getUserIds());
        }
        if (!ListUtils.isEmpty(selfRobtParamDTO.getRobotIds())) {
            paramMap.put("robotIds", selfRobtParamDTO.getRobotIds());
        }
        if (!ListUtils.isEmpty(selfRobtParamDTO.getBookIds())) {
            paramMap.put("bookIds", selfRobtParamDTO.getBookIds());
        }
        if (null != selfRobtParamDTO.getFriendState() && !ListUtils.isEmpty(selfRobtParamDTO.getDeleteUserDTOS())) {
            paramMap.put("friendState", selfRobtParamDTO.getFriendState());
            paramMap.put("deleteUserList", selfRobtParamDTO.getDeleteUserDTOS());
        }
        List<SelfRobotUserDTO> totalList = bookGroupCipherUserDao.listPageFriendInfo(paramMap);
        if (ListUtils.isEmpty(totalList)) {
            return new PageBeanNew<>();
        }
        Integer totalCount = totalList.size();
        paramMap.put("pageNum", selfRobtParamDTO.getCurrentPage() * selfRobtParamDTO.getNumPerPage());
        paramMap.put("numPerPage", selfRobtParamDTO.getNumPerPage());
        List<SelfRobotUserDTO> list = bookGroupCipherUserDao.listPageFriendInfo(paramMap);
        for (SelfRobotUserDTO userDTO : list) {
            List<BookDto> bookList = bookGroupCipherUserDao.getBookGroupListByUser(userDTO.getWxUserId(), userDTO.getRobotId());
            userDTO.setBookList(bookList);
        }
        PageBeanNew<SelfRobotUserDTO> pageBeanNew = new PageBeanNew(selfRobtParamDTO.getCurrentPage(), selfRobtParamDTO.getNumPerPage(), totalCount, list);
        return pageBeanNew;
    }

    @ParamLog("根据类型获取社群书数量")
    @Override
    public Integer getBookGroupCountByJoinGroupType( Integer joinGroupType ) {
        return bookGroupDao.getBookGroupCountByJoinGroupType(joinGroupType);
    }

    @ParamLog("获取个人号累计加好友人数")
    @Override
    public Integer getAddFriendCount() {
        return bookGroupCipherUserDao.getAddFriendCount();
    }

    @Override
    public Integer getAddFriendCount4Times(List<Long> agentIds) {
        return bookGroupCipherUserDao.getAddFriendCount4Times(agentIds);
    }

    @ParamLog("根据时间段获取个人号加好友人数")
    @Override
    public List<CountAndTimeDTO> getAddFriendCountByTime( Integer timeType, String startTime, String endTime ) {
        if (timeType == null || (1 != timeType && 2 != timeType)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "时间类型参数错误！");
        }
        if (StringUtil.isEmpty(startTime) || StringUtil.isEmpty(endTime)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "时间参数错误！");
        }
        List<CountAndTimeDTO> list = bookGroupCipherUserDao.getAddFriendCountByTime(timeType, startTime, endTime);
        groupSet.fillEmptyTime(list, timeType, startTime, endTime);
        list = list.stream().sorted(Comparator.comparing(CountAndTimeDTO::getTime)).collect(Collectors.toList());
        return list;
    }

    @ParamLog("获取出版社创建社群书数量排行")
    @Override
    public List<TopAgentBookGroupDTO> getTopAgentCreateBookGroup( Integer joinGroupType, Integer top, Boolean isSpecial ) {
        if (top == null || top < 0 || isSpecial == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误");
        }
        List<Long> allAgentId = null;
        if (isSpecial) {
            allAgentId = wechatGroupConsr.getAllAgentId();
            if (ListUtils.isEmpty(allAgentId)) {
                allAgentId = Lists.newArrayList(-1L);
            }
        }
        List<TopAgentBookGroupDTO> dtos = bookGroupDao.getTopAgentCreateBookGroup(joinGroupType, top, allAgentId);
        if (!ListUtils.isEmpty(dtos)) {
            List<Long> agentIds = dtos.stream().filter(s -> s.getAgentId() != null).map(TopAgentBookGroupDTO::getAgentId).collect(Collectors.toList());
            if (!ListUtils.isEmpty(agentIds)) {
                Map<Long, String> namesMap = agentConsr.getNames(agentIds);
                if (namesMap != null) {
                    for (TopAgentBookGroupDTO topAgentBookGroupDTO : dtos) {
                        topAgentBookGroupDTO.setAgentName(namesMap.get(topAgentBookGroupDTO.getAgentId()));
                    }
                }
            }
        }
        return dtos;
    }

    @ParamLog("补充社群书的出版社id")
    @Override
    public void fillAgentIdForBookGroup() {
        List<Long> adviserIds = bookGroupDao.getEmptyAgentIdAdviserId();
        if (ListUtils.isEmpty(adviserIds)) {
            return;
        }
        //根据adviserId拿agentId
        Map<Long, AdviserBaseInfoDto> infoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        if (infoDtoMap == null) {
            return;
        }
        //根据adviserId更新
        for (Long adviserId : adviserIds) {
            AdviserBaseInfoDto adviserBaseInfoDto = infoDtoMap.get(adviserId);
            if (adviserBaseInfoDto != null && adviserBaseInfoDto.getAgentId() != null) {
                bookGroupDao.updateAgentIdByAdviserId(adviserId, adviserBaseInfoDto.getAgentId());
            }
        }
    }

    @ParamLog("获取所有已建分类的1v1的社群码")
    @Override
    public List<Long> get1v1HasClassifyBookGroupIds() {
        return bookGroupDao.get1v1HasClassifyBookGroupIds();
    }

    @ParamLog("获取个人号读者专业或深度分布")
    @Override
    public List<LabelUserCountDTO> getUserLabelDistribution( Integer largeTemplet, Integer type ) {
        if (type == null || (type != 1 && type != 2) || largeTemplet == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误");
        }
        // 根据类型拿所有小号
        List<String> altIds = wechatGroupConsr.getRobotListByLargeTemplet(largeTemplet);
        List<LabelUserCountDTO> labelUserCountDTOS = bookGroupCipherUserDao.getUserLabelDistribution(type, altIds);
        if (!ListUtils.isEmpty(labelUserCountDTOS)) {
            List<Long> labelIds = labelUserCountDTOS.stream().filter(s -> s.getLabelId() != null).map(LabelUserCountDTO::getLabelId).collect(Collectors.toList());
            Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
            if (!MapUtils.isEmpty(labelMap)) {
                for (LabelUserCountDTO labelUserCountDTO : labelUserCountDTOS) {
                    labelUserCountDTO.setLabelName(labelMap.get(labelUserCountDTO.getLabelId()));
                }
            }
        }
        return labelUserCountDTOS;
    }

    @Override
    @ParamLog("获取出版社个人号统计信息")
    public PageBeanNew<AgentStatisticsInfoDTO> getAgentStatisticsInfo( Long agentId, Boolean isSpecial, Integer currentPage, Integer numPerPage ) {
        if (currentPage == null || numPerPage == null || currentPage < 0 || numPerPage < 0) {
            throw BookBizException.PAGE_PARAM_DELETION;
        }
        isSpecial = isSpecial==null?false:isSpecial;
        String key = BookBusinessConstants.AGENT_STATISTIC;
        String field = currentPage+"_"+numPerPage;
        String countKey = BookBusinessConstants.AGENT_STATISTIC_COUNT;
        if (null == agentId && !isSpecial){
            List<AgentStatisticsInfoDTO> list = JedisClusterUtils.hgetJson2List(key,field,AgentStatisticsInfoDTO.class);
            Integer count= 0;
            if (!StringUtil.isEmpty(JedisClusterUtils.get(countKey))){
                count = Integer.valueOf(JedisClusterUtils.get(countKey));
            }
            if (!ListUtils.isEmpty(list) && count>0){
                return new PageBeanNew<>(currentPage,numPerPage,count,list);
            }
        }
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", agentId);
        if (isSpecial != null && isSpecial) {
            List<Long> specialAgentIds = wechatGroupConsr.getAllAgentId();
            if (CollectionUtils.isEmpty(specialAgentIds)) {
                specialAgentIds.add(-1L);
            }
            paramMap.put("specialAgentIds", specialAgentIds);
        }
        PageBeanNew<AgentStatisticsInfoDTO> pageBeanNew = bookGroupDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getAgentStatisticsInfo");
        if (!CollectionUtils.isEmpty(pageBeanNew.getRecordList())) {
            List<AgentStatisticsInfoDTO> agentStatisticsInfoDTOS = pageBeanNew.getRecordList();
            groupSet.setAgentStatisticsDetailInfo(agentStatisticsInfoDTOS);
        }
        if (null == agentId && !isSpecial){
            JedisClusterUtils.hset2Json(key,field,pageBeanNew.getRecordList());
            JedisClusterUtils.expire(key,60);
            JedisClusterUtils.set(countKey,String.valueOf(pageBeanNew.getTotalCount()),60);
        }
        return pageBeanNew;
    }

    @Override
    @ParamLog("导出出版社个人号统计信息")
    public void exportAgentStatisticsInfo( Long partyId, Long agentId, Boolean isSpecial ) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("agentId", agentId);
        if (isSpecial != null && isSpecial) {
            List<Long> specialAgentIds = wechatGroupConsr.getAllAgentId();
            if (CollectionUtils.isEmpty(specialAgentIds)) {
                specialAgentIds.add(-1L);
            }
            paramMap.put("specialAgentIds", specialAgentIds);
        }
        List<AgentStatisticsInfoDTO> agentStatisticsInfoDTOS = bookGroupDao.getAgentStatisticsInfo(paramMap);
        if (CollectionUtils.isEmpty(agentStatisticsInfoDTOS)) {
            throw new BookBizException(BookBizException.RESULT_NULL, "暂无导出数据!");
        }
        //异步导出
        PLATFORM_STATISTICS_EXPORT_THREAD.execute(() -> {
            groupSet.setAgentStatisticsDetailInfo(agentStatisticsInfoDTOS);
            String fileName = "个人号出版社统计信息_" + DateUtils.getShortDateStr();
            try {
                String[] rowsName = {"序号", "出版社信息", "个人号社群书数量", "定制个人号数量", "已发消息数量"};
                List<Object[]> dataList = new ArrayList<>();
                Object[] objs;
                for (int i = 0; i < agentStatisticsInfoDTOS.size(); i++) {
                    AgentStatisticsInfoDTO dto = agentStatisticsInfoDTOS.get(i);
                    objs = new Object[rowsName.length];
                    objs[0] = i + 1;
                    objs[1] = dto.getAgentName();
                    objs[2] = dto.getGroupBookCount();
                    objs[3] = dto.getRobotCount();
                    objs[4] = dto.getSendMsgCount();
                    dataList.add(objs);
                }
                String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
                //发送站内信
                JSONObject content = new JSONObject();
                content.put("commitTime", DateUtils.formatDate(new Date()));
                content.put("type", "个人号出版社统计信息");
                messageConsr.sendLetter(partyId, partyId, content.toJSONString(), SystemCode.pcloud.code,
                        "agent_statistic_export", fileUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
            } catch (Exception e) {
                LOGGER.error("生成导出文件失败" + e.getMessage(), e);
            }
        });
    }

    @ParamLog("按时间获取资源服务点击量趋势")
    @Override
    public Map<String, List<CountAndTimeDTO>> getServeClickTendencyList( Long bookGroupId, List<String> dateList ) {
        if (bookGroupId == null || ListUtils.isEmpty(dateList)) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误");
        }
        List<CountAndTimeDTO> list = appClickRecordDao.getAppClickByBookGroupId(bookGroupId, dateList);
        Map<String, List<CountAndTimeDTO>> map = new HashMap<>();
        list = list.stream().sorted(Comparator.comparing(CountAndTimeDTO::getTime)).collect(Collectors.toList());
        for (String date : dateList) {
            List<CountAndTimeDTO> one = list.stream().filter(s -> s.getDate().equals(date)).collect(Collectors.toList());
            String start = DateUtils.getStrFormTime("yyyy-MM-dd HH:mm:ss", DateUtils.getDayStart(DateUtils.getDateByStr(date)));
            String end = DateUtils.getStrFormTime("yyyy-MM-dd HH:mm:ss", DateUtils.getDayEnd(DateUtils.getDateByStr(date)));
            groupSet.fillEmptyTime(one, 2, start, end);
            one = one.stream().sorted(Comparator.comparing(CountAndTimeDTO::getTime)).collect(Collectors.toList());
            map.put(date, one);
        }
        return map;
    }

    @ParamLog("个人号社群书统计")
    @Override
    public PageBeanNew<SelfBookGroupStDTO> getSelfBookGroupStatistics( SelfBookGroupStParamDTO selfBookGroupStParamDTO ) {
        if (selfBookGroupStParamDTO == null
                || selfBookGroupStParamDTO.getCurrentPage() == null
                || selfBookGroupStParamDTO.getNumPerPage() == null
                || selfBookGroupStParamDTO.getCurrentPage() < 0
                || selfBookGroupStParamDTO.getNumPerPage() <= 0) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
        }
        PageParam pageParam = new PageParam(selfBookGroupStParamDTO.getCurrentPage(), selfBookGroupStParamDTO.getNumPerPage());
        Map<String, Object> map = new HashMap<>();
        map.put("joinGroupTypes", Arrays.asList(JoinGroupTypeEnum.ROBOT.getCode(), JoinGroupTypeEnum.AI_ROBOT.getCode(),
                JoinGroupTypeEnum.XIAORUI.getCode()));
        map.put("name", selfBookGroupStParamDTO.getName());
        map.put("proLabelId", selfBookGroupStParamDTO.getProLabelId());
        map.put("depLabelId", selfBookGroupStParamDTO.getDepLabelId());
        map.put("bookIds", selfBookGroupStParamDTO.getBookIds());
        if (selfBookGroupStParamDTO.getIsSpecial() != null
                && selfBookGroupStParamDTO.getIsSpecial()
                && ListUtils.isEmpty(selfBookGroupStParamDTO.getAgentIds())) {
            //获取特殊出版社id集合
            List<Long> agentIds = wechatGroupConsr.getAllAgentId();
            if (ListUtils.isEmpty(agentIds)) {
                //填充缺省值
                map.put("agentIds", Lists.newArrayList(-1L));
            } else {
                map.put("agentIds", agentIds);
            }
        } else {
            map.put("agentIds", selfBookGroupStParamDTO.getAgentIds());
        }
        PageBeanNew<SelfBookGroupStDTO> pageBeanNew = bookGroupDao.listPageNew(pageParam, map, "getSelfBookGroupStatistics");
        fillStInfo(pageBeanNew.getRecordList());
        return pageBeanNew;
    }

    @ParamLog("个人号社群书统计")
    @Override
    public void exportSelfBookGroupStatistics( SelfBookGroupStParamDTO selfBookGroupStParamDTO, String systemCode, Long partyId ) {
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try {
                //导出数据
                if (selfBookGroupStParamDTO == null) {
                    throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
                }
                Map<String, Object> map = new HashMap<>();
                map.put("name", selfBookGroupStParamDTO.getName());
                map.put("proLabelId", selfBookGroupStParamDTO.getProLabelId());
                map.put("depLabelId", selfBookGroupStParamDTO.getDepLabelId());
                map.put("bookIds", selfBookGroupStParamDTO.getBookIds());
                if (selfBookGroupStParamDTO.getIsSpecial() != null
                        && selfBookGroupStParamDTO.getIsSpecial()
                        && ListUtils.isEmpty(selfBookGroupStParamDTO.getAgentIds())) {
                    //获取特殊出版社id集合
                    List<Long> agentIds = wechatGroupConsr.getAllAgentId();
                    if (ListUtils.isEmpty(agentIds)) {
                        //填充缺省值
                        map.put("agentIds", Lists.newArrayList(-1L));
                    } else {
                        map.put("agentIds", agentIds);
                    }
                } else {
                    map.put("agentIds", selfBookGroupStParamDTO.getAgentIds());
                }
                Integer count = bookGroupDao.countSelfBookGroupStatistics(map);
                if (count > 10000) {
                    throw new BookBizException(BookBizException.ERROR, "数量超出限制，请添加筛选条件！");
                }
                List<SelfBookGroupStDTO> list = new ArrayList<>();
                Integer cu = 500;
                Integer p = (count / cu) + 1;
                for (int i = 0; i < p; i++) {
                    selfBookGroupStParamDTO.setCurrentPage(i);
                    selfBookGroupStParamDTO.setNumPerPage(cu);
                    PageBeanNew<SelfBookGroupStDTO> page = getSelfBookGroupStatistics(selfBookGroupStParamDTO);
                    list.addAll(page.getRecordList());
                }
                //导出
                exportSelfBGSt(list, systemCode, partyId);
            } catch (Exception e) {
                LOGGER.error("exportSelfBookGroupStatistics+++selfBookGroupStParamDTO=" + selfBookGroupStParamDTO.toString() + "systemCode=" + systemCode + "partyId=" + partyId);
            }
        });
    }

    @ParamLog("根据小号批量获取服务社群书数量")
    @Override
    public Map<String, Integer> getBookGroupCountMapByAltIds( List<String> altIds ) {
        Map<String, Integer> map = new HashMap<>();
        if (ListUtils.isEmpty(altIds)) {
            return map;
        }
        List<AltAndCountDTO> list = bookGroupCipherUserDao.getBookGroupCountListByAltIds(altIds);
        for (AltAndCountDTO altAndCountDTO : list) {
            map.put(altAndCountDTO.getAltId(), altAndCountDTO.getCount());
        }
        return map;
    }

    @ParamLog("获取小号社群书数量")
    @Override
    public Integer getSerBookGroupCountByAltIds( List<String> altIds ) {
        if (ListUtils.isEmpty(altIds)) {
            return 0;
        }
        List<Long> bookGroupIds = bookGroupCipherUserDao.getBookGroupIdsByAltIds(altIds);
        if (ListUtils.isEmpty(bookGroupIds)) {
            return 0;
        }
        return bookGroupIds.size();
    }

    @ParamLog("出版社关联的个人号以及个人号的社群书数量")
    @Override
    public List<AltAndCountDTO> getAltAndCountDTOListByAgentId( Long agentId ) {
        List<AltAndCountDTO> list = new ArrayList<>();
        if (agentId == null) {
            return list;
        }
        List<String> altIds = bookGroupCipherUserDao.getAltIdsByAgentId(agentId);
        if (ListUtils.isEmpty(altIds)) {
            return list;
        }
        list = bookGroupCipherUserDao.getBookGroupCountListByAltIds(altIds);
        return list;
    }

    @ParamLog("导出")
    private void exportSelfBGSt( List<SelfBookGroupStDTO> list, String systemCode, Long partyId ) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Object[]> dataList = new ArrayList<>();
        for (int i = 0, size = list.size(); i < size; i++) {
            SelfBookGroupStDTO dto = list.get(i);
            Object[] obj = new Object[31];
            obj[0] = i + 1;
            obj[1] = dto.getBookName();
            obj[2] = dto.getIsbn();
            obj[3] = dto.getUniqueNumber();
            obj[4] = dto.getAdviserName();
            obj[5] = dto.getAgentName();
            obj[6] = dto.getGroupQrcodeName();
            obj[7] = dto.getGroupQrcodeUrl();
            obj[8] = dto.getDepLabelName();
            obj[9] = dto.getPurLabelName();
            obj[10] = DateUtils.getStrFormTime("yyyy-MM-dd HH:mm:ss", dto.getCreateTime());
            String altName = "";
            if (!ListUtils.isEmpty(dto.getAltIdAndNameDTOS())) {
                for (AltIdAndNameDTO altIdAndNameDTO : dto.getAltIdAndNameDTOS()) {
                    altName = altName + altIdAndNameDTO.getAltName() + "、";
                }
            }
            obj[11] = altName;
            obj[12] = dto.getScanPeopleCount();
            obj[13] = dto.getCopyCipherPeopleCount();
            obj[14] = dto.getAccAddFriendCount();
            obj[15] = dto.getScanConversionRate();
            obj[16] = dto.getPreFriendCount();
            obj[17] = dto.getDelFriendCount();
            obj[18] = dto.getFriendKeepRate();
            obj[19] = dto.getSendMessageCount();
            obj[20] = dto.getClassifyCount();
            obj[21] = dto.getAccJoinGroupCount();
            obj[22] = dto.getPreInGroupPeopleCount();
            obj[23] = dto.getGroupMessageCount();
            obj[24] = dto.getServeCount();
            obj[25] = dto.getServeClickPeopleCount();
            obj[26] = dto.getServeClickCount();
            obj[27] = dto.getAvgBrowseTime();
            obj[28] = dto.getOneServeBrowseTime();
            obj[29] = dto.getBuyPeopleCount();
            obj[30] = dto.getSaleAmount();
            dataList.add(obj);
        }
        Date date = new Date();
        String[] rowsName = {"序号", "书名", "isbn编号", "唯一编号", "编辑名称", "出版社名称", "社群码名称",
                "社群码url", "深度标签名称", "目的标签名称", "创建时间", "小号", "扫码人数",
                "复制暗号人数", "累计加好友人数", "扫码转化率", "当前好友人数", "已删好友人数",
                "好友留存率", "已发消息量", "群分类数量", "累计进群人数", "当前群总人数", "群消息数量",
                "资源服务数量", "资源点击人数", "资源点击次数", "社群书平均浏览时长", "单个服务平均浏览时长",
                "购买人数", "销售额"};
        String fileName = "个人号统计--" + DateUtils.getStrFormTime("yyyyMMdd", date);
        String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
        String letterType = "pcloud_book_group_serve";
        String content = String.format("{\"commitTime\":\"%s\",\"type\":\"%s\"}", DateUtils.formatDate(date), fileName);
        messageConsr.sendLetter(partyId, partyId, content, systemCode, letterType, fileUrl, fileName, NotifyOriginTypeEnum.BOOK_GROUP.value, null);
    }

    @ParamLog("填充个人号统计其他信息")
    private void fillStInfo( List<SelfBookGroupStDTO> list ) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Long> bookGroupIds = list.stream().filter(s -> s.getBookGroupId() != null).map(SelfBookGroupStDTO::getBookGroupId).distinct().collect(Collectors.toList());
        fillAltInfo(list);
        fillAgentNameAdviserNameLabel(list);
        fillGroupInfoAbout(list, bookGroupIds);
        fillServeAbout(list, bookGroupIds);
        fillScanPeopleCount(list, bookGroupIds);
        fillAccAddFriendCount(list, bookGroupIds);
        fillBrowse(list, bookGroupIds);
        fillSaleAbout(list, bookGroupIds);
        fillSendMessageCount(list, bookGroupIds);
        fillPreFriend(list, bookGroupIds);
        fillDefault(list);
    }

    @ParamLog("填充默认值")
    private void fillDefault( List<SelfBookGroupStDTO> list ) {
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            if (selfBookGroupStDTO.getAccAddFriendCount() == null) {
                selfBookGroupStDTO.setAccAddFriendCount(0);
            }
            if (selfBookGroupStDTO.getDelFriendCount() == null) {
                selfBookGroupStDTO.setDelFriendCount(0);
            }
            if (selfBookGroupStDTO.getSaleAmount() == null) {
                selfBookGroupStDTO.setSaleAmount(0D);
            }
            if (selfBookGroupStDTO.getBuyPeopleCount() == null) {
                selfBookGroupStDTO.setBuyPeopleCount(0L);
            }
            if (selfBookGroupStDTO.getOneServeBrowseTime() == null) {
                selfBookGroupStDTO.setOneServeBrowseTime(0L);
            }
            if (selfBookGroupStDTO.getAvgBrowseTime() == null) {
                selfBookGroupStDTO.setAvgBrowseTime(0L);
            }
            if (selfBookGroupStDTO.getServeClickCount() == null) {
                selfBookGroupStDTO.setServeClickCount(0);
            }
            if (selfBookGroupStDTO.getServeClickPeopleCount() == null) {
                selfBookGroupStDTO.setServeClickPeopleCount(0);
            }
            if (selfBookGroupStDTO.getServeCount() == null) {
                selfBookGroupStDTO.setServeCount(0);
            }
            if (selfBookGroupStDTO.getGroupMessageCount() == null) {
                selfBookGroupStDTO.setGroupMessageCount(0);
            }
            if (selfBookGroupStDTO.getPreInGroupPeopleCount() == null) {
                selfBookGroupStDTO.setPreInGroupPeopleCount(0);
            }
            if (selfBookGroupStDTO.getAccJoinGroupCount() == null) {
                selfBookGroupStDTO.setAccJoinGroupCount(0);
            }
            if (selfBookGroupStDTO.getClassifyCount() == null) {
                selfBookGroupStDTO.setClassifyCount(0);
            }
            if (selfBookGroupStDTO.getSendMessageCount() == null) {
                selfBookGroupStDTO.setSendMessageCount(0);
            }
            if (selfBookGroupStDTO.getFriendKeepRate() == null) {
                selfBookGroupStDTO.setFriendKeepRate(0D);
            }
            if (selfBookGroupStDTO.getPreFriendCount() == null) {
                selfBookGroupStDTO.setPreFriendCount(0);
            }
            if (selfBookGroupStDTO.getScanConversionRate() == null) {
                selfBookGroupStDTO.setScanConversionRate(0D);
            }
            if (selfBookGroupStDTO.getCopyCipherPeopleCount() == null) {
                selfBookGroupStDTO.setCopyCipherPeopleCount(0);
            }
            if (selfBookGroupStDTO.getScanPeopleCount() == null) {
                selfBookGroupStDTO.setScanPeopleCount(0);
            }
            if (selfBookGroupStDTO.getAltIdAndNameDTOS() == null) {
                selfBookGroupStDTO.setAltIdAndNameDTOS(new ArrayList<>());
            }
        }
    }

    @ParamLog("填充当前好友人数 已删好友人数 好友留存率")
    private void fillPreFriend( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        List<BookGroupCipherUser> alts = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupIds(bookGroupIds);
        if (ListUtils.isEmpty(alts)) {
            return;
        }
        //调内部接口获取是否还是好友关系
        List<AltAndUserDTO> altAndUserDTOS = new ArrayList<>();
        for (BookGroupCipherUser bgcu : alts) {
            AltAndUserDTO altAndUserDTO = new AltAndUserDTO();
            altAndUserDTO.setAltId(bgcu.getAltId());
            altAndUserDTO.setWxUserId(bgcu.getWxUserId());
            altAndUserDTOS.add(altAndUserDTO);
        }
        List<AltAndUserResultDTO> dtos = wechatGroupConsr.listAltAndUserRelationship(altAndUserDTOS);
        if (ListUtils.isEmpty(dtos)) {
            return;
        }
        Map<String, Boolean> map = new HashMap<>();
        for (AltAndUserResultDTO altAndUserResultDTO : dtos) {
            map.put(altAndUserResultDTO.getAltId() + altAndUserResultDTO.getWxUserId(), altAndUserResultDTO.getIsFriend());
        }
        Map<Long, List<BookGroupCipherUser>> altMap = alts.stream().collect(Collectors.groupingBy(BookGroupCipherUser::getBookGroupId));
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            List<BookGroupCipherUser> userList = altMap.get(bookGroupId);
            if (!ListUtils.isEmpty(userList)) {
                Integer preFriendCount = 0;
                for (BookGroupCipherUser bookGroupCipherUser : userList) {
                    Boolean isFriend = map.get(bookGroupCipherUser.getAltId() + bookGroupCipherUser.getWxUserId());
                    if (isFriend != null && isFriend) {
                        preFriendCount = preFriendCount + 1;
                    }
                }
                selfBookGroupStDTO.setPreFriendCount(preFriendCount);
                selfBookGroupStDTO.setDelFriendCount(selfBookGroupStDTO.getAccAddFriendCount() - preFriendCount);
                if (preFriendCount == null || selfBookGroupStDTO.getAccAddFriendCount() == null || selfBookGroupStDTO.getAccAddFriendCount() == 0) {
                    selfBookGroupStDTO.setFriendKeepRate(0D);
                } else {
                    selfBookGroupStDTO.setFriendKeepRate(selfBookGroupStDTO.getPreFriendCount().doubleValue() / selfBookGroupStDTO.getAccAddFriendCount().doubleValue());
                }
            } else {
                selfBookGroupStDTO.setPreFriendCount(0);
                selfBookGroupStDTO.setDelFriendCount(0);
                selfBookGroupStDTO.setFriendKeepRate(0D);
            }
        }
    }

    @ParamLog("填充发送消息数量")
    private void fillSendMessageCount( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        List<BookGroupCipherUser> alts = bookGroupCipherUserDao.getWxUserIdAndAltsByBookGroupIds(bookGroupIds);
        if (ListUtils.isEmpty(alts)) {
            return;
        }
        List<String> wxUserIds = alts.stream().filter(s -> s.getWxUserId() != null).map(BookGroupCipherUser::getWxUserId).collect(Collectors.toList());
        Map<String, Integer> messageCountMap = wechatGroupConsr.mapReceiveMsgCountByIds(wxUserIds);
        Map<Long, List<BookGroupCipherUser>> altMap = alts.stream().collect(Collectors.groupingBy(BookGroupCipherUser::getBookGroupId));
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Integer sendMessageCount = 0;
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            List<BookGroupCipherUser> bgcus = altMap.get(bookGroupId);
            if (bgcus != null) {
                List<String> wxIds = bgcus.stream().filter(s -> s.getWxUserId() != null).map(BookGroupCipherUser::getWxUserId).collect(Collectors.toList());
                for (String wxId : wxIds) {
                    if (messageCountMap.get(wxId) != null) {
                        sendMessageCount = sendMessageCount + messageCountMap.get(wxId);
                    }
                }
            }
            selfBookGroupStDTO.setSendMessageCount(sendMessageCount);
        }
    }

    @ParamLog("查询销售相关")
    private void fillSaleAbout( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        Map<Long, ProductSaleDetailDto> map = tradeConsr.getSaleInfo4Group(bookGroupIds, null);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long buyPeopleCount = 0L;
            Double saleAmount = 0D;
            ProductSaleDetailDto productSaleDetailDto = map.get(selfBookGroupStDTO.getBookGroupId());
            if (productSaleDetailDto != null) {
                if (productSaleDetailDto.getPayCount() != null) {
                    buyPeopleCount = productSaleDetailDto.getPayCount();
                }
                if (productSaleDetailDto.getSaleMoney() != null) {
                    saleAmount = productSaleDetailDto.getSaleMoney();
                }
            }
            //购买人数
            selfBookGroupStDTO.setBuyPeopleCount(buyPeopleCount);
            //销售额
            selfBookGroupStDTO.setSaleAmount(saleAmount);
        }
    }

    @ParamLog("填充浏览时长相关")
    private void fillBrowse( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        Map<Long, GroupBrowseStatisticVO> bookGroupBrowseMap = browseRecordConsr.mapGroupBrowseStatistic(bookGroupIds, null);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long avgBrowseTime = 0L;
            Long oneServeBrowseTime = 0L;
            GroupBrowseStatisticVO groupBrowseStatisticVO = bookGroupBrowseMap.get(selfBookGroupStDTO.getBookGroupId());
            if (groupBrowseStatisticVO != null && groupBrowseStatisticVO.getBrowseTimes() != null
                    && groupBrowseStatisticVO.getBrowserCount() != null && groupBrowseStatisticVO.getBrowserCount() != 0) {
                avgBrowseTime = groupBrowseStatisticVO.getBrowseTimes() / groupBrowseStatisticVO.getBrowserCount();
            }
            if (groupBrowseStatisticVO != null && groupBrowseStatisticVO.getBrowseTimes() != null
                    && selfBookGroupStDTO.getServeCount() != null && selfBookGroupStDTO.getServeCount() != 0) {
                oneServeBrowseTime = groupBrowseStatisticVO.getBrowseTimes() / selfBookGroupStDTO.getServeCount();
            }
            selfBookGroupStDTO.setAvgBrowseTime(avgBrowseTime);
            selfBookGroupStDTO.setOneServeBrowseTime(oneServeBrowseTime);
        }
    }

    @ParamLog("填充累计加好友人数")
    private void fillAccAddFriendCount( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        List<BookGroupIdAndCountDTO> dtos = bookGroupCipherUserDao.getAddFriendByBookGroupIds(bookGroupIds);
        Map<Long, Integer> map = new HashMap<>();
        for (BookGroupIdAndCountDTO se : dtos) {
            map.put(se.getBookGroupId(), se.getCount());
        }
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            Integer accAddFriendCount = map.get(bookGroupId) == null ? 0 : map.get(bookGroupId);
            selfBookGroupStDTO.setAccAddFriendCount(accAddFriendCount);
            Integer scanPeopleCount = selfBookGroupStDTO.getScanPeopleCount();
            //扫码转化率
            if (scanPeopleCount == null || scanPeopleCount == 0) {
                selfBookGroupStDTO.setScanConversionRate(0D);
            } else {
                selfBookGroupStDTO.setScanConversionRate(accAddFriendCount.doubleValue() / scanPeopleCount.doubleValue());
            }

        }
    }

    @ParamLog("填充扫码人数")
    private void fillScanPeopleCount( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        Map<Long, Integer> scanMap = ResponseHandleUtil.parseMap(groupMemberService.getScanUserCountByGroup(bookGroupIds), Long.class, Integer.class);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            selfBookGroupStDTO.setScanPeopleCount(scanMap.get(bookGroupId) == null ? 0 : scanMap.get(bookGroupId));
        }
    }

    @ParamLog("填充资源相关")
    private void fillServeAbout( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        //资源数量
        List<BookGroupIdAndCountDTO> serveDTOS = bookGroupAppDao.getServerCountByBookGroupIds(bookGroupIds);
        Map<Long, Integer> serveCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : serveDTOS) {
            serveCountMap.put(se.getBookGroupId(), se.getCount());
        }
        //点击复制暗号人数
        List<BookGroupIdAndCountDTO> copyCipherDTOS = copyCipherRecordDao.getCountByBookGroupIds(bookGroupIds);
        Map<Long, Integer> copyCipherCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : copyCipherDTOS) {
            copyCipherCountMap.put(se.getBookGroupId(), se.getCount());
        }
        //资源点击人数
        List<BookGroupIdAndCountDTO> serveClickPeopleCounts = appClickRecordDao.getClPeCoByBookGroupIds(bookGroupIds);
        Map<Long, Integer> serveClickPeCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : serveClickPeopleCounts) {
            serveClickPeCountMap.put(se.getBookGroupId(), se.getCount());
        }
        //资源点击次数
        List<BookGroupIdAndCountDTO> serveClickCounts = appClickRecordDao.getClCoByBookGroupIds(bookGroupIds);
        Map<Long, Integer> serveClickCountMap = new HashMap<>();
        for (BookGroupIdAndCountDTO se : serveClickCounts) {
            serveClickCountMap.put(se.getBookGroupId(), se.getCount());
        }
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            Long bookGroupId = selfBookGroupStDTO.getBookGroupId();
            selfBookGroupStDTO.setServeCount(serveCountMap.get(bookGroupId) == null ? 0 : serveCountMap.get(bookGroupId));
            selfBookGroupStDTO.setCopyCipherPeopleCount(copyCipherCountMap.get(bookGroupId) == null ? 0 : copyCipherCountMap.get(bookGroupId));
            selfBookGroupStDTO.setServeClickPeopleCount(serveClickPeCountMap.get(bookGroupId) == null ? 0 : serveClickPeCountMap.get(bookGroupId));
            selfBookGroupStDTO.setServeClickCount(serveClickCountMap.get(bookGroupId) == null ? 0 : serveClickCountMap.get(bookGroupId));
        }
    }

    @ParamLog("填充群相关")
    private void fillGroupInfoAbout( List<SelfBookGroupStDTO> list, List<Long> bookGroupIds ) {
        List<SelfBookGroupStDTO> classifyInfos = bookGroupClassifyDao.listClassifyCountInfo(bookGroupIds);
        Map<Long, SelfBookGroupStDTO> map = new HashMap<>();
        for (SelfBookGroupStDTO selfBookGroupStDTO : classifyInfos) {
            map.put(selfBookGroupStDTO.getBookGroupId(), selfBookGroupStDTO);
        }
        //群消息数量
        Map<Long, GroupMsgCountDTO> groupMsgCountDTOMap = wechatGroupConsr.mapBookGroupMsgCount(bookGroupIds);
        //累计进群人数
        Map<Long, GroupUserCountDTO> groupUserCountDTOMap = wechatGroupConsr.mapBookGroupJoinUserCount(bookGroupIds, null);
        for (SelfBookGroupStDTO sel : list) {
            SelfBookGroupStDTO selfBookGroupStDTO = map.get(sel.getBookGroupId());
            if (selfBookGroupStDTO != null) {
                sel.setClassifyCount(selfBookGroupStDTO.getClassifyCount());
                sel.setPreInGroupPeopleCount(selfBookGroupStDTO.getPreInGroupPeopleCount());
            } else {
                sel.setClassifyCount(0);
                sel.setPreInGroupPeopleCount(0);
            }
            GroupMsgCountDTO groupMsgCountDTO = groupMsgCountDTOMap.get(sel.getBookGroupId());
            if (groupMsgCountDTO != null) {
                sel.setGroupMessageCount(groupMsgCountDTO.getMsgCount());
            } else {
                sel.setGroupMessageCount(0);
            }
            GroupUserCountDTO groupUserCountDTO = groupUserCountDTOMap.get(sel.getBookGroupId());
            if (groupUserCountDTO != null) {
                sel.setAccJoinGroupCount(groupUserCountDTO.getUserCount());
            } else {
                sel.setAccJoinGroupCount(0);
            }
        }
    }

    @ParamLog("填充出版社名称和编辑名称和标签")
    private void fillAgentNameAdviserNameLabel( List<SelfBookGroupStDTO> list ) {
        List<Long> adviserIds = new ArrayList<>();
        List<Long> agentIds = new ArrayList<>();
        List<Long> labelIds = new ArrayList<>();
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            if (!adviserIds.contains(selfBookGroupStDTO.getAdviserId())) {
                adviserIds.add(selfBookGroupStDTO.getAdviserId());
            }
            if (!agentIds.contains(selfBookGroupStDTO.getAgentId())) {
                agentIds.add(selfBookGroupStDTO.getAgentId());
            }
            if (!labelIds.contains(selfBookGroupStDTO.getDepLabelId()) && selfBookGroupStDTO.getDepLabelId() != null) {
                labelIds.add(selfBookGroupStDTO.getDepLabelId());
            }
            if (!labelIds.contains(selfBookGroupStDTO.getPurLabelId()) && selfBookGroupStDTO.getPurLabelId() != null) {
                labelIds.add(selfBookGroupStDTO.getPurLabelId());
            }
        }
        Map<Long, String> adviserNamesMap = adviserConsr.getNames(adviserIds);
        Map<Long, String> agentNamesMap = agentConsr.getNames(agentIds);
        Map<Long, String> labelMap = new HashMap<>();
        if (!ListUtils.isEmpty(labelIds)) {
            labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
        }
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            selfBookGroupStDTO.setAdviserName(adviserNamesMap.get(selfBookGroupStDTO.getAdviserId()));
            selfBookGroupStDTO.setAgentName(agentNamesMap.get(selfBookGroupStDTO.getAgentId()));
            selfBookGroupStDTO.setDepLabelName(labelMap.get(selfBookGroupStDTO.getDepLabelId()));
            selfBookGroupStDTO.setPurLabelName(labelMap.get(selfBookGroupStDTO.getPurLabelId()));
        }
    }

    @ParamLog("填充小号信息")
    private void fillAltInfo( List<SelfBookGroupStDTO> list ) {
        List<Long> bookGroupIds = list.stream().filter(s -> s.getBookGroupId() != null).map(SelfBookGroupStDTO::getBookGroupId).collect(Collectors.toList());
        //填充个人号信息
        List<BookGroupAgentRecord> bookGroupAgentRecords = bookGroupAgentRecordDao.getAltIdByBookGroupIds(bookGroupIds);
        List<String> specialAltIds = new ArrayList<>();
        List<Long> specialBookGroupIds = new ArrayList<>();
        Map<Long, List<BookGroupAgentRecord>> spGroups = new HashMap<>();
        if (!ListUtils.isEmpty(bookGroupAgentRecords)) {
            spGroups = bookGroupAgentRecords.stream().collect(Collectors.groupingBy(BookGroupAgentRecord::getBookGroupId));
            for (BookGroupAgentRecord bookGroupAgentRecord : bookGroupAgentRecords) {
                if (!specialAltIds.contains(bookGroupAgentRecord.getAltId())) {
                    specialAltIds.add(bookGroupAgentRecord.getAltId());
                }
                specialBookGroupIds.add(bookGroupAgentRecord.getBookGroupId());
            }
        }
        bookGroupIds.removeAll(specialBookGroupIds);
        List<BookGroupCipherUser> bookGroupCipherUsers = bookGroupCipherUserDao.getAltIdByBookGroupIds(bookGroupIds);
        List<String> norAltIds = new ArrayList<>();
        List<Long> norBookGroupIds = new ArrayList<>();
        Map<Long, List<BookGroupCipherUser>> norGroups = new HashMap<>();
        if (!ListUtils.isEmpty(bookGroupCipherUsers)) {
            norGroups = bookGroupCipherUsers.stream().collect(Collectors.groupingBy(BookGroupCipherUser::getBookGroupId));
            for (BookGroupCipherUser bookGroupCipherUser : bookGroupCipherUsers) {
                if (!specialAltIds.contains(bookGroupCipherUser.getAltId())) {
                    norAltIds.add(bookGroupCipherUser.getAltId());
                }
                norBookGroupIds.add(bookGroupCipherUser.getBookGroupId());
            }
        }

        List<String> allAltIds = new ArrayList<>();
        allAltIds.addAll(specialAltIds);
        allAltIds.addAll(norAltIds);
        Map<String, RobotBaseInfoDTO> altsMap = wechatGroupConsr.mapRobotInfo(allAltIds);
        for (SelfBookGroupStDTO selfBookGroupStDTO : list) {
            List<AltIdAndNameDTO> altIdAndNameDTOS = new ArrayList<>();
            if (specialBookGroupIds.contains(selfBookGroupStDTO.getBookGroupId())) {
                List<BookGroupAgentRecord> records = spGroups.get(selfBookGroupStDTO.getBookGroupId());
                if (!ListUtils.isEmpty(records)) {
                    for (BookGroupAgentRecord b : records) {
                        AltIdAndNameDTO altIdAndNameDTO = new AltIdAndNameDTO();
                        altIdAndNameDTO.setAltId(b.getAltId());
                        if (altsMap.get(b.getAltId()) != null) {
                            altIdAndNameDTO.setAltName(altsMap.get(b.getAltId()).getNickName());
                        }
                        altIdAndNameDTOS.add(altIdAndNameDTO);
                    }
                }
            } else {
                List<BookGroupCipherUser> records = norGroups.get(selfBookGroupStDTO.getBookGroupId());
                if (!ListUtils.isEmpty(records)) {
                    for (BookGroupCipherUser b : records) {
                        AltIdAndNameDTO altIdAndNameDTO = new AltIdAndNameDTO();
                        altIdAndNameDTO.setAltId(b.getAltId());
                        if (altsMap.get(b.getAltId()) != null) {
                            altIdAndNameDTO.setAltName(altsMap.get(b.getAltId()).getNickName());
                        }
                        altIdAndNameDTOS.add(altIdAndNameDTO);
                    }
                }
            }
            selfBookGroupStDTO.setAltIdAndNameDTOS(altIdAndNameDTOS);
        }
    }

    @Override
    public PageBeanNew<UserBookInfoVO> listUser4SelfPush( UserSelectParamDTO userSelectParamDTO ) {
        Integer currentPage = userSelectParamDTO.getCurrentPage();
        Integer numPerPage = userSelectParamDTO.getNumPerPage();
        Map<String, Object> map = new HashMap<>();
        //判断robotid是否是小睿
        String robotId = userSelectParamDTO.getRobotId();
        Integer groupRobotType = userSelectParamDTO.getGroupRobotType();
        List<UserBookInfoVO> list = new ArrayList<>();
        Integer totalCount = 0;

        if (StringUtil.isEmpty(robotId)) {
            throw new BizException(BizException.PARAM_IS_NULL.getCode(), "robotId为空");
        }
        if (null == groupRobotType) {
            groupRobotType = AltTypeEnum.WECHAT.code;
        }
        PcloudRobot pcloudRobot = pcloudRobotBiz.getPcloudRobotByWxId(robotId);
        if (null != pcloudRobot) {
            PageBeanNew<String> wechatUserIdPage = wechatGroupConsr.listPageFriend(currentPage, numPerPage,
                    robotId, userSelectParamDTO.getUserQuery(), groupRobotType);
            if (!ListUtils.isEmpty(wechatUserIdPage.getRecordList())) {
                List<String> wechatUserIds = wechatUserIdPage.getRecordList();
                list = groupSet.setUserBookInfo4SelfPush4XIAORUI(wechatUserIds, groupRobotType);
                totalCount = wechatUserIdPage.getTotalCount();
            }
        } else {
            //用户昵称id模糊查询
            if (!StringUtil.isEmpty(userSelectParamDTO.getUserQuery())) {
                List<String> wxUserIds = wechatGroupConsr.getByUserQuery(userSelectParamDTO.getUserQuery());
                if (!ListUtils.isEmpty(wxUserIds)) {
                    map.put("wxUserIds", wxUserIds);
                } else {
                    return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
                }
            }
            map.put("depLabelId", userSelectParamDTO.getDepLabelId());
            map.put("proLabelId", userSelectParamDTO.getProLabelId());
            map.put("altId", userSelectParamDTO.getRobotId());
            map.put("bookIds", userSelectParamDTO.getBookIds());
            List<UserBookInfoVO> countlist = bookGroupCipherUserDao.listUser4SelfPush(map);
            if (ListUtils.isEmpty(countlist)) {
                return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
            }
            map.put("pageNum", currentPage * numPerPage);
            map.put("numPerPage", numPerPage);
            list = bookGroupCipherUserDao.listUser4SelfPush(map);
            //填充个人号群发用户信息、扫码书刊信息
            groupSet.setUserBookInfo4SelfPush(list);
            totalCount = countlist.size();
        }
        return new PageBeanNew<>(currentPage, numPerPage, totalCount, list);

    }

    @Override
    public PageBeanNew<UserBookInfoVO> listUser4SelfPushByAdvise( Map<String, Object> userSelectParam ) {
        Integer currentPage = (Integer) userSelectParam.get("currentPage");
        Integer numPerPage = (Integer) userSelectParam.get("numPerPage");
        Map<String, Object> map = new HashMap<>();
        //用户昵称id模糊查询
        if (!StringUtil.isEmpty((CharSequence) userSelectParam.get("userQuery"))) {
            List<String> wxUserIds = wechatGroupConsr.getByUserQuery((String) userSelectParam.get("userQuery"));
            if (!ListUtils.isEmpty(wxUserIds)) {
                map.put("wxUserIds", wxUserIds);
            } else {
                return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
            }
        }
        map.put("bookId", userSelectParam.get("bookId"));
        List<UserBookInfoVO> countlist = bookGroupCipherUserDao.listUser4SelfPushByAdvise(map);
        if (ListUtils.isEmpty(countlist)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        map.put("pageNum", currentPage * numPerPage);
        map.put("numPerPage", numPerPage);
        List<UserBookInfoVO> list = bookGroupCipherUserDao.listUser4SelfPushByAdvise(map);
        //填充个人号群发用户信息、扫码书刊信息
        groupSet.setUserBookInfo4SelfPush(list);
        return new PageBeanNew<>(currentPage, numPerPage, countlist.size(), list);
    }

    @ParamLog("根据类型获取社群书id集合")
    @Override
    public List<Long> getBookGroupIdsByJoinGroupType( Integer joinGroupType ) {
        List<Long> bookGroupIds = bookGroupDao.getIdsByJoinGroupType(joinGroupType);
        return bookGroupIds;
    }

    @ParamLog("获取随机码")
    @Override
    public String getRandomCode( Long wechatUserId ) {
        if (wechatUserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "微信id为空！");
        }
        //先查询数据库
        WxUserWechatRelevance wxUserWechatRelevance = wxUserWechatRelevanceDao.getByWechatUserId(wechatUserId);
        if (wxUserWechatRelevance != null) {
            return wxUserWechatRelevance.getRandomCode();
        }
        //之前没有就新增
        WxUserWechatRelevance wechatRelevanceNew = new WxUserWechatRelevance();
        wechatRelevanceNew.setWechatUserId(wechatUserId);
        String randomCode = createRandomCode();
        //校验库里面有没有
        WxUserWechatRelevance toCheck = wxUserWechatRelevanceDao.getByRandomCode(randomCode);
        if (toCheck != null) {
            //重新获取
            randomCode = createRandomCode();
        }
        wechatRelevanceNew.setRandomCode(randomCode);
        //新增
        wxUserWechatRelevanceDao.insert(wechatRelevanceNew);
        return randomCode;
    }

    @Override
    @ParamLog
    @Transactional(rollbackFor = Exception.class)
    public Long changeQrCodeType( ChangeQrCodeTypeDto changeQrCodeTypeDto ) {
        Long id = changeQrCodeTypeDto.getId();
        String type = changeQrCodeTypeDto.getType();
        Long bookGroupId = null;
        if (ChangeOriginTypeEnum.SCENE.getType().equals(type)) {
            bookGroupId = changeRaysBook2SelfRobotQr(id);
        } else if (ChangeOriginTypeEnum.BOOK_GROUP.getType().equals(type)) {
            bookGroupId = changeSheQun2SelfRobotQr(id);
        }
        return bookGroupId;
    }

    @Override
    public Long getChangeQrChangeTarget( Long originId, String originType ) {
        return bookGroupDao.getChangeQrChangeTarget(originId, originType);
    }

    /**
     * 将现代纸书转换为个人自由码
     */
    private Long changeRaysBook2SelfRobotQr( Long sceneId ) {
        QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(sceneId);
        if (null == sceneId) {
            return null;
        }
        String qrCodeUrl = qrcodeSceneDto.getQrcodeUrl();
        String qrcodeType = qrcodeSceneDto.getQrcodeType();
        //先创建
        BookGroup bookGroup = this.createBookGroupAfterCreateBook(qrcodeSceneDto.getAdviserBookId(), qrcodeSceneDto.getChannelPartyId(), qrcodeSceneDto.getCreatedByUserLogin(), 2, sceneId, JoinGroupTypeEnum.ROBOT.getCode(), null, null);
        //公众号码才需要覆盖sceneId
        bookGroup.setGroupQrcodeUrl(qrCodeUrl);
        if (ChannelConstants.QrCodeType.WECHAT.getName().equals(qrcodeType)) {
            bookGroup.setSceneId(sceneId);
        }
        //替换二维码
        bookGroupDao.update(bookGroup);
        //插入旧码下的资源
        Long newBookGroupId = bookGroup.getId();
        List<MessageDto> messages = qrcodeSceneDto.getMessages();
        if (!ListUtils.isEmpty(messages)) {
            List<BookGroupServe> list = new ArrayList<>();
            messages.forEach(item -> {
                BookGroupServe bookGroupServe = new BookGroupServe();
                bookGroupServe.setBookGroupId(newBookGroupId);
                bookGroupServe.setServeId(item.getFromId());
                bookGroupServe.setServeType(item.getTypeCode());
                bookGroupServe.setServeUrl(item.getUrl());
                list.add(bookGroupServe);
            });
            batchUpdateBookGroupServe(qrcodeSceneDto.getAdviserId(), list);
            bookGroupDao.updateIsSomeUpdate(newBookGroupId, true);
        }
        qrcodeSceneConsr.updateQrcodeToSelfRobotQrcode(sceneId, qrcodeSceneDto.getAdviserBookId());
        //插入转换记录表
        QrChangeRecord qrChangeRecord = QrChangeRecord.builder().oldSceneId(sceneId).newBookGroupId(newBookGroupId).build();
        bookGroupDao.insertQrChangeRecord(qrChangeRecord);
        return newBookGroupId;
    }

    /**
     * 社群书换为个人码的自由码
     */
    private Long changeSheQun2SelfRobotQr( Long oldBookGroupId ) {
        //拿到旧的社群码
        BookGroupDTO bookInfo = bookGroupDao.getDTOById(oldBookGroupId);
        if (null == bookInfo) {
            return null;
        }
        Long sceneId = bookInfo.getSceneId();
        //如果已经是个人码,不管是微信码还是自建码，都直接返回
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(bookInfo.getJoinGroupType())) {
            return null;
        }
        //创建新的社群码
        BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookInfo.getBookId(), bookInfo.getChannelId(), bookInfo.getCreateUser(), 2, sceneId, JoinGroupTypeEnum.ROBOT.getCode(), null, null);
        //替换qrCodeUrl
        bookGroup.setGroupQrcodeUrl(bookInfo.getGroupQrcodeUrl());
        bookGroup.setSceneId(sceneId);
        bookGroupDao.update(bookGroup);

        Long newBookGroupId = bookGroup.getId();
        //3.把旧码下的应用类关键词配置成资源
        List<BookGroupKeywordResourceDTO> bookGroupResourceList = bookKeywordDao.getBookGroupResourceList(oldBookGroupId);
        if (!ListUtils.isEmpty(bookGroupResourceList)) {
            List<BookGroupServe> bookGroupServes = new ArrayList<>();
            bookGroupResourceList.forEach(item -> {
                BookGroupServe bookGroupServe = new BookGroupServe();
                bookGroupServe.setBookGroupId(newBookGroupId);
                bookGroupServe.setServeType(item.getServeType());
                bookGroupServe.setServeUrl(item.getServeUrl());
                bookGroupServe.setServeId(item.getServeId());
                bookGroupServes.add(bookGroupServe);
            });
            batchUpdateBookGroupServe(bookInfo.getCreateUser(), bookGroupServes);
        }
        //删除旧数据
        bookGroupDao.deleteByBookGroupId(oldBookGroupId);
        //插入转换记录表
        QrChangeRecord qrChangeRecord = QrChangeRecord.builder().oldBookGroupId(oldBookGroupId).newBookGroupId(newBookGroupId).build();
        bookGroupDao.insertQrChangeRecord(qrChangeRecord);
        if (sceneId != null) {
            qrcodeSceneConsr.updateQrcodeToSelfRobotQrcode(sceneId, bookInfo.getBookId());
        }
        return newBookGroupId;
    }

    @ParamLog("获取社群书信息")
    @Override
    public PageBeanNew<BookGroupDTO> getListBookGroup4Adviser( Map<String, Object> paramMap, PageParam pageParam ) {
        PageBeanNew<BookGroupDTO> pageBean = bookGroupDao.listPageNew(pageParam, paramMap, "getListBookGroup4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew<>(pageParam.getNumPerPage(), pageParam.getNumPerPage(), 0, new ArrayList<>());
        }
        // 填充社群书数据
        List<BookGroupDTO> bookGroupDTOList = pageBean.getRecordList();
        //设置关联状态
        //1.获取1v1关联社群书
        List<BookGroupDTO> bookGroupAssoList = bookGroupDao.getAssocBookGroupByAppInfo(paramMap);
        //2.获取关联bookId和bookGroupId
        for (BookGroupDTO bookGroupDTO : bookGroupDTOList) {
            for (BookGroupDTO bookGroupAsso : bookGroupAssoList) {
                if (bookGroupDTO.getBookId().equals(bookGroupAsso.getBookId()) && bookGroupDTO.getId().equals(bookGroupAsso.getId())) {
                    bookGroupDTO.setAssocState(true);
                    break;
                } else {
                    bookGroupDTO.setAssocState(false);
                }
            }
        }
        fillBookGroupServe(bookGroupDTOList);
        return pageBean;
    }

    @ParamLog("获取1v1社群书关联信息")
    @Override
    public PageBeanNew<BookGroupDTO> getAssocBookGroupByAppInfo( Map<String, Object> paramMap, PageParam pageParam ) {
        if (null == paramMap.get("channelId") || null == paramMap.get("serveId") || null == paramMap.get("serveType")) {
            throw new BookBizException(BookBizException.ERROR, "缺少必要参数！");
        }
        PageBeanNew<BookGroupDTO> pageBean = bookGroupDao.listPageNew(pageParam, paramMap, "getAssocBookGroupByAppInfo");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew<>(pageParam.getNumPerPage(), pageParam.getNumPerPage(), 0, new ArrayList<>());
        }
        return pageBean;
    }

    @ParamLog("获取1v1社群书关联名称和数量")
    @Override
    public List<BookGroupDTO> getAssocBookGroupByServeInfo( Long adviserId, Long serveId, String serveType ) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("serveId", serveId);
        paramMap.put("serveType", serveType);
        paramMap.put("adviserId", adviserId);
        if (null == paramMap.get("serveId") || null == paramMap.get("serveType")) {
            throw new BookBizException(BookBizException.ERROR, "缺少必要参数！");
        }
        List<BookGroupDTO> bookGroupDtos = bookGroupDao.getAssocBookGroupByAppInfo(paramMap);
        return bookGroupDtos;
    }

    @Override
    public List<BookGroupCountDTO> getAssocBookGroupCount( List<BookGroupCountDTO> dtos ) {
        if (ListUtils.isEmpty(dtos)) {
            return new ArrayList<>();
        }
        Long adviserId = dtos.get(0).getAdviserId();
        List<Long> appIds = dtos.stream().filter(d -> AppAndProductTypeEnum.APP.value.equals(d.getServeType()))
                .map(BookGroupCountDTO::getServeId).collect(Collectors.toList());
        List<Long> productIds = dtos.stream().filter(d -> AppAndProductTypeEnum.PRODUCT.value.equals(d.getServeType()))
                .map(BookGroupCountDTO::getServeId).collect(Collectors.toList());
        List<BookGroupCountDTO> resultDtos = new ArrayList<>();
        if (!ListUtils.isEmpty(appIds)) {
            List<BookGroupCountDTO> countDtos = bookGroupServeDao.getCountByServeIds(appIds, AppAndProductTypeEnum.APP.value, adviserId);
            resultDtos.addAll(countDtos);
        }
        if (!ListUtils.isEmpty(productIds)) {
            List<BookGroupCountDTO> countDtos = bookGroupServeDao.getCountByServeIds(productIds, AppAndProductTypeEnum.PRODUCT.value, adviserId);
            resultDtos.addAll(countDtos);
        }
        return resultDtos;
    }

    @Override
    @ParamLog("ERP创建社群二维码")
    public ErpBookGroupDTO createGroupQrcode4Erp( ErpGroupQrcodeDTO erpGroupQrcodeDTO ) {
        ErpBookGroupDTO bookGroupDTO = new ErpBookGroupDTO();

        Long bookId = erpGroupQrcodeDTO.getBookId();
        Long channelId = erpGroupQrcodeDTO.getChannelId();
        Long adviserId = erpGroupQrcodeDTO.getAdviserId();
        Integer addType = erpGroupQrcodeDTO.getAddType();
        Integer joinGroupType = erpGroupQrcodeDTO.getJoinGroupType();
        BookGroupDTO dto = bookGroupDao.getDTOByBookId(bookId, channelId, adviserId);
        if (null != dto) {
            bookGroupDTO.setCreateState("exist");
            return bookGroupDTO;
        }

        BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookId, channelId, adviserId, addType, null, joinGroupType, null, null);
        bookGroup.setGroupQrcodeName(erpGroupQrcodeDTO.getGroupQrcodeName());
        bookGroup.setIsInviteGroup(true);
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(joinGroupType)) {
            bookGroup.setAddFriendGuide("我是学习助手，请添加我为好友，我将为你提供本书配套资源服务");
            bookGroup.setCustomerServiceName("学习助手");
        } else {
            bookGroup.setJoinSlogan("请选择你喜欢的群分类，我们会根据你的选择，推荐进入对应的微信群，方便你与相同兴趣的群友交流");
            bookGroup.setJoinTitle("选择你想加入的微信群");
        }
        bookGroupDao.update(bookGroup);
        bookGroupDTO.setId(bookGroup.getId());
        bookGroupDTO.setGroupQrcodeUrl(bookGroup.getGroupQrcodeUrl());
        bookGroupDTO.setCreateState("success");
        return bookGroupDTO;
    }

    @ParamLog("填充资源配置名称和链接")
    private void fillBookGroupServe( List<BookGroupDTO> bookGroupDTOList ) {
        if (ListUtils.isEmpty(bookGroupDTOList)) {
            return;
        }
        List<Long> bookGroupIds = bookGroupDTOList.stream().filter(s -> s.getId() != null).map(BookGroupDTO::getId).collect(Collectors.toList());
        if (!ListUtils.isEmpty(bookGroupIds)) {
            List<BookGroupServe> bookGroupServeList = bookGroupServeDao.getListByBookGroupIds(bookGroupIds);
            List<Long> productIds = new ArrayList<>();
            List<Long> appIds = new ArrayList<>();
            for (BookGroupServe bookGroupServe : bookGroupServeList) {
                if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                    productIds.add(bookGroupServe.getServeId());
                }
                if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                    appIds.add(bookGroupServe.getServeId());
                }
            }
            Map<Long, ProductDto> productDtoMap = new HashMap<>();
            Map<Long, AppDto> appDtoMap = new HashMap<>();
            if (!ListUtils.isEmpty(productIds)) {
                productDtoMap = productConsr.getProBasesByIds(productIds);
            }
            if (!ListUtils.isEmpty(appIds)) {
                appDtoMap = appConsr.mapByIds(appIds);
            }
            for (BookGroupServe bookGroupServe : bookGroupServeList) {
                if (AppAndProductTypeEnum.PRODUCT.value.equals(bookGroupServe.getServeType())) {
                    ProductDto productDto = productDtoMap.get(bookGroupServe.getServeId());
                    if (productDto != null) {
                        bookGroupServe.setServeName(productDto.getProductName());
                    }
                }
                if (AppAndProductTypeEnum.APP.value.equals(bookGroupServe.getServeType())) {
                    AppDto appDto = appDtoMap.get(bookGroupServe.getServeId());
                    if (appDto != null) {
                        bookGroupServe.setServeName(appDto.getTitle());
                    }
                }
            }
            Map<Long, List<BookGroupServe>> map = bookGroupServeList.stream().collect(Collectors.groupingBy(BookGroupServe::getBookGroupId));
            for (BookGroupDTO bookGroupDto : bookGroupDTOList) {
                List<BookGroupServe> bookGroupServes = map.get(bookGroupDto.getId());
                bookGroupDto.setBookGroupServes(bookGroupServes);
            }

        }
    }

    @ParamLog("生成随机码")
    private String createRandomCode() {
        //生成暗号规则：abcdefg，7位字符串
        Random random = new Random();
        String s = "";
        for (int i = 0; i < 7; i++) {
            int result = 97 + random.nextInt(26);
            s = s + String.valueOf((char) result);
        }
        return s;
    }

    @Override
    public List<String> getFriendIdListByBookAndRobot( String altId, List<Long> bookIds ) {
        return bookGroupCipherUserDao.getFriendIdListByBookAndRobot(altId, bookIds);
    }

    @Override
    public Map<String, List<UserBookBaseInfoDTO>> mapUserScanBook( String altId, List<String> wxUserIdList ) {
        Map<String, List<UserBookBaseInfoDTO>> map = new HashMap<>();
        if (ListUtils.isEmpty(wxUserIdList)) {
            return new HashMap<>();
        }
        for (String wxUserId : wxUserIdList) {
            List<UserBookInfoItemVO> bookList = bookGroupCipherUserDao.getScanBookInfoByUser(wxUserId, altId);
            List<UserBookBaseInfoDTO> bookInfoList = new ArrayList<>();
            if (!ListUtils.isEmpty(bookList)) {
                List<Long> adviserIds = bookList.stream().filter(s -> s.getAdviserId() != null).map(UserBookInfoItemVO::getAdviserId).distinct().collect(Collectors.toList());
                Map<Long, AdviserBaseInfoDto> adviserBaseInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
                for (UserBookInfoItemVO infoItemVO : bookList) {
                    UserBookBaseInfoDTO baseInfoDTO = new UserBookBaseInfoDTO();
                    BeanUtils.copyProperties(infoItemVO, baseInfoDTO);
                    if (!MapUtils.isEmpty(adviserBaseInfoDtoMap) && adviserBaseInfoDtoMap.containsKey(infoItemVO.getAdviserId())) {
                        AdviserBaseInfoDto adviserBaseInfoDto = adviserBaseInfoDtoMap.get(infoItemVO.getAdviserId());
                        baseInfoDTO.setAdviserName(adviserBaseInfoDto.getPartyName());
                        baseInfoDTO.setAgentId(adviserBaseInfoDto.getAgentId());
                        baseInfoDTO.setAgentName(adviserBaseInfoDto.getAgentName());
                        baseInfoDTO.setPhoneNum(adviserBaseInfoDto.getPhoneNum());
                    }
                    bookInfoList.add(baseInfoDTO);
                }
            }
            if (!ListUtils.isEmpty(bookInfoList)) {
                map.put(wxUserId, bookInfoList);
            }
        }
        return map;
    }

    @Override
    public void updateSpecialState( Long id, Boolean belongSpecialAgent ) {
        bookGroupDao.updateSpecialState(id, belongSpecialAgent);
    }

    @Override
    public Long getLatestCipherBookGroup( String altId, String wxUserId ) {
        Long bookGroupId = bookGroupCipherUserDao.getLatestCipherBookGroup(altId, wxUserId);
        return bookGroupId;
    }

    @Override
    public BookGroupStatistic4AgentDTO getBookGroupStatisticsByAgent( Long bookId ,Long agentId,Long adviserId,Long channelId) {
        BookGroupStatistic4AgentDTO groupStatistic4AgentDTO = bookGroupDao.getBaseInfoByBookId(bookId,agentId,adviserId,channelId);
        if (null == groupStatistic4AgentDTO) {
            return new BookGroupStatistic4AgentDTO();
        }
        Long bookGroupId = groupStatistic4AgentDTO.getBookGroupId();
        //资源浏览量
        Integer browseCount = 0;
        Integer browserCount = 0;
        Long browseTimes = 0L;
        Map<Long, GroupBrowseStatisticVO> browseMap = browseRecordConsr.mapGroupBrowseStatistic(Arrays.asList(bookGroupId), null);
        if (!MapUtils.isEmpty(browseMap) && browseMap.containsKey(bookGroupId)) {
            GroupBrowseStatisticVO browseStatisticVO = browseMap.get(bookGroupId);
            browseCount = browseStatisticVO.getBrowseCount();
            browserCount = browseStatisticVO.getBrowserCount();
            browseTimes = browseStatisticVO.getBrowserCount() == 0 ? 0 : browseStatisticVO.getBrowseTimes() / browseStatisticVO.getBrowserCount();
        }
        groupStatistic4AgentDTO.setBrowseCount(browseCount);
        groupStatistic4AgentDTO.setBrowserCount(browserCount);
        groupStatistic4AgentDTO.setAvgbrowseTimes(browseTimes);
        //购买次数 销售额
        Long saleCount = 0L;
        Double saleAmount = 0D;
        Map<Long, ProductSaleDetailDto> saleMap = tradeConsr.getSaleInfo4Group(Arrays.asList(bookGroupId), null);
        if (!MapUtils.isEmpty(saleMap) && saleMap.containsKey(bookGroupId)) {
            ProductSaleDetailDto productSaleDetailDto = saleMap.get(bookGroupId);
            saleCount = productSaleDetailDto.getSaleCount();
            saleAmount = productSaleDetailDto.getSaleMoney();
        }
        groupStatistic4AgentDTO.setSaleCount(saleCount);
        groupStatistic4AgentDTO.setSaleAmount(saleAmount);
        if (JoinGroupTypeEnum.ROBOT.getCode().equals(groupStatistic4AgentDTO.getJoinGroupType())) {
            //个人号信息
            List<AltAndCountDTO> altAndCountDTOS = bookGroupCipherUserDao.getAltFriendList(bookGroupId);
            if (!ListUtils.isEmpty(altAndCountDTOS)) {
                List<String> altList = altAndCountDTOS.stream().filter(s -> s.getAltId() != null).map(AltAndCountDTO::getAltId).collect(Collectors.toList());
                Map<String, RobotBaseInfoDTO> robotBaseInfoDTOMap = wechatGroupConsr.mapRobotInfo(altList);
                for (AltAndCountDTO altAndCountDTO : altAndCountDTOS) {
                    if (!MapUtils.isEmpty(robotBaseInfoDTOMap) && robotBaseInfoDTOMap.containsKey(altAndCountDTO.getAltId())) {
                        RobotBaseInfoDTO dto = robotBaseInfoDTOMap.get(altAndCountDTO.getAltId());
                        altAndCountDTO.setNickName(dto == null ? "" : dto.getNickName());
                    }
                }
            }
            groupStatistic4AgentDTO.setAltAndCountDTOS(altAndCountDTOS);
            //个人号配置资源
            List<BookGroupServe> list = bookGroupServeDao.getListByBookGroupId(bookGroupId);
            groupSet.setBookGroupServeStatistic(list, bookGroupId);
            groupStatistic4AgentDTO.setBookGroupServeList(list);
        }
        return groupStatistic4AgentDTO;
    }

    @Override
    public List<ListKeywordVO> getClassifyKeywordStatistic( Long classifyId ) {
        ClassifyDTO classifyDTO = bookGroupClassifyDao.getById(classifyId);
        if (null == classifyDTO) {
            return new ArrayList<>();
        }
        Long bookGroupId = classifyDTO.getBookGroupId();
        //所有的关键词（群分类+书）
        List<ListKeywordVO> listKeywordVOS = new ArrayList<>();
        //按分类设置的关键词
        List<ListKeywordVO> classifyKeywordVOS = bookKeywordDao.getAppKeywordsByClassifyId(classifyId, bookGroupId, null);
        List<Long> keywordIdList = new ArrayList<>();
        if (!ListUtils.isEmpty(classifyKeywordVOS)) {
            keywordIdList = classifyKeywordVOS.stream().filter(s -> s.getKeywordId() != null).map(ListKeywordVO::getKeywordId).distinct().collect(Collectors.toList());
            listKeywordVOS.addAll(classifyKeywordVOS);
        }
        //按书设置的关键词
        List<ListKeywordVO> bookKeywordVOS = bookKeywordDao.getAppKeywordsByClassifyId(0L, bookGroupId, keywordIdList);
        if (!ListUtils.isEmpty(bookKeywordVOS)) {
            listKeywordVOS.addAll(bookKeywordVOS);
        }
        if (!ListUtils.isEmpty(listKeywordVOS)) {
            groupSet.setKeyWordStatistic(classifyId, bookGroupId, listKeywordVOS);
        }
        return listKeywordVOS;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog("新增微信用户和rays系统用户关联关系")
    @Override
    public void createWxWechatUserCorrelation( Long wechatUserId, WxWechatUserCorrelation wxWechatUserCorrelation ) {
        if (wxWechatUserCorrelation == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数为空！");
        }
        if (wxWechatUserCorrelation.getBookGroupId() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "bookGroupId参数为空！");
        }
        if (StringUtil.isEmpty(wxWechatUserCorrelation.getWxId())) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "wxUserId参数为空！");
        }
        wxWechatUserCorrelation.setWechatUserId(wechatUserId);
        //判断库里有没有
        WxWechatUserCorrelation old = wxWechatUserCorrelationDao.getByWxIdAndBookGroupId(wxWechatUserCorrelation.getBookGroupId(), wxWechatUserCorrelation.getWxId());
        if (old != null) {
            return;
        }
        wxWechatUserCorrelationDao.insert(wxWechatUserCorrelation);
    }

    @Override
    public SelfRobotBookGroupDTO getSelfRobotBookGroupInfoByUser( String wxUserId, Long bookGroupId ) {
        SelfRobotBookGroupDTO dto = bookGroupCipherUserDao.getSelfRobotBookGroupInfoByUser(wxUserId, bookGroupId);
        if (null != dto) {
            GroupRobotDTO robotDTO = wechatGroupConsr.getGroupRobotByWxId(dto.getWxId());
            dto.setWxNickName(robotDTO.getNickName());
        }
        return dto;
    }

    @Override
    public PageBeanNew<UserBookInfoVO> listUser4ReadingActivity( UserSelectParamDTO userSelectParamDTO ) {
        Integer currentPage = userSelectParamDTO.getCurrentPage();
        Integer numPerPage = userSelectParamDTO.getNumPerPage();
        Map<String, Object> map = new HashMap<>();
        //用户昵称id模糊查询
        if (!StringUtil.isEmpty(userSelectParamDTO.getUserQuery())) {
            List<String> wxUserIds = wechatGroupConsr.getByUserQuery(userSelectParamDTO.getUserQuery());
            if (!ListUtils.isEmpty(wxUserIds)) {
                map.put("wxUserIds", wxUserIds);
            } else {
                return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
            }
        }
        map.put("bookIds", userSelectParamDTO.getBookIds());
        map.put("robotId", userSelectParamDTO.getRobotId());
        map.put("invitedFilter", userSelectParamDTO.getInvitedFilter());
        List<Long> countlist = bookGroupCipherUserDao.listId4ReadingActivity(map);
        if (ListUtils.isEmpty(countlist)) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        map.put("pageNum", currentPage * numPerPage);
        map.put("numPerPage", numPerPage);
        List<Long> idList = bookGroupCipherUserDao.listId4ReadingActivity(map);
        List<UserBookInfoVO> list = bookGroupCipherUserDao.listUserByIds(idList);
        //填充用户信息、扫码书刊信息,小号信息
        groupSet.setUserBookInfo4ReadingActivity(list);
        return new PageBeanNew<>(currentPage, numPerPage, countlist.size(), list);
    }

    @ParamLog("生成小程序码")
    @Override
    public void createBookGroupAppletUrl(Long bookGroupId, Long bookId, Long channelId, Long adviserId ) {
        BookAppletScene appletScene = bookAppletSceneDao.getByBookGroupId(bookGroupId);
        if (null != appletScene) {
            LOGGER.info("小程序码已存在, bookGroupId"+bookGroupId);
            return;
        }
        Long raysClassifyId = null;
        BookAdviserDto bookAdviserDto = bookAdviserDao.getBase(bookId, channelId, adviserId);
        if (null != bookAdviserDto && null != bookAdviserDto.getTempletId()) {
            raysClassifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(bookAdviserDto.getTempletId());
            if (null == raysClassifyId) {
                LOGGER.warn("书刊分类没有对应的小睿分类" + bookGroupId);
            }
        }
        String page = null;//小程序跳转页 todo
        String appletId = createOneAppletId();
        BookAppletScene applet = bookAppletSceneDao.getByAppletId(appletId);
        while (null != applet) {
            appletId = createOneAppletId();
            applet = bookAppletSceneDao.getByAppletId(appletId);
        }
        Long accoutnSettingId = getAccountSettingByAdviser(adviserId);
        //直接跳小程序，不创建小程序码
//        String url = wechatConsr.create4MiniApp(accoutnSettingId, appletId, null, page);
        BookAppletScene bookAppletScene = new BookAppletScene();
        bookAppletScene.setBookGroupId(bookGroupId);
        bookAppletScene.setRaysClassifyId(raysClassifyId);
        bookAppletScene.setAppletId(appletId);
        bookAppletScene.setAppletUrl(null);
        bookAppletScene.setAccountSettingId(accoutnSettingId);
        bookAppletSceneDao.insert(bookAppletScene);
    }

    @ParamLog("生成一个小程序id")
    private String createOneAppletId() {
        /*Random random = new Random();
        String charStr = "0123456789abcdefghijklmnopqrstuvwxyz";
        String s = "";
        for (int i = 0; i < 20; i++) {
            int index = random.nextInt(charStr.length());
            s = s + charStr.charAt(index);
        }
        return s;*/
        return UUIDUitl.generateString(20);
    }

    @Override
    public BookAppletSceneDTO getBookGroupAppletByAppletId( String appletId ) {
        BookAppletScene bookAppletScene = bookAppletSceneDao.getByAppletId(appletId);
        BookAppletSceneDTO dto = new BookAppletSceneDTO();
        if (null != bookAppletScene) {
            BeanUtils.copyProperties(bookAppletScene, dto);
        }
        return dto;
    }

    @Override
    public BookAppletSceneDTO getBookGroupAppletByBookGroupId(Long bookGroupId, String requestIp) {
        BookAppletScene bookAppletScene = bookAppletSceneDao.getByBookGroupId(bookGroupId);
        BookAppletSceneDTO dto = new BookAppletSceneDTO();
        if (null != bookAppletScene) {
            BeanUtils.copyProperties(bookAppletScene, dto);
        }
        BookGroupDTO bookGroupDTO = bookGroupDao.getBookBaseInfoById(bookGroupId);
        // 新增埋点
        BookBrowseRecord bookBrowseRecord = new BookBrowseRecord();
        bookBrowseRecord.setBookId(bookGroupDTO.getBookId());
        bookBrowseRecord.setIp(requestIp);
        bookBrowseRecordBiz.addBookRecord4BookId(bookBrowseRecord);
        //1v1走小睿流程
        if (bookGroupDTO.getOpenWeapp() &&
                (JoinGroupTypeEnum.ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType())
                        || JoinGroupTypeEnum.AI_ROBOT.getCode().equals(bookGroupDTO.getJoinGroupType()))) {
            return dto;
        } else {
            dto.setBookName(StringUtil.addBracket(bookGroupDTO.getBookName()));
            //权益
            RightsSettingDto rightsSettingDto = rightsSettingBiz.getRightsSettingByBookId4AppletHome(bookGroupDTO.getBookId(), bookGroupDTO.getCreateUser(), bookGroupDTO.getChannelId());
            if (null != rightsSettingDto) {
                dto.setRightsSettingId(rightsSettingDto.getId());
                dto.setRightsSettingDetail(rightsSettingDto.getDetail());
                dto.setRightsSettingIntroduce(rightsSettingDto.getIntroduce());
                dto.setRightsSettingCount(rightsSettingDto.getCount());
            }
        }
        return dto;
    }

    @Override
    public void updateBookGroupRaysClassify( Book book ) {
        //小睿类型更新分类
        BookGroupDTO bookGroupDTO = bookGroupDao.getDTOByBookId(book.getBookId(), book.getChannelId(), book.getLastModifiedUser());
        if (null != bookGroupDTO && JoinGroupTypeEnum.XIAORUI.getCode().equals(bookGroupDTO.getJoinGroupType())) {
            Long raysClassifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(book.getTempletId());
            if (null != raysClassifyId) {
                bookAppletSceneDao.updateRaysClassifyIdByBookGroupId(raysClassifyId, bookGroupDTO.getId());
            }
        }
    }

    @Override
    public Long getBookGroupId4OldData( Long raysBookId ) {
        return bookGroupDao.getBookGroupId4OldData(raysBookId);
    }

    @Override
    public BookGroupDTO getByAppletScene( Long wechatUserId, String scene, Long officialAccountsId) {
        BookGroupDTO dto = new BookGroupDTO();
        BookAppletScene bookAppletScene = bookAppletSceneDao.getByAppletId(scene);
        if (null == bookAppletScene) {
            return dto;
        }
        if (null != bookAppletScene.getBookGroupId()) {
            BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookAppletScene.getBookGroupId());
            BeanUtils.copyProperties(bookGroupDTO, dto);
            dto.setAdviserId(bookGroupDTO.getCreateUser());
            //用户书刊埋点
            AppletUserBookcase appletUserBookcase = new AppletUserBookcase();
            appletUserBookcase.setWechatUserId(wechatUserId);
            appletUserBookcase.setAdviserId(bookGroupDTO.getCreateUser());
            appletUserBookcase.setBookId(bookGroupDTO.getBookId());
            appletUserBookcase.setChannelId(bookGroupDTO.getChannelId());
            appletUserBookcase.setOfficialAccountsId(officialAccountsId);
            AppletTaskDTO appletTaskDTO = appletUserBookcaseBiz.addUserBook(appletUserBookcase);
            if (null != appletTaskDTO && YesOrNoEnums.YES.getValue().equals(appletTaskDTO.getIsFinishTask())) {
                dto.setIsFinshTask(appletTaskDTO.getIsFinishTask());
            }
            //社群书埋点
            AppletGroupSearchRecord appletGroupSearchRecord = new AppletGroupSearchRecord();
            appletGroupSearchRecord.setAdviserId(bookGroupDTO.getCreateUser());
            appletGroupSearchRecord.setBookGroupId(bookAppletScene.getBookGroupId());
            appletGroupSearchRecord.setBookId(bookGroupDTO.getBookId());
            appletGroupSearchRecord.setChannelId(bookGroupDTO.getChannelId());
            appletGroupSearchRecord.setWechatUserId(wechatUserId);
            appletGroupSearchRecordBiz.insert(appletGroupSearchRecord);
            //足迹埋点
            AppletRecord appletRecord = new AppletRecord();
            appletRecord.setWechatUserId(wechatUserId);
            appletRecord.setFromId(bookGroupDTO.getBookId());
            appletRecord.setFromName(bookBiz.getBaseById(bookGroupDTO.getBookId()).getBookName());
            appletRecord.setRecordType(AppletRecordTypeEnum.BOOK.value);
            appletRecord.setBookId(bookGroupDTO.getBookId());
            appletRecord.setAdviserId(bookGroupDTO.getCreateUser());
            appletRecord.setChannelId(bookGroupDTO.getChannelId());
            appletRecordBiz.insert(appletRecord);
        } else if (bookAppletScene.getSceneId() != null) {
            QrcodeSceneDto byId = qrcodeSceneConsr.getById(bookAppletScene.getSceneId());
            dto.setBookId(byId.getAdviserBookId());
            dto.setAdviserId(byId.getCreatedByUserLogin());
            dto.setSceneId(bookAppletScene.getSceneId());
            dto.setChannelId(byId.getChannelPartyId());
            //用户书刊埋点
            AppletUserBookcase appletUserBookcase = new AppletUserBookcase();
            appletUserBookcase.setWechatUserId(wechatUserId);
            appletUserBookcase.setOfficialAccountsId(officialAccountsId);
            appletUserBookcase.setAdviserId(byId.getCreatedByUserLogin());
            appletUserBookcase.setBookId(byId.getAdviserBookId());
            appletUserBookcase.setChannelId(byId.getChannelPartyId());
            AppletTaskDTO appletTaskDTO = appletUserBookcaseBiz.addUserBook(appletUserBookcase);
            if (null != appletTaskDTO && YesOrNoEnums.YES.getValue().equals(appletTaskDTO.getIsFinishTask())) {
                dto.setIsFinshTask(appletTaskDTO.getIsFinishTask());
            }
            //足迹埋点
            AppletRecord appletRecord = new AppletRecord();
            appletRecord.setWechatUserId(wechatUserId);
            appletRecord.setFromId(byId.getAdviserBookId());
            appletRecord.setFromName(bookBiz.getBaseById(byId.getAdviserBookId()).getBookName());
            appletRecord.setRecordType(AppletRecordTypeEnum.BOOK.value);
            appletRecord.setBookId(byId.getAdviserBookId());
            appletRecord.setAdviserId(byId.getCreatedByUserLogin());
            appletRecord.setChannelId(byId.getChannelPartyId());
            appletRecordBiz.insert(appletRecord);
        }
        return dto;
    }

    @Override
    public PageBeanNew<BookServeDTO> getBookAndBookGroupServeList(Long adviserId, Long bookId, Long channelId, Long wechatUserId) {
        //社群书和现代纸书下资源
        List<BookServeDTO> serveDTOList = getBookAndBookGroupServeIds(adviserId, bookId, channelId);
        if (ListUtils.isEmpty(serveDTOList)) {
            return new PageBeanNew<>(0, 1, 0, new ArrayList<>());
        }
        //填充资源信息
        fillBookServe(serveDTOList);
        //移除不能购买的应用或作品
        removeCanNotBuy(serveDTOList);
        if (ListUtils.isEmpty(serveDTOList)) {
            return new PageBeanNew<>(0, 1, 0, new ArrayList<>());
        }
        fillCollect4Book(wechatUserId, serveDTOList);
        PageBeanNew<BookServeDTO> pageBeanNew = new PageBeanNew<BookServeDTO>(0, serveDTOList.size(), serveDTOList.size(), serveDTOList);
        pageBeanNew.setPageCount(1);
        return pageBeanNew;
    }

    @Override
    public void fillCollect4Book(Long wechatUserId, List<BookServeDTO> serveDTOList) {
        if (ListUtils.isEmpty(serveDTOList) || null == wechatUserId) {
            return;
        }
        List<ServeCollect> serveCollects = new ArrayList<>();
        serveDTOList.forEach(e -> {
            ServeCollect serveCollect = new ServeCollect();
            serveCollect.setWechatUserId(wechatUserId);
            serveCollect.setServeId(e.getServeId());
            serveCollect.setServeType(Objects.equals(e.getServeType(), AppAndProductTypeEnum.PRODUCT.value) ? AppletRecordTypeEnum.PRODUCT.value : AppletRecordTypeEnum.APP.value);
            serveCollects.add(serveCollect);
        });
        List<ServeCollect> serveCollectList = serveCollectBiz.getList4RightsSetting(serveCollects);
        if (ListUtils.isEmpty(serveCollectList)) {
            return;
        }
        List<ServeCollect> collect4Product = serveCollectList.stream().filter(e -> Objects.equals(e.getServeType(), AppletRecordTypeEnum.PRODUCT.value)).collect(Collectors.toList());
        List<ServeCollect> collect4App = serveCollectList.stream().filter(e -> Objects.equals(e.getServeType(), AppletRecordTypeEnum.APP.value)).collect(Collectors.toList());
        Map<Long, ServeCollect> serveCollectMap4Product = new HashMap<>();
        Map<Long, ServeCollect> serveCollectMap4App = new HashMap<>();
        if (!ListUtils.isEmpty(collect4Product)) {
            serveCollectMap4Product = collect4Product.stream().collect(Collectors.toMap(e -> e.getServeId(), a -> a, (k1, k2) -> k1));
        }
        if (!ListUtils.isEmpty(collect4App)) {
            serveCollectMap4App = collect4App.stream().collect(Collectors.toMap(e -> e.getServeId(), a -> a, (k1, k2) -> k1));
        }
        for (BookServeDTO bookServeDTO : serveDTOList) {
            if (Objects.equals(bookServeDTO.getServeType(), AppAndProductTypeEnum.PRODUCT.value) && MapUtils.isNotEmpty(serveCollectMap4Product) &&
                    null != serveCollectMap4Product.get(bookServeDTO.getServeId())) {
                bookServeDTO.setIsCollect(YesOrNoEnums.YES.getValue());
            } else if (Objects.equals(bookServeDTO.getServeType(), AppAndProductTypeEnum.APP.value) && MapUtils.isNotEmpty(serveCollectMap4App) &&
                    null != serveCollectMap4App.get(bookServeDTO.getServeId())) {
                bookServeDTO.setIsCollect(YesOrNoEnums.YES.getValue());
            }
        }
    }

    @Override
    @ParamLog("移除不能购买的应用或作品")
    public void removeCanNotBuy( List<BookServeDTO> list ) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<BookServeDTO> toRemoveList = new ArrayList<>();
        for (BookServeDTO item : list) {
            if ((AppAndProductTypeEnum.APP.value.equals(item.getServeType()) && ArrayUtils.contains(RightsSettingConstant.APPLET_APP_NOT_SUPPORT, item.getFromType()))
                    || (AppAndProductTypeEnum.PRODUCT.value.equals(item.getServeType()) && ArrayUtils.contains(RightsSettingConstant.APPLET_PRODUCT_NOT_SUPPORT, item.getFromType())) || StringUtil.isEmpty(item.getFromType())) {
                toRemoveList.add(item);
            }
        }
        if (!ListUtils.isEmpty(toRemoveList)) {
            list.removeAll(toRemoveList);
        }
    }

    @Override
    public List<BookServeDTO> getBookAndBookGroupServeIdsFive(Long adviserId, Long bookId, Long channelId) {
        List<BookServeDTO> serveDTOList = new ArrayList<>();
        List<Long> appIds = new ArrayList<>();
        List<Long> productIds = new ArrayList<>();
        AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
        if (null == accountSettingDto){
            return new ArrayList<>();
        }
        //先排纸书二维码资源，后排社群书资源，张文庆
        //现代纸书二维码配置资源
        BookServeParamVO serveParamVO = new BookServeParamVO();
        serveParamVO.setAdviserId(adviserId);
        serveParamVO.setBookId(bookId);
        serveParamVO.setChannelId(channelId);
        List<BookServeVO> bookServeVOS = qrcodeSceneConsr.listBookServeIds(serveParamVO);
        if (!ListUtils.isEmpty(bookServeVOS)) {
            for (BookServeVO bookServeVO : bookServeVOS) {
                if(serveDTOList.size()>=5){
                    break;
                }
                Long serveId = bookServeVO.getServeId();
                BookServeDTO bookServeDTO = new BookServeDTO();
                bookServeDTO.setTypeCode(bookServeVO.getTypeCode());
                bookServeDTO.setFromType(bookServeVO.getFromType());
                bookServeDTO.setFromTypeName(bookServeVO.getFromTypeName());
                String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookServeVO.getUrl());
                if (AppAndProductTypeEnum.APP.value.equals(bookServeVO.getTypeCode()) && !appIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    bookServeDTO.setUrl(url);
                    serveDTOList.add(bookServeDTO);
                    appIds.add(serveId);
                } else if (AppAndProductTypeEnum.PRODUCT.value.equals(bookServeVO.getTypeCode()) && !productIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    bookServeDTO.setUrl(url);
                    serveDTOList.add(bookServeDTO);
                    productIds.add(serveId);
                }
            }
        }
        if (serveDTOList.size()<5) {//有社群书
            //社群书配置资源
            List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBook(bookId, channelId, adviserId);
            if (!ListUtils.isEmpty(bookGroupServes)) {
                for (BookGroupServe bookGroupServe : bookGroupServes) {
                    if(serveDTOList.size()>=5){
                        break;
                    }
                    BookServeDTO bookServeDTO = new BookServeDTO();
                    BeanUtils.copyProperties(bookGroupServe, bookServeDTO);
                    String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookGroupServe.getServeUrl());
                    bookServeDTO.setUrl(url);
                    bookServeDTO.setTypeCode(bookServeDTO.getServeType());
                    bookServeDTO.setFromType(bookGroupServe.getTypeCode());
                    bookServeDTO.setFromTypeName(bookGroupServe.getFromType());
                    Long serveId = bookGroupServe.getServeId();
                    if (AppAndProductTypeEnum.APP.value.equals(bookServeDTO.getServeType()) && !appIds.contains(serveId)) {
                        serveDTOList.add(bookServeDTO);
                        appIds.add(serveId);
                    } else if (AppAndProductTypeEnum.PRODUCT.value.equals(bookServeDTO.getServeType()) && !productIds.contains(serveId)){
                        serveDTOList.add(bookServeDTO);
                        productIds.add(serveId);
                    }
                }
            }
        }
        return serveDTOList;
    }

    @Override
    public List<BookServeDTO> getBookAndBookGroupServeIds( Long adviserId, Long bookId, Long channelId ) {
        List<BookServeDTO> result = new ArrayList();
        String key = "getBookAndBookGroupServeIds"+adviserId+"_"+bookId+"_"+channelId;
        if(JedisClusterUtils.exists(key)){
            result = JedisClusterUtils.getJsonList(key, BookServeDTO.class);
        }else {
            result = getBookServes(adviserId, bookId, channelId);
            JedisClusterUtils.setJsonList(key,result,300);
        }
        return result;
    }



    private List<BookServeDTO> getBookServes( Long adviserId, Long bookId, Long channelId ) {
        List<BookServeDTO> serveDTOList = new ArrayList<>();
        List<Long> appIds = new ArrayList<>();
        List<Long> productIds = new ArrayList<>();
        AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
        if (null == accountSettingDto){
            return new ArrayList<>();
        }
        //先排纸书二维码资源，后排社群书资源，张文庆
        //现代纸书二维码配置资源
        BookServeParamVO serveParamVO = new BookServeParamVO();
        serveParamVO.setAdviserId(adviserId);
        serveParamVO.setBookId(bookId);
        serveParamVO.setChannelId(channelId);
        List<BookServeVO> bookServeVOS = qrcodeSceneConsr.listBookServeIds(serveParamVO);
        if (!ListUtils.isEmpty(bookServeVOS)) {
            for (BookServeVO bookServeVO : bookServeVOS) {
                Long serveId = bookServeVO.getServeId();
                BookServeDTO bookServeDTO = new BookServeDTO();
                bookServeDTO.setTypeCode(bookServeVO.getTypeCode());
                bookServeDTO.setFromType(bookServeVO.getFromType());
                bookServeDTO.setFromTypeName(bookServeVO.getFromTypeName());
                String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookServeVO.getUrl());
                if (AppAndProductTypeEnum.APP.value.equals(bookServeVO.getTypeCode()) && !appIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    bookServeDTO.setUrl(url);
                    serveDTOList.add(bookServeDTO);
                    appIds.add(serveId);
                } else if (AppAndProductTypeEnum.PRODUCT.value.equals(bookServeVO.getTypeCode()) && !productIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    bookServeDTO.setUrl(url);
                    serveDTOList.add(bookServeDTO);
                    productIds.add(serveId);
                }
            }
        }
        //社群书配置资源,（二维码已统一，无需两边查询）
       /* List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBook(bookId, channelId, adviserId);
        if (!ListUtils.isEmpty(bookGroupServes)) {
            for (BookGroupServe bookGroupServe : bookGroupServes) {
                BookServeDTO bookServeDTO = new BookServeDTO();
                BeanUtils.copyProperties(bookGroupServe, bookServeDTO);
                String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookGroupServe.getServeUrl());
                bookServeDTO.setUrl(url);
                bookServeDTO.setTypeCode(bookServeDTO.getServeType());
                bookServeDTO.setFromType(bookGroupServe.getTypeCode());
                bookServeDTO.setFromTypeName(bookGroupServe.getFromType());
                Long serveId = bookGroupServe.getServeId();
                if (AppAndProductTypeEnum.APP.value.equals(bookServeDTO.getServeType()) && !appIds.contains(serveId)) {
                    serveDTOList.add(bookServeDTO);
                    appIds.add(serveId);
                } else if (AppAndProductTypeEnum.PRODUCT.value.equals(bookServeDTO.getServeType()) && !productIds.contains(serveId)){
                    serveDTOList.add(bookServeDTO);
                    productIds.add(serveId);
                }
            }
        }*/
        return serveDTOList;
    }

    @Override
    public BookAppletSceneDTO getBookAppletBySceneId( Long sceneId ) {
        BookAppletScene bySceneId = bookAppletSceneDao.getBySceneId(sceneId);
        if (bySceneId == null) {
            //关联书刊是否开启小睿流程
            QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(sceneId);
            if (null == qrcodeSceneDto || !qrcodeSceneDto.getQrcodeType().equals("ali")) {
                return null;
            }
            BookAdviserDto bookAdviserDto = bookAdviserDao.getBase(qrcodeSceneDto.getAdviserBookId(), qrcodeSceneDto.getChannelPartyId(), qrcodeSceneDto.getCreatedByUserLogin());
            if (null == bookAdviserDto || YesOrNoEnums.NO.getValue().equals(bookAdviserDto.getIsOpenRobotProcess())) {
                return null;
            }
            //给二维码创建小睿码
            ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
                bookBiz.createBookGroupAppletUrl(qrcodeSceneDto.getAdviserBookId(), qrcodeSceneDto.getChannelPartyId(), qrcodeSceneDto.getCreatedByUserLogin(), Arrays.asList(sceneId));
            });
            bySceneId = new BookAppletScene();
            bySceneId.setSceneId(sceneId);
        }
        BookAppletSceneDTO dto = new BookAppletSceneDTO();
        BeanUtils.copyProperties(bySceneId, dto);
        return dto;
    }

    @Override
    public void fillBookServe(List<BookServeDTO> serveDTOList) {
        if (ListUtils.isEmpty(serveDTOList)) {
            return;
        }
        List<Long> appIds = new ArrayList<>();
        List<Long> productIds = new ArrayList<>();
        for (BookServeDTO bookServeDTO : serveDTOList){
            if (bookServeDTO.getServeType().equals(AppAndProductTypeEnum.APP.value) && !appIds.contains(bookServeDTO.getServeId())){
                appIds.add(bookServeDTO.getServeId());
            } else if (bookServeDTO.getServeType().equals(AppAndProductTypeEnum.PRODUCT.value) && !productIds.contains(bookServeDTO.getServeId())){
                productIds.add(bookServeDTO.getServeId());
            }
        }
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMap = productConsr.getProBasesByIds(productIds);
        }
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMap = appConsr.mapByIds(appIds);
        }
        List<BookServeDTO> removeList = new ArrayList<>();
        for (BookServeDTO bookServeDTO : serveDTOList) {
            if (!MapUtils.isEmpty(productDtoMap) && AppAndProductTypeEnum.PRODUCT.value.equals(bookServeDTO.getServeType())) {
                ProductDto productDto = productDtoMap.get(bookServeDTO.getServeId());
                if (productDto != null) {
                    bookServeDTO.setServeName(productDto.getProductName());
                    bookServeDTO.setCoverImg(productDto.getCoverImg());
                    ProductTypeDto productTypeDto = productDto.getProductTypeDto();
                    if (productTypeDto != null) {
                        bookServeDTO.setFromType(productTypeDto.getTypeCode());
                        bookServeDTO.setFromTypeName(productTypeDto.getTypeName());
                    }
                    if (!StringUtil.isEmpty(productDto.getSkipUrl())){
                        bookServeDTO.setHasThirdLink(true);
                    } else {
                        bookServeDTO.setHasThirdLink(false);
                    }
                    if (checkRayUrl(productDto.getSkipUrl()) && ProductTypeConstant.ARTICLE.equals(bookServeDTO.getFromType())){
                        removeList.add(bookServeDTO);
                    }
                } else {
                    removeList.add(bookServeDTO);
                }
            }
            if (!MapUtils.isEmpty(appDtoMap) && AppAndProductTypeEnum.APP.value.equals(bookServeDTO.getServeType())) {
                AppDto appDto = appDtoMap.get(bookServeDTO.getServeId());
                if (appDto != null) {
                    bookServeDTO.setServeName(appDto.getTitle());
                    bookServeDTO.setCoverImg(appDto.getSquareImg());
                    bookServeDTO.setFromType(appDto.getTypeCode());
                    bookServeDTO.setFromTypeName(appDto.getTypeName());
                    if (!StringUtil.isEmpty(appDto.getTurnUrl())){
                        bookServeDTO.setHasThirdLink(true);
                    } else {
                        bookServeDTO.setHasThirdLink(false);
                    }
                    if (checkRayUrl(appDto.getTurnUrl()) && AppTypeEnum.ARTICLE.value.equals(appDto.getTypeCode())){
                        removeList.add(bookServeDTO);
                    }
                } else {
                    removeList.add(bookServeDTO);
                }
            }
        }
        serveDTOList.removeAll(removeList);
    }

    @Override
    public Map<String, Object> getBookBaseInfo4Applet( Long adviserId, Long channelId, Long bookId ) {
        Map<String, Object> map = new HashMap<>();
        //是否开启小睿
        map.put("openRays", resourcePageBiz.isOpenRaysBook(bookId, channelId, adviserId));
        //书刊分类对应的小睿分类
        BookAdviserDto adviserDto = bookAdviserDao.getBase(bookId, channelId, adviserId);
        map.put("isK12", Boolean.FALSE);
        if (null != adviserDto) {
            // 新增判断是否K12分类
            if (Objects.nonNull(adviserDto.getTempletId())) {
                if (CollUtil.toList(RightsSettingConstant.K12_TEMPLET_ID_NEW).contains(adviserDto.getTempletId())) {
                    map.put("isK12", Boolean.TRUE);
                }
                map.put("templetId", adviserDto.getTempletId());
                AssistTempletDTO templetDTO = assistTempletConsr.getTempletById(adviserDto.getTempletId());
                if (Objects.nonNull(templetDTO)) map.put("templateName", templetDTO.getTempletName());

                if (Objects.nonNull(adviserDto.getSecondTempletId())) {
                    map.put("secondTempletId", adviserDto.getSecondTempletId());
                    AssistTempletDTO secondTempletDTO = assistTempletConsr.getTempletById(adviserDto.getSecondTempletId());
                    if (Objects.nonNull(secondTempletDTO)) map.put("secondTempletName", secondTempletDTO.getTempletName());
                }

                if (Objects.nonNull(adviserDto.getThirdTempletId())) {
                    map.put("thirdTempletId", adviserDto.getThirdTempletId());
                    AssistTempletDTO thirdTempletDTO = assistTempletConsr.getTempletById(adviserDto.getThirdTempletId());
                    if (Objects.nonNull(thirdTempletDTO)) map.put("thirdTempletName", thirdTempletDTO.getTempletName());
                }
            }
            Long raysClassifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(adviserDto.getTempletId());
            if (null != raysClassifyId) {
                map.put("raysClassifyId", raysClassifyId);
            }
        }
        //获取书名
        BookDto bookDto = bookBiz.getBaseById(bookId);
        if (null != bookDto) {
            map.put("bookName", bookDto.getBookName());
            map.put("coverImg", bookDto.getCoverImg());
            map.put("publish", bookDto.getPublish());
        }
        map.put("isLibraryBook", bookBiz.checkIsLibraryBook(adviserId, bookId) ? 1 : 0);
        //资源数量
      /*  List<BookServeDTO> serveDTOList = this.getBookAndBookGroupServeIds(adviserId, bookId, channelId);
        this.removeCanNotBuy(serveDTOList);
        map.put("resourceCount",  ListUtils.isEmpty(serveDTOList) ? 0 : serveDTOList.size());*/
        //获取本书阅读人数
        String redisKey4Random = "BOOK:READER_COUNT:" + bookId + ":" + channelId + ":" + adviserId;
        String redisKey4Set = "BOOK:READER_SET:" + bookId + ":" + channelId + ":" + adviserId;
        String readerCountStr = JedisClusterUtils.get(redisKey4Random);
        Integer readerCount4Random = null;
        Integer readerCount4Set = null;
        if (null != readerCountStr && NumberUtil.isNumber(readerCountStr)) {
            readerCount4Random =  Integer.valueOf(readerCountStr);
        } else {
            List<Integer> readerCountList = READER_COUNT_MAP.get(DateUtil.hour(new Date(), Boolean.TRUE));
            readerCount4Random =  RandomUtil.randomInt(readerCountList.get(0), readerCountList.get(1));
        }
        if (JedisClusterUtils.exists(redisKey4Set)) {
            readerCount4Set = JedisClusterUtils.scard(redisKey4Set).intValue();
        } else {
           readerCount4Set = 0;
        }
        map.put("readerCount", readerCount4Random + readerCount4Set);
        return map;
    }

    @Override
    public PageBeanNew<BookGroupClassifyDTO> getBookGroupClassifyByAdviserId(Long adviserId, String classify, Integer currentPage , Integer numPerPage) {
        Map<String,Object> map=new HashMap<>();
        map.put("adviserId",adviserId);
        map.put("classify",classify);
        return bookGroupClassifyDao.listPageNew(new PageParam(currentPage,numPerPage),map,"getBookGroupClassifyByAdviserId");
    }

    @Override
    public void updateBookGroupOpenWeapp(Long bookGroupId, Boolean openWeapp) {
        if (openWeapp){//开启了，创建小程序码,转成小睿码20200717
            BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
            this.createBookGroupAppletUrl(bookGroupId,bookGroupDTO.getBookId(),bookGroupDTO.getChannelId(),bookGroupDTO.getCreateUser());
            //修改joinGroupType
            bookGroupDao.updateJoinGroupType(bookGroupId,JoinGroupTypeEnum.XIAORUI.getCode());
        }
        bookGroupDao.updateBookGroupOpenWeapp(bookGroupId, openWeapp);
    }

    @Override
    public Long createSingleBookGroup(BookGroup bookGroup, Long adviserId) {
        BookGroup bookGroupNew = this.createBookGroupAfterCreateBook(0L, 0L, adviserId, 2, null,
                JoinGroupTypeEnum.GROUP_QRCODE.getCode(), null, null);
        bookGroup.setId(bookGroupNew.getId());
        bookGroup.setSingleGroup(true);
        this.updateBookGroup(bookGroup);
        return bookGroupNew.getId();
    }

    @Override
    public void updateRelatedBookGroup(Long bookGroupId, Long relatedBookGroupId) {
        bookGroupDao.updateRelatedBookGroup(bookGroupId,relatedBookGroupId);
    }

    @Override
    public PageBeanNew<BookGroupDTO> listSingleBookGroup4Adviser(String name, Integer currentPage, Integer numPerPage, Long adviserId) {
        Map<String, Object> map = new HashMap<>();
        map.put("adviserId", adviserId);
        map.put("name", name);
        PageBeanNew<BookGroupDTO> pageBeanNew = bookGroupDao.listPageNew(new PageParam(currentPage, numPerPage), map, "listSingleBookGroup4Adviser");
        return pageBeanNew;
    }

    @Override
    public Map<String, Integer> mapServeCount4Applet(List<Long> bookIds) {
        List<BookGroupServeCountVO> list = bookGroupServeDao.getServeList4Applet(bookIds);
        if (ListUtils.isEmpty(list)) {
            return new HashMap<>();
        }
        Map<String, Integer> map = new HashMap<>();
        for (BookGroupServeCountVO bookServeCountVO : list) {
            String key = bookServeCountVO.getBookId() + "-" + bookServeCountVO.getAdviserId() + "-" + bookServeCountVO.getChannelId();
            map.put(key, bookServeCountVO.getServeCount());
        }
        return map;
    }

    @Override
    public Map<String, BookGroupServeCountDTO> mapBookGroupServeCount(List<Long> adviserIds, List<Long> bookIds, List<Long> channelIds){
        if(CollectionUtils.isEmpty(adviserIds) || CollectionUtils.isEmpty(bookIds) || CollectionUtils.isEmpty(channelIds)){
            throw new ChannelBizException(ChannelBizException.FILED_NULL, "adviserIds、bookIds、channelIds 参数为空！");
        }
        return bookGroupServeDao.mapBookGroupServeCount(adviserIds, bookIds, channelIds);
    }

    @Override
    public Map<String, BookGroupServeCountDTO> mapBookGroupQrcodeServeCount(List<Long> adviserIds, List<Long> bookIds, List<Long> channelIds, Integer joinGroupType){
        if(CollectionUtils.isEmpty(adviserIds) || CollectionUtils.isEmpty(bookIds) || CollectionUtils.isEmpty(channelIds)){
            throw new ChannelBizException(ChannelBizException.FILED_NULL, "adviserIds、bookIds、channelIds 参数为空！");
        }
        return bookGroupServeDao.mapBookGroupQrcodeServeCount(adviserIds, bookIds, channelIds, joinGroupType);
    }

    @Override
    public String getGroupNewsMaterialById(Long bookGroupQrcodeId, Long classifyId, Integer useType, Long groupActivityId) {
        String mediaId = null;
        if (UseTypeEnum.NORMAL_GROUP.value.equals(useType)) {
            if (bookGroupQrcodeId == null) {
                // 切群,获取新切群的群二维码
                String groupQrCode = groupQrcodeBiz.getChangeGroupQrCode(classifyId);
                // 通过群二维码反查 bookGroupQrcodeId
                ClassifyQrcodeVO groupQrcodeInfo = groupQrcodeBiz.getGroupQrcodeInfo(groupQrCode, classifyId);
                if (Objects.isNull(groupQrcodeInfo)) {
                    throw new BookBizException(BookBizException.PARAM_IS_NULL, "未查询到分类下群二维码");
                }
                bookGroupQrcodeId = groupQrcodeInfo.getId();
            }

            if (Objects.isNull(bookGroupQrcodeId)){
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "未获取到图文素材链接");
            }
            // 直接获取 素材地址 如果获取到直接返回
            String materialUrl = bizMaterialMapper.selectMaterialUrl4Biz(bookGroupQrcodeId, UseTypeEnum.NORMAL_GROUP.value);
            if (StrUtil.isNotBlank(materialUrl)){
                return materialUrl;
            }

            // 获取不到则新增
            GroupQrcodeBaseInfoVO groupInfo = groupQrcodeDao.getBaseById(bookGroupQrcodeId);
            GroupMaterialAccount activeAccount = groupMaterialAccountBiz.getActiveAccount(UseTypeEnum.NORMAL_GROUP.value);
            materialUrl = uploadBizMaterial4Group(groupInfo,activeAccount);

            if (StrUtil.isBlank(materialUrl)) {
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "未获取到图文素材链接");
            }
            return materialUrl;

        } else if (UseTypeEnum.THIRD_GROUP.value.equals(useType)) {
            PcloudGroupActivity pcloudGroupActivity = pcloudGroupActivityBiz.getById(groupActivityId);
            if (null == pcloudGroupActivity || null == pcloudGroupActivity.getGroupType() || StringUtil.isEmpty(pcloudGroupActivity.getGroupExtLink())) {
                throw new BookBizException(BookBizException.PARAM_IS_NULL, "pcloudGroupActivity或type为空");
            }
            mediaId = pcloudGroupActivity.getMediaId();
            if (StringUtil.isEmpty(mediaId)) {
                String link = pcloudGroupActivity.getGroupExtLink();
                String url = QrcodeUtils.create(link);
                mediaId = updateMediaId4Activity(url, pcloudGroupActivity);
            }
        }
        if (StringUtil.isEmpty(mediaId)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "mediaId为空");
        }
        return ResponseHandleUtil.parseResponse(materialService.getGroupNewsMaterialByMediaId(mediaId), String.class);
    }

    private String uploadBizMaterial4Group(GroupQrcodeBaseInfoVO groupInfo, GroupMaterialAccount activeAccount) {
        if (Objects.nonNull(groupInfo) && Objects.nonNull(activeAccount) && Objects.nonNull(activeAccount.getAccountId())) {
            GroupMaterialAccount account = groupMaterialAccountBiz.getByAccountId(activeAccount.getAccountId());
            GroupNewsMaterialAddDTO groupNewsMaterialAddDTO = new GroupNewsMaterialAddDTO();
            groupNewsMaterialAddDTO.setAccountId(account.getAccountId());
            groupNewsMaterialAddDTO.setGroupHeadImg(account.getHeadMediaId());
            groupNewsMaterialAddDTO.setCoverMediaId(account.getCoverMediaId());
            groupNewsMaterialAddDTO.setGroupName(groupInfo.getGroupName());
            groupNewsMaterialAddDTO.setQrcodeUrl(groupInfo.getQrcodeUrl());
            try {
                String mediaId = ResponseHandleUtil.parseResponse(materialService.getGroupNewsMaterial(groupNewsMaterialAddDTO), String.class);
                if (StrUtil.isNotBlank(mediaId)) {
                    BizMaterial bizMaterial = new BizMaterial();
                    bizMaterial.setAccountId(Math.toIntExact(account.getAccountId()));
                    bizMaterial.setBizId(Math.toIntExact(groupInfo.getGroupQrcodeId()));
                    bizMaterial.setBizType(UseTypeEnum.NORMAL_GROUP.value);
                    bizMaterial.setCreateTime(new Date());
                    bizMaterial.setMediaId(mediaId);
                    String materialUrl = ResponseHandleUtil.parseResponse(materialService.getGroupNewsMaterialByMediaId(mediaId), String.class);
                    bizMaterial.setMaterialUrl(materialUrl);
                    bizMaterialMapper.insertOrUpdate(bizMaterial);
                    return materialUrl;
                }
            } catch (Exception e) {
                LOGGER.error("[BookGroupBizImpl.uploadBizMaterial4Group]] 上传素材失败！ groupInfo:{}  activeAccount:{}", groupInfo,activeAccount);
            }
        }
        return null;
    }

    @Override
    public String updateMediaId4Activity(String url, PcloudGroupActivity pcloudGroupActivity) {
        GroupMaterialAccount account = groupMaterialAccountBiz.getActiveAccount(UseTypeEnum.THIRD_GROUP.value);
        if (null == account) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "activeAccount为空，没有可用公众号");
        }
        GroupNewsMaterialAddDTO groupNewsMaterialAddDTO = new GroupNewsMaterialAddDTO();
        groupNewsMaterialAddDTO.setAccountId(account.getAccountId());
        groupNewsMaterialAddDTO.setCoverMediaId(account.getCoverMediaId());
        groupNewsMaterialAddDTO.setGroupHeadImg(account.getHeadMediaId());
        groupNewsMaterialAddDTO.setGroupName(pcloudGroupActivity.getName());
        groupNewsMaterialAddDTO.setQrcodeUrl(url);
        groupNewsMaterialAddDTO.setMediaId(pcloudGroupActivity.getMediaId());
        groupNewsMaterialAddDTO.setHtml(BookConstant.GROUP_QRCODE_NEWS_MATERIAL_HTML);
        String mediaId = ResponseHandleUtil.parseResponse(materialService.getGroupNewsMaterial(groupNewsMaterialAddDTO), String.class);
        if (null == pcloudGroupActivity.getMediaId()) {
            pcloudGroupActivity.setMediaId(mediaId);
            pcloudGroupActivityBiz.updateMediaId(pcloudGroupActivity);
        }
        return mediaId;
    }

    @Override
    public List<GroupQrcodeDTO> getMigrateGroup(List<String> groups) {
        return groupQrcodeDao.getMigrateGroup(groups);
    }

    private String updateMediaId(GroupQrcodeBaseInfoVO groupInfo, GroupMaterialAccount account, Long bookGroupQrcodeId) {
        if (groupInfo != null) {
            String mediaId = groupQrcodeDao.getMediaId(bookGroupQrcodeId);
            if (StrUtil.isBlank(mediaId) && account != null) {
                GroupNewsMaterialAddDTO groupNewsMaterialAddDTO = new GroupNewsMaterialAddDTO();
                groupNewsMaterialAddDTO.setAccountId(account.getAccountId());
                groupNewsMaterialAddDTO.setCoverMediaId(account.getCoverMediaId());
                groupNewsMaterialAddDTO.setGroupHeadImg(account.getHeadMediaId());
                groupNewsMaterialAddDTO.setGroupName(groupInfo.getGroupName());
                groupNewsMaterialAddDTO.setQrcodeUrl(groupInfo.getQrcodeUrl());
                groupNewsMaterialAddDTO.setMediaId(mediaId);
                mediaId = ResponseHandleUtil.parseResponse(materialService.getGroupNewsMaterial(groupNewsMaterialAddDTO), String.class);
                groupQrcodeDao.updateMediaId(bookGroupQrcodeId, mediaId, new Date());
            }
            return mediaId;
        }
        return null;
    }

    @Override
    public PageBean listBookGroup4AppletAgent(Map<String, Object> paramMap, PageParam pageParam) {
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listBookGroup4AppletAgent");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        //填充社群书数据
        List<Long> relatedGroupIds = new ArrayList<>();
        List<Long> adviserIds = new ArrayList<>();
        pageBean.getRecordList().forEach(obj -> {
            BookDto bookDto = (BookDto) obj;
            if (null != bookDto.getRelatedBookGroupId() && !relatedGroupIds.contains(bookDto.getRelatedBookGroupId())) {
                relatedGroupIds.add(bookDto.getRelatedBookGroupId());
            }
            if (null != bookDto.getAdviserId() && !adviserIds.contains(bookDto.getAdviserId())){
                adviserIds.add(bookDto.getAdviserId());
            }
        });
        Map<Long, BookGroupDTO> relatedBookGroupMap = new HashMap<>();
        Map<Long, AdviserBaseInfoDto> adviserMap = new HashMap();
        if (!ListUtils.isEmpty(relatedGroupIds)){
            relatedBookGroupMap = bookGroupDao.mapDTOByIds(relatedGroupIds);
        }
        if (!ListUtils.isEmpty(adviserIds)){
            adviserMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        }
        for (Object object : pageBean.getRecordList()) {
            BookDto bookDto = (BookDto) object;
            bookDto.setBookName(null != bookDto.getBookName() ? StringUtil.addBracket(bookDto.getBookName()) : null);
            if (!MapUtils.isEmpty(relatedBookGroupMap) && relatedBookGroupMap.containsKey(bookDto.getRelatedBookGroupId())) {
                BookGroupDTO relatedBookGroup = relatedBookGroupMap.get(bookDto.getRelatedBookGroupId());
                bookDto.setRelatedBookGroup(relatedBookGroup);
            }
            if (!MapUtils.isEmpty(adviserMap) && adviserMap.containsKey(bookDto.getAdviserId())){
                AdviserBaseInfoDto adviserBaseInfoDto = adviserMap.get(bookDto.getAdviserId());
                bookDto.setAdviserName(adviserBaseInfoDto.getPartyName());
                bookDto.setPhone(adviserBaseInfoDto.getPhoneNum());
            }
        }
        return pageBean;
    }

    @Override
    public Long getAccountSettingByAdviser(Long adviserId) {
        Long accountSettingId = BookProps.getMiniOfficialAccountsId();
        if (null == adviserId || adviserId == 0L) {
            return accountSettingId;
        }
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        Long accountSetting = channelConsr.getAccountSettingIdByAgentId(agentId);
        if (null != accountSetting) {
            return accountSetting;
        }
        return accountSettingId;
    }

    @Override
    public Integer getBookGroupCountByAgent(Integer joinGroupType, Long agentId) {
        return bookGroupDao.getBookGroupCountByAgent(joinGroupType,agentId);
    }

    @Override
    public List<BookServeDTO> getBookAndBookGroupServeIds4Price(Long adviserId, Long bookId, Long channelId) {
        List<BookServeDTO> serveDTOList = new ArrayList<>();
        List<Long> appIds = new ArrayList<>();
        List<Long> productIds = new ArrayList<>();
        AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
        if (null == accountSettingDto){
            return new ArrayList<>();
        }
        //社群书配置资源
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBook(bookId, channelId, adviserId);
        if (!ListUtils.isEmpty(bookGroupServes)) {
            for (BookGroupServe bookGroupServe : bookGroupServes) {
                BookServeDTO bookServeDTO = new BookServeDTO();
                BeanUtils.copyProperties(bookGroupServe, bookServeDTO);
                String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookGroupServe.getServeUrl());
                bookServeDTO.setUrl(url);
                bookServeDTO.setTypeCode(bookServeDTO.getServeType());
                bookServeDTO.setFromType(bookGroupServe.getTypeCode());
                serveDTOList.add(bookServeDTO);
                if (AppAndProductTypeEnum.APP.value.equals(bookServeDTO.getServeType())) {
                    appIds.add(bookGroupServe.getServeId());
                } else {
                    productIds.add(bookGroupServe.getServeId());
                }
            }
        }
        //设置应用名称与价格
        setAppPrice(serveDTOList);
        //现代纸书二维码配置资源
        BookServeParamVO serveParamVO = new BookServeParamVO();
        serveParamVO.setAdviserId(adviserId);
        serveParamVO.setBookId(bookId);
        serveParamVO.setChannelId(channelId);
        List<BookServeVO> bookServeVOS = qrcodeSceneConsr.listBookServe(serveParamVO);
        if (!ListUtils.isEmpty(bookServeVOS)) {
            for (BookServeVO bookServeVO : bookServeVOS) {
                Long serveId = bookServeVO.getServeId();
                BookServeDTO bookServeDTO = new BookServeDTO();
                bookServeDTO.setServeName(bookServeVO.getServeName());
                bookServeDTO.setPrice(bookServeVO.getRetailPrice());
                bookServeDTO.setTypeCode(bookServeVO.getTypeCode());
                bookServeDTO.setFromType(bookServeVO.getFromType());
                bookServeDTO.setFromTypeName(bookServeVO.getFromTypeName());
                String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookServeVO.getUrl());
                if (AppAndProductTypeEnum.APP.value.equals(bookServeVO.getTypeCode()) && !appIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    bookServeDTO.setUrl(url);
                    serveDTOList.add(bookServeDTO);
                    appIds.add(serveId);
                } else if (AppAndProductTypeEnum.PRODUCT.value.equals(bookServeVO.getTypeCode()) && !productIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    bookServeDTO.setUrl(url);
                    serveDTOList.add(bookServeDTO);
                    productIds.add(serveId);
                }
            }
        }
        return serveDTOList;
    }

    @Override
    public BookGroupDTO getRayBookByBookGroupId(Long bookGroupId) {
        BookGroupDTO bookGroupDTO = bookGroupDao.getBookBaseInfoById(bookGroupId);
        if (null == bookGroupDTO){
            return new BookGroupDTO();
        }
        bookGroupDTO.setAdviserId(bookGroupDTO.getCreateUser());
        BookAdviserDto bookAdviserDto = bookAdviserDao.getBase(bookGroupDTO.getBookId(), bookGroupDTO.getChannelId(), bookGroupDTO.getCreateUser());
        if (null != bookAdviserDto && YesOrNoEnums.YES.getValue().equals(bookAdviserDto.getIsOpenRobotProcess())) {
            bookGroupDTO.setOpenWeapp(true);
        } else {
            bookGroupDTO.setOpenWeapp(false);
        }
        return bookGroupDTO;
    }

    private void setAppPrice(List<BookServeDTO> serveDTOList) {
        if (ListUtils.isEmpty(serveDTOList)) {
            return;
        }
        List<Long> productIds = serveDTOList.stream().filter(s -> s.getServeId() != null
                && MessageFromTypeEnum.PRODUCT.value.equalsIgnoreCase(s.getTypeCode())).
                map(BookServeDTO::getServeId).distinct().collect(Collectors.toList());
        List<Long> appIds = serveDTOList.stream().filter(s -> s.getServeId() != null
                && MessageFromTypeEnum.APP.value.equalsIgnoreCase(s.getTypeCode())).
                map(BookServeDTO::getServeId).distinct().collect(Collectors.toList());
        //获取详情
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, BigDecimal> appPriceMap = new HashMap<>();
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMap = appConsr.mapByIds(appIds);
            List<AppPriceCacheDTO> appPriceCacheDTOS = new ArrayList<>();
            for (Long appId : appIds) {
                if (appDtoMap.get(appId) != null) {
                    AppPriceCacheDTO appPriceCacheDTO = new AppPriceCacheDTO();
                    appPriceCacheDTO.setAppTypeEnum(AppTypeEnum.APP_TYPE_MAP.get(appDtoMap.get(appId).getTypeCode()));
                    appPriceCacheDTO.setAppId(appId);
                    appPriceCacheDTOS.add(appPriceCacheDTO);
                }
            }
            appPriceMap = appConsr.getAppPrice(appPriceCacheDTOS);
        }
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMap = productConsr.getProductInfoByIds(productIds);
        }
        for (BookServeDTO item : serveDTOList) {
            String originType = item.getTypeCode();
            Long id = item.getServeId();
            if (MessageFromTypeEnum.PRODUCT.value.equalsIgnoreCase(originType)) {
                if (productDtoMap != null && productDtoMap.get(id) != null) {
                    ProductDto productDto = productDtoMap.get(id);
                    item.setServeName(productDto.getProductName());
                    item.setCoverImg(productDto.getCoverImg());
                    ProductTypeDto productTypeDto = productDto.getProductTypeDto();
                    if (productTypeDto != null) {
                        item.setFromTypeName(productTypeDto.getTypeName());
                    }
                    List<SpecificationDto> specificationDtos = productDto.getSpecification();
                    if (!ListUtils.isEmpty(specificationDtos)) {
                        SpecificationDto specificationDto = specificationDtos.get(0);
                        if (specificationDto != null) {
                            item.setPrice(specificationDto.getAdvisePrice());
                        }
                    }
                }
            }
            if (MessageFromTypeEnum.APP.value.equalsIgnoreCase(originType)) {
                if (appDtoMap != null && appDtoMap.get(id) != null) {
                    AppDto appDto = appDtoMap.get(id);
                    item.setFromTypeName(appDto.getTypeName());
                    item.setServeName(appDto.getTitle());
                    item.setCoverImg(appDto.getSquareImg());
                }
                if (appPriceMap != null) {
                    if (appPriceMap.get(id) != null) {
                        item.setPrice(appPriceMap.get(id).doubleValue());
                    }
                }
            }
        }
    }


    @Override
    public BookGroupDTO getMaxScanCountBookGroup(Long agentId, Integer joinGroupType) {
        if (null != agentId) {
            List<Long> bookGroupIds = bookGroupDao.getBookGroupIdsByAgent(agentId, joinGroupType);
            if (!ListUtils.isEmpty(bookGroupIds)) {
                Long bookGroupId = wechatGroupConsr.getMaxScanCountBookGroup(bookGroupIds);
                if (null == bookGroupId) {
                    bookGroupId = bookGroupIds.get(0);
                }
                BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
                return bookGroupDTO;
            }
        } //编辑账号下随机取一个
        Long adviserId = 0L;
        switch (BookProps.getSystemEnv()) {
            case "test":
                adviserId = 1404L;
                break;
            case "uat":
                adviserId = 12829L;
                break;
            case "pro":
                adviserId = 1000026494L;
                break;
        }
        List<BookGroupDTO> list = bookGroupDao.getBookGroupByAdviser(adviserId, joinGroupType);
        if (ListUtils.isEmpty(list)) {
            return new BookGroupDTO();
        } else {
            return list.get(new Random().nextInt(list.size()));
        }
    }



    @Override
    public List<BookGroupDTO> getBookGroupsByBookIds(List<Long> bookIds, List<Long> adviserIds, List<Long> channelIds) {
        if(CollectionUtils.isEmpty(bookIds)){
            return new ArrayList<>();
        }
        List<BookGroupDTO> bookGroupDTOList = bookGroupDao.getDTOByBookIds(bookIds, adviserIds, channelIds);
        if(CollectionUtils.isEmpty(bookGroupDTOList)){
            return new ArrayList<>();
        }
        List<Long> bookGroupIds = bookGroupDTOList.stream().map(x -> x.getId()).collect(Collectors.toList());
        Map<Long, GroupUserCountDTO> groupUserCountDTOMap = wechatGroupConsr.getScanCountByGroup(bookGroupIds, null);
        if(MapUtils.isEmpty(groupUserCountDTOMap)){
            return new ArrayList<>();
        }
        for (BookGroupDTO bookGroupDTO : bookGroupDTOList) {
            GroupUserCountDTO groupUserCountDTO = groupUserCountDTOMap.get(bookGroupDTO.getId());
            bookGroupDTO.setScanCount(groupUserCountDTO == null ? 0 : groupUserCountDTO.getCount());
            bookGroupDTO.setUserCount(groupUserCountDTO == null ? 0 : groupUserCountDTO.getUserCount());
        }
        return bookGroupDTOList;
    }

    @Override
    public Boolean checkRayUrl(String url) {
        // https://qrcode.raysgo.com/2233
        // https://qrcode.raysgo.com/t-2/1404/2280
        if (!StringUtil.isEmpty(url) && url.startsWith(bookGroupQrcodeDomain)){
            return true;
        }
        return false;
    }

    @Override
    public Map<String, Object> getBookBase4Applet(Long sceneId, Long bookGroupId) {
        Long bookId = 0L;
        Long channelId = 0L;
        Long adviserId = 0L;
        if (null != bookGroupId) {
            BookGroupDTO bookGroupDTO = bookGroupDao.getDTOById(bookGroupId);
            if (null != bookGroupDTO) {
                bookId = bookGroupDTO.getBookId();
                channelId = bookGroupDTO.getChannelId();
                adviserId = bookGroupDTO.getCreateUser();
            }
        } else {
            QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(sceneId);
            if (null != qrcodeSceneDto) {
                bookId = qrcodeSceneDto.getAdviserBookId();
                channelId = qrcodeSceneDto.getChannelPartyId();
                adviserId = qrcodeSceneDto.getCreatedByUserLogin();
            }
        }
        Map<String, Object> map = this.getBookBaseInfo4Applet(adviserId, channelId, bookId);
        Map<Long, AdviserBaseInfoDto> adviserInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(Lists.newArrayList(adviserId));
        if (MapUtils.isNotEmpty(adviserInfoDtoMap) && null != adviserInfoDtoMap.get(adviserId)) {
            map.put("agentName", adviserInfoDtoMap.get(adviserId).getAgentName());
        }
        map.put("bookId", bookId);
        map.put("adviserId", adviserId);
        map.put("channelId", channelId);
        return map;
    }

    @Override
    public BookGroupSceneDTO getSceneQrcodeByBookGroupId(Long bookGroupId) {
        BookGroupSceneDTO bookGroupSceneDTO = new BookGroupSceneDTO();
        BookGroupDTO bookGroupDTO = bookGroupDao.getBookBaseInfoById(bookGroupId);
        if (null == bookGroupDTO || null == bookGroupDTO.getSceneId()){
            return new BookGroupSceneDTO();
        }
        bookGroupSceneDTO.setBookGroupId(bookGroupId);
        bookGroupSceneDTO.setBookId(bookGroupDTO.getBookId());
        bookGroupSceneDTO.setChannelId(bookGroupDTO.getChannelId());
        bookGroupSceneDTO.setAdviserId(bookGroupDTO.getCreateUser());
        bookGroupSceneDTO.setBookName(bookGroupDTO.getBookName());
        Long agentId = adviserConsr.getAgentIdByAdviser(bookGroupDTO.getCreateUser());
        if (null != agentId){
            bookGroupSceneDTO.setAgentName(agentConsr.getNameById(agentId));
        }
        bookGroupSceneDTO.setSceneId(bookGroupDTO.getSceneId());
        QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(bookGroupDTO.getSceneId());
        bookGroupSceneDTO.setQrcodeUrl(null == qrcodeSceneDto?null:qrcodeSceneDto.getQrcodeUrl());
        //1004306返回本书服务5个
        List<BookServeDTO> bookServeDTOS = getBookAndBookGroupServeIdsFive(bookGroupDTO.getCreateUser(), bookGroupDTO.getBookId(), bookGroupDTO.getChannelId());
        if (ListUtils.isEmpty(bookServeDTOS) || bookServeDTOS.size()<5) {
            //权益中补充资源
            List<BookServeDTO> serveDTOList = rightsSettingBiz.getRightsSettingAppProduct(bookGroupDTO.getBookId(), bookGroupDTO.getChannelId(), bookGroupDTO.getCreateUser(), 5-bookServeDTOS.size());
            if (!ListUtils.isEmpty(serveDTOList)) {
                bookServeDTOS.addAll(serveDTOList);
            }
        }
        //填充资源信息
        fillBookServe4RightsSetting(bookServeDTOS);
        bookGroupSceneDTO.setBookServeDTOS(bookServeDTOS);
        return bookGroupSceneDTO;
    }


    @Override
    public BackgroundGroupQrcodeDTO getBackgroundGroupQr(BackgroundGroupQrcodeDTO backgroundGroupQrcodeDTO) {
        BookGroup group = bookGroupDao.getById(backgroundGroupQrcodeDTO.getBookGroupId());
        if (null == group) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "群二维码不存在！");
        }
        //二维码跳转链接
        String groupQrcodeLink = group.getGroupQrcodeLink();
        //设置社群码样式
        //每次更新之前都重新生成
        String qrcode = QrcodeUtils.createWithMargin(groupQrcodeLink, 1);
        GroupQrcodeStyle groupQrcodeStyle = groupQrcodeStyleDao.getQrcodeStyleByBookGroupId(group.getId());
        if(null!=groupQrcodeStyle){
            //如果有颜色样式
            qrcode = createQrcode(groupQrcodeStyle, groupQrcodeLink);
        }
        //如果有图片样式
        if(null!=backgroundGroupQrcodeDTO.getBackgroundType() && backgroundGroupQrcodeDTO.getBackgroundType()>0){
            qrcode= QrcodeUtils.getStyleQr(qrcode, backgroundGroupQrcodeDTO.getBackgroundType(), null);
        }
        backgroundGroupQrcodeDTO.setBackgroundQrUrl(qrcode);
        return backgroundGroupQrcodeDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BookGroup createBookGroup(BookGroupCreateDTO bookGroupCreateDTO) {
        Long bookId = bookGroupCreateDTO.getBookId();
        Long channelId = bookGroupCreateDTO.getChannelId();
        Long adviserId = bookGroupCreateDTO.getAdviserId();
        Integer joinGroupType = bookGroupCreateDTO.getJoinGroupType();
        Integer jumpType = bookGroupCreateDTO.getJumpType();
        if (JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType) && null == jumpType){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"缺少跳转类型");
        }
        BookGroup bookGroup = this.createBookGroupAfterCreateBook(bookId,channelId,adviserId,null, null,joinGroupType,jumpType,bookGroupCreateDTO.getJumpUrl());
        bookGroupCreateDTO.setId(bookGroup.getId());
        this.updateBookGroup(bookGroupCreateDTO);
        //更新至超级搜索
        searchProducer.create(bookGroup.getId());
        return bookGroup;
    }

    @Override
    public List<BookServeDTO> getServeListByBookGroupId(Long bookGroupId, Long channelId) {
        List<BookServeDTO> serveDTOList = new ArrayList<>();
        AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
        if (null == accountSettingDto) {
            return new ArrayList<>();
        }
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getListByBookGroupId(bookGroupId);
        if (!ListUtils.isEmpty(bookGroupServes)) {
            for (BookGroupServe bookGroupServe : bookGroupServes) {
                BookServeDTO bookServeDTO = new BookServeDTO();
                BeanUtils.copyProperties(bookGroupServe, bookServeDTO);
                String url = SendWeixinRequestTools.splitUrl(accountSettingDto, bookGroupServe.getServeUrl());
                bookServeDTO.setUrl(url);
                bookServeDTO.setTypeCode(bookServeDTO.getServeType());
                bookServeDTO.setFromType(bookGroupServe.getTypeCode());
                bookServeDTO.setFromTypeName(bookGroupServe.getFromType());
                serveDTOList.add(bookServeDTO);
            }
        }
        return serveDTOList;
    }

    @Override
    public List<String> getWxUserInAgents(List<Long> agentIds) {
        if(CollectionUtils.isEmpty(agentIds)){
            return new ArrayList<>();
        }
        List<String> list= bookGroupDao.getWxUserInAgents(agentIds);
        return list;
    }

    @Override
    public List<Long> getBookGroupIdInAgents(List<Long> agentIds) {
        if(CollectionUtils.isEmpty(agentIds)){
            return new ArrayList<>();
        }
        List<Long> list= bookGroupDao.getBookGroupIdInAgents(agentIds);
        return list;
    }

    @Override
    public void fillBookServe4RightsSetting(List<BookServeDTO> serveDTOList) {
        if (ListUtils.isEmpty(serveDTOList)) {
            return;
        }
        List<Long> appIds = new ArrayList<>();
        List<Long> productIds = new ArrayList<>();
        for (BookServeDTO bookServeDTO : serveDTOList){
            if (bookServeDTO.getServeType().equals(AppAndProductTypeEnum.APP.value) && !appIds.contains(bookServeDTO.getServeId())){
                appIds.add(bookServeDTO.getServeId());
            } else if (bookServeDTO.getServeType().equals(AppAndProductTypeEnum.PRODUCT.value) && !productIds.contains(bookServeDTO.getServeId())){
                productIds.add(bookServeDTO.getServeId());
            }
        }
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        List<BookServeDTO> removeList = new ArrayList<>(); //存储已经删除群的群分类; 精选文章类型并且跳转链接包含qrcode.5rs.me
        FutureTask<Map<Long, ProductDto>> task = null;
        FutureTask<Map<Long, AppDto>> task2 = null;
        if (!ListUtils.isEmpty(productIds)) {
            Callable<Map<Long, ProductDto>> callable = () -> productConsr.getProBasesByIds(productIds);
            task = new FutureTask<>(callable);
            new Thread(task).start();
        }
        if (!ListUtils.isEmpty(appIds)) {
            Callable<Map<Long, AppDto>> callable = () -> appConsr.mapByIds4AuditPass(appIds);
            task2 = new FutureTask<>(callable);
            new Thread(task2).start();
        }
        if (task!=null) {
            try {
                productDtoMap = task.get();
            } catch (InterruptedException e) {
                LOGGER.error("获取商品失败fillProductAndApp");
            } catch (ExecutionException e) {
                LOGGER.error("获取商品失败fillProductAndApp");
            }
        }
        if (task2!=null) {
            try {
                appDtoMap = task2.get();
            } catch (InterruptedException e) {
                LOGGER.error("获取应用失败fillProductAndApp");
            } catch (ExecutionException e) {
                LOGGER.error("获取应用失败fillProductAndApp");
            }
        }
         Map<Long,AccountSettingDto>offMap = new HashMap<>();
        for (BookServeDTO bookServeDTO : serveDTOList) {
            AccountSettingDto accountSettingDto;
            if (AppAndProductTypeEnum.PRODUCT.value.equals(bookServeDTO.getServeType())) {
                if (!MapUtils.isEmpty(productDtoMap) && null != productDtoMap.get(bookServeDTO.getServeId())) {
                    ProductDto productDto = productDtoMap.get(bookServeDTO.getServeId());
                    bookServeDTO.setServeName(productDto.getProductName());
                    bookServeDTO.setCoverImg(productDto.getCoverImg());
                    bookServeDTO.setTransverseImg(productDto.getPicture1());
                    if (productDto.getProductTypeDto() != null) {
                        bookServeDTO.setFromType(productDto.getProductTypeDto().getTypeCode());
                        bookServeDTO.setFromTypeName(productDto.getProductTypeDto().getTypeName());
                    }
                    if (checkRayUrl(productDto.getSkipUrl()) && ProductTypeConstant.ARTICLE.equals(bookServeDTO.getFromType())) {
                        removeList.add(bookServeDTO);
                        continue;
                    }
                    //获取channelId,/C1404/product/display/10234028?adviserId=1001587&proType=MEMBER&source_type=QRCODE
                    Long channelId = null;
                    String url = bookServeDTO.getUrl();
                    if (url.contains("/C") && !url.startsWith("https")) {
                        url = url.substring(url.indexOf("/C") + 2);
                        url = url.substring(0, url.indexOf("/"));
                        if (!StringUtil.isEmpty(url)) {
                            channelId = Long.valueOf(url);
                        }
                    }
                    if (null != channelId) {
                        accountSettingDto = offMap.get(channelId);
                        if (accountSettingDto == null) {
                            accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
                            offMap.put(channelId, accountSettingDto);
                        }
                        if (null == accountSettingDto) {
                            LOGGER.info("运营平台未配置公众号channelId"+channelId);
                            removeList.add(bookServeDTO);
                        }
                        String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, url);
                        bookServeDTO.setResultUrl(resultLinkUrl);
                    } else {
                        bookServeDTO.setResultUrl(url);
                    }
                    if (!StringUtil.isEmpty(productDto.getSkipUrl())) {
                        bookServeDTO.setHasThirdLink(true);
                    } else {
                        bookServeDTO.setHasThirdLink(false);
                    }
                } else {
                    removeList.add(bookServeDTO);
                }
                continue;
            }
            if (AppAndProductTypeEnum.APP.value.equals(bookServeDTO.getServeType())) {
                List<String> typeCodes = appConsr.getRaysAppTypeCodes();
                if (!MapUtils.isEmpty(appDtoMap) && null != appDtoMap.get(bookServeDTO.getServeId())) {
                    AppDto appDto = appDtoMap.get(bookServeDTO.getServeId());
                    if (checkRayUrl(appDto.getTurnUrl()) && AppTypeEnum.ARTICLE.value.equals(appDto.getTypeCode())){
                        removeList.add(bookServeDTO);
                        continue;
                    }
                    //RAYS应用在小程序里单独展示,不展示在配套资料中
                    if (!ListUtils.isEmpty(typeCodes) && typeCodes.contains(appDto.getTypeCode())) {
                        removeList.add(bookServeDTO);
                        continue;
                    }
                    bookServeDTO.setServeName(appDto.getTitle());
                    bookServeDTO.setCoverImg(appDto.getSquareImg());
                    bookServeDTO.setFromType(appDto.getTypeCode());
                    bookServeDTO.setFromTypeName(appDto.getTypeName());
                    bookServeDTO.setTransverseImg(appDto.getTransverseImg());
                    accountSettingDto = offMap.get(appDto.getChannelId());
                    if(accountSettingDto==null){
                        accountSettingDto = qrcodeSceneConsr.getWechatInfo(appDto.getChannelId());
                        offMap.put(appDto.getChannelId(),accountSettingDto);
                    }
                    if (null == accountSettingDto){
                        LOGGER.info("运营平台未配置公众号channelId"+appDto.getChannelId());
                        removeList.add(bookServeDTO);
                    }
                    String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, bookServeDTO.getUrl());
                    bookServeDTO.setResultUrl(resultLinkUrl);
                    if (!StringUtil.isEmpty(appDto.getTurnUrl())){
                        bookServeDTO.setHasThirdLink(true);
                    } else {
                        bookServeDTO.setHasThirdLink(false);
                    }
                } else {
                    removeList.add(bookServeDTO); //把要移除的统一放在一个集合
                }
                continue;
            }
        }
        serveDTOList.removeAll(removeList);
    }

    @Override
    @ParamLog("通过自有码sceneId查询小程序相关信息")
    public BookAppletSceneDTO getOneBookAppletBySceneIds(List<Long> sceneIds) {
        if (ListUtils.isEmpty(sceneIds)) {
            return  new BookAppletSceneDTO();
        }
        BookAppletSceneDTO bookAppletSceneDTO = bookAppletSceneDao.getBySceneIds(sceneIds);
        return bookAppletSceneDTO;
    }

    @Override
    public Long getRightsSettingId4Book(Long adviserId, Long channelId, Long bookId) {
        // 查询图书权益ID
        RightsSettingDto rightsSettingDto = rightsSettingBiz.getRightsSettingByBookId4AppletHome(bookId, adviserId, channelId);
        // 没有则返回兜底权益ID
        return Optional.ofNullable(rightsSettingDto).map(RightsSettingDto::getId).orElse(bookBiz.getDefaultRightsSettingId());
    }

    @Override
    public List<HotAppDTO> listHotApp() {
        String cacheKey = BookConstant.BOOK_HOT_APP + DateUtil.format(new Date(), DatePattern.NORM_DATE_FORMAT);
        if (JedisClusterUtils.exists(cacheKey)) {
            String json = JedisClusterUtils.get(cacheKey);
            if (StrUtil.isNotBlank(json)){
                List<HotAppDTO> list = new ArrayList<>();
                try{
                    list = JSONObject.parseArray(json,HotAppDTO.class);
                }catch (Exception e){
                    LOGGER.warn("[listHotApp]json转换失败 json:{}", json, e);
                }
                if (CollUtil.isNotEmpty(list)) return list.stream().sorted(Comparator.comparing(HotAppDTO::getCount).reversed()).limit(5).collect(Collectors.toList());;
            }
        }

        String cacheKeyOld = BookConstant.BOOK_HOT_APP + DateUtil.format(DateUtil.yesterday(), DatePattern.NORM_DATE_FORMAT);
        // 存在旧数据 计算应用热度值作为增长数据
        boolean hasOldData = JedisClusterUtils.exists(cacheKeyOld);
        Map<String, Integer> oldMap = new HashMap<>();
        if (hasOldData) {
            String oldJson = JedisClusterUtils.get(cacheKeyOld);
            if (StrUtil.isNotBlank(oldJson)){
                List<HotAppDTO> dtoList = new ArrayList<>();
                try{
                    dtoList = JSONObject.parseArray(oldJson,HotAppDTO.class);
                }catch (Exception e){
                    hasOldData = false;
                    LOGGER.warn("[listHotApp]json转换失败 oldJson:{}", oldJson, e);
                }
                oldMap = Optional.ofNullable(dtoList.stream().filter(x -> Objects.nonNull(x) && Objects.nonNull(x.getTypeCode()))
                        .collect(Collectors.toMap(HotAppDTO::getTypeCode, HotAppDTO::getCount))).orElse(new HashMap<>());
            }

        }

        // 不存在旧数据则 直接查询旧数据
        CompletableFuture<Map<String, AppTypeUseCount>> channel = CompletableFuture.supplyAsync(() -> {
            List<AppTypeUseCount> counts = qrcodeSceneConsr.listAppTypeCount();
            return counts.stream().filter(x -> Objects.nonNull(x) && Objects.nonNull(x.getTypeCode()))
                    .collect(Collectors.toMap(AppTypeUseCount::getTypeCode, t -> t));
        });
        CompletableFuture<Map<String, Integer>> bookCount = CompletableFuture.supplyAsync(() -> {
            List<HotAppDTO> hotAppDTOS = Optional.ofNullable(bookGroupDao.listHotApp()).orElse(new ArrayList<>());
            return hotAppDTOS.stream().filter(x -> Objects.nonNull(x) && Objects.nonNull(x.getTypeCode()))
                    .collect(Collectors.toMap(HotAppDTO::getTypeCode, HotAppDTO::getCount));
        });
        CompletableFuture<Map<String, Integer>> bookIncrement = CompletableFuture.supplyAsync(() -> {
            List<HotAppDTO> hotAppDTOS = Optional.ofNullable(bookGroupDao.listHotAppIncrement()).orElse(new ArrayList<>());
            return hotAppDTOS.stream().filter(x -> Objects.nonNull(x) && Objects.nonNull(x.getTypeCode()))
                    .collect(Collectors.toMap(HotAppDTO::getTypeCode, HotAppDTO::getIncrement));
        });
        CompletableFuture<Map<String, AppTypeDto>> appInfo = CompletableFuture.supplyAsync(() -> appConsr.listAllCode());

        // 聚合
        CompletableFuture<Void> completableFuture = CompletableFuture.allOf(channel, bookCount, bookIncrement, appInfo);
        try {
            completableFuture.get();
            Map<String, AppTypeUseCount> channelMap = Optional.ofNullable(channel.get()).orElse(new HashMap<>());
            Map<String, Integer> bookCountMap = Optional.ofNullable(bookCount.get()).orElse(new HashMap<>());
            Map<String, Integer> bookIncrementMap = Optional.ofNullable(bookIncrement.get()).orElse(new HashMap<>());
            Map<String, AppTypeDto> appInfoMap = Optional.ofNullable(appInfo.get()).orElse(new HashMap<>());

            List<HotAppDTO> hotAppDTOS = new ArrayList<>();

            if (appInfoMap.isEmpty()) return hotAppDTOS;
            for (String key : appInfoMap.keySet()) {
                if (Objects.isNull(key)) continue;
                HotAppDTO hotAppDTO = new HotAppDTO();
                hotAppDTO.setTypeName(Optional.ofNullable(appInfoMap.get(key)).map(AppTypeDto::getTypeName).orElse(""));
                hotAppDTO.setTypeCode(key);
                hotAppDTO.setCount(
                        Optional.ofNullable(channelMap.get(key)).map(AppTypeUseCount::getCount).orElse(0) +
                                Optional.ofNullable(bookCountMap.get(key)).orElse(0)
                );
                if (hasOldData){
                    hotAppDTO.setIncrement(hotAppDTO.getCount() - Optional.ofNullable(oldMap.get(key)).orElse(0));
                }else {
                    hotAppDTO.setIncrement(
                            Optional.ofNullable(channelMap.get(key)).map(AppTypeUseCount::getIncrement).orElse(0) +
                                    Optional.ofNullable(bookIncrementMap.get(key)).orElse(0)
                    );
                }

                hotAppDTOS.add(hotAppDTO);
            }
            JedisClusterUtils.set(cacheKey, JSONObject.toJSONString(hotAppDTOS), 48 * 60 * 60);
            return hotAppDTOS.stream().sorted(Comparator.comparing(HotAppDTO::getCount).reversed()).limit(5).collect(Collectors.toList());
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.warn("listHotApp 查询热门APP信息失败");
        }
        return new ArrayList<>();
    }

    @Override
    public List<BookServeDTO> getBookAndBookGroupRaysApps(Long adviserId, Long bookId, Long channelId) {
        List<BookServeDTO> serveDTOList = new ArrayList<>();
        List<Long> raysAppIds = new ArrayList<>();
        List<String> typeCodes = appConsr.getRaysAppTypeCodes();
        //书刊配置的RAYS应用
        BookServeParamVO serveParamVO = new BookServeParamVO();
        serveParamVO.setAdviserId(adviserId);
        serveParamVO.setBookId(bookId);
        serveParamVO.setChannelId(channelId);
        serveParamVO.setFromTypes(typeCodes);
        List<BookServeVO> bookServeVOS = qrcodeSceneConsr.listBookServeIdsByType(serveParamVO);
        if (!ListUtils.isEmpty(bookServeVOS)) {
            for (BookServeVO bookServeVO : bookServeVOS) {
                Long serveId = bookServeVO.getServeId();
                BookServeDTO bookServeDTO = new BookServeDTO();
                BeanUtils.copyProperties(bookServeVO, bookServeDTO);
                if (!raysAppIds.contains(serveId)) {
                    bookServeDTO.setServeId(serveId);
                    bookServeDTO.setServeType(bookServeVO.getTypeCode());
                    serveDTOList.add(bookServeDTO);
                    raysAppIds.add(serveId);
                }
            }
        }
        //社群书配置的RAYS应用
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBookAndType(bookId, channelId, adviserId, typeCodes);
        if (!ListUtils.isEmpty(bookGroupServes)) {
            for (BookGroupServe bookGroupServe : bookGroupServes) {
                BookServeDTO bookServeDTO = new BookServeDTO();
                BeanUtils.copyProperties(bookGroupServe, bookServeDTO);
                bookServeDTO.setUrl(bookGroupServe.getServeUrl());
                bookServeDTO.setTypeCode(bookGroupServe.getServeType());
                bookServeDTO.setFromType(bookGroupServe.getTypeCode());
                Long serveId = bookGroupServe.getServeId();
                if (!raysAppIds.contains(serveId)) {
                    serveDTOList.add(bookServeDTO);
                    raysAppIds.add(serveId);
                }
            }
        }
        Map<Long, AppRaysDTO> appRaysDTOMap = appConsr.mapRaysApp(raysAppIds);
        List<BookServeDTO> resultList = new ArrayList<>();
        if (!MapUtils.isEmpty(appRaysDTOMap)) {
            AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
            for (BookServeDTO bookServeDTO : serveDTOList) {
                AppRaysDTO appRaysDTO = appRaysDTOMap.get(bookServeDTO.getServeId());
                if (null != appRaysDTO) {
                    bookServeDTO.setServeName(appRaysDTO.getTitle());
                    bookServeDTO.setFromTypeName(appRaysDTO.getTypeName());
                    bookServeDTO.setCoverImg(appRaysDTO.getSquareImg());
                    bookServeDTO.setTransverseImg(appRaysDTO.getTransverseImg());
                    if (null != accountSettingDto){
                        String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, bookServeDTO.getUrl());
                        bookServeDTO.setResultUrl(resultLinkUrl);
                    }
                    resultList.add(bookServeDTO);
                }
            }
        }
        //是否配了背单词小程序
        Boolean hasMiniWord = wordappConsr.hasMiniWord(bookId);
        if (hasMiniWord) {
            BookServeDTO bookServeDTO = new BookServeDTO();
            bookServeDTO.setFromType(AppTypeEnum.RECITE_WORD.value);
            bookServeDTO.setFromTypeName(AppTypeEnum.RECITE_WORD.name);
            resultList.add(bookServeDTO);
        }
        return resultList;
    }

    @Override
    public List<BookGroupServeDTO> getBookGroupServeListByBook(BookServeQueryDTO bookServeQueryDTO) {
        if (null == bookServeQueryDTO || null == bookServeQueryDTO.getBookId() || null == bookServeQueryDTO.getChannelId()
                || null == bookServeQueryDTO.getAdviserId()) {
            return new ArrayList<>();
        }
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBookAndType(bookServeQueryDTO.getBookId(), bookServeQueryDTO.getChannelId(),
                bookServeQueryDTO.getAdviserId(), bookServeQueryDTO.getTypeCodes());
        if (ListUtils.isEmpty(bookGroupServes)) {
            return new ArrayList<>();
        }
        List<BookGroupServeDTO> serveDTOList = new ArrayList<>();
        BeanUtils.copyListProperties(bookGroupServes, serveDTOList, BookGroupServeDTO.class);
        return serveDTOList;
    }

    @Override
    public PageBeanNew<BookServeDTO> listPageCourse4ExerciseBook(BookServeQueryDTO bookServeQueryDTO) {
        if (null == bookServeQueryDTO || null == bookServeQueryDTO.getCurrentPage() || null == bookServeQueryDTO.getNumPerPage()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"分页参数缺失");
        }
        if (null == bookServeQueryDTO.getModuleType()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"模块类型缺失");
        }
        if (StringUtil.isEmpty(bookServeQueryDTO.getSubjectLabelName()) || StringUtil.isEmpty(bookServeQueryDTO.getGradeLabelName())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"标签参数缺失");
        }
        Map<Integer, CourseModuleDTO> moduleDTOMap = exerciseBookConsr.getCourseModuleMap();
        if (MapUtils.isEmpty(moduleDTOMap) || !moduleDTOMap.containsKey(bookServeQueryDTO.getModuleType())) {
            return new PageBeanNew<>();
        }
        CourseModuleDTO moduleDTO = moduleDTOMap.get(bookServeQueryDTO.getModuleType());
        final Long channelId = moduleDTO.getChannelId();
        final Long adviserId = moduleDTO.getAdviserId();
        final Long bookId = moduleDTO.getBookId();
        List<String> typeCodes = Arrays.asList(ProductTypeConstant.VIDEO_SCHEDULE);
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBookAndType(bookId, channelId, adviserId, typeCodes);
        if (ListUtils.isEmpty(bookGroupServes)) {
            return new PageBeanNew<>();
        }
        List<Long> productIds = bookGroupServes.stream().filter(s->s.getServeType().equals(AppAndProductTypeEnum.PRODUCT.value)).map(BookGroupServe::getServeId).distinct().collect(Collectors.toList());
        //资源中心查询
        ProductVideoScheduleQueryDTO productVideoScheduleQueryDTO = new ProductVideoScheduleQueryDTO();
        productVideoScheduleQueryDTO.setChannelId(channelId);
        productVideoScheduleQueryDTO.setProductIds(productIds);
        productVideoScheduleQueryDTO.setGradeLabelName(bookServeQueryDTO.getGradeLabelName());
        productVideoScheduleQueryDTO.setSubjectLabelName(bookServeQueryDTO.getSubjectLabelName());
        List<ProductVideoScheduleDTO> scheduleDTOS = resourceConsr.getProductVideoCourseList4ExerciseBook(productVideoScheduleQueryDTO);
        if (ListUtils.isEmpty(scheduleDTOS)) {
            return new PageBeanNew<>();
        }
        //根据筛选条件bookGroupServe查询
        List<Long> serveIds = scheduleDTOS.stream().map(ProductVideoScheduleDTO::getProductId).collect(Collectors.toList());
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        paramMap.put("bookId", bookId);
        paramMap.put("channelId", channelId);
        paramMap.put("serveIds", serveIds);
        PageBeanNew<BookGroupServe> servePageBeanNew = bookGroupServeDao.listPageNew(new PageParam(bookServeQueryDTO.getCurrentPage(), bookServeQueryDTO.getNumPerPage()),
                paramMap, "listServeListByBook");
        if (ListUtils.isEmpty(servePageBeanNew.getRecordList())) {
            return new PageBeanNew<>();
        }
        List<BookServeDTO> serveDTOList = fillServeCourse4ExerciseBook(servePageBeanNew.getRecordList(), channelId, scheduleDTOS);
        PageBeanNew<BookServeDTO> pageBeanNew = new PageBeanNew<>(bookServeQueryDTO.getCurrentPage(),
                bookServeQueryDTO.getNumPerPage(),servePageBeanNew.getTotalCount(), serveDTOList);
        return pageBeanNew;
    }

    private List<BookServeDTO> fillServeCourse4ExerciseBook(List<BookGroupServe> serveList, Long channelId, List<ProductVideoScheduleDTO> scheduleDTOS) {
        if (ListUtils.isEmpty(serveList)) {
            return new ArrayList<>();
        }
        List<Long> serveIds = serveList.stream().map(BookGroupServe::getServeId).distinct().collect(Collectors.toList());
        //课程数量
        Map<Long, Integer> courseNumMap = ResponseHandleUtil.parseMap(scheduleService.countAuditResourceByProductIds(serveIds),Long.class, Integer.class );
        //上分MVP公众号
        AccountSetting accountSetting = channelConsr.getAppInfo(66108L);
        //课程信息
        Map<Long, List<ProductVideoScheduleDTO>> videoScheduleDTOMap = scheduleDTOS.stream().collect(Collectors.groupingBy(ProductVideoScheduleDTO::getProductId));
        List<BookServeDTO> serveDTOList = new ArrayList<>();
        for (BookGroupServe bookGroupServe: serveList) {
            BookServeDTO bookServeDTO = new BookServeDTO();
            BeanUtils.copyProperties(bookGroupServe, bookServeDTO);
            bookServeDTO.setUrl(bookGroupServe.getServeUrl());
            bookServeDTO.setTypeCode(bookGroupServe.getServeType());
            bookServeDTO.setFromType(bookGroupServe.getTypeCode());
            List<ProductVideoScheduleDTO> dtos = videoScheduleDTOMap.get(bookGroupServe.getServeId());
            if (!ListUtils.isEmpty(dtos)) {
                ProductVideoScheduleDTO dto = dtos.get(0);
                bookServeDTO.setServeName(dto.getProductName());
                bookServeDTO.setCoverImg(dto.getCoverImg());
                bookServeDTO.setTransverseImg(dto.getPicture1());
                bookServeDTO.setPrice(dto.getRetailPrice());
            }
            if (null != accountSetting) {
                AccountSettingDto accountSettingDto = new AccountSettingDto();
                BeanUtils.copyProperties(accountSetting, accountSettingDto);
                String resultLinkUrl = SendWeixinRequestTools.splitUrl(accountSettingDto, bookGroupServe.getServeUrl());
                bookServeDTO.setResultUrl(resultLinkUrl);
            }
            if (!MapUtils.isEmpty(courseNumMap) && courseNumMap.containsKey(bookGroupServe.getServeId())) {
                bookServeDTO.setCourseNum(courseNumMap.get(bookGroupServe.getServeId()));
            } else {
                bookServeDTO.setCourseNum(0);
            }
            serveDTOList.add(bookServeDTO);
        }
        return serveDTOList;
    }

    @Override
    public List<ExerciseBookCourseVO> listCourse4ExerciseBook(BookServeQueryDTO bookServeQueryDTO) {
        if (StringUtil.isEmpty(bookServeQueryDTO.getSubjectLabelName()) || StringUtil.isEmpty(bookServeQueryDTO.getGradeLabelName())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"标签参数缺失");
        }
        Map<Integer, CourseModuleDTO> moduleDTOMap = exerciseBookConsr.getCourseModuleMap();
        if (MapUtils.isEmpty(moduleDTOMap)) {
            return new ArrayList<>();
        }
        Map<Long, CourseModuleDTO> bookModuleMap = new HashMap<>();
        Long channelId = null;
        List<Long> bookIds = new ArrayList<>();
        for (Map.Entry<Integer, CourseModuleDTO> entry:moduleDTOMap.entrySet()) {
            bookIds.add(entry.getValue().getBookId());
            channelId = entry.getValue().getChannelId();
            bookModuleMap.put(entry.getValue().getBookId(), entry.getValue());
        }
        //所有资源
        List<BookGroupServe> bookGroupServes = bookGroupServeDao.getServeListByBookList(bookIds, Arrays.asList(ProductTypeConstant.VIDEO_SCHEDULE));
        if (ListUtils.isEmpty(bookGroupServes)) {
            return new ArrayList<>();
        }
        //标签筛选
        List<Long> productIds = bookGroupServes.stream().filter(s->s.getServeType().equals(AppAndProductTypeEnum.PRODUCT.value)).distinct().map(BookGroupServe::getServeId).distinct().collect(Collectors.toList());
        ProductVideoScheduleQueryDTO productVideoScheduleQueryDTO = new ProductVideoScheduleQueryDTO();
        productVideoScheduleQueryDTO.setChannelId(channelId);
        productVideoScheduleQueryDTO.setProductIds(productIds);
        productVideoScheduleQueryDTO.setGradeLabelName(bookServeQueryDTO.getGradeLabelName());
        productVideoScheduleQueryDTO.setSubjectLabelName(bookServeQueryDTO.getSubjectLabelName());
        List<ProductVideoScheduleDTO> scheduleDTOS = resourceConsr.getProductVideoCourseList4ExerciseBook(productVideoScheduleQueryDTO);
        if (ListUtils.isEmpty(scheduleDTOS)) {
            return new ArrayList<>();
        }
        List<Long> serveIds = scheduleDTOS.stream().map(ProductVideoScheduleDTO::getProductId).collect(Collectors.toList());
        //数据筛选
        Map<Long, List<BookGroupServe>> listMap = bookGroupServes.stream().collect(Collectors.groupingBy(BookGroupServe::getBookId));
        Map<Long, Integer> serveCountMap = new HashMap<>();
        List<BookGroupServe> serveList = new ArrayList<>();
        for (Map.Entry<Long, List<BookGroupServe>> entry: listMap.entrySet()) {
            List<BookGroupServe> list = new ArrayList<>();
            CourseModuleDTO moduleDTO = bookModuleMap.get(entry.getKey());
            List<Integer> top10Modules = Arrays.asList(6,7);
            for (BookGroupServe groupServe:entry.getValue()) {
                if (top10Modules.contains(moduleDTO.getModuleType())) {//热门课程Top10
                    if (list.size()>=10) {
                        break;
                    }
                } else if (list.size()>=2) {//每个模块最多两个展示课程
                    break;
                }
                if (serveIds.contains(groupServe.getServeId())) {
                    list.add(groupServe);
                }
            }
            serveList.addAll(list);
            List<Long> serves = entry.getValue().stream().filter(s->serveIds.contains(s.getServeId())).map(BookGroupServe::getServeId).distinct().collect(Collectors.toList());
            serveCountMap.put(entry.getKey(), serves.size());
        }
        List<BookServeDTO> serveDTOList = fillServeCourse4ExerciseBook(serveList, channelId, scheduleDTOS);
        Map<Long, List<BookServeDTO>> bookServeMap = serveDTOList.stream().collect(Collectors.groupingBy(BookServeDTO::getBookId));
        List<ExerciseBookCourseVO> resultList = new ArrayList<>();
        for (Map.Entry<Long, List<BookServeDTO>> entry:bookServeMap.entrySet()) {
            CourseModuleDTO moduleDTO = bookModuleMap.get(entry.getKey());
            ExerciseBookCourseVO courseVO = new ExerciseBookCourseVO();
            courseVO.setModuleType(moduleDTO.getModuleType());
            courseVO.setModuleName(moduleDTO.getModuleName());
            courseVO.setBookServeDTOS(entry.getValue());
            courseVO.setServeCount(serveCountMap.get(entry.getKey()));
            resultList.add(courseVO);
        }
        return resultList;
    }

    @Override
    public PageBeanNew<BookGroupDTO> getAllRaysScene(Integer currentPage, Integer numPerPage) {
        return bookGroupDao.listPageNew(new PageParam(currentPage, numPerPage), new HashMap<>(),"getAllRaysScene");
    }

    @Override
    public List<BookGroupScanStatisticsRespDTO> getBookGroupScanStatistics(BookGroupScanStatisticsRequestDTO reqDTO) {
        if (ObjectUtil.hasEmpty(reqDTO, reqDTO.getBookIds(), reqDTO.getAdviserIds(), reqDTO.getChannelIds(), reqDTO.getStart(), reqDTO.getEnd()))
            return new ArrayList<>();

        List<BookGroupDTO> bookGroupDTOS = bookGroupDao.listBookGroupIds(null, reqDTO.getAdviserIds(), reqDTO.getChannelIds());
        if (CollUtil.isEmpty(bookGroupDTOS)) return new ArrayList<>();
        bookGroupDTOS = bookGroupDTOS.stream().filter(e -> reqDTO.getBookIds().contains(e.getBookId())).collect(Collectors.toList());
        if (CollUtil.isEmpty(bookGroupDTOS)) return new ArrayList<>();
        List<Long> bookGroupIds = bookGroupDTOS.stream().filter(Objects::nonNull).map(BookGroupDTO::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(bookGroupIds)) return new ArrayList<>();
        Integer maxCount = 500;
        Integer pageCount = 0;
        List<BookGroupScanStatisticsDTO> bookGroupScanStatistics = new ArrayList<>();
        BookGroupScanStatisticsReqDTO bookGroupScanStatisticsReqDTO = new BookGroupScanStatisticsReqDTO();
        bookGroupScanStatisticsReqDTO.setStart(reqDTO.getStart());
        bookGroupScanStatisticsReqDTO.setEnd(reqDTO.getEnd());
        if (bookGroupIds.size() > maxCount) {
            //超过500, 则分批查询
            while (true) {
                Integer endCount = maxCount * (pageCount + 1);
                List<Long> subList = bookGroupIds.subList(pageCount * maxCount, bookGroupIds.size() < endCount ? bookGroupIds.size() : endCount);
                bookGroupScanStatisticsReqDTO.setBookGroupIds(subList);
                List<BookGroupScanStatisticsDTO> subBookGroupScanStatistics =  wechatGroupConsr.getBookGroupScanStatistics(bookGroupScanStatisticsReqDTO);
                if (!ListUtils.isEmpty(subBookGroupScanStatistics)) {
                    bookGroupScanStatistics.addAll(subBookGroupScanStatistics);
                }
                if (subList.size() < maxCount){
                    break;
                }
                pageCount++;
            }
        } else {
            bookGroupScanStatisticsReqDTO.setBookGroupIds(bookGroupIds);
            bookGroupScanStatistics = wechatGroupConsr.getBookGroupScanStatistics(bookGroupScanStatisticsReqDTO);
        }
        if (CollUtil.isEmpty(bookGroupScanStatistics)) return new ArrayList<>();
        Map<Long, BookGroupScanStatisticsDTO> statisticsDTOMap = bookGroupScanStatistics.stream().filter(x ->
                ObjectUtil.isAllNotEmpty(x, x.getBookGroupId())).collect(Collectors.toMap(BookGroupScanStatisticsDTO::getBookGroupId, Function.identity()));

        List<BookGroupScanStatisticsRespDTO> list = new ArrayList<>();
        for (BookGroupDTO bookGroupDTO : bookGroupDTOS) {
            if (ObjectUtil.hasEmpty(bookGroupDTO,bookGroupDTO.getId())) continue;
            BookGroupScanStatisticsRespDTO respDTO = new BookGroupScanStatisticsRespDTO();
            respDTO.setBookId(bookGroupDTO.getBookId());
            respDTO.setAdviserId(bookGroupDTO.getCreateUser());
            respDTO.setChannelId(bookGroupDTO.getChannelId());
            respDTO.setScanCount(Optional.ofNullable(statisticsDTOMap.get(bookGroupDTO.getId())).map(BookGroupScanStatisticsDTO::getScanCount).orElse(0));
            respDTO.setReaderCount(Optional.ofNullable(statisticsDTOMap.get(bookGroupDTO.getId())).map(BookGroupScanStatisticsDTO::getReaderCount).orElse(0));
            list.add(respDTO);
        }
        return list;
    }


    @Override
    public List<BookGroup4CatalogDTO> listBookGroup4BookCatalog(Long bookId, Long adviserId, Long channelId, String name, Integer rank) {
        return bookGroupServeDao.listBookGroup4BookCatalog(bookId, adviserId, channelId, name, rank);
    }

    @Override
    public void updateBookGroupSeq(Long bookGroupId, Integer seq) {
        bookGroupDao.updateBookGroupSeq(bookGroupId, seq);
    }
}
