/**
 *
 */
package com.pcloud.book.book.biz.impl;

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

import com.alibaba.fastjson.JSONObject;
import com.pcloud.analysisengine.qrcode.dto.BookTimeSourceDto;
import com.pcloud.appcenter.app.dto.AppDto;
import com.pcloud.appcenter.assist.dto.AssistTempletDTO;
import com.pcloud.appcenter.base.dto.AppPriceCacheDTO;
import com.pcloud.appcenter.base.exception.AppBizException;
import com.pcloud.appcenter.cache.service.AppPriceCacheService;
import com.pcloud.book.applet.biz.AppletBookClassifyBiz;
import com.pcloud.book.applet.dao.AnswerSubscribeDao;
import com.pcloud.book.applet.entity.AnswerSubscribe;
import com.pcloud.book.applet.entity.AppletUserLabelRelation;
import com.pcloud.book.applet.enums.LabelTypeEnum;
import com.pcloud.book.base.enums.BookFreezeEnum;
import com.pcloud.book.base.enums.BookStatusEnum;
import com.pcloud.book.base.enums.BookTypeEnum;
import com.pcloud.book.base.exception.BookBizException;
import com.pcloud.book.book.biz.BookAdviserBiz;
import com.pcloud.book.book.biz.BookAdviserErpBiz;
import com.pcloud.book.book.biz.BookAppBiz;
import com.pcloud.book.book.biz.BookBiz;
import com.pcloud.book.book.biz.BookFreezeBiz;
import com.pcloud.book.book.biz.BookFundBiz;
import com.pcloud.book.book.biz.BookLabelBiz;
import com.pcloud.book.book.biz.BookProductBiz;
import com.pcloud.book.book.biz.BookResourceBiz;
import com.pcloud.book.book.biz.BookSerialNumberBiz;
import com.pcloud.book.book.cache.BookCache;
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.BookEdtionDao;
import com.pcloud.book.book.dao.BookLabelDao;
import com.pcloud.book.book.dao.BookRaysClassifyDao;
import com.pcloud.book.book.dao.BookTypeDao;
import com.pcloud.book.book.dao.EdtionRecordDao;
import com.pcloud.book.book.dao.QrcodeSceneErpDao;
import com.pcloud.book.book.dao.SeriesBookDao;
import com.pcloud.book.book.dao.SeriesBookRecordDao;
import com.pcloud.book.book.dto.AdviserBookInfoDTO;
import com.pcloud.book.book.dto.BookAdviserDto;
import com.pcloud.book.book.dto.BookAdviserUpdateTimeDTO;
import com.pcloud.book.book.dto.BookAssocCount;
import com.pcloud.book.book.dto.BookCoverImgUpdateDTO;
import com.pcloud.book.book.dto.BookDetialDTO;
import com.pcloud.book.book.dto.BookDto;
import com.pcloud.book.book.dto.BookFreezeDto;
import com.pcloud.book.book.dto.BookFundDto;
import com.pcloud.book.book.dto.BookInfo4AnlysicsDTO;
import com.pcloud.book.book.dto.BookInfoAnalysicsDTO;
import com.pcloud.book.book.dto.BookInfoAndAuthStatusDTO;
import com.pcloud.book.book.dto.BookMinimumSupportDTO;
import com.pcloud.book.book.dto.BookNameUpdateDTO;
import com.pcloud.book.book.dto.BookTypeDto;
import com.pcloud.book.book.dto.BookUniqueNumberDTO;
import com.pcloud.book.book.dto.CreateBookResultVO;
import com.pcloud.book.book.dto.CreateBookVO;
import com.pcloud.book.book.dto.CreateQrcodeVO;
import com.pcloud.book.book.dto.ErpBookApprovalDTO;
import com.pcloud.book.book.dto.MapResourceTotalCountDTO;
import com.pcloud.book.book.dto.EditionAnalysisListVO;
import com.pcloud.book.book.dto.EditionAnalysisResultVO;
import com.pcloud.book.book.dto.EditionAnalysisVO;
import com.pcloud.book.book.dto.QrcodeServeDto;
import com.pcloud.book.book.dto.RelateAdviserVO;
import com.pcloud.book.book.entity.Book;
import com.pcloud.book.book.entity.BookAdviser;
import com.pcloud.book.book.entity.BookAdviserErp;
import com.pcloud.book.book.entity.BookEdition;
import com.pcloud.book.book.entity.BookLabel;
import com.pcloud.book.book.entity.BookSerialNumber;
import com.pcloud.book.book.entity.EditionRecord;
import com.pcloud.book.book.entity.QrcodeSceneErp;
import com.pcloud.book.book.entity.SeriesBook;
import com.pcloud.book.book.entity.SeriesBookRecord;
import com.pcloud.book.book.set.BookSet;
import com.pcloud.book.book.tools.BookTools;
import com.pcloud.book.book.vo.BookInfo4ScanCount;
import com.pcloud.book.book.vo.BookLabelVO;
import com.pcloud.book.book.vo.BookQualifyVO;
import com.pcloud.book.book.vo.BookResourceNumDTO;
import com.pcloud.book.book.vo.BookSaleVO;
import com.pcloud.book.book.vo.ListNoAuthBookParam;
import com.pcloud.book.book.vo.ListNoAuthGroupBookParam;
import com.pcloud.book.book.vo.SearchBookVO;
import com.pcloud.book.book.vo.request.BookInfo4ScanCountRequestVO;
import com.pcloud.book.book.vo.request.BookQualifyInfoVO;
import com.pcloud.book.book.vo.request.BookSearchParamVO;
import com.pcloud.book.book.vo.request.UpdateBookRobotProcessDto;
import com.pcloud.book.consumer.analysisengine.SceneRecordConsr;
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.erp.ErpConsr;
import com.pcloud.book.consumer.isbn.IsbnConsr;
import com.pcloud.book.consumer.label.LabelConsr;
import com.pcloud.book.consumer.message.MessageConsr;
import com.pcloud.book.consumer.raystask.MainLineConsr;
import com.pcloud.book.consumer.resource.ProductConsr;
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.user.MerchantConsr;
import com.pcloud.book.consumer.user.PartyConsr;
import com.pcloud.book.consumer.wechat.WechatConsr;
import com.pcloud.book.copyright.biz.BookAuthInfoBiz;
import com.pcloud.book.copyright.vo.BookAuthInfoVO;
import com.pcloud.book.es.biz.ESBookAndAdviserBiz;
import com.pcloud.book.es.entity.ESBookAndAdviser;
import com.pcloud.book.group.biz.BookGroupBiz;
import com.pcloud.book.group.dao.BookAppletSceneDao;
import com.pcloud.book.group.dao.BookGroupDao;
import com.pcloud.book.group.dao.BookGroupServeDao;
import com.pcloud.book.group.dto.BookGroupDTO;
import com.pcloud.book.group.dto.BookServeDTO;
import com.pcloud.book.group.entity.BookAppletScene;
import com.pcloud.book.group.entity.BookGroup;
import com.pcloud.book.group.entity.BookGroupServe;
import com.pcloud.book.group.enums.JoinGroupTypeEnum;
import com.pcloud.book.mq.producer.BookMQProducer;
import com.pcloud.book.rightsSetting.constants.RightsSettingConstant;
import com.pcloud.book.rightsSetting.dao.RightsNowItemDao;
import com.pcloud.book.rightsSetting.dao.RightsSettingItemDao;
import com.pcloud.book.rightsSetting.mapper.RightsSettingBookRelationMapper;
import com.pcloud.book.util.common.ThreadPoolUtils;
import com.pcloud.book.util.common.YesOrNoEnums;
import com.pcloud.channelcenter.qrcode.dto.QrcodeLocationDto;
import com.pcloud.channelcenter.qrcode.dto.QrcodeSceneDto;
import com.pcloud.channelcenter.qrcode.entity.QrcodeLabel;
import com.pcloud.channelcenter.qrcode.entity.QrcodeScene;
import com.pcloud.channelcenter.qrcode.entity.QrcodeStyle;
import com.pcloud.channelcenter.wechat.dto.AdviserBookResourceNumRespDTO;
import com.pcloud.channelcenter.wechat.dto.BookServeParamVO;
import com.pcloud.channelcenter.wechat.dto.MessageDto;
import com.pcloud.channelcenter.wechat.vo.BookServeVO;
import com.pcloud.common.core.aspect.ParamLog;
import com.pcloud.common.core.constant.AgentTypeEnum;
import com.pcloud.common.core.constant.SystemCode;
import com.pcloud.common.enums.AppTypeEnum;
import com.pcloud.common.exceptions.BizException;
import com.pcloud.common.exceptions.ExportException;
import com.pcloud.common.page.PageBean;
import com.pcloud.common.page.PageBeanNew;
import com.pcloud.common.page.PageParam;
import com.pcloud.common.utils.DateUtils;
import com.pcloud.common.utils.ListUtils;
import com.pcloud.common.utils.NumberUtil;
import com.pcloud.common.utils.ResponseHandleUtil;
import com.pcloud.common.utils.cache.redis.JedisClusterUtils;
import com.pcloud.common.utils.string.StringUtil;
import com.pcloud.commoncenter.export.service.ExportService;
import com.pcloud.labelcenter.label.service.LabelService;
import com.pcloud.resourcecenter.product.dto.ProductDto;
import com.pcloud.resourcecenter.product.dto.SpecificationDto;
import com.pcloud.usercenter.party.adviser.dto.AdviserBaseInfoDto;
import com.pcloud.usercenter.party.agent.dto.SaleAgentDTO;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;

/**
 * @描述：书籍业务层接口实现类
 * @作者：songx
 * @创建时间：2016年12月23日,下午3:00:08 @版本：1.0
 */
@Service("bookBiz")
public class BookBizImpl implements BookBiz {

    /**
     *
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(BookBizImpl.class);
    private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(5);
    @Autowired
    private BookDao bookDao;
    @Autowired
    private BookFundBiz bookFundBiz;
    @Autowired
    private BookProductBiz bookProductBiz;
    @Autowired
    private BookAppBiz bookAppBiz;
    @Autowired
    private QrcodeSceneConsr qrcodeSceneConsr;
    @Autowired
    private BookAdviserBiz bookAdviserBiz;
    @Autowired
    private BookSet bookSet;
    @Autowired
    private ChannelConsr channelConsr;
    @Autowired
    private IsbnConsr isbnConsr;
    @Autowired
    private BookResourceBiz bookResourceBiz;
    @Autowired
    private BookCache bookCache;
    @Autowired
    private SceneRecordConsr sceneRecordConsr;
    @Autowired
    private AgentConsr agentConsr;
    @Autowired
    private AdviserConsr adviserConsr;
    @Autowired
    private PartyConsr partyConsr;
    @Autowired
    private BookFreezeBiz bookFreezeBiz;
    @Autowired
    private AssistTempletConsr assistTempletConsr;
    @Autowired
    private BookMQProducer bookMQProducer;
    @Autowired
    private BookAuthInfoBiz bookAuthInfoBiz;
    @Autowired
    private MainLineConsr mainLineConsr;
    @Autowired
    private BookGroupBiz bookGroupBiz;
    @Autowired
    private BookLabelDao bookLabelDao;

    @Autowired
    private ExportService exportService;
    @Autowired
    private ExportConsr exportConsr;
    @Autowired
    private MessageConsr messageConsr;
    @Autowired
    private ESBookAndAdviserBiz esBookAndAdviserBiz;
    @Autowired
    private BookGroupDao bookGroupDao;
    @Autowired
    private BookRaysClassifyDao bookRaysClassifyDao;

    @Autowired
    private BookAppletSceneDao bookAppletSceneDao;

    @Autowired
    private BookAdviserDao bookAdviserDao;


    @Autowired
    private WechatConsr wechatConsr;
    @Autowired
    private RightsSettingBookRelationMapper rightsSettingBookRelationMapper;


    @Autowired
    private AppletBookClassifyBiz appletBookClassifyBiz;
    @Autowired
    private BookSerialNumberBiz bookSerialNumberBiz;
    @Autowired
    private BookAdviserErpBiz bookAdviserErpBiz;
    @Autowired
    private QrcodeSceneErpDao qrcodeSceneErpDao;

    @Autowired
    private ErpConsr erpConsr;
    @Autowired
    private LabelService labelService;
    @Autowired
    private ProductConsr productConsr;
    @Autowired
    private AppConsr appConsr;
    @Autowired
    private BookGroupServeDao bookGroupServeDao;
    @Autowired
    private AppPriceCacheService appPriceCacheService;
    @Autowired
    private MerchantConsr merchantConsr;
    @Autowired
    private BookBiz bookBiz;
    @Autowired
    private LabelConsr labelConsr;
    @Value("${system.env}")
    private String envStr;
    @Autowired
    private AnswerSubscribeDao answerSubscribeDao;
    @Autowired
    private BookLabelBiz bookLabelBiz;
    @Autowired
    private SeriesBookDao seriesBookDao;
    @Autowired
    private SeriesBookRecordDao seriesBookRecordDao;
    @Autowired
    private BookEdtionDao bookEdtionDao;
    @Autowired
    private EdtionRecordDao edtionRecordDao;
    @Autowired
    private BookTypeDao bookTypeDao;
    @Autowired
    private RightsNowItemDao rightsNowItemDao;

    /**
     * 创建书籍,同时建立与编辑的推广关系
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BookDto create(Book book, String systemCode) throws BizException {
        LOGGER.info("【书籍基础】创建书籍基础信息,<START>.[book]:{};systemCode:{}", book, systemCode);
        this.checkAddParam(book);
        // 判断书籍ISBN码是否存在,同时判断书籍ISBN码是否符合规范
        if (this.isbnExists(book.getTypeCode(), book.getIsbn(), book.getSerialNumber())) {
            throw new BookBizException(BookBizException.DB_SELECT_MORE, "书刊已存在");
        }

        if (SystemCode.adviser.code.equalsIgnoreCase(systemCode) &&
                (Objects.isNull(book.getTempletId()) || Objects.isNull(book.getSecondTempletId()))) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊分类");
        }

        bookDao.insert(book);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        BookDto bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
        bookDto.setBookId(book.getBookId());
        bookDto.setTempletId(book.getTempletId());
        bookDto.setSecondTempletId(book.getSecondTempletId());
        bookDto.setThirdTempletId(book.getThirdTempletId());
        // 如果是编辑创建的书籍、默认建立编辑与书籍的推广关系
        if (SystemCode.adviser.code.equalsIgnoreCase(systemCode)) {
            setBookAdviserRelation(book);
        }
        // 书籍总数缓存加1
        bookCache.incrObject(BookConstant.BOOK_CACHE + "PLATFORM_BOOK_COUNT");
        //插入版次记录
        insertEdition(book.getCreatedUser(), book.getEdition(), book.getId());
        return bookDto;

    }

    private void insertEdition(Long userId, String bookEdition, Long bookId) {
        if (!StringUtils.isEmpty(bookEdition)) {
            String[] split = bookEdition.split(",");
            if (split.length < 3) {
                throw new IllegalArgumentException(String.format("缺少年月版等信息！"));
            }
            String month=split[1];
            if(split[1].length()==1){
                month="0"+split[1];
            }
            String editionYear = split[0] + "-" + month;
            String edition = split[2];
            BookEdition projectEdition = new BookEdition();
            projectEdition.setEditionYear(editionYear);
            projectEdition.setEdition(StringUtils.isEmpty(edition) ? null : Integer.valueOf(edition));
            projectEdition.setBookId(bookId);
            projectEdition.setUpdateUser(userId);
            EditionRecord editionRecord = new EditionRecord();
            editionRecord.setEditionYear(editionYear);
            editionRecord.setEdition(StringUtils.isEmpty(edition) ? null : Integer.valueOf(edition));
            editionRecord.setBookId(bookId);
            editionRecord.setUpdateUser(userId);
            bookEdtionDao.insert(projectEdition);
            edtionRecordDao.insert(editionRecord);
        }
    }

    /**
     * 校验参数
     */
    private void checkAddParam(Book book) throws BizException {
        if (StringUtil.isEmpty(book.getIsbn())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍ISBN码不能为空");
        }
        if (StringUtil.isEmpty(book.getBookName())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍名称不能为空");
        }
        if (StringUtil.isEmpty(book.getTypeCode())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "类型编码不能为空");
        }
        if (StringUtil.isEmpty(book.getPublishDate())) {
            book.setPublishDate(null);
        }
        if (StringUtil.isEmpty(book.getSerialNumber())) {
            book.setSerialNumber(null);
        }
    }

    /**
     * 修改书籍
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Book book) throws BizException {
        LOGGER.info("【书籍基础】修改书籍基础信息,<PARAM>.[book]={}", book);
        // 校验参数
        this.checkParam(book);
        //获取图书基本信息
        BookDto bookDto = this.getBaseById(book.getBookId());
        checkIsUpdateCoverImgAndSendTopic(bookDto, book.getCoverImg());
        checkIsUpdateBookNameAndSendTopic(bookDto, book.getBookName());
        bookDao.update(book);
        //修改版次信息
        insertEdition(book.getLastModifiedUser(),book.getEdition(),book.getBookId());
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        // 清除redis中数据
        bookCache.clearRedisByBook(book.getBookId(), book.getIsbn(), book.getSerialNumber());
    }

    @ParamLog("校验是否修改图书名称并发送修改名称topic")
    private void checkIsUpdateBookNameAndSendTopic(BookDto oldBook, String newBookName) {
        if (newBookName != null && !newBookName.equalsIgnoreCase(oldBook.getBookName())) {
            BookNameUpdateDTO bookNameUpdateDTO = new BookNameUpdateDTO();
            bookNameUpdateDTO.setBookId(oldBook.getBookId());
            bookNameUpdateDTO.setBookName(newBookName);
            bookMQProducer.sendUpdateBookNameTopic(bookNameUpdateDTO);
        }
    }

    @ParamLog("校验是否修改图书封面图并发送修改封面图topic")
    void checkIsUpdateCoverImgAndSendTopic(BookDto oldBook, String newCoverImg) {
        if (newCoverImg != null && !newCoverImg.equalsIgnoreCase(oldBook.getCoverImg())) {
            BookCoverImgUpdateDTO bookCoverImgUpdateDTO = new BookCoverImgUpdateDTO();
            bookCoverImgUpdateDTO.setBookId(oldBook.getBookId());
            bookCoverImgUpdateDTO.setCoverImg(newCoverImg);
            bookMQProducer.sendUpdateBookCoverImgTopic(bookCoverImgUpdateDTO);
        }
    }

    /**
     * 修改书籍封面图
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCoverImg(Book book) throws BizException {
        LOGGER.info("【书籍基础】修改书籍基础信息,<PARAM>.[book]=" + book);
        // 获取图书基本信息校验是否默认图书
        BookDto bookDto = this.getBaseById(book.getBookId());
        if (BookConstant.DEFAULT_BOOK_ISBN.equals(bookDto.getIsbn())
                && StringUtils.isEmpty(bookDto.getSerialNumber())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "默认图书不能修改！");
        }
        bookDao.updateCoverImg(book);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        checkIsUpdateCoverImgAndSendTopic(bookDto, book.getCoverImg());
        // 清除redis中数据
        bookCache.clearRedisByBook(bookDto.getBookId(), bookDto.getIsbn(), bookDto.getSerialNumber());
    }

    /**
     * 修改书籍(编辑)
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BookDto updateByAdviser(Book book) throws BizException {
        LOGGER.info("【书籍基础】修改书籍基础信息,<PARAM>.[book]=" + book);
        checkParam(book);
        // 设置编辑书刊关联关系
        setBookAdviserRelation(book);
        if (BookConstant.DEFAULT_BOOK_ISBN.equals(book.getIsbn()) && StringUtils.isEmpty(book.getSerialNumber())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "默认图书不能修改！");
        }
        // 修改书籍
        bookDao.update(book);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        BookDto bookDto = new BookDto();
        bookDto.setBookId(book.getBookId());
        bookDto.setTempletId(book.getTempletId());
        bookDto.setSecondTempletId(book.getSecondTempletId());
        bookDto.setThirdTempletId(book.getThirdTempletId());
        // 清除redis中数据
        bookCache.clearRedisByBook(book.getBookId(), book.getIsbn(), book.getSerialNumber());
        checkIsUpdateCoverImgAndSendTopic(bookDto, book.getCoverImg());
        checkIsUpdateBookNameAndSendTopic(bookDto, book.getBookName());
        return bookDto;
    }

    /**
     * 校验参数
     */
    private void checkParam(Book book) throws BizException {
        if (StringUtil.isEmpty(book.getIsbn())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍ISBN码不能为空");
        }
        if (StringUtil.isEmpty(book.getBookName())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍名称不能为空");
        }
        if (BookTypeEnum.BOOK.value.equalsIgnoreCase(book.getTypeCode())) {
            if (!StringUtils.isEmpty(book.getPublishDate())) {
                try {
                    DateUtils.StringToShortDate(book.getPublishDate());
                } catch (Exception e) {
                    LOGGER.warn("【书籍-编辑】参数校验:时间格式非法,<ERROR>:" + e.getMessage(), e);
                    throw new BookBizException(BookBizException.TIME_FORMAT_ERROR, "出版时间格式非法");
                }
            }
        }
        if (StringUtil.isEmpty(book.getPublishDate())) {
            book.setPublishDate(null);
        }
        if (StringUtil.isEmpty(book.getSerialNumber())) {
            book.setSerialNumber(null);
        }
        if (StringUtil.isEmpty(book.getCoverImg())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "图书封面图不能为空");
        }
        if (BookConstant.DEFAULT_BOOK_ISBN.equals(book.getIsbn()) && StringUtils.isEmpty(book.getSerialNumber())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "默认图书不能修改！");
        }
        //modify 20200601 /book/update 平台端去掉校验
       /* if (Objects.isNull(book.getTempletId()) || Objects.isNull(book.getSecondTempletId())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊分类");
        }*/
    }

    /**
     * 删除书籍
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long bookId, Long deleteUserId) throws BizException {
        LOGGER.info("【书籍基础】删除书籍,<PARAM>.[bookId]=" + bookId + "[deleteUserId]=" + deleteUserId);
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择要删除的书刊");
        }
        BookDto book = getBaseById(bookId);
        if (BookConstant.DEFAULT_BOOK_ISBN.equals(book.getIsbn()) && StringUtils.isEmpty(book.getSerialNumber())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "默认图书不能删除！");
        }
        // 判断是否有基金
        List<BookFundDto> bookFundList = bookFundBiz.getByBookId(bookId);
        if (!ListUtils.isEmpty(bookFundList)) {
            throw new BookBizException(BookBizException.ERROR, "该书刊已经有基金支持，不能删除！");
        }
        // 判断当前和以后图书是否被冻结
        List<BookFreezeDto> bookFreezeList = bookFreezeBiz.getFreezeInfo(bookId);
        if (!ListUtils.isEmpty(bookFreezeList)) {
            throw new BookBizException(BookBizException.ERROR, "该书刊已经被冻结，不能删除！");
        }

        // 删除书籍与编辑关联关系
        bookAdviserBiz.deleteByBook(bookId);
        // 删除图书
        Integer result = bookDao.deleteBook(bookId, deleteUserId);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        if (result == 0) {
            throw BookBizException.DB_DELETE_RESULT_0;
        }
        // 发送书籍删除topic
        bookSet.sendBookDeleteTopic(bookId);
        // 书籍总数缓存减1
        bookCache.decrObject(BookConstant.BOOK_CACHE + "PLATFORM_BOOK_COUNT");
        // 清除缓存
        bookCache.clearRedisByBook(bookId, book.getIsbn(), book.getSerialNumber());
    }

    /**
     * 批量删除书籍
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deletes(String bookIdStrs, Long deleteUserId) throws BizException {
        LOGGER.info("【书籍基础】批量删除书籍,<PARAM>.[bookIdStrs]=" + bookIdStrs + "[deleteUserId]=" + deleteUserId);
        if (StringUtil.isEmpty(bookIdStrs)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择要删除的书刊");
        }
        List<Long> bookIds = Arrays.asList(bookIdStrs.split(",")).stream().map(s -> Long.parseLong(s.trim()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(bookIds)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择要删除的书刊");
        }

        // 判断当前和以后基金是否被冻结
        List<BookFreezeDto> bookFreezeList = bookFreezeBiz.listFreezeInfo(bookIds);
        if (!ListUtils.isEmpty(bookFreezeList)) {
            throw new BookBizException(BookBizException.ERROR, "所选书刊中有一部分书刊已经被冻结，不能删除！");
        }

        Integer result = bookDao.deleteByIds(bookIds, deleteUserId);
        esBookAndAdviserBiz.updateBookAndAdviserToES(bookIds);
        if (result == 0) {
            throw BookBizException.DB_DELETE_RESULT_0;
        }

        // 发送书籍批量删除topic
        bookSet.sendBooksDeleteTopic(bookIds);

        // 书籍总数缓存减去相应大小
        Integer bookCount = bookCache.getBookCountToRedis();
        if (null == bookCount || bookCount.equals(0)) {
            bookCount = bookCount - bookIds.size();
        }
        // 清除并将数据存入redis
        bookCache.delBookCountToRedis();
        bookCache.setBookCountToRedis(bookCount);
    }

    /**
     * 获取书籍基础信息
     */
    @Override
    public BookDto getBaseById(Long bookId) throws BizException {
        LOGGER.info("【书籍基础】获取书籍基础信息,<PARAM>.[bookId]=" + bookId);
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        Long adviserId = null;
        // 从redis获取书籍信息
        BookDto bookDto = bookCache.getBookToRedis(bookId);
        if (null == bookDto) {
            bookDto = bookDao.getBaseById(bookId);
            BookAdviserDto bookAdviserDto = bookAdviserBiz.getOneMainBook(bookId);
            if (null != bookDto && null != bookAdviserDto) {
                bookDto.setBookAdviserDto(bookAdviserDto);
                bookDto.setTempletId(bookAdviserDto.getTempletId());
                bookSet.setFirstTemplateName(bookDto);
                adviserId = bookAdviserDto.getAdviserId();
                bookDto.setGraLabelId(bookAdviserDto.getGraLabelId());
                bookDto.setSubLabelId(bookAdviserDto.getSubLabelId());
                bookDto.setVerLabelId(bookAdviserDto.getVerLabelId());
                bookDto.setVolLabelId(bookAdviserDto.getVolLabelId());
            }
            if (Objects.nonNull(bookDto)){
                bookDto.setIsLibraryBook(checkIsLibraryBook(adviserId, bookId) ? 1 : 0);
            }
            // 将数据存入redis
            bookCache.setBookToRedis(bookDto);
        }
        return bookDto == null ? new BookDto() : bookDto;
    }

    /**
     * 调用外部接口新增书籍信息
     */
    public void insertBook(String isbn) {
        try {
            // 调用外部接口获取该图书的基本信息
            Book bookInfo = isbnConsr.getBook(isbn);
            if (bookInfo != null && bookInfo.getIsbn() != null) {
                // 添加书籍信息(设置添加人为平台)
                bookInfo.setCreatedUser(0l);
                try {
                    bookDao.insert(bookInfo);
                    esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(bookInfo.getBookId()));
                } catch (Exception e) {
                    LOGGER.error("书刊已存在" + e.getMessage(), e);
                }
            }
        } catch (Exception e) {
            LOGGER.error("ISBN新增书籍失败！" + e.getMessage(), e);
        }
    }

    /**
     * 根据ISBN获取书刊信息
     */
    @Override
    public BookDto getByIsbn(String isbn, String serialNumber) throws BizException {
        LOGGER.info("【书刊基础】根据ISBN获取书刊信息,<START>.[isbn]=" + isbn);
        if (StringUtil.isEmpty(isbn)) {
            throw new AppBizException(AppBizException.PARAM_IS_NULL, "请选择书刊");
        }
        if (StringUtils.isEmpty(serialNumber)) {
            serialNumber = null;
        }
        // 从redis获取书刊信息
        BookDto bookDto = bookCache.getBookToRedisByIsbn(isbn, serialNumber);
        if (bookDto == null) {
            bookDto = bookDao.getByIsbnAndSnumContainsDelete(isbn, serialNumber);
            // 将数据存入redis
            bookCache.setBookToRedisByIsbn(bookDto);
        }
        return bookDto;
    }

    /**
     * 判断ISBN是否存在
     */
    @Override
    public Boolean isbnExists(String typeCode, String isbn, String serialNumber) throws BizException {
        LOGGER.info("【书籍基础】判断ISBN是否存在,<START>.[isbn]=" + isbn + ",[typeCode]=" + typeCode);
        if (StringUtil.isEmpty(isbn)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "ISBN码不能为空");
        }
        if (StringUtil.isEmpty(typeCode)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "书籍类型不能为空");
        }
        if (StringUtil.isEmpty(serialNumber)) {
            serialNumber = null;
        }

        // 校验书号
        bookSet.checkISBN(typeCode, isbn);
        BookDto bookDto = bookDao.getByIsbnAndSnum(isbn, serialNumber);
        return bookDto != null;
    }

    /**
     * 获取单个书籍基础信息(包含统计信息)
     */
    @Override
    public BookDto getById(Long bookId, Long adviserId, Long channelId) throws BizException {
        LOGGER.info("【书籍基础】获取单个书籍基础信息(包含统计信息),<START>.[bookId]=" + bookId + ",[adviserId]=" + adviserId
                + ",[channelId]=" + channelId);
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        if (channelId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
        }
        BookDto bookDto = null;
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", adviserId);
        paramMap.put("channelId", channelId);
        bookDto = bookDao.getById(paramMap);
        if (bookDto == null) {
            return new BookDto();
        }
        // 设置渠道信息
        bookDto.setChannelId(channelId);
        bookDto.setChannelName(channelConsr.getNameById(channelId));
        // 设置主编辑信息
        Long mainAdviserId = bookAdviserBiz.getMainAdviserId(bookId, channelId);
        bookSet.setMainEditorInfo(bookDto, mainAdviserId);
        // 设置是否冻结
        bookSet.setFreezeStatus(bookDto);
        //	设置模板名字
        bookSet.setTemplateName(bookDto);
        // 设置专业深度目的标签
        bookSet.setProDepPurLabelName(bookDto);
        // 设置唯一编号
        bookDto.setUniqueNumber("BK" + bookDto.getBookId());
        // 设置二维码个数
        bookDto.setQrcodeCount(qrcodeSceneConsr.getBookQRCountByMap(adviserId, channelId, bookId));
        return bookDto;
    }

    /**
     * 获取单个书籍基础信息(包含统计信息)
     */
    @Override
    public BookDto getById4Platform(Long bookId, Long adviserId, Long channelId) throws BizException {
        LOGGER.info("【书籍基础】获取单个书籍基础信息,<START>.[bookId]=" + bookId + ",[adviserId]=" + adviserId
                + ",[channelId]=" + channelId);
        if (bookId == null || channelId == null || adviserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "参数有误！");
        }
        BookDto bookDto = null;
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", adviserId);
        paramMap.put("channelId", channelId);
        bookDto = bookDao.getById(paramMap);
        if (bookDto == null) {
            return new BookDto();
        }
        bookDto.setAdviserId(adviserId);
        bookDto.setChannelId(channelId);
        String adviserName = adviserConsr.getNameById(adviserId);
        bookDto.setAdviserName(adviserName);
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        Map<Long, String> agentNameMap = agentConsr.getNames(Collections.singletonList(agentId));
        if (!MapUtils.isEmpty(agentNameMap) && agentNameMap.containsKey(agentId)) {
            bookDto.setAgentName(agentNameMap.get(agentId));
        }
        return bookDto;
    }

    /**
     * 批量获取书籍信息
     */
    @Override
    public Map<Long, BookDto> getListByIds(List<Long> bookIds) throws BizException {
        LOGGER.info("【书籍基础】批量获取书籍信息,<PARAM>.[bookIds]=" + bookIds.toString());
        if (bookIds == null || bookIds.isEmpty()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        Map<Long, BookDto> bookMap = null;
        try {
            bookMap = bookDao.getMapByIds(bookIds);
            if (bookMap == null) {
                bookMap = Maps.newHashMap();
            }
        } catch (Exception e) {
            LOGGER.error("【书籍基础】批量获取书籍信息,<ERROR>.[bookDao.getMapByIds]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        return bookMap;
    }

    /**
     * 批量获取书籍信息（书名 与书刊序号 封面图）
     */
    @Override
    public Map<Long, BookDto> listBaseByIds(List<Long> bookIds) throws BizException {
        LOGGER.info("【书籍基础】批量获取书籍信息（书名 与书刊序号 封面图）,<PARAM>.[bookIds]=" + bookIds);
        if (bookIds == null || bookIds.isEmpty()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        Map<Long, BookDto> bookMap;
        try {
            bookMap = bookDao.listBaseMapByIds(bookIds);
            if (bookMap == null) {
                bookMap = Maps.newHashMap();
            }
        } catch (Exception e) {
            LOGGER.error("【书籍基础】批量获取书籍信息（书名 与书刊序号 封面图）,<ERROR>.[bookDao.listBaseByIds]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        return bookMap;
    }

    @Override
    public Map<String, BookDto> listBookGroupByBookIds(MapResourceTotalCountDTO bookDetailDTO) throws BizException {
        Map<String, BookDto> bookMap = Maps.newHashMap();
        if (null != bookDetailDTO && !ListUtils.isEmpty(bookDetailDTO.getBookIds()) && !ListUtils.isEmpty(bookDetailDTO.getChannelIds()) && !ListUtils.isEmpty(bookDetailDTO.getAdviserIds())) {

            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("bookIds", bookDetailDTO.getBookIds());
            paramMap.put("channelIds", bookDetailDTO.getChannelIds());
            paramMap.put("adviserIds", bookDetailDTO.getAdviserIds());
            List<BookDto> bookDtos = bookDao.listBookGroupByBookIds(bookDetailDTO.getBookIds(), bookDetailDTO.getChannelIds(),bookDetailDTO.getAdviserIds());
            if (!ListUtils.isEmpty(bookDtos)) {
                for (BookDto bookDto : bookDtos) {
                    bookMap.put(bookDto.getBookId() + "_" + bookDto.getChannelId() + "_" + bookDto.getAdviserId(), bookDto);
                }
            }
        }
        return bookMap;
    }

    @Override
    public Map<String, BookDto> listDetailByIds(BookDetialDTO bookDetialDTO) throws BizException {
        Map<String, BookDto> bookMap = null;
        if (null != bookDetialDTO && !(null == bookDetialDTO || ListUtils.isEmpty(bookDetialDTO.getBookIds()) || ListUtils.isEmpty(bookDetialDTO.getChannelId()))) {
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("bookIds", bookDetialDTO.getBookIds());
            paramMap.put("channelIds", bookDetialDTO.getChannelId());
            paramMap.put("adviserId", bookDetialDTO.getAdviserId());
            List<BookDto> bookDtos = bookDao.listDetailByIds(paramMap);
            if (!ListUtils.isEmpty(bookDtos)) {
                bookMap = Maps.newHashMap();
                for (BookDto bookDto : bookDtos) {
                    bookMap.put(bookDto.getChannelId() + "_" + bookDto.getBookId(), bookDto);
                }
            }
        }
        return bookMap;
    }

    /**
     * 获取书籍列表
     */
    @Override
    public PageBeanNew<BookDto> getListPage(String isbn, String bookName, String publish, String fundName,
            String serialNumber, Integer isCurrentMonth, Integer currentPage, Integer numPerPage) throws BizException {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("isbn", isbn != null && "".equals(isbn.trim()) ? null : isbn);
        paramMap.put("bookName", bookName != null && "".equals(bookName.trim()) ? null : bookName);
        paramMap.put("publish", publish != null && "".equals(publish.trim()) ? null : publish);
        paramMap.put("fundName", fundName != null && "".equals(fundName.trim()) ? null : fundName);
        paramMap.put("serialNumber", serialNumber != null && "".equals(serialNumber.trim()) ? null : serialNumber);
        paramMap.put("isCurrentMonth", isCurrentMonth);
        paramMap.put("currentPage", currentPage * numPerPage);
        paramMap.put("numPerPage", numPerPage);

        if(!StringUtil.isEmpty(bookName)){
            String[] bookNameList = bookName.trim().split("\\s+");
            paramMap.put("bookNameList",Lists.newArrayList(bookNameList));
        }

        List<BookDto> bookList = bookDao.getListPage4Platform(paramMap);

        // 获取平台端所有账号用户名
        Map<Long, String> pcloudUserMap = partyConsr.getAllUserLoginName(0L, SystemCode.pcloud.code);
        if (!ListUtils.isEmpty(bookList) && !pcloudUserMap.isEmpty()) {
            for (BookDto bookDto : bookList) {
                List<BookFundDto> bookFunds = bookDto.getBookFunds();
                Integer freezeStatus = BookFreezeEnum.WAIT_FREEZE.value;
                boolean isFundSupport = false;
                BookFreezeDto bf = bookFreezeBiz.getById(bookDto.getBookId());
                String transferor = bf == null ? null : bf.getTransferor();
                if (!ListUtils.isEmpty(bookFunds)) {
                    for (BookFundDto bookFundDto : bookFunds) {
                        if (StringUtil.isEmpty(transferor)) {
                            transferor = bookFundDto.getTransferor();
                        }
                        Date startTime = bookFundDto.getStartTime();
                        Date endTime = bookFundDto.getEndTime();
                        if (new Date().before(startTime)) {
                            bookFundDto.setButton(2);
                            freezeStatus = BookFreezeEnum.NO_FREEZE.value;
                        } else if (new Date().after(startTime) && new Date().before(endTime)) {
                            bookFundDto.setButton(1);
                            freezeStatus = BookFreezeEnum.NO_FREEZE.value;
                        } else {
                            bookFundDto.setButton(0);
                        }
                        Long opearateUserId = bookFundDto.getLastModifiedUser();
                        if (pcloudUserMap.containsKey(opearateUserId)) {
                            bookFundDto.setOperateUserName(pcloudUserMap.get(opearateUserId));
                        }
                        if (new Date().before(endTime)) {
                            isFundSupport = true;
                        }
                    }
                    bookDto.setIsHaveFund(true);
                }
                bookDto.setTransferor(transferor);
                bookDto.setIsFundSupport(isFundSupport);
                bookDto.setFreezeStatus(freezeStatus);
            }
        }
        int totalCount;
        if (StringUtil.isEmpty(isbn) && StringUtil.isEmpty(bookName) && StringUtil.isEmpty(publish)
                && StringUtil.isEmpty(fundName) && StringUtil.isEmpty(serialNumber) && null == isCurrentMonth) {
            totalCount = this.getAllBookCount();
        } else {
            totalCount = bookDao.getBookCount4Platform(paramMap);
        }
        if (!ListUtils.isEmpty(bookList)) {
            bookSet.setPageDetailInfo4Platform(bookList);
        }
        PageBeanNew<BookDto> result = new PageBeanNew<>();
        result.setCurrentPage(currentPage);
        result.setNumPerPage(numPerPage);
        result.setRecordList(bookList);
        result.setTotalCount(totalCount);
        return result;
    }

    /**
     * 获取书籍总数信息
     * @return
     */
    public int getAllBookCount() {
        Integer bookCount = bookCache.getBookCountToRedis();
        if (null == bookCount || bookCount < 10) {
            try {
                bookCount = bookDao.getAllBookCount();
                // 将数据存入redis
                bookCache.setBookCountToRedis(bookCount);
            } catch (Exception e) {
                LOGGER.error("【书籍基础】获取书籍总数信息,<ERROR>.[getAllBookCount]:" + e.getMessage(), e);
                throw BizException.DB_SELECT_IS_FAIL;
            }
        }
        return bookCount;
    }

    /**
     * 获取书籍列表(编辑)
     */
    @Override
    public PageBean getListPage4Adviser(Map<String, Object> paramMap, PageParam pageParam, Long adviserId, Integer hasQrcode) throws BizException {
        LOGGER.info("【书籍应用】获取书籍列表,<START>.[paramMap]=" + paramMap);
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "getListPage4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        if (null != hasQrcode && 1 == hasQrcode) {
            List<Long> channelIds = BookTools.listChannelIds(pageBean.getRecordList());
            List<com.pcloud.channelcenter.qrcode.dto.BookDto> bookIds = qrcodeSceneConsr.getQrcodeBookIds(channelIds, adviserId);
            if (ListUtils.isEmpty(bookIds)){
                return new PageBean(0, 0, new ArrayList<>());
            }
            paramMap.put("bookIds", bookIds);
            pageBean = bookDao.listPage(pageParam, paramMap, "getListPage4Adviser");
            if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
                return new PageBean(0, 0, new ArrayList<>());
            }
        }
        // 填充渠道基础信息
        bookSet.setChannelInfoList(pageBean.getRecordList());
        bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
        // 填充模板信息
        bookSet.setTemplateName(pageBean.getRecordList());
        // 设置是否被冻结
        bookSet.setFreezeStatus(pageBean.getRecordList());
        // 设置图书是否关联二维码
        bookSet.setIsRelationQrcodeAndCount(pageBean.getRecordList(), adviserId);
        //设置图书收益
        bookSet.setBookIncome(pageBean.getRecordList());
        // 设置二维码相关信息
        bookSet.setQrInfo(pageBean.getRecordList());
        //社群书相关信息
        bookSet.setBookGroupInfo(pageBean.getRecordList());
        return pageBean;
    }

    @ParamLog(description = "首页展示正在做的图书", isAfterReturn = false)
    @Override
    public List<BookDto> getList4Adviser(Long adviserId, Integer num, Boolean isPrint) throws BizException {
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("adviserId", adviserId);
        paramMap.put("num", num);
        paramMap.put("isPrint", isPrint);
        paramMap.put("isbns", BookConstant.DEFAULT_BOOK_ISBN);
        List<BookDto> bookDtos = bookDao.getList4Adviser(paramMap);
        if (!ListUtils.isEmpty(bookDtos)) {
            // 填充渠道基础信息
            bookSet.setChannelInfoList(Lists.newArrayList(bookDtos));
            bookSet.setBookSvUvPv4Object(Lists.newArrayList(bookDtos));
            // 填充模板信息
            bookSet.setTemplateName(Lists.newArrayList(bookDtos));
            // 设置是否被冻结
            bookSet.setFreezeStatus(Lists.newArrayList(bookDtos));
            // 设置图书是否关联二维码
            bookSet.setIsRelationQrcodeAndCount(Lists.newArrayList(bookDtos), adviserId);
            //设置图书收益
            bookSet.setBookIncome(Lists.newArrayList(bookDtos));
            // 设置二维码相关信息
            bookSet.setQrInfo(Lists.newArrayList(bookDtos));
            // 填充社群码相关信息
            bookSet.seBookGroupInfo(Lists.newArrayList(bookDtos));
        }
        return bookDtos;
    }

    /**
     * 微信端获取书籍列表(编辑)
     */
    @Override
    public PageBean getListPage4Wechat(Map<String, Object> paramMap, PageParam pageParam, Long adviserId)
            throws BizException {
        LOGGER.info("【书籍应用】微信端获取书籍列表,<START>.[paramMap]=" + paramMap);
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "getListPage4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        // 填充渠道基础信息
        bookSet.setPageDetailInfo4Wechat(pageBean.getRecordList(), adviserId);
        // 设置图书扫码量读者量浏览量
        bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
        // 填充模板信息
        bookSet.setTemplateName(pageBean.getRecordList());
        // 设置冻结状态
        bookSet.setFreezeStatus(pageBean.getRecordList());
        return pageBean;
    }

    /**
     * 获取书籍详细信息
     */
    @Override
    public BookDto getDetailById(Long bookId, Long adviserId, Long channelId) throws BizException {
        LOGGER.info("【书籍应用】获取书籍详细信息,<START>.[bookId]=" + bookId + ",[channelId]=" + channelId + ",[adviserId]="
                + adviserId);
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        if (channelId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
        }
        // 如果编辑标识为空，取配置该书籍的编辑的top1
        if (adviserId == null) {
            adviserId = bookAdviserBiz.getAdviserTop1(bookId, channelId);
        }
        // 获取书籍基本信息
        BookDto bookDto = this.getBaseById(bookId);
        if (BookTypeEnum.JOURNAL.value.equals(bookDto.getTypeCode())) {
            // 获取运营名称
            String channelName = channelConsr.getNameById(channelId);
            bookDto.setChannelName(channelName);
            bookDto.setAgentType(agentConsr.getAgentType(channelId, SystemCode.channel.code));
        }
        // 填充书籍关联的问答
        bookDto.setProducts(bookProductBiz.getQaListById(bookId, adviserId, channelId));
        return bookDto;
    }

    /**
     * 根据名称获取ID
     */
    @Override
    public List<Long> getIdsByName(String bookName) throws BizException {
        LOGGER.info("【书籍顾问】根据名称获取ID,<START>.[bookName]=" + bookName);
        if (StringUtil.isEmpty(bookName)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请输入书籍名称");
        }
        List<Long> bookIds = null;
        try {
            bookIds = bookDao.getIdsByName(bookName);
            if (bookIds == null) {
                bookIds = Lists.newArrayList();
            }
        } catch (Exception e) {
            LOGGER.error("【书籍-顾问】根据名称获取ID,<ERROR>.[getIdsByName]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        return bookIds;
    }

    /**
     * 根据名称获取ID
     */
    @Override
    public List<Long> getIdsByName(String bookName, Long adviserId) throws BizException {
        LOGGER.info("【书籍顾问】根据名称获取ID,<START>.[bookName|adviserId]=" + bookName + "|" + adviserId);
        if (StringUtil.isEmpty(bookName)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请输入书籍名称");
        }
        if (adviserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请输入编辑ID");
        }
        List<Long> bookIds = null;
        try {
            Map<String, Object> paramMap = new HashMap<String, Object>();
            paramMap.put("bookName", bookName);
            paramMap.put("adviserId", adviserId);
            bookIds = bookDao.getIdsByNameMap(paramMap);
            if (bookIds == null) {
                bookIds = Lists.newArrayList();
            }
        } catch (Exception e) {
            LOGGER.error("【书籍-顾问】根据名称获取ID,<ERROR>.[getIdsByNameMap]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        return bookIds;
    }

    /**
     * 图书收益，获取单个书籍基础信息(包含统计信息)
     */
    @Override
    public BookDto getById4Profit(Long bookId, Long adviserId, Long channelId) throws BizException {
        LOGGER.info("【图书收益】获取单个书籍基础信息(包含统计信息),<PARAM>.[bookId]=" + bookId + ",[adviserId]=" + adviserId
                + ",[channelId]=" + channelId);
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        if (channelId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
        }
        BookDto bookDto = this.getBaseById(bookId);
        if (bookDto.getBookId() == null) {
            return bookDto;
        }
        // 获取第一次扫描时间
        BookTimeSourceDto bookTimeSourceDto = sceneRecordConsr.getBookScanInfo(bookId, channelId, adviserId);
        if (bookTimeSourceDto != null) {
            bookDto.setFirstScanDate(bookTimeSourceDto.getScanTimes());
            bookDto.setFirstSceneName(bookTimeSourceDto.getSceneName());
        }
        // 设置渠道名称
        bookDto.setChannelName(channelConsr.getNameById(channelId));
        return bookDto;
    }

    /**
     * 判断isbn是否存在,存在返回书籍信息
     * @throws IOException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BookDto isbnExistsOrGetInfo(Book book) {
        LOGGER.info("【书籍基础】判断ISBN是否存在,<PARAM>.[isbn]=" + book.getIsbn());
        // 校验书号合法性
        bookSet.checkISBN(book.getTypeCode(), book.getIsbn());
        if (StringUtils.isEmpty(book.getSerialNumber())) {
            book.setSerialNumber(null);
        }
        // 获取最近书刊信息
        BookDto journalDto = bookDao.getByIsbn(book.getIsbn());
        if (BookTypeEnum.BOOK.value.equals(book.getTypeCode()) && journalDto == null) {
            try {
                // 调用外部接口查询书籍信息
                insertBook(book.getIsbn());
                journalDto = bookDao.getByIsbn(book.getIsbn());
            } catch (Exception e) {
                LOGGER.error("【书刊基础】根据ISBN获取书刊信息,<ERROR>.[getByJournIsbn]:" + e.getMessage(), e);
                throw BizException.DB_SELECT_IS_FAIL;
            }
        }

        if (null != journalDto) {
            BookDto journal = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
            if (journal != null) {
                journalDto = journal;
            }
        }

        return journalDto;
    }

    /**
     * 创建书籍顾问关联关系
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setBookAdviserRelation(Book book) throws BizException {
        BookAdviser bookAdviser = new BookAdviser();
        bookAdviser.setBookId(book.getBookId());
        bookAdviser.setAdviserId(book.getCreatedUser());
        bookAdviser.setChannelId(book.getChannelId());
        bookAdviser.setCreatedUser(book.getCreatedUser());
        bookAdviser.setSerialNumber(book.getSerialNumber());// 设置刊物序号
        bookAdviser.setTempletId(book.getTempletId());
        bookAdviser.setSecondTempletId(book.getSecondTempletId());
        bookAdviser.setThirdTempletId(book.getThirdTempletId());
        bookAdviserBiz.create(bookAdviser);
    }

    /**
     * 获取书籍基本信息
     */
    @Override
    public BookDto getBaseInfoById4Wechat(Long bookId) {
        LOGGER.info("【书籍-应用-微信】获取书籍基本信息,<START>.[bookId]=" + bookId);
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊");
        }
        // 获取书籍基本信息
        BookDto bookDto = this.getBaseById(bookId);
        bookSet.setLabelNames(Arrays.asList(bookDto));
        return bookDto;
    }

    /**
     * 根据ISBN获取期刊分页列表
     */
    @Override
    public PageBean getJournalPageByIsbn(PageParam pageParam, String typeCode, String isbn, Long channelId,
            Long wechatUserId) {
        LOGGER.info("【书籍-书刊管理-微信】根据ISBN获取期刊分页列表getJournalPageByIsbn,<START>.[isbn]=" + isbn);
        if (isbn == null || "".equals(isbn.toLowerCase().trim())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "isbn不存在!");
        }
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("typeCode", typeCode);
        paramMap.put("isbn", isbn);
        paramMap.put("channelId", channelId);
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "getJournalPage4Adviser");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean();
        }
        // 设置是否加入书架
        bookSet.setIsHaveAddBookcase(pageBean.getRecordList(), wechatUserId);
        // 设置模板名称
        bookSet.setTemplateName(pageBean.getRecordList());
        return pageBean;
    }

    /**
     * 获取书刊列表（微信客户端）
     */
    @Override
    public PageBean listPage4Wechat(PageParam pageParam, Long channelId, Long wechatUserId) {
        LOGGER.info("【书籍-书刊管理-微信】分页获取书刊列表,<START>.[channelId]=" + channelId);
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("channelId", channelId);
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listPage4Wechat");
        if (pageBean == null || pageBean.getRecordList().isEmpty()) {
            return new PageBean();
        }
        // 设置是否加入书架
        bookSet.setIsHaveAddBookcase(pageBean.getRecordList(), wechatUserId);
        // 设置图书扫码量读者量浏览量
        bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
        // 设置模板名称(图书类型)
        bookSet.setTemplateName(pageBean.getRecordList());
        return pageBean;
    }

    /**
     * 根据ISBN码获取书籍详情（包含二维码个数，应用个数，商品个数）
     */
    @Override
    public BookDto getDetailByIsbn(String isbn, String serialNumber) {
        LOGGER.info("根据ISBN码获取书籍详情（包含二维码个数，应用个数，商品个数）,isbn=" + isbn);
        Map<String, Object> paramMap = new HashMap<String, Object>();
        paramMap.put("isbn", isbn);
        paramMap.put("serialNumber", serialNumber);
        // 获取书籍基本信息
        BookDto bookDto = bookDao.getDetailByIsbn(paramMap);
        if (bookDto != null) {
            Map<String, Object> qrMap = qrcodeSceneConsr.getQr4Book(bookDto.getBookId());
            if (qrMap != null) {
                bookDto.setQrcodeCount((Integer) qrMap.get("qrCount"));
                bookDto.setLatestQrcode((String) qrMap.get("qrcodeUrl"));
            }
        }
        return bookDto;
    }

    /**
     * 获取书刊信息
     */
    @Override
    public List<Object> listBook(Long adviserId, Integer number) {
        LOGGER.info("【书籍-首页】 获取书刊信息,<START>.[adviserId]=" + adviserId + "number" + number);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        paramMap.put("number", number);
        List<Object> books = bookDao.listBy(paramMap, "listBook");
        // 填充渠道基础信息
        bookSet.setChannelInfoList(books);
        // 设置图书扫码量读者量浏览量
        bookSet.setBookSvUvPv4Object(books);
        // 设置模板名称(图书类型)
        bookSet.setTemplateName(books);
        return books;
    }

    /**
     * 获取书刊信息 app - 编辑
     */
    @Override
    public PageBean listBook4App(Long adviserId, PageParam pageParam, String bookName) {
        LOGGER.info("【书籍-首页】 获取书刊信息,<START>.[adviserId]=" + adviserId + "pageParam" + pageParam);
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        paramMap.put("bookName", bookName);
        PageBean pageBean = null;
        try {
            pageBean = bookDao.listPage(pageParam, paramMap, "listBook4App");
        } catch (Exception e) {
            LOGGER.error("【书籍-首页】获取书籍列表,<ERROR>.[listPage]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean();
        }
        // 设置模板名称(图书类型)
        bookSet.setTemplateName(pageBean.getRecordList());
        // 设置图书扫码量读者量浏览量
        bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
        // 设置基金状态
        bookSet.setFreezeStatus(pageBean.getRecordList());
        return pageBean;
    }

    /**
     * 书刊列表-出版端
     */
    @Override
    public PageBean listPage4Agent(PageParam pageParam, Map<String, Object> paramMap, Long agentId) {
        LOGGER.info("书刊列表-出版端,<START>.[paramMap]=" + paramMap + ",agentId" + agentId);
        List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, (String) paramMap.get("bookName"));
        List<Long> agent4AdviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
        paramMap.put("adviserIds", adviserIds);
        paramMap.put("agent4AdviserIds", agent4AdviserIds);
        if (ListUtils.isEmpty(agent4AdviserIds)) {
            return new PageBean(0, 0, new ArrayList<>());
        }
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listPage4Agent");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean();
        }
        // 填充渠道基础信息
        bookSet.setChannelInfoList(pageBean.getRecordList());
        // 设置编辑名称
        bookSet.setAdviserName4BookDto(pageBean.getRecordList());
        // 设置图书扫码量读者量浏览量
        bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
        // 设置冻结状态
        bookSet.setFreezeStatus(pageBean.getRecordList());
        // 设置模板名称(图书类型)
        bookSet.setTemplateName(pageBean.getRecordList());
        if (agentId.equals(getAgentIdByType())) {
            //	设置待审核二维码个数
            bookSet.setAuditWaitNum(pageBean.getRecordList());
        }
        return pageBean;
    }

    /**
     * 获取应用关联图书
     */
    @Override
    public List<BookDto> listBookByAppId(Long appId, Long channelId) {
        LOGGER.info("【编辑书刊】获取应用关联图书,<START>.[appId]=" + appId + ",[channelId]=" + channelId);
        try {
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("appId", appId);
            paramMap.put("channelId", channelId);
            return bookDao.listBookByAppId(paramMap);
        } catch (Exception e) {
            LOGGER.error("【编辑书刊】获取应用关联图书,<ERROR>.[listBookByAppId]:" + e.getMessage(), e);
            throw new BookBizException(BookBizException.DB_DML_FAIL, "获取应用关联图书失败");
        }
    }

    /**
     * 书刊回收站列表（30天内删除的书刊列表）
     */
    @Override
    public PageBean listPageDelete4Adviser(Long adviserId, PageParam pageParam) {
        LOGGER.info("【编辑书刊】书刊回收站列表,<START>.[adviserId]=" + adviserId);
        PageBean pageBean = null;
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        try {
            pageBean = bookDao.listPage(pageParam, paramMap, "listPageDelete4Adviser");
        } catch (Exception e) {
            LOGGER.error("【编辑书刊】书刊回收站列表,<ERROR>.[listPageDelete4Adviser]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        // 填充渠道基础信息
        bookSet.setChannelInfoList(pageBean.getRecordList());
        // 设置图书扫码量读者量浏览量
        bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
        // 设置图书类型
        bookSet.setTemplateName(pageBean.getRecordList());
        return pageBean;
    }

    /**
     * 获取图书关联统计个数(商品，应用，资源)
     */
    @Override
    public BookAssocCount getCount4BookAssoc(Long bookId, Long channelId, Long adviserId) {
        LOGGER.info("【编辑书刊】获取图书关联统计个数(商品，应用，资源),<START>.[bookId]=" + bookId + ",channelId=" + channelId);
        BookAssocCount bookAssocCount = new BookAssocCount();
        bookAssocCount.setResourceCount(bookResourceBiz.getResourceCount(adviserId, bookId, channelId));
        bookAssocCount.setProductCount(bookProductBiz.getProCount(adviserId, bookId, channelId));
        bookAssocCount.setSuperProCount(bookProductBiz.getSuperProCount(adviserId, bookId, channelId));
        bookAssocCount.setAppCount(bookAppBiz.getAppCount(adviserId, bookId, channelId));
        return bookAssocCount;
    }

    /**
     * 导出出版下所有书刊excel表（出版端）
     */
    @Override
    public void exportBookToExcel(Long agentId) {
        LOGGER.info("导出出版下所有书刊excel表（出版端），agentId=" + agentId);
        // 获取代理下所有编辑
        List<Long> adviserIds = adviserConsr.getByAgentId(agentId);
        if (ListUtils.isEmpty(adviserIds)) {
            throw new BookBizException(BookBizException.ERROR, "您还没有图书！");
        }
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(new Runnable() {
            public void run() {
                Date sendDate = new Date();
                try {
                    // 获取出版下所有二维码
                    Map<String, Object> param = new HashMap<String, Object>();
                    param.put("adviserIds", adviserIds);
                    // 获取默认书籍
                    BookDto book = getByIsbn("9787507600000", null);
                    if (book != null) {
                        param.put("bookId", book.getBookId());
                    }
                    // 获取图书总数除RAYS现代纸书
                    Integer count = bookDao.getAllBookCount4Agent(param);
                    List<Object[]> dataList = new ArrayList<Object[]>();
                    if (count > BookConstant.BOOK_SELECT_COUNT) {
                        for (int i = 0, titalCount = (count + BookConstant.BOOK_SELECT_COUNT - 1)
                                / BookConstant.BOOK_SELECT_COUNT; i < titalCount; i++) {
                            param.put("currentPage", i * BookConstant.BOOK_SELECT_COUNT);
                            param.put("numPerPage", BookConstant.BOOK_SELECT_COUNT);
                            List<Object> agentBook = bookDao.listBy(param, "getAllBook4Agent");
                            List<Object[]> excelData = bookSet.getExcelData(agentBook);
                            dataList.addAll(excelData);
                            agentBook.clear();
                            excelData.clear();
                        }
                    } else {
                        List<Object> agentBook = bookDao.listBy(param, "getAllBook4Agent");
                        List<Object[]> excelData = bookSet.getExcelData(agentBook);
                        dataList.addAll(excelData);
                    }
                    // 生成excel
                    String url = bookSet.createExcel(dataList);
                    if (!StringUtils.isEmpty(url)) {
                        // 发送站内信
                        bookSet.sendBookExportLetter(agentId, url, sendDate);
                    }
                } catch (Exception e) {
                    LOGGER.error("生成导出文件失败", e);
                }
            }
        });

    }

    /**
     * 根据isbn获取图书信息
     */
    @Override
    public Map<Long, BookDto> listByIsbn(String isbn) {
        LOGGER.info("根据isbn获取图书信息isbn=" + isbn);
        Map<Long, BookDto> bookMap = bookDao.listByIsbn(isbn);
        LOGGER.info("根据isbn获取图书信息END");
        return bookMap;
    }

    /**
     * 图书列表（平台端）
     */
    @Override
    public PageBean listBookClassify(PageParam pageParam, Map<String, Object> paramMap) {
        LOGGER.info("图书列表（平台端）<START>,paramMap=" + paramMap);
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "listBookClassify", "listBookClassifyCount");
        if (pageBean != null) {
            // 设置编辑名称,手机号
            bookSet.setAdviserInfo4BookDto(pageBean.getRecordList());
            // 设置图书读者量、扫码量、浏览量
            bookSet.setBookSvUvPv4Object(pageBean.getRecordList());
            // 设置书刊分类
            bookSet.setTemplateNameNew(pageBean.getRecordList());
            // 设置运营平台名称
            bookSet.setChannelInfoList(pageBean.getRecordList());
            // 设置出版社名称 避免循环调接口
            bookSet.setAgentId4BookDto(pageBean.getRecordList());
            //bookSet.setAgentName4BookDto(pageBean.getRecordList());
            // 设置图书收益
            bookSet.setBookIncome(pageBean.getRecordList());
            // 设置编辑账户信息
            bookSet.setUserLoginInfo(pageBean.getRecordList());
        } else {
            pageBean = new PageBean();
        }
        return pageBean;
    }

    @ParamLog("导出图书列表（平台端）")
    @Override
    public void exportBookClassify(Map<String, Object> paramMap) {
        Long count = bookDao.listBookClassifyCount(paramMap);
        if (count <= 0) {
            throw new BookBizException(BookBizException.ERROR, "图书列表为空！");
        }
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try {
                List<Object> list = new ArrayList<>();
                Integer cu = BookConstant.BOOK_SELECT_COUNT;
                Integer p = (count.intValue() / cu) + 1;
                for (int i = 0; i < p; i++) {
                    PageBean page = listBookClassify(new PageParam(i, cu), paramMap);
                    list.addAll(page.getRecordList());
                }
                List<Object[]> dataList = bookSet.getExcelData4Platform(list);
                String url = bookSet.createExcel(dataList);
                if (!StringUtils.isEmpty(url)) {
                    // 发送站内信
                    bookSet.sendBookExportLetter4Platform(-1L, url, new Date());
                }
            } catch (Exception e) {
                LOGGER.error("导出图书列表（平台端）生成导出文件失败", e);
            }
        });
    }

    /**
     * 导出平台下所有书刊excel表（平台端）
     */
    @Override
    public void exportBookToExcel4Platform() {

        List<Object> platformBook = bookDao.listBy(null, "getAllBook4Platform");
        if (ListUtils.isEmpty(platformBook)) {
            throw new BookBizException(BookBizException.ERROR, "您还没有图书！");
        }

        EXECUTOR_SERVICE.execute(new Runnable() {
            public void run() {
                Date sendDate = new Date();
                try {
                    // 获取出版下所有二维码
                    Map<String, Object> param = new HashMap<String, Object>();
                    // 获取默认书籍
                    BookDto book = getByIsbn("9787507600000", null);
                    if (book != null) {
                        param.put("bookId", book.getBookId());
                    }
                    // 获取图书总数除RAYS现代纸书
                    Integer count = bookDao.getAllBookCount4Platform(param);
                    List<Object[]> dataList = new ArrayList<Object[]>();
                    if (count > BookConstant.BOOK_SELECT_COUNT) {
                        for (int i = 0, titalCount = (count + BookConstant.BOOK_SELECT_COUNT - 1)
                                / BookConstant.BOOK_SELECT_COUNT; i < titalCount; i++) {
                            param.put("currentPage", i * BookConstant.BOOK_SELECT_COUNT);
                            param.put("numPerPage", BookConstant.BOOK_SELECT_COUNT);
                            List<Object> partPlatformBook = bookDao.listBy(param, "getAllBook4Platform");

                            // 设置编辑名称
                            bookSet.setAdviserName4BookDto(partPlatformBook);
                            // 设置图书读者量、扫码量、浏览量
                            bookSet.setBookSvUvPv4Object(partPlatformBook);
                            // 设置书刊分类
                            bookSet.setTemplateName(partPlatformBook);
                            // 设置运营平台名称
                            bookSet.setChannelInfoList(partPlatformBook);
                            // 设置图书收益
                            bookSet.setBookIncome(partPlatformBook);

                            List<Object[]> excelData = bookSet.getExcelData4Platform(partPlatformBook);
                            dataList.addAll(excelData);
                            partPlatformBook.clear();
                            excelData.clear();
                        }
                    } else {
                        List<Object> partPlatformBook = bookDao.listBy(param, "getAllBook4Platform");

                        // 设置编辑名称
                        bookSet.setAdviserName4BookDto(partPlatformBook);
                        // 设置图书读者量、扫码量、浏览量
                        bookSet.setBookSvUvPv4Object(partPlatformBook);
                        // 设置书刊分类
                        bookSet.setTemplateName(partPlatformBook);
                        // 设置运营平台名称
                        bookSet.setChannelInfoList(partPlatformBook);
                        // 设置图书收益
                        bookSet.setBookIncome(partPlatformBook);

                        List<Object[]> excelData = bookSet.getExcelData4Platform(partPlatformBook);
                        dataList.addAll(excelData);
                    }
                    // 生成excel
                    String url = bookSet.createExcel(dataList);
                    if (!StringUtils.isEmpty(url)) {
                        // 发送站内信
                        bookSet.sendBookExportLetter4Platform(-1L, url, sendDate);
                    }
                } catch (Exception e) {
                    LOGGER.error("生成导出文件失败", e);
                }
            }
        });

    }


    /**
     * 获取图书基本信息（编辑 - 运营 - 图书）
     */
    @Override
    public BookDto getBookById(Long adviserId, Long channelId, Long bookId) {
        LOGGER.info(
                "获取图书基本信息（编辑 - 运营 - 图书）<START>adviserId=" + adviserId + "channelId=" + channelId + "bookId=" + bookId);
        BookDto bookDto = this.getBaseById(bookId);
        if (bookDto != null) {
            // 获取图书类型
            Long templetId = bookDao.getTempletId(adviserId, channelId, bookId);
            bookDto.setTempletId(templetId);
            // 设置图书类型名称
            bookSet.setTemplateName(bookDto);
        }
        return bookDto;
    }

    /**
     * 根据ISBN获取书刊信息
     */
    @Override
    public BookDto getByIsbnAndTypeCode(String isbn, String typeCode) throws BizException {
        LOGGER.info("【书刊基础】根据ISBN获取书刊信息,<START>.[isbn]=" + isbn + "typeCode=" + typeCode);
        if (StringUtil.isEmpty(isbn)) {
            throw new AppBizException(AppBizException.PARAM_IS_NULL, "请选择书刊");
        }
        BookDto bookDto = bookDao.getByIsbn(isbn);
    /*	if (BookTypeEnum.BOOK.value.equals(typeCode) && bookDto == null) {
            // 调用外部接口查询书籍信息
			insertBook(isbn);
			bookDto = bookDao.getByIsbn(isbn);
		}*/
        return bookDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BookDto create4Adviser(Book book) {
        LOGGER.info("编辑新增图书book=" + book);
        this.checkAddParam(book);
        if (book.getChannelId() == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
        }
        if (Objects.isNull(book.getTempletId()) || Objects.isNull(book.getSecondTempletId())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊分类");
        }
        // 校验书号
        bookSet.checkISBN(book.getTypeCode(), book.getIsbn());
        BookDto bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
        if (bookDto == null) {
            // 图书不存在，新增图书
            bookDao.insert(book);
            esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        } else {
            // 图书已存在
            book.setLastModifiedUser(book.getCreatedUser());
            book.setBookId(bookDto.getBookId());
        }
        // 查看现代纸书是否存在
        final BookGroupDTO dtoByBookId = bookGroupBiz.getDTOByBookId(book.getBookId(), book.getChannelId(), book.getCreatedUser());
        // 新增图书与编辑关联关系
        createBookAdviserRelation(book);
        /*BookGroup bookGroup = null;
        if (null != book.getIsBookGroup() && book.getIsBookGroup()) {
            bookGroup = bookGroupBiz.createBookGroupAfterCreateBook(book.getBookId(), book.getChannelId(), book.getCreatedUser());
        }*/
        //插入版次记录
        insertEdition(book.getCreatedUser(), book.getEdition(), book.getBookId());
        // 图书不存在，新增图书，图书数量加1
        if (bookDto == null) {
            // 书籍总数缓存加1
            bookCache.incrObject(BookConstant.BOOK_CACHE + "PLATFORM_BOOK_COUNT");
        } else {
            // 主编辑才能修改书刊信息
            Long mainAdviserId = bookAdviserBiz.getMainAdviserId(book.getBookId(), book.getChannelId());
            if (book.getCreatedUser().equals(mainAdviserId)) {
                checkIsUpdateCoverImgAndSendTopic(bookDto, book.getCoverImg());
                checkIsUpdateBookNameAndSendTopic(bookDto, book.getBookName());
                // 修改图书基本信息
                bookDao.updateByAdviser(book);
                esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
                // 周任务书刊埋点
                mainLineConsr.sendAddBookTask(bookDto.getBookId(), book.getCreatedUser());
                // 清除redis中数据
                bookCache.clearRedisByBook(book.getBookId(), book.getIsbn(), book.getSerialNumber());
            }
        }
        bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
        bookDto.setChannelId(book.getChannelId());
        /*if (null != bookGroup) {
            bookDto.setBookGroupId(bookGroup.getId());
            bookDto.setGroupQrcodeUrl(bookGroup.getGroupQrcodeUrl());
        }*/
        // 关联社群码和社群书信息
        if (null != book.getIsBookGroup() && book.getIsBookGroup() && null != book.getBookGroupId()) {
            bookGroupBiz.linkBookGroup(book.getBookId(), book.getBookGroupId(), book.getCreatedUser());
        }
        bookDto.setIsDelete(null == dtoByBookId ? 1 : dtoByBookId.getIsDelete() ? 1 : 0);
        return bookDto;
    }


    /**
     * 修改图书与图书类型
     * @param book
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateBookAndBookType(Book book) {
        LOGGER.info("修改图书基本信息与类型book=" + book);
        this.checkParam(book);
        //获取图书基本信息
        BookDto bookDto = this.getBaseById(book.getBookId());
        checkIsUpdateCoverImgAndSendTopic(bookDto, book.getCoverImg());
        checkIsUpdateBookNameAndSendTopic(bookDto, book.getBookName());
        // 修改图书基本信息
        bookDao.updateByAdviser(book);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        // 清除redis中数据
        bookCache.clearRedisByBook(book.getBookId(), book.getIsbn(), book.getSerialNumber());
        //修改图书类型
        bookAdviserBiz.updateBookTemplet(book);
        //更新小睿分类
        bookGroupBiz.updateBookGroupRaysClassify(book);
        insertEdition(book.getLastModifiedUser(),book.getEdition(),book.getBookId());
        LOGGER.info("修改图书基本信息与类型[END]");
    }

    /**
     * 新增图书与编辑关联关系
     * @param book
     */
    void createBookAdviserRelation(Book book) {
        BookAdviser bookAdviser = new BookAdviser();
        bookAdviser.setBookId(book.getBookId());
        bookAdviser.setAdviserId(book.getCreatedUser());
        bookAdviser.setChannelId(book.getChannelId());
        bookAdviser.setCreatedUser(book.getCreatedUser());
        bookAdviser.setTempletId(book.getTempletId());
        bookAdviser.setSecondTempletId(book.getSecondTempletId());
        bookAdviser.setThirdTempletId(book.getThirdTempletId());
        bookAdviser.setSubLabelId(book.getSubLabelId());
        bookAdviser.setGraLabelId(book.getGraLabelId());
        bookAdviser.setAreaLabelId(book.getAreaLabelId());
        bookAdviser.setVerLabelId(book.getVerLabelId());
        bookAdviser.setProLabelId(book.getProLabelId());
        bookAdviser.setDepLabelId(book.getDepLabelId());
        bookAdviser.setPurLabelId(book.getPurLabelId());
        bookAdviser.setVolLabelId(book.getVolLabelId());
        if(book.getIsBookGroup()!=null&&book.getIsBookGroup()){
            bookAdviser.setIsOpenRobotProcess(1);
        }else{
            bookAdviser.setIsOpenRobotProcess(0);
        }
        bookAdviserBiz.create(bookAdviser);
        book.setBookAdviserId(bookAdviser.getBookAdviserId());
    }

    @Override
    public Boolean checkISBN4App(String isbn) {
        bookSet.checkISBNEx(BookTypeEnum.BOOK.value, isbn);
        return true;
    }

    Long getAgentIdByType() {
        Long checkAgentId = agentConsr.getAgentIdByType(AgentTypeEnum.AGENT_TYPE_WYS.getCode());
        return checkAgentId;
    }

    /**
     * 根据渠道ID分页获取图书列表
     */
    @ParamLog(description = "根据渠道ID分页获取图书列表")
    @Override
    public PageBean getBookBaseInfoListByChannelId4Adviser(Long partyId, Long channelId, PageParam pageParam, String name) throws BizException {
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("adviserId", partyId);
        paramMap.put("channelId", channelId);
        paramMap.put("name", name);
        /*paramMap.put("typeCode",BookTypeEnum.BOOK.value);*/
        PageBean pageBean = bookDao.listPage(pageParam, paramMap, "getListPage4Adviser");
        if (null == pageBean || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBean(0, 0, Lists.newArrayList());
        } else {
            // 设置模板名字
            bookSet.setTemplateName(pageBean.getRecordList());
        }
        return pageBean;
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog(description = "根据ID修改时间")
    @Override
    public void updateTimeById(Long bookId) throws BizException {
        if (null == bookId) {
            return;
        }
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        bookDao.updateTimeById(paramMap);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(bookId));
    }

    @Transactional(rollbackFor = Exception.class)
    @ParamLog(description = "批量根据ID修改时间")
    @Override
    public void updateTimeByIds(BookAdviserUpdateTimeDTO bookAdviserUpdateTimeDTO) throws BizException {
        if (ListUtils.isEmpty(bookAdviserUpdateTimeDTO.getBookIds()) && null == bookAdviserUpdateTimeDTO.getBookId()) {
            return;
        }
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("adviserId", bookAdviserUpdateTimeDTO.getAdviserId());
        paramMap.put("channelId", bookAdviserUpdateTimeDTO.getChannelId());
        if (null != bookAdviserUpdateTimeDTO.getBookId()) {
            paramMap.put("bookId", bookAdviserUpdateTimeDTO.getBookId());
        } else {
            paramMap.put("bookIds", bookAdviserUpdateTimeDTO.getBookIds());
        }
        bookDao.updateTimeByIds(paramMap);
        if (null != bookAdviserUpdateTimeDTO.getBookId()) {
            esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(bookAdviserUpdateTimeDTO.getBookId()));
        } else {
            esBookAndAdviserBiz.updateBookAndAdviserToES(bookAdviserUpdateTimeDTO.getBookIds());
        }
    }

    @ParamLog(description = "获取书刊信息")
    @Override
    public Map<String, BookInfoAnalysicsDTO> getBookInfoBy(List<BookInfoAnalysicsDTO> bookInfoAnalysicsDTOS, String
            monthDate) throws BizException {
        Map<String, BookInfoAnalysicsDTO> bookInfoAnalysicsDTOMap = null;
        if (!ListUtils.isEmpty(bookInfoAnalysicsDTOS)) {
            List<Long> bookIds = Lists.newArrayList();
            List<Long> adviserIds = Lists.newArrayList();
            List<Long> channelIds = Lists.newArrayList();
            for (BookInfoAnalysicsDTO bookInfoAnalysicsDTO : bookInfoAnalysicsDTOS) {
                bookIds.add(bookInfoAnalysicsDTO.getBookId());
                adviserIds.add(bookInfoAnalysicsDTO.getAdviserId());
                channelIds.add(bookInfoAnalysicsDTO.getChannelId());
            }
            Map<String, Object> paramMap = Maps.newHashMap();
            if (!ListUtils.isEmpty(bookIds)) {
                paramMap.put("bookIds", bookIds);
            }
            if (!ListUtils.isEmpty(adviserIds)) {
                paramMap.put("adviserIds", adviserIds);
            }
            if (!ListUtils.isEmpty(channelIds)) {
                paramMap.put("channelIds", channelIds);
            }
            if (!StringUtil.isEmpty(monthDate)) {
                paramMap.put("statisTime", monthDate);
            }
            List<BookInfoAnalysicsDTO> bookInfoAnalysicsDTOList = bookDao.getBookInfoBy(paramMap);
            if (!ListUtils.isEmpty(bookInfoAnalysicsDTOList)) {
                bookInfoAnalysicsDTOMap = Maps.newHashMap();
                for (BookInfoAnalysicsDTO bookInfoAnalysicsDTO : bookInfoAnalysicsDTOList) {
                    String key = bookInfoAnalysicsDTO.getBookId() + "_" + bookInfoAnalysicsDTO.getChannelId() + "_" + bookInfoAnalysicsDTO.getAdviserId();
                    bookInfoAnalysicsDTOMap.put(key, bookInfoAnalysicsDTO);
                }
            }
        }

        return bookInfoAnalysicsDTOMap;
    }

    @Override
    public Long getBookTempletIdId(Long adviserId, Long channelId, Long bookId) {
        // 获取图书类型
        Long templetId = bookDao.getTempletId(adviserId, channelId, bookId);
        return templetId;
    }

    @ParamLog(description = "获取书刊信息--分析引擎内部接口")
    @Override
    public Map<Long, BookInfo4AnlysicsDTO> getBookAnalysis(List<Long> bookIds, String monthDate) throws BizException {
        if (ListUtils.isEmpty(bookIds)) {
            return null;
        }
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookIds", bookIds);
        if (!StringUtil.isEmpty(monthDate)) {
            paramMap.put("monthDate", monthDate);
        }
        Map<Long, BookInfo4AnlysicsDTO> resultMap = null;
        List<BookInfo4AnlysicsDTO> bookList = bookDao.getBookAnalysis(paramMap);
        if (!ListUtils.isEmpty(bookList)) {
            resultMap = bookList.stream().collect(Collectors.toMap(BookInfo4AnlysicsDTO::getBookId, bookInfo4AnlysicsDTO -> bookInfo4AnlysicsDTO));
        }
        return resultMap;
    }

    @Override
    public PageBean getListPage4PC(PageParam pageParam, String name) throws BizException {
        Map<String, Object> paramMap = Maps.newHashMap();
        if (!StringUtil.isEmpty(name)) {
            paramMap.put("name", name);
        }
        return bookDao.listPage(pageParam, paramMap, "getBookBaseInfo");
    }

    @Override
    @ParamLog("未设置版权保护的图书")
    public PageBeanNew listNoAuthBook(ListNoAuthBookParam listNoAuthBookParam, Long adviserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        paramMap.put("isMainEditor", listNoAuthBookParam.getIsMainEditor());
        paramMap.put("isFundSupport", listNoAuthBookParam.getIsFundSupport());
        paramMap.put("channelId", listNoAuthBookParam.getChannelId());
        paramMap.put("name", listNoAuthBookParam.getName() != null && "".equals(listNoAuthBookParam.getName().trim()) ? null : listNoAuthBookParam.getName());
        paramMap.put("typeCode", listNoAuthBookParam.getTypeCode() != null && "".equals(listNoAuthBookParam.getTypeCode().trim()) ? null : listNoAuthBookParam.getTypeCode());
        paramMap.put("templetId", listNoAuthBookParam.getTempletId());
        paramMap.put("secondTempletIds", Optional.ofNullable(listNoAuthBookParam.getSecondTempletId()).map(Lists::newArrayList).orElse(Lists.newArrayList()));
        paramMap.put("thirdTempletIds", Optional.ofNullable(listNoAuthBookParam.getThirdTempletId()).map(Lists::newArrayList).orElse(Lists.newArrayList()));
        PageParam pageParam = new PageParam(listNoAuthBookParam.getCurrentPage(), listNoAuthBookParam.getNumPerPage());
        PageBeanNew pageBean = bookDao.listPageNew(pageParam, paramMap, "listNoAuthBook");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew(listNoAuthBookParam.getCurrentPage(), listNoAuthBookParam.getNumPerPage(), new ArrayList<>());
        }
        //设置类型名称
        bookSet.setTempletNames(pageBean.getRecordList());
        //设置运营平台名称
        bookSet.setChannelName(pageBean.getRecordList());
        return pageBean;
    }

    @Override
    @ParamLog("未设置版权保护的社群书")
    public PageBeanNew listNoAuthGroupBook(ListNoAuthGroupBookParam listNoAuthGroupBookParam, Long adviserId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("adviserId", adviserId);
        paramMap.put("channelId", listNoAuthGroupBookParam.getChannelId());
        paramMap.put("name", listNoAuthGroupBookParam.getName() != null && "".equals(listNoAuthGroupBookParam.getName().trim()) ? null : listNoAuthGroupBookParam.getName());
        paramMap.put("typeCode", listNoAuthGroupBookParam.getTypeCode() != null && "".equals(listNoAuthGroupBookParam.getTypeCode().trim()) ? null : listNoAuthGroupBookParam.getTypeCode());
        paramMap.put("templetId", listNoAuthGroupBookParam.getTempletId());
        paramMap.put("secondTempletIds", Optional.ofNullable(listNoAuthGroupBookParam.getSecondTempletId()).map(Lists::newArrayList).orElse(Lists.newArrayList()));
        PageParam pageParam = new PageParam(listNoAuthGroupBookParam.getCurrentPage(), listNoAuthGroupBookParam.getNumPerPage());
        PageBeanNew pageBean = bookDao.listPageNew(pageParam, paramMap, "listNoAuthGroupBook");
        if (pageBean == null || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew(listNoAuthGroupBookParam.getCurrentPage(), listNoAuthGroupBookParam.getNumPerPage(), new ArrayList<>());
        }
        //设置类型名称
        bookSet.setTempletNames(pageBean.getRecordList());
        //设置运营平台名称
        bookSet.setChannelName(pageBean.getRecordList());
        return pageBean;
    }

    @Override
    @ParamLog("获取图书基本信息与授权状态")
    public BookInfoAndAuthStatusDTO getBaseAndAuthStatus(Long bookId, Long channelId, Long adviserId) {
        BookDto book = getBaseById(bookId);
        if (book == null)
            return null;
        //获取编辑是否删除这本书
        BookAdviserDto bookAdviser = bookAdviserBiz.getBase(bookId, channelId, adviserId);
        BookInfoAndAuthStatusDTO bookInfoAndAuthStatusDTO = new BookInfoAndAuthStatusDTO();
        BeanUtils.copyProperties(book, bookInfoAndAuthStatusDTO);
        //获取授权状态
        BookAuthInfoVO infoByBook = bookAuthInfoBiz.getInfoByBook(bookId, channelId, adviserId, null);
        if (infoByBook != null) {
            BeanUtils.copyProperties(infoByBook, bookInfoAndAuthStatusDTO);
        }
        bookInfoAndAuthStatusDTO.setIsDelete(bookAdviser == null ? BookStatusEnum.BookDeleteStatus.DELETE.value : bookAdviser.getIsDelete());
        return bookInfoAndAuthStatusDTO;
    }

    @ParamLog("根据书名或ISBN编号获取书id集合")
    @Override
    public List<Long> getIdsByNameOrISBN(String keyword, Long adviserId) {
        LOGGER.info("【书籍顾问】根据书名或ISBN编号获取书id集合,<START>.[keyword|adviserId]=" + keyword + "|" + adviserId);
        if (StringUtil.isEmpty(keyword)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请输入关键词");
        }
        if (adviserId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请输入编辑ID");
        }
        List<Long> bookIds ;
        try {
            Map<String, Object> paramMap = new HashMap<String, Object>();
            paramMap.put("keyword", keyword);
            paramMap.put("adviserId", adviserId);
            bookIds = bookDao.getIdsByNameOrISBN(paramMap);
            if (bookIds == null) {
                bookIds = Lists.newArrayList();
            }
        } catch (Exception e) {
            LOGGER.error("【书籍-顾问】根据书名或ISBN编号获取书id集合,<ERROR>.[getIdsByNameOrISBN]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        return bookIds;
    }

    @Override
    public PageBeanNew<AdviserBookInfoDTO> getListPage4SelfBookGroup(Integer currentPage, Integer numPerPage, String name,Long adviserId, Long graLabelId, Long subLabelId, Long verLabelId, Long areaLabelId) {
        Map<String, Object> paramMap = new HashMap<>();
        if (!StringUtil.isEmpty(name)) {
            paramMap.put("name", name);
        }
        if (adviserId != null) {
            paramMap.put("adviserId", adviserId);
        }
        paramMap.put("joinGroupTypes", Arrays.asList(JoinGroupTypeEnum.ROBOT.getCode(),JoinGroupTypeEnum.AI_ROBOT.getCode(),
                JoinGroupTypeEnum.XIAORUI.getCode()));
        paramMap.put("graLabelId",graLabelId);
        paramMap.put("subLabelId",subLabelId);
        paramMap.put("verLabelId",verLabelId);
        paramMap.put("areaLabelId",areaLabelId);
        PageBeanNew<AdviserBookInfoDTO> pageBean = bookDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getListPage4BookGroup");
        if (null == pageBean || ListUtils.isEmpty(pageBean.getRecordList())) {
            return new PageBeanNew<>(currentPage, numPerPage, 0, new ArrayList<>());
        }
        List<AdviserBookInfoDTO> list = pageBean.getRecordList();
        List<Long> adviserIds = list.stream().filter(s -> s.getAdviserId() != null).map(AdviserBookInfoDTO::getAdviserId).distinct().collect(Collectors.toList());
        Map<Long, AdviserBaseInfoDto> adviserMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        for (AdviserBookInfoDTO dto : list) {
            if (!MapUtils.isEmpty(adviserMap) && null != dto.getAdviserId() && adviserMap.containsKey(dto.getAdviserId())) {
                AdviserBaseInfoDto adviserBaseInfoDto = adviserMap.get(dto.getAdviserId());
                if (null != adviserBaseInfoDto){
                    dto.setAdviserName(adviserBaseInfoDto.getPartyName());
                    dto.setAgentName(adviserBaseInfoDto.getAgentName());
                }
            }
        }
        return pageBean;
    }

    @ParamLog("获取书籍标签")
    @Override
    public Map<Integer, List<BookLabel>> getBookLabels(Long partyId) {
        Map<Integer, List<BookLabel>> map = new HashMap<>();
        String key = BookConstant.BOOK_LABEL_CACHE;
        List<BookLabel> bookLabels = JedisClusterUtils.hgetJson2List(key, partyId.toString(), BookLabel.class);
        if (ListUtils.isEmpty(bookLabels)){
            bookLabels = bookLabelDao.getAll(partyId);
            JedisClusterUtils.hset2Json(key, partyId.toString(), bookLabels);
            JedisClusterUtils.expire(key, 24*3600);
        }
        if (!ListUtils.isEmpty(bookLabels)) {
            map = bookLabels.stream().collect(Collectors.groupingBy(BookLabel::getType));
        }
        return map;
    }

    @ParamLog("书刊收益列表--出版端")
    @Override
    public PageBeanNew<BookSaleVO> listPageIncomeDetail(PageParam pageParam, Map<String, Object> paramMap, Long agentId) {
        List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, (String) paramMap.get("keyWord"));
        List<Long> agent4AdviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
        paramMap.put("adviserIds", adviserIds);
        paramMap.put("agent4AdviserIds", agent4AdviserIds);
        if (ListUtils.isEmpty(agent4AdviserIds)) {
            return new PageBeanNew<>(0, 0, new ArrayList<>());
        }
        PageBeanNew<BookSaleVO> pageNew = bookDao.listPageNew(pageParam, paramMap, "listIncomePage4Agent");
        //填充收益
        bookSet.setAgentSalesInfo(pageNew.getRecordList(),agentId);
        return pageNew;
    }

    /**
     * 时代大屏用
     */
    @Override
    public PageBeanNew<BookSaleVO> listPageIncomeDetail4Times(PageParam pageParam, Map<String, Object> paramMap, Long agentId) {
        List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, (String) paramMap.get("keyWord"));
        List<Long> agent4AdviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
        paramMap.put("adviserIds", adviserIds);
        paramMap.put("agent4AdviserIds", agent4AdviserIds);
        if (ListUtils.isEmpty(agent4AdviserIds)) {
            return new PageBeanNew<>(0, 0, new ArrayList<>());
        }
        PageBeanNew<BookSaleVO> pageNew = bookDao.listPageNew(pageParam, paramMap, "listIncomePage4Agent");
        //填充收益
        bookSet.setAgentSalesInfo4Times(pageNew.getRecordList(),agentId);
        return pageNew;
    }

    /**
     * 导出书刊收益--时代大屏用
     */
    @Override
    public  Map<String,Object> exportBookIncomeDetail4Times(Map<String, Object> paramMap, Long agentId) {
        //导出数据
        if (paramMap == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
        }
        List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, (String) paramMap.get("keyWord"));
        List<Long> agent4AdviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
        paramMap.put("adviserIds", adviserIds);
        paramMap.put("agent4AdviserIds", agent4AdviserIds);
        Long count = bookDao.countIncomePage4Agent(paramMap);
        if(count>1500){
            throw new ExportException(ExportException.OPERATE_ERROR, "数量超过限制，请添加条件再导出！");
        }
        Map<String,Object> map=new HashMap<>();
        try{
            List<BookSaleVO> list = new ArrayList<>();
            Integer cu = 100;
            Integer p = (count.intValue() / cu) + 1;
            for (int i = 0; i < p; i++) {
                PageBeanNew<BookSaleVO> pageBeanNew=listPageIncomeDetail(new PageParam(i,cu), paramMap, agentId);
                List<BookSaleVO> bookSaleVOS=pageBeanNew.getRecordList();
                list.addAll(bookSaleVOS);
            }
            List<Object[]> dataList = new ArrayList<>();
            for (int i = 0, size = list.size(); i < size; i++) {
                BookSaleVO bookSaleVO = list.get(i);
                Object[] obj = new Object[9];
                obj[0] = i + 1;
                obj[1] = bookSaleVO.getBookName();
                obj[2] = bookSaleVO.getIsbn();
                if (bookSaleVO.getIsFundSupport()==true){
                    obj[3] = "是";
                }else{
                    obj[3] = "否";
                }
                obj[4] = bookSaleVO.getAdviserName();
                obj[5] = bookSaleVO.getChannelName();
                if (bookSaleVO.getAgentBookIncomeDTO()!=null){
                    obj[6] = bookSaleVO.getAgentBookIncomeDTO().getBookIncome();
                    obj[7] = bookSaleVO.getAgentBookIncomeDTO().getAdviserIncome();
                    obj[8] = bookSaleVO.getAgentBookIncomeDTO().getAgentIncome();
                }
                dataList.add(obj);
            }
            Date date = new Date();
            String[] rowsName = {"序号", "书刊名称", "书刊号", "是否基金书", "主编辑", "运营平台", "销售总额", "编辑收益", "出版社收益"};
            String fileName = "书刊收益统计--" + DateUtils.getStrFormTime("yyyyMMdd", date);
            String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
            map.put("fileName",fileName);
            map.put("fileUrl",fileUrl);
        }catch (Exception e) {
            LOGGER.error("exportBookIncomeDetail+++paramMap=" + paramMap.toString());
        }
        return map;
    }

    @ParamLog("导出书刊收益导出--出版端")
    @Override
    public void exportBookIncomeDetail(Map<String, Object> paramMap, Long agentId, Long partyId, String systemCode) {
        //导出数据
        if (paramMap == null) {
            throw new BookBizException(BookBizException.PARAM_IS_ERROR, "参数错误！");
        }
        List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, (String) paramMap.get("keyWord"));
        List<Long> agent4AdviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
        paramMap.put("adviserIds", adviserIds);
        paramMap.put("agent4AdviserIds", agent4AdviserIds);
        Long count = bookDao.countIncomePage4Agent(paramMap);
        if(count>1500){
            throw new ExportException(ExportException.OPERATE_ERROR, "数量超过限制，请添加条件再导出！");
        }
        ThreadPoolUtils.EXPORT_THREAD_POOL.execute(() -> {
            try{
                List<BookSaleVO> list = new ArrayList<>();
                Integer cu = 100;
                Integer p = (count.intValue() / cu) + 1;
                for (int i = 0; i < p; i++) {
                    PageBeanNew<BookSaleVO> pageBeanNew=listPageIncomeDetail(new PageParam(i,cu), paramMap, agentId);
                    List<BookSaleVO> bookSaleVOS=pageBeanNew.getRecordList();
                    list.addAll(bookSaleVOS);
                }
                List<Object[]> dataList = new ArrayList<>();
                for (int i = 0, size = list.size(); i < size; i++) {
                    BookSaleVO bookSaleVO = list.get(i);
                    Object[] obj = new Object[9];
                    obj[0] = i + 1;
                    obj[1] = bookSaleVO.getBookName();
                    obj[2] = bookSaleVO.getIsbn();
                    if (bookSaleVO.getIsFundSupport()==true){
                        obj[3] = "是";
                    }else{
                        obj[3] = "否";
                    }
                    obj[4] = bookSaleVO.getAdviserName();
                    obj[5] = bookSaleVO.getChannelName();
                    if (bookSaleVO.getAgentBookIncomeDTO()!=null){
                        obj[6] = bookSaleVO.getAgentBookIncomeDTO().getBookIncome();
                        obj[7] = bookSaleVO.getAgentBookIncomeDTO().getAdviserIncome();
                        obj[8] = bookSaleVO.getAgentBookIncomeDTO().getAgentIncome();
                    }
                    dataList.add(obj);
                }
                Date date = new Date();
                String[] rowsName = {"序号", "书刊名称", "书刊号", "是否基金书", "主编辑", "运营平台", "销售总额", "编辑收益", "出版社收益"};
                String fileName = "书刊收益统计--" + DateUtils.getStrFormTime("yyyyMMdd", date);
                String fileUrl = exportConsr.exportExcel(fileName, rowsName, dataList);
                String letterType = "book_download";
                String content = String.format("{\"commitTime\":\"%s\",\"type\":\"%s\"}", DateUtils.formatDate(date), fileName);
                messageConsr.sendLetter(partyId, partyId, content, systemCode, letterType, fileUrl, fileName);
            }catch (Exception e) {
                LOGGER.error("exportBookIncomeDetail+++paramMap=" + paramMap.toString() + "systemCode=" + systemCode + "partyId=" + partyId);
            }
        });
    }

    @ParamLog("根据书名模糊匹配，获得所有book_id")
    @Override
    public List<Long> getBookIdsByBookName(String bookName) {
        LOGGER.info("根据书名模糊匹配，获得所有book_id,<START>.[bookName]=" + bookName);
        if (StringUtil.isEmpty(bookName)) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请输入书名");
        }
        List<Long> bookIds;
        try {
            bookIds = bookDao.getBookIdsByBookName(bookName);
            if (bookIds == null) {
                bookIds = Lists.newArrayList();
            }
        } catch (Exception e) {
            LOGGER.error("根据书名模糊匹配，获得所有book_id,<ERROR>.[getBookIdsByBookName]:" + e.getMessage(), e);
            throw BizException.DB_SELECT_IS_FAIL;
        }
        return bookIds;
    }

    @ParamLog("平台端获取编辑书刊")
    @Override
    public PageBeanNew<BookDto> getAdviserBooks4Pcloud(String keyword, Long agentId, Long templetId, Long secondTempletId, Long thirdTempletId, String typeCode, Integer currentPage, Integer numPerPage) {
        String redisKey=BookConstant.ADVISER_BOOK_CACHE + "_" + keyword + "_" + agentId + "_" + templetId
                + "_" + secondTempletId + "_" + typeCode + "_" + currentPage + "_" + numPerPage;
        String data = JedisClusterUtils.get(redisKey);
        //加缓存
        if(StringUtil.isNotBlank(data)){
            PageBeanNew pageBeanNew = JSONObject.parseObject(data, PageBeanNew.class);
            if(null!=pageBeanNew) {
                return pageBeanNew;
            }
        }
        Map<String,Object> map=new HashMap<>();
        map.put("keyword",keyword);
        map.put("templetId",templetId);
        map.put("secondTempletId",secondTempletId);
        map.put("thirdTempletId",thirdTempletId);
        map.put("typeCode",typeCode);
        if (agentId != null){
            List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
            if (ListUtils.isEmpty(adviserIds)){
                map.put("adviserIds",Arrays.asList(-1L));
            }else {
                map.put("adviserIds",adviserIds);
            }
        }
        if(!StringUtil.isEmpty(keyword)) {
            // 模糊匹配编辑名称
            List<Long> adviserIds = adviserConsr.getAdviserIdsByName(keyword);
            map.put("adviserIds4Name", adviserIds);
        }
        PageBeanNew<BookDto> page = bookDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getAdviserBooks4Pcloud", "getAdviserBooksCount4Pcloud");
        fillBookInfo(page.getRecordList());
        if(!ListUtils.isEmpty(page.getRecordList())) {
            JedisClusterUtils.set(redisKey, JSONObject.toJSONString(page), 3600);
        }
        return page;
    }

    @ParamLog("获取编辑书刊H5")
    @Override
    public PageBeanNew<BookDto> getAdviserBooks4H5(String grayStatus, String keyword, Long templetId, Long secondTempletId,
                                                   Long thirdTempletId, Integer currentPage, Integer numPerPage) {
        Page<ESBookAndAdviser> esPage = esBookAndAdviserBiz.getAdviserBooks4ES(StringUtils.isEmpty(grayStatus) ? "0" : grayStatus,keyword
                , templetId, secondTempletId, thirdTempletId, currentPage, numPerPage);
        List<ESBookAndAdviser> esBookAndAdvisers=esPage.getContent();
        if (ListUtils.isEmpty(esBookAndAdvisers)){
            return new PageBeanNew<>();
        }
        List<BookDto> bookDtos=changeToBookDto(esBookAndAdvisers);
        fillOtherBookInfo(bookDtos);
        fillBookInfo(bookDtos);
        PageBeanNew<BookDto> page=new PageBeanNew<>(currentPage,numPerPage,(int)esPage.getTotalElements(),bookDtos);
        return page;
    }

    @ParamLog("转化为bookDto")
    private List<BookDto> changeToBookDto(List<ESBookAndAdviser> esBookAndAdvisers) {
        List<BookDto> bookDtos=new ArrayList<>();
        for (ESBookAndAdviser esBookAndAdviser:esBookAndAdvisers){
            BookDto bookDto=new BookDto();
            BeanUtils.copyProperties(esBookAndAdviser, bookDto);
            bookDto.setBookId(esBookAndAdviser.getBookId()==null?null:new Long(esBookAndAdviser.getBookId()));
            bookDto.setBookAdviserId(esBookAndAdviser.getBookAdviserId()==null?null:new Long(esBookAndAdviser.getBookAdviserId()));
            bookDto.setAdviserId(esBookAndAdviser.getAdviserId()==null?null:new Long(esBookAndAdviser.getAdviserId()));
            bookDto.setChannelId(esBookAndAdviser.getChannelId()==null?null:new Long(esBookAndAdviser.getChannelId()));
            bookDto.setTempletId(esBookAndAdviser.getTempletId()==null?null:new Long(esBookAndAdviser.getTempletId()));
            bookDto.setSecondTempletId(esBookAndAdviser.getSecondTempletId()==null?null:new Long(esBookAndAdviser.getSecondTempletId()));
            bookDto.setIsMainEditor(esBookAndAdviser.getIsMainEditor());
            bookDto.setTypeCode(esBookAndAdviser.getTypeCode());
            bookDto.setIsbn(esBookAndAdviser.getIsbn());
            bookDto.setBookName(esBookAndAdviser.getBookName());
            bookDto.setLastModifiedDate(esBookAndAdviser.getLastModifiedDate());
            bookDto.setGraLabelId(esBookAndAdviser.getGraLabelId());
            bookDto.setSubLabelId(esBookAndAdviser.getSubLabelId());
            bookDto.setAreaLabelId(esBookAndAdviser.getAreaLabelId());
            bookDto.setVerLabelId(esBookAndAdviser.getVerLabelId());
            bookDto.setRightsSettingId(esBookAndAdviser.getRightsSettingId());
            if (null != esBookAndAdviser.getHasAnswer() && esBookAndAdviser.getHasAnswer()==1) {
                bookDto.setHasAnswer(true);
            } else {
                bookDto.setHasAnswer(false);
            }
            bookDtos.add(bookDto);
        }
        return bookDtos;
    }

    private void fillOtherBookInfo(List<BookDto> bookDtos) {
        if (ListUtils.isEmpty(bookDtos)){
            return;
        }
        List<Long> bookIds=bookDtos.stream().filter(s->s.getBookId()!=null).map(BookDto::getBookId).distinct().collect(Collectors.toList());
        Map<Long, BookDto> bookDtoMap = bookDao.getMapByBookIds(bookIds);
        for (BookDto dto:bookDtos){
            BookDto bookDto=bookDtoMap.get(dto.getBookId());
            if (bookDto==null){
                continue;
            }
            dto.setRemark(bookDto.getRemark());
            dto.setAuthor(bookDto.getAuthor());
            dto.setPublish(bookDto.getPublish());
            dto.setPublishDate(bookDto.getPublishDate());
            dto.setCoverImg(bookDto.getCoverImg());
            dto.setOriginName(bookDto.getOriginName());
            dto.setBookPrice(bookDto.getBookPrice());
            dto.setIssn(bookDto.getIssn());
            dto.setSerialNumber(bookDto.getSerialNumber());
            dto.setTypeName(bookDto.getTypeName());
            dto.setUniqueNumber("BK"+dto.getBookId());
        }

    }

    @Override
    public PageBeanNew<BookDto> getBookAndServeList4Channel(Integer currentPage, Integer numPerPage, Long channelId,String name,
            Integer isFundSupport, String startDate, String endDate) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("channelId", channelId);
        paramMap.put("name", name);
        paramMap.put("startDate", startDate);
        paramMap.put("endDate", endDate);
        paramMap.put("isFundSupport", isFundSupport);
        PageBeanNew<BookDto> pageBeanNew = bookDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getBookAndServeList4Channel");
        if (null==pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())){
            return new PageBeanNew<>(currentPage,numPerPage,0,new ArrayList<>());
        }
        List<BookDto> bookDtos = pageBeanNew.getRecordList();
        List<Long> adviserIds = bookDtos.stream().filter(s->s.getAdviserId()!=null).map(BookDto::getAdviserId).distinct().collect(Collectors.toList());
        Map<Long, String> nameMap = adviserConsr.getNames(adviserIds);
        for (BookDto bookDto : bookDtos){
            if (!MapUtils.isEmpty(nameMap) && nameMap.containsKey(bookDto.getAdviserId())){
                bookDto.setAdviserName(nameMap.get(bookDto.getAdviserId()));
            }
            BookServeParamVO bookServeParamVO = new BookServeParamVO();
            bookServeParamVO.setChannelId(channelId);
            bookServeParamVO.setAdviserId(bookDto.getAdviserId());
            bookServeParamVO.setBookId(bookDto.getBookId());
            List<BookServeVO> bookServeVOS = qrcodeSceneConsr.listBookServe(bookServeParamVO);
            List<Object> objects = new ArrayList<>();
            objects.addAll(bookServeVOS);
            bookDto.setResourceFiles(objects);
            bookDto.setResourceCount(bookServeVOS.size());
        }
        return pageBeanNew;
    }

    @ParamLog("获取书刊")
    @Override
    public BookDto getAdviserBook(Long bookId, Long adviserId, Long channelId, Long sceneId) {
        if (bookId==null && null==sceneId){
            throw new BookBizException(BookBizException.PARAM_IS_NULL,"参数有误");
        }
        if (null != sceneId) {
            QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(sceneId);
            if (null != qrcodeSceneDto) {
                bookId = qrcodeSceneDto.getAdviserBookId();
                channelId = qrcodeSceneDto.getChannelPartyId();
                adviserId = qrcodeSceneDto.getCreatedByUserLogin();
            }
        }
        if (adviserId==null||channelId==null||adviserId<=0||channelId<=0){
            return bookDao.getBaseById(bookId);
        }
        Map<String, Object> paramMap = Maps.newHashMap();
        paramMap.put("bookId", bookId);
        paramMap.put("adviserId", adviserId);
        paramMap.put("channelId", channelId);
        BookDto bookDto = bookDao.getById(paramMap);
        if (bookDto == null) {
            return new BookDto();
        }
        Integer joinGroupType = bookGroupDao.getJoinGroupType(paramMap);
        if(null!=joinGroupType && JoinGroupTypeEnum.XIAORUI.getCode().equals(joinGroupType)){
            Long classifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(bookDto.getTempletId());
            bookDto.setClassifyId(null!=classifyId ? classifyId.intValue():null);
        }
        //	设置模板名字
        List<Long> templetIds = new ArrayList<>();
        if(bookDto.getTempletId()!=null) {
            templetIds.add(bookDto.getTempletId());
        }
        if(bookDto.getSecondTempletId()!=null) {
            templetIds.add(bookDto.getSecondTempletId());
        }
        if(bookDto.getThirdTempletId()!=null) {
            templetIds.add(bookDto.getThirdTempletId());
        }
        Map<Long, AssistTempletDTO> assistTempletDTOMap = assistTempletConsr.mapByIds(templetIds);
        Long thirdTempletId = bookDto.getThirdTempletId();
        Long secondTempletId = bookDto.getSecondTempletId();
        Long templetId = bookDto.getTempletId();
        if (thirdTempletId != null && assistTempletDTOMap != null) {
            AssistTempletDTO templetDTO = assistTempletDTOMap.get(thirdTempletId);
            bookDto.setThirdTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
        }
        if (secondTempletId!=null&&assistTempletDTOMap!=null) {
            AssistTempletDTO templetDTO = assistTempletDTOMap.get(secondTempletId);
            bookDto.setSecondTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
        }
        if (templetId!=null&&assistTempletDTOMap!=null) {
            AssistTempletDTO templetDTO = assistTempletDTOMap.get(templetId);
            bookDto.setTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
        }
        return bookDto;
    }

    @ParamLog("填充书刊信息")
    private void fillBookInfo(List<BookDto> list) {
        if (ListUtils.isEmpty(list)){
            return;
        }
        //填充出版社信息
        List<Long> adviserIds=list.stream().filter(s->s.getAdviserId()!=null).map(BookDto::getAdviserId).distinct().collect(Collectors.toList());
        Map<Long, AdviserBaseInfoDto> infoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        List<Long> templetIds = new ArrayList<>();
        list.forEach(BookDto -> {
            if (Objects.nonNull(BookDto.getTempletId())) {
                templetIds.add(BookDto.getTempletId());
            }
            if (Objects.nonNull(BookDto.getSecondTempletId())) {
                templetIds.add(BookDto.getSecondTempletId());
            }
            if (Objects.nonNull(BookDto.getThirdTempletId())) {
                templetIds.add(BookDto.getThirdTempletId());
            }
        });
        Map<Long, AssistTempletDTO> assistTempletDTOMap = assistTempletConsr.mapByIds4Classify(templetIds);
        list.forEach(bookDto -> {
            Long thirdTempletId = bookDto.getThirdTempletId();
            Long secondTempletId = bookDto.getSecondTempletId();
            Long templetId = bookDto.getTempletId();
            if (secondTempletId!=null&&assistTempletDTOMap!=null) {
                AssistTempletDTO templetDTO = assistTempletDTOMap.get(secondTempletId);
                bookDto.setSecondTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
            }
            if (templetId!=null&&assistTempletDTOMap!=null) {
                AssistTempletDTO templetDTO = assistTempletDTOMap.get(templetId);
                bookDto.setTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
            }
            if (thirdTempletId!=null&&assistTempletDTOMap!=null) {
                AssistTempletDTO templetDTO = assistTempletDTOMap.get(thirdTempletId);
                bookDto.setThirdTempletName(Optional.ofNullable(templetDTO).map(AssistTempletDTO::getTempletName).orElse(null));
            }
            Long adviserId=bookDto.getAdviserId();
            if (infoDtoMap!=null){
                AdviserBaseInfoDto infoDto = infoDtoMap.get(adviserId);
                if (infoDto!=null){
                    bookDto.setAgentId(infoDto.getAgentId());
                    bookDto.setAgentName(infoDto.getAgentName());
                    bookDto.setAdviserName(infoDto.getPartyName());
                }
            }
        });
    }

    @Override
    public List<Long> getBookIdsByIsbn(String isbn) {
        return bookDao.getBookIdsByIsbn(isbn);
    }

    @Override
    public void updateBookQualifyInfo(BookQualifyInfoVO bookQualifyInfo, Long adviserId) {
        Map<String,Object> map=new HashMap<>();
        map.put("bookIds",bookQualifyInfo.getBookIds());
        map.put("adviserId",adviserId);
        map.put("isShowQualifyInfo",bookQualifyInfo.getIsShowQualifyInfo());
        bookDao.updateBookQualifyInfo(map);
    }

    @Override
    public PageBeanNew<BookQualifyVO> getAddBookQualifyList(Integer currentPage, Integer numPerPage, String name, Integer isShowQualifyInfo,Long adviserId) {
        Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("isShowQualifyInfo", isShowQualifyInfo);
            paramMap.put("name", name);
            paramMap.put("adviserId", adviserId);
            PageBeanNew<BookQualifyVO> pageBeanNew = bookDao.listPageNew(new PageParam(currentPage, numPerPage), paramMap, "getAddBookQualifyList");
            if (null==pageBeanNew || ListUtils.isEmpty(pageBeanNew.getRecordList())){
                return new PageBeanNew<>(currentPage,numPerPage,0,new ArrayList<>());
            }
        return pageBeanNew;
    }

    @Override
    public SearchBookVO getBookInfoByBookGroupId(Long bookGroupId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("bookGroupId", bookGroupId);
        SearchBookVO bookVO=bookDao.getBookInfoByBookGroupId(paramMap);
        if(bookVO!=null) {
            //通过agentId查找出版社名称
            List<Long> agentIds = new ArrayList<>();
            agentIds.add(bookVO.getAgentId());
            Map<Long, String> names = agentConsr.getNames(agentIds);
            String name = names.get(bookVO.getAgentId());
            bookVO.setAgentName(name);
            //通过编辑id查找编辑名称
            List<Long> adviserIds = new ArrayList<>();
            adviserIds.add(bookVO.getAdviserId());
            Map<Long, String> map = adviserConsr.getNames(adviserIds);
            String adviserName = map.get(bookVO.getAdviserId());
            bookVO.setAdviserName(adviserName);
        }
        return bookVO;
    }

    @Override
    public void updateIsOpenRobotProcess(Long adviserId, UpdateBookRobotProcessDto robotProcessDto) {
        Map<String,Object> map=new HashMap<>();
        map.put("bookId",robotProcessDto.getBookId());
        map.put("adviserId",adviserId);
        map.put("isOpenRobotProcess",robotProcessDto.getIsOpenRobotProcess());
        bookDao.updateIsOpenRobotProcess(map);
    }

    @Override
    public void updateIsOpenRobotProcess4Now(Long adviserId, UpdateBookRobotProcessDto robotProcessDto) {
        Map<String,Object> map=new HashMap<>();
        map.put("bookId",robotProcessDto.getBookId());
        map.put("adviserId",adviserId);
        map.put("isOpenRobotProcess",robotProcessDto.getIsOpenRobotProcess());
        bookDao.updateIsOpenRobotProcess(map);
        //根据channelId和bookId获取书下面所有自建码，在根据自建码的senceId创建小程序二维码
        List<Long> sceneIds=qrcodeSceneConsr.getAliQrByBookId(robotProcessDto.getBookId());
        if(!ListUtils.isEmpty(sceneIds)) {
            createBookGroupAppletUrl(robotProcessDto.getBookId(), robotProcessDto.getChannelId(), adviserId, sceneIds);
        }

    }

    @Override
    public PageBeanNew<BookDto> getAdviserBooks4Rights(String keyword, Long agentId, Long templetId, Long secondTempletId, String typeCode,
                                                       Integer currentPage, Integer numPerPage, Integer isIgnore, Long thirdTempletId) {
        Map<String,Object> map=new HashMap<>();
        map.put("keyword",keyword);
        map.put("templetId",templetId);
        map.put("secondTempletId",secondTempletId);
        map.put("thirdTempletId", thirdTempletId);
        map.put("typeCode",typeCode);
        if (agentId != null){
            List<Long> adviserIds = adviserConsr.getIdsByNameAndAgentId(agentId, null);
            if (ListUtils.isEmpty(adviserIds)){
                map.put("adviserIds", Collections.singletonList(-1L));
            }else {
                map.put("adviserIds",adviserIds);
            }
        }
        if(!StringUtil.isEmpty(keyword)) {
            // 模糊匹配编辑名称
            List<Long> adviserIds = adviserConsr.getAdviserIdsByName(keyword);
            map.put("adviserIds4Name", adviserIds);
        }
        //获取已被权益选择的书刊
        if ((null == isIgnore) || YesOrNoEnums.NO.getValue().equals(isIgnore)) {
            List<Long> bookIds = rightsSettingBookRelationMapper.getAllBookIds();
            if (!ListUtils.isEmpty(bookIds)){
                map.put("ignoreBookIds", bookIds);
            }
        }
        PageBeanNew<BookDto> page = bookDao.listPageNew(new PageParam(currentPage, numPerPage), map, "getAdviserBooks4Rights");
        fillBookInfo(page.getRecordList());
        bookSet.setProDepPurLabelNames(page.getRecordList());
        bookSet.setLabelNames(page.getRecordList());
        return page;
    }

    @Override
    public void createBookGroupAppletUrl(Long bookId, Long channelId, Long adviserId,List<Long> sceneIds){
        BookAdviserDto bookAdviserDto = bookAdviserDao.getBase(bookId,channelId,adviserId);
        Long raysClassifyId = bookRaysClassifyDao.getClassifyIdByBookTemplateId(bookAdviserDto.getTempletId());
        String page=null;//小程序跳转页 todo
        List<BookAppletScene> list=new ArrayList<>();
        Long accoutnSettingId = bookGroupBiz.getAccountSettingByAdviser(adviserId);
        for (Long sceneId:sceneIds){
            //通过sceneId查询是否已经存在，如果已经存在就不创建
            BookAppletScene appletScene = bookAppletSceneDao.getBySceneId(sceneId);
            if(appletScene!=null){
                continue;
            }
            String appletId = createOneAppletId();
            BookAppletScene applet = bookAppletSceneDao.getByAppletId(appletId);
            while (null != applet) {
                appletId = createOneAppletId();
                applet = bookAppletSceneDao.getByAppletId(appletId);
            }
            //直接跳小程序，不创建小程序码
//            String url = wechatConsr.create4MiniApp(accoutnSettingId, appletId, null, page);
            BookAppletScene bookAppletScene = new BookAppletScene();
            bookAppletScene.setRaysClassifyId(raysClassifyId);
            bookAppletScene.setAppletId(appletId);
            bookAppletScene.setAppletUrl(null);
            bookAppletScene.setSceneId(sceneId);
            bookAppletScene.setAccountSettingId(accoutnSettingId);
            list.add(bookAppletScene);
        }
        bookAppletSceneDao.insert(list);

    }

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

    @Override
    public PageBeanNew<BookDto> getAdviserBooks4Applet(BookSearchParamVO bookSearchParamVO) {
        List<Long> templetIds = new ArrayList<>();
        if (null != bookSearchParamVO.getBookClassifyId()) {
            templetIds = appletBookClassifyBiz.getRelationBookTempletByBookClassify(bookSearchParamVO.getBookClassifyId());
        }
        List<Long> graLabelIds = new ArrayList<>();
        List<Long> subLabelIds = new ArrayList<>();
        List<Long> scecondTempletIds = new ArrayList<>();
        if (!ListUtils.isEmpty(bookSearchParamVO.getAppletUserLabelIdList())) {
            Long appletUserLabelId = bookSearchParamVO.getAppletUserLabelIdList().get(0);//先支持一个标签
            List<AppletUserLabelRelation> relations = appletBookClassifyBiz.getByAppletUserLabelId(appletUserLabelId);
            if (!ListUtils.isEmpty(relations)) {
                for (AppletUserLabelRelation relation : relations) {
                    if (relation.getLabelType().equals(LabelTypeEnum.grade_label.code)) {
                        graLabelIds.add(relation.getBookLabelId());
                    } else if (relation.getLabelType().equals(LabelTypeEnum.subject_label.code)) {
                        subLabelIds.add(relation.getBookLabelId());
                    } else if (relation.getLabelType().equals(LabelTypeEnum.sceond_templet.code)){
                        scecondTempletIds.add(relation.getBookLabelId());
                    }
                }
            }
        }
        String grayStatus = StringUtils.isEmpty(bookSearchParamVO.getGrayStatus()) ? "0" : bookSearchParamVO.getGrayStatus();
        String keyword = bookSearchParamVO.getKeyword();
        Integer currentPage = bookSearchParamVO.getCurrentPage();
        Integer numPerPage = bookSearchParamVO.getNumPerPage();
        Integer  isAdviserBook = bookSearchParamVO.getIsAdviserBook();
        Long  agentId = bookSearchParamVO.getAgentId();
        List<Long> adviserIds = new ArrayList<>();
        if (null != agentId) {
           adviserIds = adviserConsr.getByAgentId(agentId);
        }
        Page<ESBookAndAdviser> esPage = esBookAndAdviserBiz.getESAdviserBooks4Applet(grayStatus, keyword, templetIds, graLabelIds, subLabelIds,
                currentPage, numPerPage,scecondTempletIds, isAdviserBook, adviserIds, agentId);
        List<ESBookAndAdviser> esBookAndAdvisers = esPage.getContent();
        if (ListUtils.isEmpty(esBookAndAdvisers)) {
            return new PageBeanNew<>(currentPage,numPerPage,0,new ArrayList<>());
        }
        List<BookDto> bookDtos = changeToBookDto(esBookAndAdvisers);
        fillOtherBookInfo(bookDtos);
        fillBookInfo(bookDtos);
        bookSet.setProDepPurLabelNames(bookDtos);
        bookSet.setLabelNames(bookDtos);
        //丢书流程填充出版社店铺信息
        if (null != isAdviserBook) {
            fillAgentSale(bookDtos);
        }
        PageBeanNew<BookDto> page = new PageBeanNew<>(currentPage, numPerPage, (int) esPage.getTotalElements(), bookDtos);
        return page;
    }

    @Override
    public void fillAgentSale(List<BookDto> bookDtos) {
        if (ListUtils.isEmpty(bookDtos)) {
            return;
        }
        List<Long> agentIds = bookDtos.stream().map(e -> e.getAgentId()).collect(Collectors.toList());
        if (ListUtils.isEmpty(agentIds)) {
            return;
        }
        Map<Long, SaleAgentDTO> saleAgentDTOMap = agentConsr.getSaleAgentMap(agentIds);
        if (MapUtils.isEmpty(saleAgentDTOMap)) {
            return;
        }
        //填充出版社商铺信息
        bookDtos.forEach(bookDto -> {
            Long agentId = bookDto.getAgentId();
            SaleAgentDTO saleAgentDTO = saleAgentDTOMap.get(agentId);
            if (null != agentId && null != saleAgentDTO) {
                BeanUtils.copyProperties(saleAgentDTO, bookDto,"id","agentName");
            }
        });
    }

    @ParamLog("获取书籍标签")
    @Override
    public Map<Integer, List<BookLabel>> getBookLabels4Erp() {
        Map<Integer, List<BookLabel>> map = new HashMap<>();
        List<BookLabel> bookLabels = bookLabelDao.getAll(0L);
        if (!ListUtils.isEmpty(bookLabels)) {
            map = bookLabels.stream().collect(Collectors.groupingBy(BookLabel::getType));
        }
        return map;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void relateUniqueNumber4Erp(List<BookUniqueNumberDTO> bookUniqueNumberVos) {
        if(ListUtils.isEmpty(bookUniqueNumberVos)){
            return;
        }
        bookDao.relateUniqueNumber4Erp(bookUniqueNumberVos);
    }

    /**
     * 获取书籍基础信息
     */
    @Override
    public BookDto getBaseById4Erp(Long bookId, Long channelId, Long adviserId) throws BizException {
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "bookId 不能为空");
        }
        BookDto bookDto = null;
        if(channelId != null && adviserId != null){
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("bookId", bookId);
            paramMap.put("adviserId", adviserId);
            paramMap.put("channelId", channelId);
            bookDto = bookDao.getById(paramMap);

            bookDto.setAdviserId(adviserId);
            bookDto.setChannelId(channelId);
            bookDto.setChannelName(channelConsr.getNameById(channelId));
            bookDto.setAdviserName(adviserConsr.getNameById(adviserId));
            Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
            Map<Long, String> agentNameMap = agentConsr.getNames(Collections.singletonList(agentId));
            if (!MapUtils.isEmpty(agentNameMap) && agentNameMap.containsKey(agentId)) {
                bookDto.setAgentName(agentNameMap.get(agentId));
            }
        } else {
            // 从redis获取书籍信息
            bookDto = bookCache.getBookToRedis(bookId);
            if (null == bookDto) {
                bookDto = bookDao.getBaseById(bookId);
                // 将数据存入redis
                bookCache.setBookToRedis(bookDto);
            }
        }
        return bookDto == null ? new BookDto() : bookDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void relateBookAdviser4Erp(RelateAdviserVO relateAdviserVO){
        if(null==relateAdviserVO || null==relateAdviserVO.getProjectId() || null==relateAdviserVO.getRaysAdviserId() || null==relateAdviserVO.getRaysBookId() || null == relateAdviserVO.getRaysChannelId()){
            throw new BizException(BizException.PARAM_IS_NULL.getCode(), "参数缺失");
        }
        Long bookId = relateAdviserVO.getRaysBookId().longValue();
        BookAdviserErp bookAdviserErp = bookAdviserErpBiz.getByBookId(bookId.longValue());
        QrcodeSceneErp qrcodeSceneErp = qrcodeSceneErpDao.getByBookId(bookId.longValue());
        if(bookAdviserErp == null || qrcodeSceneErp == null){
            throw new BizException(BizException.PARAM_IS_NULL.getCode(), "未找到与 bookId 匹配的相关信息，无法进行关联");
        }
        // 更新创建人
        Book updateBook = new Book();
        updateBook.setCreatedUser(relateAdviserVO.getRaysAdviserId().longValue());
        updateBook.setLastModifiedUser(relateAdviserVO.getRaysAdviserId().longValue());
        bookDao.updateByPrimaryKeySelective(updateBook);

        // 创建书和编辑关系
        Book book = new Book();
        BeanUtils.copyProperties(bookAdviserErp, book);
        book.setBookAdviserId(relateAdviserVO.getRaysAdviserId().longValue());
        book.setCreatedUser(relateAdviserVO.getRaysAdviserId().longValue());
        book.setChannelId(relateAdviserVO.getRaysChannelId().longValue());
        book.setIsBookGroup(bookAdviserErp.getIsOpenRobotProcess() == 1);
        createBookAdviserRelation(book);

        if(null != bookAdviserErp.getIsOpenRobotProcess() && bookAdviserErp.getIsOpenRobotProcess() == 1){
            // 小睿书
            BookGroupDTO bookGroupDTO = bookGroupBiz.getBookGroupInfoByBookId(book.getBookId(), book.getChannelId(), book.getCreatedUser(), null, null, 4, null,null);
            BookGroup bookGroup = new BookGroup();
            bookGroup.setId(bookGroupDTO.getId());
            bookGroup.setAddFriendGuide("嗨，你好！我是您的专属学习助手。我会根据您的需求量身定制学习计划与学习内容，提高您的学习效率，提升您的语文学习能力");
            bookGroup.setGroupQrcodeName(qrcodeSceneErp.getSceneName());
            bookGroup.setGroupQrcodeLocationId(qrcodeSceneErp.getLocationId().intValue());
            bookGroup.setJoinGroupType(4);
            bookGroupBiz.updateBookGroup(bookGroup);
        } else {
            ThreadPoolUtils.OTHER_THREAD_POOL.execute(()-> {
                // 现代纸书创建二维码
                QrcodeScene qrcodeScene = new QrcodeScene();
                BeanUtils.copyProperties(qrcodeSceneErp, qrcodeScene);
                qrcodeScene.setAdviserBookId(bookId);
                qrcodeScene.setCreatedByUserLogin(relateAdviserVO.getRaysAdviserId().longValue());
                qrcodeScene.setLastModifiedByUserLogin(relateAdviserVO.getRaysAdviserId().longValue());
                qrcodeScene.setChannelPartyId(relateAdviserVO.getRaysChannelId().longValue());
                QrcodeLabel qrcodeLabel = new QrcodeLabel();
                qrcodeLabel.setProLabelId(qrcodeSceneErp.getProLabelId());
                qrcodeLabel.setDepLabelId(qrcodeSceneErp.getDepLabelId());
                qrcodeLabel.setPurLabelId(qrcodeSceneErp.getPurLabelId());
                qrcodeScene.setQrcodeLabel(qrcodeLabel);
                QrcodeStyle qrcodeStyle = new QrcodeStyle();
                qrcodeStyle.setStyleType(0);
                qrcodeScene.setQrcodeStyle(qrcodeStyle);
                qrcodeSceneConsr.createQrcodeScene4Erp(qrcodeScene);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<CreateBookResultVO> batchCreateBook4Erp(List<CreateBookVO> createBookVOList){
        List<CreateBookResultVO> resultList = Lists.newArrayList();
        if(CollectionUtils.isEmpty(createBookVOList)){
            return resultList;
        }
        this.checkLabel(createBookVOList);
        this.fillDefaultChannel(createBookVOList);
        Book book;
        CreateBookResultVO createBookResultVO;
        for (CreateBookVO createBookVO : createBookVOList) {
            book = new Book();
            BeanUtils.copyProperties(createBookVO, book);
            book.setCreatedUser(createBookVO.getAdviserId());
            book.setLastModifiedUser(createBookVO.getAdviserId());
            book.setFromErp(1);
            // 创建现代纸书或者小睿书
            this.create4Erp(book);
            // 创建二维码
            this.createQrcode4Erp(createBookVO, book);
            // 构建返回值
            createBookResultVO = new CreateBookResultVO();
            createBookResultVO.setProjectId(createBookVO.getProjectId());
            createBookResultVO.setBookId(book.getBookId());
            createBookResultVO.setAdviserId(createBookVO.getAdviserId());
            createBookResultVO.setChannelId(createBookVO.getChannelId());
            resultList.add(createBookResultVO);
        }
        erpConsr.batchUpdateRelateInfo(resultList);
        return resultList;
    }

    private void checkLabel(List<CreateBookVO> createBookVOList) {
        for (CreateBookVO createBookVO : createBookVOList) {
            if(!createBookVO.getIsBookGroup()
                    && (!NumberUtil.isNumber(createBookVO.getCreateQrcodeVO().getProLabelId()) || !NumberUtil.isNumber(createBookVO.getCreateQrcodeVO().getDepLabelId()) || !NumberUtil.isNumber(createBookVO.getCreateQrcodeVO().getPurLabelId()))) {
                throw new BizException(BizException.PARAM_IS_NULL.getCode(), "二维码标签不能为空！");
            }
        }
    }

    private void fillDefaultChannel(List<CreateBookVO> createBookVOList) {
        CreateBookVO createBookVOFirst = createBookVOList.stream().findFirst().get();
        // 如果是小睿书，并且 channelId 为空，且 adviserId 有值，则获取编辑的默认渠道
        if(null != createBookVOFirst.getIsBookGroup() && createBookVOFirst.getIsBookGroup() && !NumberUtil.isNumber(createBookVOFirst.getChannelId()) && NumberUtil.isNumber(createBookVOFirst.getAdviserId())){
            Long defaultChannelId = channelConsr.getDefaultChannelId(createBookVOFirst.getAdviserId());
            // 因为是批量创建，所以所有的编辑是同一个，渠道也是同一个
            for (CreateBookVO createBookVO : createBookVOList) {
                createBookVO.setChannelId(defaultChannelId);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void createQrcode4Erp(CreateBookVO createBookVO, Book book) {
        if(NumberUtil.isNumber(book.getBookAdviserId())){
            // 正常创建二维码
            if(book.getIsBookGroup()){
                // 小睿二维码
                BookGroupDTO bookGroupDTO = bookGroupBiz.getBookGroupInfoByBookId(book.getBookId(), book.getChannelId(), book.getCreatedUser(), null, null, 4,null,null);

                BookGroup bookGroup = new BookGroup();
                bookGroup.setId(bookGroupDTO.getId());
                bookGroup.setAddFriendGuide("嗨，你好！我是您的专属学习助手。我会根据您的需求量身定制学习计划与学习内容，提高您的学习效率，提升您的语文学习能力");
                bookGroup.setGroupQrcodeName(createBookVO.getCreateQrcodeVO().getSceneName());
                bookGroup.setGroupQrcodeLocationId(createBookVO.getCreateQrcodeVO().getLocationId().intValue());
                bookGroup.setJoinGroupType(4);
                bookGroupBiz.updateBookGroup(bookGroup);
            } else {
                ThreadPoolUtils.OTHER_THREAD_POOL.execute(()->{
                    // 现代纸书二维码
                    QrcodeScene qrcodeScene = new QrcodeScene();
                    CreateQrcodeVO createQrcodeVO = createBookVO.getCreateQrcodeVO();
                    BeanUtils.copyProperties(createQrcodeVO, qrcodeScene);
                    qrcodeScene.setAdviserBookId(book.getBookId());
                    qrcodeScene.setCreatedByUserLogin(book.getCreatedUser());
                    qrcodeScene.setLastModifiedByUserLogin(book.getCreatedUser());
                    qrcodeScene.setChannelPartyId(book.getChannelId());
                    qrcodeScene.setClientCode(1);
                    QrcodeLabel qrcodeLabel = new QrcodeLabel();
                    qrcodeLabel.setProLabelId(createQrcodeVO.getProLabelId());
                    qrcodeLabel.setDepLabelId(createQrcodeVO.getDepLabelId());
                    qrcodeLabel.setPurLabelId(createQrcodeVO.getPurLabelId());
                    qrcodeScene.setQrcodeLabel(qrcodeLabel);
                    QrcodeStyle qrcodeStyle = new QrcodeStyle();
                    qrcodeStyle.setStyleType(0);
                    qrcodeScene.setQrcodeStyle(qrcodeStyle);
                    qrcodeSceneConsr.createQrcodeScene4Erp(qrcodeScene);
                });
            }
        } else {
            // 小睿码
            // 存储qrcode创建参数，待关联时创建二维码
            QrcodeSceneErp qrcodeSceneErp = new QrcodeSceneErp();
            BeanUtils.copyProperties(createBookVO.getCreateQrcodeVO(), qrcodeSceneErp);
            qrcodeSceneErp.setClientCode(1);
            qrcodeSceneErp.setBookId(book.getBookId());
            qrcodeSceneErpDao.insert(qrcodeSceneErp);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public BookDto create4Erp(Book book) {
        LOGGER.info("Erp自动创建图书book=" + book);
        this.checkAddParam(book);
//        if (book.getChannelId() == null) {
//            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择运营平台");
//        }
        if (Objects.isNull(book.getTempletId()) || Objects.isNull(book.getSecondTempletId())) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "请选择书刊分类");
        }
        // 校验书号
        bookSet.checkISBN(book.getTypeCode(), book.getIsbn());
        BookDto bookDto;
        while (true){
            bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
            if (bookDto == null) {
                break;
            }
            // 图书已存在,重新生成序号
            book.setSerialNumber(this.builderSerialNumber(book.getIsbn()));
        }
        // 新增图书
        bookDao.insert(book);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        // 查看现代纸书是否存在
        BookGroupDTO dtoByBookId = null;
        if(NumberUtil.isNumber(book.getChannelId()) && book.getChannelId() > 0
                && NumberUtil.isNumber(book.getCreatedUser()) && book.getCreatedUser() > 0){
            dtoByBookId = bookGroupBiz.getDTOByBookId(book.getBookId(), book.getChannelId(), book.getCreatedUser());
            // 新增图书与编辑关联关系
            createBookAdviserRelation(book);
        } else {
            // 如果没有编辑id，暂时将数据存放到临时表，后续关联编辑时再建立关系
            createBookAdviserErpRelation(book);
        }
        // 书籍总数缓存加1
        bookCache.incrObject(BookConstant.BOOK_CACHE + "PLATFORM_BOOK_COUNT");
        bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
        bookDto.setChannelId(book.getChannelId());
        // 关联社群码和社群书信息
        if (null != book.getIsBookGroup() && book.getIsBookGroup() && null != book.getBookGroupId()) {
            bookGroupBiz.linkBookGroup(book.getBookId(), book.getBookGroupId(), book.getCreatedUser());
        }
        bookDto.setIsDelete(null == dtoByBookId ? 1 : dtoByBookId.getIsDelete() ? 1 : 0);
        return bookDto;
    }

    @Transactional(rollbackFor = Exception.class)
    public BookDto create4ErpNew(Book book) {
        LOGGER.info("Erp自动创建图书book=" + book);
        BookDto bookDto;
        while (true){
            bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
            if (bookDto == null) {
                break;
            }
            // 图书已存在,重新生成序号
            book.setSerialNumber(this.builderSerialNumber(book.getIsbn()));
        }
        // 新增图书
        bookDao.insert(book);
        esBookAndAdviserBiz.updateBookAndAdviserToES(Collections.singletonList(book.getBookId()));
        // 查看现代纸书是否存在
        BookGroupDTO dtoByBookId = null;
        // 如果没有编辑id，暂时将数据存放到临时表，后续关联编辑时再建立关系
        createBookAdviserErpRelation(book);
        // 书籍总数缓存加1
        bookCache.incrObject(BookConstant.BOOK_CACHE + "PLATFORM_BOOK_COUNT");
        bookDto = bookDao.getByIsbnAndSnum(book.getIsbn(), book.getSerialNumber());
        if(null==bookDto){
            return new BookDto();
        }
        bookDto.setChannelId(book.getChannelId());
        bookDto.setIsDelete(null == dtoByBookId ? 1 : dtoByBookId.getIsDelete() ? 1 : 0);
        return bookDto;
    }

    /**
     * 新增图书与编辑关联关系
     * @param book
     */
    void createBookAdviserErpRelation(Book book) {
        BookAdviserErp bookAdviserErp = new BookAdviserErp();
        bookAdviserErp.setBookId(book.getBookId());
        bookAdviserErp.setAdviserId(book.getCreatedUser());
        bookAdviserErp.setChannelId(book.getChannelId());
        bookAdviserErp.setCreatedUser(book.getCreatedUser());
        bookAdviserErp.setTempletId(book.getTempletId());
        bookAdviserErp.setSecondTempletId(book.getSecondTempletId());
        bookAdviserErp.setSubLabelId(book.getSubLabelId());
        bookAdviserErp.setGraLabelId(book.getGraLabelId());
        bookAdviserErp.setAreaLabelId(book.getAreaLabelId());
        bookAdviserErp.setVerLabelId(book.getVerLabelId());
        bookAdviserErp.setProLabelId(book.getProLabelId());
        bookAdviserErp.setDepLabelId(book.getDepLabelId());
        bookAdviserErp.setPurLabelId(book.getPurLabelId());
        bookAdviserErp.setVolLabelId(book.getVolLabelId());
        if(book.getIsBookGroup()!=null&&book.getIsBookGroup()){
            bookAdviserErp.setIsOpenRobotProcess(1);
        }else{
            bookAdviserErp.setIsOpenRobotProcess(0);
        }
        bookAdviserErpBiz.create(bookAdviserErp);
    }

    /**
     * 生成书刊序号
     * @return
     */
    private String builderSerialNumber(String isbn) {
        BookSerialNumber bookSerialNumber = bookSerialNumberBiz.getByIsbn(isbn);
        if(bookSerialNumber == null){
            bookSerialNumber = new BookSerialNumber();
            bookSerialNumber.setIsbn(isbn);
            bookSerialNumber.setSerialNumber(1L);
            try {
                bookSerialNumberBiz.insert(bookSerialNumber);
            } catch (DuplicateKeyException e){
                bookSerialNumber = new BookSerialNumber();
                bookSerialNumber.setIsbn(isbn);
                bookSerialNumberBiz.update(bookSerialNumber);
            }
        } else {
            bookSerialNumber = new BookSerialNumber();
            bookSerialNumber.setIsbn(isbn);
            bookSerialNumberBiz.update(bookSerialNumber);
        }
        Calendar date = Calendar.getInstance();
        String year = String.valueOf(date.get(Calendar.YEAR));
        return year + bookSerialNumber.getSerialNumber();
    }

    @Override
    public void addCreateInfoToMq(List<CreateBookVO> createBookVOList) {
        if(ListUtils.isEmpty(createBookVOList)){
            return;
        }
        bookMQProducer.addCreateInfoToMq(createBookVOList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<CreateBookResultVO> batchCreateBook4ErpNew(List<CreateBookVO> createBookVOList) {
        List<CreateBookResultVO> resultList = Lists.newArrayList();
        if(CollectionUtils.isEmpty(createBookVOList)){
            return resultList;
        }
        Book book;
        CreateBookResultVO createBookResultVO;
        for (CreateBookVO createBookVO : createBookVOList) {
            book = new Book();
            BeanUtils.copyProperties(createBookVO, book);
            book.setCreatedUser(createBookVO.getAdviserId());
            book.setLastModifiedUser(createBookVO.getAdviserId());
            book.setFromErp(1);
            // 创建现代纸书或者小睿书
            this.create4ErpNew(book);
            // 构建返回值
            createBookResultVO = new CreateBookResultVO();
            createBookResultVO.setProjectId(createBookVO.getProjectId());
            createBookResultVO.setBookId(book.getBookId());
            createBookResultVO.setAdviserId(createBookVO.getAdviserId());
            createBookResultVO.setChannelId(createBookVO.getChannelId());
            resultList.add(createBookResultVO);
        }
        erpConsr.batchUpdateRelateInfo(resultList);
        return resultList;
    }

    @Override
    public List<BookGroupDTO> getQrcode4Erp(Long bookId, Long channelId, Long adviserId) {
        if(bookId == null || channelId == null || adviserId == null){
            return null;
        }
        // 获取所有的现代纸书二维码
        List<QrcodeSceneDto> qrcodeSceneDtos = qrcodeSceneConsr.getQrCodeList(bookId, adviserId, channelId);
        if(CollectionUtils.isEmpty(qrcodeSceneDtos)){
            qrcodeSceneDtos = Lists.newArrayList();
        }
        // 获取所有的社群码
        List<BookGroupDTO> bookGroupList = bookGroupDao.getDTOByBookIdsAdviserIdsChannelIds(Lists.newArrayList(bookId), Lists.newArrayList(adviserId), Lists.newArrayList(channelId));
        if(CollectionUtils.isEmpty(bookGroupList)){
            bookGroupList = Lists.newArrayList();
        }
        // 填充二维码位置
        this.fillLocationName(bookGroupList);
        // 整合结果
        this.mergeQrcodeData(qrcodeSceneDtos, bookGroupList);
        // 填充书刊标签
        this.setBookGroupLabel(bookGroupList);
        return bookGroupList;
    }

    private void mergeQrcodeData(List<QrcodeSceneDto> qrcodeSceneDtos, List<BookGroupDTO> bookGroupList) {
        BookGroupDTO tempBookGroupDTO;
        for (QrcodeSceneDto qrcodeSceneDto : qrcodeSceneDtos) {
            tempBookGroupDTO = new BookGroupDTO();
            tempBookGroupDTO.setSceneId(qrcodeSceneDto.getSceneId());
            tempBookGroupDTO.setGroupQrcodeName(qrcodeSceneDto.getSceneName());
            tempBookGroupDTO.setGroupQrcodeUrl(qrcodeSceneDto.getQrcodeUrl());
            tempBookGroupDTO.setLocationName(joinLocationName(qrcodeSceneDto.getQrcodeLocations()));
            if(qrcodeSceneDto.getQrcodeLabelDto() != null) {
                tempBookGroupDTO.setProLabelId(qrcodeSceneDto.getQrcodeLabelDto().getProLabelId());
                tempBookGroupDTO.setDepLabelId(qrcodeSceneDto.getQrcodeLabelDto().getDepLabelId());
                tempBookGroupDTO.setPurLabelId(qrcodeSceneDto.getQrcodeLabelDto().getPurLabelId());
            }
            tempBookGroupDTO.setCreateTime(qrcodeSceneDto.getCreatedDate());
            tempBookGroupDTO.setChannelId(qrcodeSceneDto.getChannelPartyId());
            tempBookGroupDTO.setQrcodeType(qrcodeSceneDto.getQrcodeType());
            bookGroupList.add(tempBookGroupDTO);
        }
    }

    private void fillLocationName(List<BookGroupDTO> bookGroupList) {
        List<Long> locationIds = Lists.newArrayList();
        for (BookGroupDTO bookGroupDTO : bookGroupList) {
            if(!NumberUtil.isNumber(bookGroupDTO.getGroupQrcodeLocationId())){
                continue;
            }
            locationIds.add(bookGroupDTO.getGroupQrcodeLocationId().longValue());
        }
        Map<Long, String> locationNameMap = channelConsr.listLocationNames(locationIds);
        if(MapUtils.isEmpty(locationNameMap)){
            return;
        }
        for (BookGroupDTO bookGroupDTO : bookGroupList) {
            if(!NumberUtil.isNumber(bookGroupDTO.getGroupQrcodeLocationId())){
                continue;
            }
            bookGroupDTO.setLocationName(locationNameMap.get(bookGroupDTO.getGroupQrcodeLocationId().longValue()));
        }
    }

    private String joinLocationName(List<QrcodeLocationDto> locationDtos){
        if(CollectionUtils.isEmpty(locationDtos)){
            return "";
        }
        return String.join(";", locationDtos.stream().map(x->x.getLocationName()).collect(Collectors.toList()));
    }

    private void setBookGroupLabel(List<BookGroupDTO> bookGroupList) {
        List<Long> labelIds = new ArrayList<>();
        for (BookGroupDTO bookGroupDTO : bookGroupList) {
            if (null != bookGroupDTO.getProLabelId()) {
                labelIds.add(bookGroupDTO.getProLabelId());
            }
            if (null != bookGroupDTO.getDepLabelId()) {
                labelIds.add(bookGroupDTO.getDepLabelId());
            }
            if (null != bookGroupDTO.getPurLabelId()) {
                labelIds.add(bookGroupDTO.getPurLabelId());
            }
        }
        labelIds = labelIds.stream().distinct().collect(Collectors.toList());
        if (CollectionUtils.isEmpty(labelIds)) {
            return;
        }
        Map<Long, String> labelMap = ResponseHandleUtil.parseMap(labelService.getLabelName(labelIds), Long.class, String.class);
        if (MapUtils.isEmpty(labelMap)) {
            return;
        }
        for (BookGroupDTO bookGroupDTO : bookGroupList) {
            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()));
            }
        }
    }

    @Override
    public PageBeanNew<QrcodeServeDto> getQrcodeDetail4Erp(Long sceneId, Long bookGroupId, Long channelId, Integer currentPage, Integer numPerPage) {
        if(sceneId == null && bookGroupId == null){
            throw new BizException(BizException.PARAM_IS_NULL.getCode(), "sceneId 或者 bookGroupId 不能为空");
        }

        if(sceneId != null && bookGroupId != null){
            throw new BizException(BizException.PARAM_IS_NULL.getCode(), "sceneId 和 bookGroupId 不能同时存在");
        }

        List<QrcodeServeDto> qrcodeServeDtoList = Lists.newArrayList();
        if(bookGroupId != null && bookGroupId > 0){
            List<BookGroupServe> bookGroupServes = bookGroupServeDao.getListByBookGroupId(bookGroupId);
            if(!CollectionUtils.isEmpty(bookGroupServes)){
                for (BookGroupServe bookGroupServe : bookGroupServes) {
                    QrcodeServeDto qrcodeServeDto = new QrcodeServeDto();
                    BeanUtils.copyProperties(bookGroupServe, qrcodeServeDto);
                    qrcodeServeDtoList.add(qrcodeServeDto);
                }
            }
        }

        if(sceneId != null && sceneId > 0){
            QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getById(sceneId);
            List<MessageDto> messages = qrcodeSceneDto.getMessages();
            if(!CollectionUtils.isEmpty(messages)){
                QrcodeServeDto qrcodeServeDto;
                for (MessageDto message : messages) {
                    qrcodeServeDto = new QrcodeServeDto();
                    qrcodeServeDto.setServeId(message.getFromId());
                    qrcodeServeDto.setServeType(message.getTypeCode());
                    qrcodeServeDto.setServeUrl(message.getUrl());
                    qrcodeServeDto.setTypeCode(message.getFromType());
                    qrcodeServeDto.setSceneId(sceneId);
                    qrcodeServeDtoList.add(qrcodeServeDto);
                }
            }
        }
        int totalCount = qrcodeServeDtoList.size();
        qrcodeServeDtoList = qrcodeServeDtoList.stream().skip(currentPage * numPerPage).limit(numPerPage).collect(Collectors.toList());
        // 填充价格（销售价、协议价）
        this.fillPrice(qrcodeServeDtoList, channelId);
        // 填充标签
        this.fillLabels(qrcodeServeDtoList);
        // 填充编辑、作者
        this.fillCreateName(qrcodeServeDtoList);
        return new PageBeanNew<>(currentPage, numPerPage, totalCount, qrcodeServeDtoList);
    }

    private void fillLabels(List<QrcodeServeDto> dtoList) {
        if(CollectionUtils.isEmpty(dtoList)){
            return;
        }
        dtoList = dtoList.stream().filter(x-> "APP".equalsIgnoreCase(x.getServeType())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(dtoList)){
            return;
        }
        List<Long> labelId = Lists.newArrayList();
        for (QrcodeServeDto vo : dtoList) {
            labelId.add(vo.getProLabelId());
            labelId.add(vo.getPurLabelId());
            labelId.add(vo.getDepLabelId());
        }
        Map<Long, String> labelName = labelConsr.getLabelName(labelId);
        if(MapUtils.isEmpty(labelName)){
            return;
        }
        for (QrcodeServeDto vo : dtoList) {
            vo.setPurLabelName(labelName.get(vo.getPurLabelId()));
            vo.setProLabelName(labelName.get(vo.getProLabelId()));
            vo.setDepLabelName(labelName.get(vo.getDepLabelId()));
        }
    }

    private void fillCreateName(List<QrcodeServeDto> list) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        List<Long> adviserIds = list.stream().filter(s -> "APP".equalsIgnoreCase(s.getServeType())).map(x -> x.getServeCreateUser()).collect(Collectors.toList());
        List<Long> merchantIds = list.stream().filter(s -> "PRODUCT".equalsIgnoreCase(s.getServeType())).map(x -> x.getServeCreateUser()).collect(Collectors.toList());

        Map<Long, String> merchantNameMap = merchantConsr.getNamesByIdList(merchantIds);
        Map<Long, String> adviserNameMap = adviserConsr.getNames(adviserIds);
        if(MapUtils.isEmpty(merchantNameMap)){
            merchantNameMap = new HashMap<>();
        }
        if(MapUtils.isEmpty(adviserNameMap)){
            adviserNameMap = new HashMap<>();
        }

        for (QrcodeServeDto serveDto : list) {
            if("PRODUCT".equals(serveDto.getServeType())){
                serveDto.setServeCreateUserName(merchantNameMap.get(serveDto.getServeCreateUser()));
            } else if ("APP".equals(serveDto.getServeType())){
                serveDto.setServeCreateUserName(adviserNameMap.get(serveDto.getServeCreateUser()));
            }
        }
    }

    private void fillPrice(List<QrcodeServeDto> list, Long channelId) {
        if (ListUtils.isEmpty(list)) {
            return;
        }
        // AccountSettingDto accountSettingDto = qrcodeSceneConsr.getWechatInfo(channelId);
        List<Long> appIds = list.stream().filter(s -> "APP".equalsIgnoreCase(s.getServeType())).map(x -> x.getServeId()).collect(Collectors.toList());
        List<Long> productIds = list.stream().filter(s -> "PRODUCT".equalsIgnoreCase(s.getServeType())).map(x -> x.getServeId()).collect(Collectors.toList());
        Map<Long, ProductDto> productDtoMap = new HashMap<>();
        Map<Long, AppDto> appDtoMap = new HashMap<>();
        // 销售价协议价
        Map<Long, BigDecimal> appPriceMap = new HashMap<>();
        if (!ListUtils.isEmpty(productIds)) {
            productDtoMap = productConsr.getProBasesByIds(productIds);
        }
        if (!ListUtils.isEmpty(appIds)) {
            appDtoMap = appConsr.mapByIds(appIds);
            List<AppPriceCacheDTO> appPriceCacheDTOS = new ArrayList<>();
            for (Long appId : appIds) {
                if (null != appDtoMap.get(appId)) {
                    AppPriceCacheDTO appPriceCacheDTO = new AppPriceCacheDTO();
                    appPriceCacheDTO.setAppId(appId);
                    appPriceCacheDTO.setAppTypeEnum(AppTypeEnum.APP_TYPE_MAP.get(appDtoMap.get(appId).getTypeCode()));
                    appPriceCacheDTOS.add(appPriceCacheDTO);
                }
            }
            appPriceMap = ResponseHandleUtil.parseMapResponse(appPriceCacheService.getCaches(appPriceCacheDTOS), Long.class, BigDecimal.class);
        }
        for (QrcodeServeDto serveDto : list) {
            Long serveId = serveDto.getServeId();
            if ("PRODUCT".equals(serveDto.getServeType())) {
                if (!MapUtils.isEmpty(productDtoMap) && productDtoMap.containsKey(serveId)) {
                    ProductDto productDto = productDtoMap.get(serveId);
                    if (productDto != null) {
                        serveDto.setServeName(productDto.getProductName());
                        if (productDto.getProductTypeDto() != null) {
                            serveDto.setFromType(productDto.getProductTypeDto().getTypeCode());
                            serveDto.setDescription(productDto.getProductTypeDto().getTypeName());
                            serveDto.setPicUrl(productDto.getCoverImg());
                            serveDto.setUniqueNumber(productDto.getUniqueNumber());
                            if(!CollectionUtils.isEmpty(productDto.getProductLabels())){
                                serveDto.setProLabelName(productDto.getProductLabels().get(0).getProLabelName());
                                serveDto.setDepLabelName(productDto.getProductLabels().get(0).getDepLabelName());
                                serveDto.setPurLabelName(productDto.getProductLabels().get(0).getPurLabelName());
                            }
                            // serveDto.setShortUrl(SendWeixinRequestTools.splitUrl(accountSettingDto, serveDto.getServeUrl()));
                            serveDto.setServeCreateUser(productDto.getAuthor());
                            serveDto.setTransverseImg(productDto.getPicture1());
                        }
                        List<SpecificationDto> specificationDtos = productDto.getSpecification();
                        if (!ListUtils.isEmpty(specificationDtos)) {
                            SpecificationDto specificationDto = specificationDtos.get(0);
                            if (null != specificationDto) {
                                serveDto.setRetailPrice(specificationDto.getAdvisePrice());
                                serveDto.setDealPrice(specificationDto.getDealPrice());
                            }
                        }
                    }
                }
            } else if ("APP".equals(serveDto.getServeType())) {
                if (!MapUtils.isEmpty(appDtoMap) && appDtoMap.containsKey(serveId)) {
                    AppDto appDto = appDtoMap.get(serveId);
                    if (appDto != null) {
                        serveDto.setServeName(appDto.getTitle());
                        serveDto.setFromType(appDto.getTypeCode());
                        serveDto.setDescription(appDto.getTypeName());
                        serveDto.setPicUrl(appDto.getSquareImg());
                        serveDto.setUniqueNumber(appDto.getUniqueNumber());
                        serveDto.setProLabelId(appDto.getProLabelId());
                        serveDto.setDepLabelId(appDto.getDepLabelId());
                        serveDto.setPurLabelId(appDto.getPurLabelId());
                        // serveDto.setShortUrl(SendWeixinRequestTools.splitUrl(accountSettingDto, serveDto.getServeUrl()));
                        serveDto.setServeCreateUser(appDto.getCreatedUser());
                        serveDto.setTransverseImg(appDto.getTransverseImg());
                    }
                }
                if (!MapUtils.isEmpty(appPriceMap)) {
                    if (appPriceMap.get(serveId) != null) {
                        serveDto.setRetailPrice(appPriceMap.get(serveId).doubleValue());
                        serveDto.setDealPrice(0D);
                    }
                }
            }
        }
    }

    @Override
    public BookGroupDTO checkQrcodeDetail4Erp(String url) {
        List<CompletableFuture> futureList = Lists.newArrayList();

        // 社群书二维码
        getGroupQrcodeInfo(url,null, futureList);
        // 现代纸书二维码
        getBookQrcodeInfo(url, futureList);

        // 等待执行完成
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join();
        BookGroupDTO bookGroupInfo = null;
        for (CompletableFuture completableFuture : futureList) {
            try {
                bookGroupInfo = (BookGroupDTO) completableFuture.get(5, TimeUnit.SECONDS);
            } catch (Exception e){
                LOGGER.info("质检查询二维码信息失败；");
            }
            if(bookGroupInfo != null){
                return bookGroupInfo;
            }
        }
        return bookGroupInfo;
    }

    @Override
    public Boolean checkIsLibraryBook(Long adviserId, Long bookId) {
        if ("pro".equals(envStr) && Objects.equals(adviserId, 1000027204L)) {
            return Boolean.TRUE;
        } else if ("uat".equalsIgnoreCase(envStr) && Objects.equals(bookId, 1398300L)) {
            return Boolean.TRUE;
        } else if ("test".equalsIgnoreCase(envStr) && Objects.equals(bookId, 5210703L)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    @Override
    public Long getDefaultRightsSettingId() {
        if ("pro".equals(envStr)) {
            return 2267L;
        } else if ("uat".equalsIgnoreCase(envStr)) {
            return 119L;
        } else if ("test".equalsIgnoreCase(envStr)) {
            return 818L;
        }
        return 0L;
    }


    @Override
    public void clearCache4BookBaseInfo(String pwd) {
        if (StringUtil.isBlank(pwd) || !"clearCache4BookBaseInfo".equals(pwd)) {
            return;
        }

        if (JedisClusterUtils.setnx(BookConstant.BOOK_CACHE + "CLEAR_CACHE", DateUtil.now())) {
            JedisClusterUtils.expire(BookConstant.BOOK_CACHE + "CLEAR_CACHE", 60 * 60 * 3);
            int currentPage = 0;
            PageBeanNew<Long> pageBeanNew = bookDao.listPageNew(new PageParam(currentPage, 1000), null, "listBookId");
            while (CollUtil.isNotEmpty(pageBeanNew.getRecordList()) && pageBeanNew.getPageCount() > currentPage++) {
                for (Long aLong : pageBeanNew.getRecordList()) {
                    bookCache.clearCache4BookBaseInfo(aLong);
                }
                pageBeanNew = bookDao.listPageNew(new PageParam(currentPage, 1000), null, "listBookId");
            }
            JedisClusterUtils.del(BookConstant.BOOK_CACHE + "CLEAR_CACHE");
        }
    }

    @Override
    public BookDto getBaseById4Buy(Long bookId, Long adviserId, Long channelId) {
        if (bookId == null) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "bookId 不能为空");
        }
        BookDto bookDto = null;
        if(channelId != null && adviserId != null){
            Map<String, Object> paramMap = Maps.newHashMap();
            paramMap.put("bookId", bookId);
            paramMap.put("adviserId", adviserId);
            paramMap.put("channelId", channelId);
            bookDto = bookDao.getBaseById4Buy(paramMap);

            bookDto.setAdviserId(adviserId);
            bookDto.setChannelId(channelId);
            Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
            Map<Long, String> agentNameMap = agentConsr.getNames(Collections.singletonList(agentId));
            if (!MapUtils.isEmpty(agentNameMap) && agentNameMap.containsKey(agentId)) {
                bookDto.setAgentName(agentNameMap.get(agentId));
                bookDto.setAgentId(agentId);
            }
        } else {
            // 从redis获取书籍信息
            bookDto = bookCache.getBookToRedis(bookId);
            if (null == bookDto) {
                bookDto = bookDao.getBaseById(bookId);
                // 将数据存入redis
                bookCache.setBookToRedis(bookDto);
            }
        }
        return bookDto == null ? new BookDto() : bookDto;
    }

    /**
     * 查询社群书二维码信息
     */
    private void getGroupQrcodeInfo(String url,Long bookGroupId, List<CompletableFuture> futureList) {
        // https://qrcode.raysgo.com/2233   https://qrcode.raysgo.com/t-2/1404/2280
        Boolean flag=false;
        String strBookGroupId = url.substring(url.lastIndexOf("/")+1);
        if(null!=bookGroupId){
            flag=true;
        }else{
            if(NumberUtil.isNumber(strBookGroupId)){
                flag=true;
            }
        }
        if(flag){
            futureList.add(CompletableFuture.supplyAsync(()->{
                BookGroupDTO bookGroupInfo = null;
                try {
                    bookGroupInfo = bookGroupBiz.getBookGroupInfo(null!=bookGroupId ? bookGroupId :Long.valueOf(strBookGroupId));
                } catch (Exception ex) {
                }
                if (bookGroupInfo != null) {
                    // 填充二维码位置
                    this.fillLocationName(Lists.newArrayList(bookGroupInfo));
                    BookDto bookInfo = bookGroupInfo.getBookInfo();
                    if (bookInfo != null) {
                        Map<Long, AdviserBaseInfoDto> adviserInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(Lists.newArrayList(bookInfo.getCreatedUser()));
                        if(MapUtils.isNotEmpty(adviserInfoDtoMap) && adviserInfoDtoMap.containsKey(bookInfo.getCreatedUser())){
                            AdviserBaseInfoDto adviserBaseInfoDto = adviserInfoDtoMap.get(bookInfo.getCreatedUser());
                            if(null!=adviserBaseInfoDto) {
                                bookInfo.setAdviserName(adviserBaseInfoDto.getPartyName());
                                bookGroupInfo.setAdviserPhone(adviserBaseInfoDto.getPhoneNum());
                                bookInfo.setAgentId(adviserBaseInfoDto.getAgentId());
                                bookInfo.setAgentName(adviserBaseInfoDto.getAgentName());
                                bookInfo.setTelephone(adviserBaseInfoDto.getPhoneNum());
                            }
                        }
                    }
                }
                return bookGroupInfo;
            }, ThreadPoolUtils.FILL_APPLET_RECORD));
        }
    }

    /**
     * 查询现代纸书二维码信息
     */
    private void getBookQrcodeInfo(String url, List<CompletableFuture> futureList) {
        // http://weixin.qq.com/q/02mGra51v48q_10000M07-
        QrcodeSceneDto qrcodeSceneDto = qrcodeSceneConsr.getByUrl(url);
        if (qrcodeSceneDto != null && qrcodeSceneDto.getSceneId() > 0) {
            BookGroupDTO bookGroupDTO = bookGroupDao.getBaseInfoBySceneId(qrcodeSceneDto.getSceneId());
            if (null != bookGroupDTO) {
                getGroupQrcodeInfo(url,bookGroupDTO.getId(), futureList);
            } else {
                futureList.add(CompletableFuture.supplyAsync(() -> {
                    BookGroupDTO bookGroupInfo = null;
                    bookGroupInfo = new BookGroupDTO();
                    bookGroupInfo.setGroupQrcodeUrl(qrcodeSceneDto.getQrcodeUrl());
                    bookGroupInfo.setGroupQrcodeName(qrcodeSceneDto.getSceneName());
                    bookGroupInfo.setLocationName(qrcodeSceneDto.getQrcodeLocations().get(0).getLocationName());
                    bookGroupInfo.setProLabelId(qrcodeSceneDto.getQrcodeLabelDto().getProLabelId());
                    bookGroupInfo.setDepLabelId(qrcodeSceneDto.getQrcodeLabelDto().getDepLabelId());
                    bookGroupInfo.setPurLabelId(qrcodeSceneDto.getQrcodeLabelDto().getPurLabelId());
                    bookGroupInfo.setCreateTime(qrcodeSceneDto.getCreatedDate());
                    bookGroupInfo.setBookId(qrcodeSceneDto.getAdviserBookId());
                    bookGroupInfo.setAdviserId(qrcodeSceneDto.getCreatedByUserLogin());
                    BookDto bookInfo = bookBiz.getBaseById(bookGroupInfo.getBookId());
                    if (null != bookInfo) {
                        bookInfo.setBookName(null != bookInfo.getBookName() ? StringUtil.addBracket(bookInfo.getBookName()) : null);
                        Map<Long, AdviserBaseInfoDto> adviserInfoDtoMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(Lists.newArrayList(bookInfo.getCreatedUser()));
                        if (MapUtils.isNotEmpty(adviserInfoDtoMap) && adviserInfoDtoMap.containsKey(bookInfo.getCreatedUser())) {
                            AdviserBaseInfoDto adviserBaseInfoDto = adviserInfoDtoMap.get(bookInfo.getCreatedUser());
                            if (null != adviserBaseInfoDto) {
                                bookInfo.setAdviserName(adviserBaseInfoDto.getPartyName());
                                bookGroupInfo.setAdviserPhone(adviserBaseInfoDto.getPhoneNum());
                                bookInfo.setAgentId(adviserBaseInfoDto.getAgentId());
                                bookInfo.setAgentName(adviserBaseInfoDto.getAgentName());
                                bookInfo.setTelephone(adviserBaseInfoDto.getPhoneNum());
                            }
                        }
                        bookGroupInfo.setBookInfo(bookInfo);
                    }
                    // 填充标签
                    this.setBookGroupLabel(Lists.newArrayList(bookGroupInfo));
                    return bookGroupInfo;
                }, ThreadPoolUtils.FILL_APPLET_RECORD));
            }
        }
    }

    @Override
    public PageBeanNew<BookDto> getESAdviserBooks4Answer(Long wechatUserId, BookSearchParamVO bookSearchParamVO) {
        Long graLabelId = bookSearchParamVO.getGraLabelId();
        Long subLabelId = bookSearchParamVO.getSubLabelId();
        Long verLabelId = bookSearchParamVO.getVerLabelId();
        Integer currentPage = bookSearchParamVO.getCurrentPage() == null?0:bookSearchParamVO.getCurrentPage();
        Integer numPerPage = bookSearchParamVO.getNumPerPage() == null?10:bookSearchParamVO.getNumPerPage();
        List<Long> templetIds = new ArrayList<>();
        if (null != graLabelId || null != subLabelId || null != verLabelId){
            templetIds = Arrays.asList(RightsSettingConstant.K12_VOLUME_ID);
        }
        Page<ESBookAndAdviser> esPage = esBookAndAdviserBiz.getESAdviserBooks4Answer(bookSearchParamVO.getGrayStatus(), bookSearchParamVO.getKeyword(),
                graLabelId, subLabelId, verLabelId, currentPage, numPerPage, templetIds);
        List<ESBookAndAdviser> esBookAndAdvisers = esPage.getContent();
        if (ListUtils.isEmpty(esBookAndAdvisers)) {
            return new PageBeanNew<>(currentPage, numPerPage, (int) esPage.getTotalElements(),new ArrayList<>());
        }
        List<BookDto> bookDtos = changeToBookDto(esBookAndAdvisers);
        fillOtherBookInfo(bookDtos);
        for (BookDto bookDto : bookDtos) {
            bookDto.setHasAnswer(false);
            //标记是否有答案
            List<BookServeDTO> bookServeVOS = bookGroupBiz.getBookAndBookGroupServeIds(bookDto.getAdviserId(), bookDto.getBookId(), bookDto.getChannelId());
            bookGroupBiz.fillBookServe(bookServeVOS);
            bookGroupBiz.removeCanNotBuy(bookServeVOS);
            if (!ListUtils.isEmpty(bookServeVOS)) {
                List<BookServeDTO> answerList = bookServeVOS.stream().
                        filter(s -> s.getServeName().contains("答案") || s.getFromType().equals(AppTypeEnum.ANSWER.value)).collect(Collectors.toList());
                if (!ListUtils.isEmpty(answerList)) {
                    bookDto.setHasAnswer(true);
                }
            }
            //订阅状态
            Boolean subscribeState = false;
            AnswerSubscribe answerSubscribe = new AnswerSubscribe();
            answerSubscribe.setBookId(bookDto.getBookId());
            answerSubscribe.setChannelId(bookDto.getChannelId());
            answerSubscribe.setAdviserId(bookDto.getAdviserId());
            answerSubscribe.setWechatUserId(wechatUserId);
            List<AnswerSubscribe> list = answerSubscribeDao.getRecordByUserBook(answerSubscribe);
            if (!ListUtils.isEmpty(list)) {
                subscribeState = true;
            }
            bookDto.setSubscribeState(subscribeState);
        }
        bookSet.setLabelNames(bookDtos);
        PageBeanNew<BookDto> page = new PageBeanNew<>(currentPage, numPerPage, (int) esPage.getTotalElements(), bookDtos);
        return page;
    }


    @Override
    public List<BookLabelVO> getSubjectLabelList4SeriesBook(Long seriesBookId, Long graLabelId) {
        SeriesBook seriesBook = seriesBookDao.getById(seriesBookId);
        if (null == seriesBook){
            return new ArrayList<>();
        }
        //系列书关键词
        String[] keywords = seriesBook.getSeriesBookKeyword().split(" ");
        List<String> keywordList = new ArrayList<String>(Arrays.asList(keywords));
        //编辑id
        List<Long> adviserIds = adviserConsr.getByAgentId(seriesBook.getAgentId());
        Integer currentPage = 0;
        Integer numPerPage = 50;
        Page<ESBookAndAdviser> esPage = esBookAndAdviserBiz.getAdviserBooks4SeriesBook(keywordList, currentPage, numPerPage, adviserIds, seriesBook.getAgentId(), null, graLabelId, seriesBook.getSerialNumber());
        List<ESBookAndAdviser> esBookAndAdvisers = esPage.getContent();
        if (ListUtils.isEmpty(esBookAndAdvisers)) {
            return new ArrayList<>();
        }
        List<Long> subjectLabels = esBookAndAdvisers.stream().filter(s->s.getSubLabelId()!=null).map(ESBookAndAdviser::getSubLabelId).distinct().collect(Collectors.toList());
        List<BookLabelVO> bookLabelList = bookLabelBiz.getLabelByIds(subjectLabels);
        return bookLabelList;
    }

    @Override
    public Map<String, Object> isSeriesBook(Long bookId, Long adviserId, Long channelId) {
        Map<String, Object> map = new HashMap<>();
        Boolean isSeriesBook = false;
        map.put("isSeriesBook", isSeriesBook);
        BookDto book = bookBiz.getBaseById(bookId);
        if (null == book || StringUtil.isEmpty(book.getBookName())){
            return map;
        }
        BookAdviserDto bookAdviserDto = bookAdviserDao.getBase(bookId, channelId, adviserId);
        if (null == bookAdviserDto){
            return map;
        }
        Long agentId = adviserConsr.getAgentIdByAdviser(adviserId);
        if (null == agentId){
            return map;
        }
        //k12教育分类校验
        List<Long> templetIds = Arrays.asList(RightsSettingConstant.K12_TEMPLET_ID_NEW);
        // 如果不是k12分类，则无系列书
        if(!templetIds.contains(bookAdviserDto.getTempletId())){
            return map;
        }
        List<SeriesBook> seriesBooks = seriesBookDao.getSeriesBookByAgent(agentId);
        if (ListUtils.isEmpty(seriesBooks)) {
            return map;
        }
        List<String> keywordList = new ArrayList<>();
        Long seriesBookId = null;
        String serialNumber = null;
        for (SeriesBook seriesBook:seriesBooks){
            String[] keywords = seriesBook.getSeriesBookKeyword().split(" ");
            Boolean hasKeyword = true;
            //关键词匹配
            for (String keyword:keywords){
                if (!book.getBookName().contains(keyword)){
                    hasKeyword = false;
                    break;
                }
            }
            //书刊序号匹配
            if (!StringUtil.isEmpty(seriesBook.getSerialNumber())) {
                if (StringUtil.isEmpty(book.getSerialNumber()) || !book.getSerialNumber().trim().equals(seriesBook.getSerialNumber())) {
                    hasKeyword = false;
                }
            }
            if (hasKeyword){
                isSeriesBook = true;
                seriesBookId = seriesBook.getId();
                keywordList = Arrays.asList(keywords);
                serialNumber = seriesBook.getSerialNumber();
                break;
            }
        }
        if (isSeriesBook){
            List<Long> adviserIds = adviserConsr.getByAgentId(agentId);
            Page<ESBookAndAdviser> esPage = esBookAndAdviserBiz.getAdviserBooks4SeriesBook(keywordList, 0, 50, adviserIds, agentId, null, bookAdviserDto.getGraLabelId(), serialNumber);
            List<ESBookAndAdviser> esBookAndAdvisers = esPage.getContent();
            List<Long> subjectLabels = new ArrayList<>();
            if (!ListUtils.isEmpty(esBookAndAdvisers)) {
                subjectLabels = esBookAndAdvisers.stream().filter(s->s.getSubLabelId()>0).map(ESBookAndAdviser::getSubLabelId).distinct().collect(Collectors.toList());
            }
            //无系列书或只有一本，不展示切换
            if (ListUtils.isEmpty(esBookAndAdvisers) || esBookAndAdvisers.size()==1 || ListUtils.isEmpty(subjectLabels)) {
                isSeriesBook = false;
            } else {
                map.put("seriesBookId", seriesBookId);
                map.put("subLabelId", bookAdviserDto.getSubLabelId());
                map.put("graLabelId", bookAdviserDto.getGraLabelId());
            }
        }
        map.put("isSeriesBook", isSeriesBook);
        return map;
    }

    @Override
    public PageBeanNew<BookDto> getSeriesBookList(Long seriesBookId, Long subLabelId, Long graLabelId, Integer currentPage, Integer numPerPage) {
        SeriesBook seriesBook = seriesBookDao.getById(seriesBookId);
        if (null == seriesBook){
            return new PageBeanNew<>();
        }
        //系列书关键词
        String[] keywords = seriesBook.getSeriesBookKeyword().split(" ");
        List<String> keywordList = new ArrayList<String>(Arrays.asList(keywords));
        //编辑id
        List<Long> adviserIds = adviserConsr.getByAgentId(seriesBook.getAgentId());
        if(!NumberUtil.isNumber(currentPage) || !NumberUtil.isNumber(numPerPage)){
            currentPage = 0;
            numPerPage = 50;
        }
        Page<ESBookAndAdviser> esPage = esBookAndAdviserBiz.getAdviserBooks4SeriesBook(keywordList, currentPage, numPerPage, adviserIds, seriesBook.getAgentId(), subLabelId, graLabelId, seriesBook.getSerialNumber());
        List<ESBookAndAdviser> esBookAndAdvisers = esPage.getContent();
        if (ListUtils.isEmpty(esBookAndAdvisers)) {
            return new PageBeanNew<>();
        }
        List<BookDto> bookDtos = changeToBookDto(esBookAndAdvisers);
        fillOtherBookInfo(bookDtos);
        fillBookInfo(bookDtos);
        fillLabelNames(bookDtos);
        PageBeanNew<BookDto> page = new PageBeanNew<>(currentPage,numPerPage,(int)esPage.getTotalElements(),bookDtos);
        return page;
    }

    private void fillLabelNames(List<BookDto> recordList) {
        if (ListUtils.isEmpty(recordList)) {
            return;
        }
        List<Long> bookLabelIds = new ArrayList<>();
        recordList.stream().forEach(appletUserBookcaseDTO -> {

            if (null != appletUserBookcaseDTO.getGraLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getGraLabelId());
            }
            if (null != appletUserBookcaseDTO.getSubLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getSubLabelId());
            }
            if (null != appletUserBookcaseDTO.getVolLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getVolLabelId());
            }
            if (null != appletUserBookcaseDTO.getVerLabelId()){
                bookLabelIds.add(appletUserBookcaseDTO.getVerLabelId());
            }
            if (null != appletUserBookcaseDTO.getAreaLabelId()) {
                bookLabelIds.add(appletUserBookcaseDTO.getAreaLabelId());
            }
        });
        Map<Long, BookLabel> bookLabelMap = new HashMap<>();

        if (!ListUtils.isEmpty(bookLabelIds)) {
            bookLabelMap = bookLabelDao.getMapByIds(bookLabelIds);
        }

        for (BookDto bookDto : recordList) {
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(bookDto.getGraLabelId())) {
                bookDto.setGraLabelName(bookLabelMap.get(bookDto.getGraLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(bookDto.getSubLabelId())) {
                bookDto.setSubLabelName(bookLabelMap.get(bookDto.getSubLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(bookDto.getVolLabelId())) {
                bookDto.setVolLabelName(bookLabelMap.get(bookDto.getVolLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(bookDto.getVerLabelId())) {
                bookDto.setVerLabelName(bookLabelMap.get(bookDto.getVerLabelId()).getName());
            }
            if (!MapUtils.isEmpty(bookLabelMap) && bookLabelMap.containsKey(bookDto.getAreaLabelId())) {
                bookDto.setAreaLabelName(bookLabelMap.get(bookDto.getAreaLabelId()).getName());
            }
        }
    }

    @Override
    public void addSeriesBookRecord(SeriesBookRecord seriesBookRecord) {
        if (null == seriesBookRecord.getRecordType() || null == seriesBookRecord.getBookId()) {
            throw new BookBizException(BookBizException.PARAM_IS_NULL, "参数缺失");
        }
        //操作类型（1按钮曝光2按钮点击）
        ThreadPoolUtils.OTHER_THREAD_POOL.execute(() -> {
            seriesBookRecordDao.insert(seriesBookRecord);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BookDto createBook4Erp(Book book) {
        BookDto bookDto = this.create4Adviser(book);
        if (book.getIsBookGroup() != null && book.getIsBookGroup()) {
            // 自动创建二维码
            // 小睿二维码
            BookGroupDTO bookGroupDTO = bookGroupBiz.getBookGroupInfoByBookId(book.getBookId(), book.getChannelId(), book.getCreatedUser(), null, null, 4,null,null);

            BookGroup bookGroup = new BookGroup();
            bookGroup.setId(bookGroupDTO.getId());
            bookGroup.setAddFriendGuide("嗨，你好！我是您的专属学习助手。我会根据您的需求量身定制学习计划与学习内容，提高您的学习效率，提升您的语文学习能力");
            bookGroup.setGroupQrcodeName(book.getBookName());
            bookGroup.setGroupQrcodeLocationId(1);
            bookGroup.setJoinGroupType(4);
            bookGroupBiz.updateBookGroup(bookGroup);
        }
        return bookDto;
    }

    @Override
    public EditionAnalysisResultVO bookEditionAnalysis(Long adviserId) {
        EditionAnalysisResultVO resultVO = new EditionAnalysisResultVO();
        List<EditionAnalysisListVO> list=bookEdtionDao.projectEditionAnalysis(adviserId);
        if(CollectionUtils.isEmpty(list)){
            return resultVO;
        }
        //获取分析后的结果
        EditionAnalysisVO editionAnalysisVO=new EditionAnalysisVO();
        String closedDate=list.get(list.size()-1).getEditionDate();
        String earliestDate=list.get(0).getEditionDate();
        Integer maxEdition=list.stream().mapToInt(a -> a.getEdition()).summaryStatistics().getMax();
        List<EditionAnalysisListVO> countSorted=bookEdtionDao.projectCountSorted(adviserId);
        String maxBookCountDate=CollectionUtils.isEmpty(countSorted) ? null  : countSorted.get(0).getEditionDate();
        String minBookCountDate=CollectionUtils.isEmpty(countSorted) ? null  : countSorted.get(countSorted.size()-1).getEditionDate();
        editionAnalysisVO.setClosedDate(closedDate);
        editionAnalysisVO.setEarliestDate(earliestDate);
        editionAnalysisVO.setMaxEdition(maxEdition);
        editionAnalysisVO.setMinBookCountDate(minBookCountDate);
        editionAnalysisVO.setMaxBookCountDate(maxBookCountDate);
        //设置值返回
        resultVO.setEditionAnalysisListVOList(list);
        resultVO.setEditionAnalysisVO(editionAnalysisVO);
        return resultVO;
    }

    @Override
    public PageBeanNew<BookDto> listPageBookMinimunSupport4Platform(Integer currentPage, Integer numPerPage, String isbn, String bookName, String publish, String serialNumber, Integer isCurrentMonth, Integer isOverdue, Long agentId) throws BizException {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("isbn", isbn != null && "".equals(isbn.trim()) ? null : isbn);
        paramMap.put("bookName", bookName != null && "".equals(bookName.trim()) ? null : bookName);
        paramMap.put("publish", publish != null && "".equals(publish.trim()) ? null : publish);
        paramMap.put("serialNumber", serialNumber != null && "".equals(serialNumber.trim()) ? null : serialNumber);
        paramMap.put("isCurrentMonth", isCurrentMonth);
        paramMap.put("isOverdue", isOverdue);
        paramMap.put("currentPage", currentPage * numPerPage);
        paramMap.put("numPerPage", numPerPage);
        if (null != agentId){
            List<Long> adviserIds = adviserConsr.getByAgentId(agentId);
            if (ListUtils.isEmpty(adviserIds)) {
                return new PageBeanNew<>(currentPage,numPerPage,0,new ArrayList<>());
            }
            paramMap.put("adviserIds", adviserIds);
        }
        Integer totalCount = bookDao.getBookMinimunSupportCount4Platform(paramMap);
        if (totalCount<=0){
            return new PageBeanNew<>(currentPage,numPerPage,0,new ArrayList<>());
        }
        List<BookDto> bookList = bookDao.listPageBookMinimunSupport4Platform(paramMap);
        if (ListUtils.isEmpty(bookList)){
            return new PageBeanNew<>(currentPage,numPerPage,totalCount,new ArrayList<>());
        }
        // 获取图书类型名称
        Map<String, BookTypeDto> typeCodeMap = bookTypeDao.getTypeCodeMap();
        List<Long> adviserIds = bookList.stream().map(x -> x.getAdviserId()).distinct().collect(Collectors.toList());
        Map<Long, AdviserBaseInfoDto> agentMap = adviserConsr.getAdviserId2AdviserInfoDtoMap(adviserIds);
        for (BookDto bookDto:bookList){
            List<BookMinimumSupportDTO> supportDTOS = bookDto.getBookMinimumSupports();
            boolean minimumSupport = false;
            if (!ListUtils.isEmpty(supportDTOS)) {
                for (BookMinimumSupportDTO supportDTO : supportDTOS) {
                    Date endTime = supportDTO.getEndTime();
                    if (new Date().before(endTime)) {
                        minimumSupport = true;
                        break;
                    }
                }
            }
            bookDto.setMinimumSupport(minimumSupport);
            // 设置图书类型名称
            if (null != typeCodeMap && typeCodeMap.get(bookDto.getTypeCode()) != null) {
                String typeName = typeCodeMap.get(bookDto.getTypeCode()).getTypeName();
                bookDto.setTypeName(typeName);
            }
            // 设置出版社名称
            if (!MapUtils.isEmpty(agentMap) && agentMap.containsKey(bookDto.getAdviserId())) {
                AdviserBaseInfoDto dto = agentMap.get(bookDto.getAdviserId());
                if (Objects.nonNull(dto)) {
                    bookDto.setAgentId(dto.getAgentId());
                    bookDto.setAgentName(dto.getAgentName());
                }
            }
        }
        return new PageBeanNew<>(currentPage, numPerPage, totalCount, bookList);
    }

    @Override
    public List<BookInfo4ScanCount> fetchBookListByScanCount(List<BookInfo4ScanCountRequestVO> requestVOS) {
        List<Long> adviserIds = requestVOS.stream().filter(Objects::nonNull).map(BookInfo4ScanCountRequestVO::getAdviserId).collect(Collectors.toList());
        List<Long> bookIds = requestVOS.stream().filter(Objects::nonNull).map(BookInfo4ScanCountRequestVO::getBookId).collect(Collectors.toList());
        List<Long> channelIds = requestVOS.stream().filter(Objects::nonNull).map(BookInfo4ScanCountRequestVO::getChannelId).collect(Collectors.toList());

        if (CollUtil.isEmpty(adviserIds) || CollUtil.isEmpty(bookIds) || CollUtil.isEmpty(channelIds)) return new ArrayList<>();

        // ERP查询是否立项
        CompletableFuture<Map<String, ErpBookApprovalDTO>> isApprovalFuture = CompletableFuture.supplyAsync(() -> Optional.ofNullable(erpConsr.getIsApproval(adviserIds, channelIds, bookIds)).orElse(new HashMap<>()));

        // 查询图书信息
        CompletableFuture<List<BookInfo4ScanCount>> bookInfoFuture = CompletableFuture.supplyAsync(() -> Optional.ofNullable(bookAdviserDao.listBookInfo4ScanCount(adviserIds, channelIds, bookIds)).orElse(new ArrayList<>()));

        // 补充资源数量 - 平台端相关配置 part1. 非立享权益
        Map<String, BookResourceNumDTO> pcloudResourceNumMap = new HashMap<>();
        CompletableFuture<Void> pcloudResourceNumFuture = CompletableFuture.runAsync(() -> {
            List<BookResourceNumDTO> list = rightsSettingBookRelationMapper.listReousrceNum4Book(adviserIds, channelIds, bookIds);
            Map<String, BookResourceNumDTO> map = Optional.ofNullable(list).map(x -> x.stream().collect(
                    Collectors.toMap(book -> book.getBookId() + "-" + book.getAdviserId() + "-" + book.getChannelId(), Function.identity())))
                    .orElse(new HashMap<>());
            pcloudResourceNumMap.putAll(map);
        });

        // 补充资源数量 - 平台端相关配置 part2. 立享权益
        Map<String, BookResourceNumDTO> pcloudResource4NowNumMap = new HashMap<>();
        CompletableFuture<Void> pcloudResource4NowNumFuture = CompletableFuture.runAsync(() -> {
            List<BookResourceNumDTO> list = rightsNowItemDao.listResourceNum4AdviserBook(adviserIds, channelIds, bookIds);
            Map<String, BookResourceNumDTO> map = Optional.ofNullable(list).map(x -> x.stream().collect(
                    Collectors.toMap(book -> book.getBookId() + "-" + book.getAdviserId() + "-" + book.getChannelId(), Function.identity())))
                    .orElse(new HashMap<>());
            pcloudResource4NowNumMap.putAll(map);
        });

        // 补充资源数量 - 编辑端相关配置 part1. 渠道获取数据
        Map<String, AdviserBookResourceNumRespDTO> adviserResourceNum4ChannelMap = new HashMap<>();
        CompletableFuture<Void> adviserResourceNum4ChannelFuture = CompletableFuture.runAsync(() -> {
            List<AdviserBookResourceNumRespDTO> respDTOS = qrcodeSceneConsr.listResourceNum4AdviserBook(adviserIds, channelIds, bookIds);
            Map<String, AdviserBookResourceNumRespDTO> map = Optional.ofNullable(respDTOS).map(x -> x.stream().collect(
                    Collectors.toMap(book -> book.getBookId() + "-" + book.getAdviserId() + "-" + book.getChannelId(), Function.identity())))
                    .orElse(new HashMap<>());
            adviserResourceNum4ChannelMap.putAll(map);
        });

        // 补充资源数量 - 编辑端相关配置 part2. 图书获取数据
        Map<String, BookResourceNumDTO> adviserResourceNum4BookMap = new HashMap<>();
        CompletableFuture<Void> adviserResourceNum4BookFuture = CompletableFuture.runAsync(() -> {
            List<BookResourceNumDTO> list = bookGroupServeDao.listResourceNum4AdviserBook(adviserIds, channelIds, bookIds);
            Map<String, BookResourceNumDTO> map = Optional.ofNullable(list).map(x -> x.stream().collect(
                    Collectors.toMap(book -> book.getBookId() + "-" + book.getAdviserId() + "-" + book.getChannelId(), Function.identity())))
                    .orElse(new HashMap<>());
            adviserResourceNum4BookMap.putAll(map);
        });

        // 资源数量任务组
        CompletableFuture<Void> resourceNumGroupFuture = CompletableFuture.allOf(pcloudResourceNumFuture, adviserResourceNum4ChannelFuture, adviserResourceNum4BookFuture, pcloudResource4NowNumFuture);

        // 等待结果返回
        try {
            List<BookInfo4ScanCount> bookInfo4ScanCounts = bookInfoFuture.get();
            Map<Long, String> bookLabelMap = new HashMap<>();
            Map<Long, String> centerLabelMap = new HashMap<>();
            Map<Long, AssistTempletDTO> templetIdMap = new HashMap<>();

            // 聚合所有的 bookLabelId
            CompletableFuture<Void> bookLabelIdFuture = CompletableFuture.runAsync(() -> {
                List<Long> bookLabelIds = Stream.of(
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getGraLabelId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getSubLabelId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getVerLabelId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getAreaLabelId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getVolLabelId)
                ).flatMap(stream -> stream).filter(Objects::nonNull).collect(Collectors.toList());
                // 查询标签信息
                bookLabelMap.putAll(Optional.ofNullable(bookLabelBiz.getLabelMapByIds(bookLabelIds)).orElse(new HashMap<>()));

            });

            // 聚合所有的 centerLabelId
            CompletableFuture<Void> centerLabelIdFuture = CompletableFuture.runAsync(() -> {
                List<Long> labelCenterIds = Stream.of(
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getProLabelId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getDepLabelId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getPurLabelId)
                ).flatMap(stream -> stream).filter(Objects::nonNull).collect(Collectors.toList());
                centerLabelMap.putAll(Optional.ofNullable(labelConsr.getLabelName(labelCenterIds)).orElse(new HashMap<>()));
            });

            CompletableFuture<Void> templateFuture = CompletableFuture.runAsync(() -> {
                List<Long> templetIds = Stream.of(
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getTempletId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getSecondTempletId),
                        bookInfo4ScanCounts.stream().map(BookInfo4ScanCount::getThirdTempletId)
                ).flatMap(stream -> stream).filter(Objects::nonNull).collect(Collectors.toList());
                templetIdMap.putAll(Optional.ofNullable(assistTempletConsr.mapByIds4Classify(templetIds)).orElse(new HashMap<>()));
            });

            // 等待所有任务完成
            CompletableFuture.allOf(isApprovalFuture, bookLabelIdFuture, centerLabelIdFuture, templateFuture, resourceNumGroupFuture).get();

            Map<String, ErpBookApprovalDTO> isApprovalDTOMap = isApprovalFuture.get();

            // 填充所有信息
            for (BookInfo4ScanCount book : bookInfo4ScanCounts) {
                // 填充 book_label
                book.setGraLabelName(bookLabelMap.get(book.getGraLabelId()));
                book.setSubLabelName(bookLabelMap.get(book.getSubLabelId()));
                book.setVerLabelName(bookLabelMap.get(book.getVerLabelId()));
                book.setAreaLabelName(bookLabelMap.get(book.getAreaLabelId()));
                book.setVolLabelName(bookLabelMap.get(book.getVolLabelId()));

                // 填充 专业 目的 深度 标签
                book.setProLabelName(centerLabelMap.get(book.getProLabelId()));
                book.setDepLabelName(centerLabelMap.get(book.getDepLabelId()));
                book.setPurLabelName(centerLabelMap.get(book.getPurLabelId()));
                
                // 填充书刊分类
                book.setTempletName(Objects.nonNull(templetIdMap.get(book.getTempletId()))?templetIdMap.get(book.getTempletId()).getTempletName():null);
                book.setSecondTempletName(Objects.nonNull(templetIdMap.get(book.getSecondTempletId()))?templetIdMap.get(book.getSecondTempletId()).getTempletName():null);
                book.setThirdTempletName(Objects.nonNull(templetIdMap.get(book.getThirdTempletId()))?templetIdMap.get(book.getThirdTempletId()).getTempletName():null);

                // 填充 是否立项
                book.setIsApproval(0);
                String key = book.getBookId() + "-" + book.getAdviserId() + "-" + book.getChannelId();
                ErpBookApprovalDTO erpBookApprovalDTO = isApprovalDTOMap.get(key);
                if (Objects.isNull(erpBookApprovalDTO) || Objects.isNull(erpBookApprovalDTO.getIsApproval())) {
                    book.setIsApproval(1);
                }
                // 配置资源数 = 平台端配置非立享权益资源数 + 平台端配置立享权益资源数 + 渠道来源的编辑端配置资源数 + 图书来源的编辑端配置资源数
                book.setResourceNum(
                        Optional.of(pcloudResourceNumMap).map(x -> x.get(key)).map(BookResourceNumDTO::getResourceNum).orElse(0) +
                                Optional.of(pcloudResource4NowNumMap).map(x -> x.get(key)).map(BookResourceNumDTO::getResourceNum).orElse(0) +
                                Optional.of(adviserResourceNum4ChannelMap).map(x -> x.get(key)).map(AdviserBookResourceNumRespDTO::getResourceNum).orElse(0) +
                                Optional.of(adviserResourceNum4BookMap).map(x -> x.get(key)).map(BookResourceNumDTO::getResourceNum).orElse(0)
                );
            }
            return bookInfo4ScanCounts;
        } catch (Exception e) {
            LOGGER.warn("fetchBookListByScanCount 失败 requestVOS：{}", requestVOS, e);
        }
        return new ArrayList<>();
    }
}
