package com.qmth.distributed.print.business.templete.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.itextpdf.text.DocumentException;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.distributed.print.business.bean.dto.*;
import com.qmth.distributed.print.business.bean.params.DownloadPaperFileParam;
import com.qmth.distributed.print.business.bean.params.SerialNumberParams;
import com.qmth.distributed.print.business.bean.result.DictionaryResult;
import com.qmth.distributed.print.business.bean.result.TSyncExamStudentScoreResult;
import com.qmth.distributed.print.business.cache.CreatePdfCacheUtil;
import com.qmth.distributed.print.business.entity.*;
import com.qmth.distributed.print.business.enums.*;
import com.qmth.distributed.print.business.service.*;
import com.qmth.distributed.print.business.templete.service.TaskLogicService;
import com.qmth.distributed.print.business.util.CreatePdfUtil;
import com.qmth.distributed.print.business.util.HtmlToPdfUtil;
import com.qmth.teachcloud.common.annotation.ExcelDBFieldDesc;
import com.qmth.teachcloud.common.base.BaseEntity;
import com.qmth.teachcloud.common.bean.dto.excel.*;
import com.qmth.teachcloud.common.bean.params.ArraysParams;
import com.qmth.teachcloud.common.config.DictionaryConfig;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.*;
import com.qmth.teachcloud.common.enums.*;
import com.qmth.teachcloud.common.service.*;
import com.qmth.teachcloud.common.util.*;
import com.qmth.teachcloud.common.util.excel.ExcelError;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.LinkedMultiValueMap;

import javax.annotation.Resource;
import java.io.*;
import java.lang.reflect.Field;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 任务处理逻辑impl
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2021/3/29
 */
@Service
public class TaskLogicServiceImpl implements TaskLogicService {
    private final static Logger log = LoggerFactory.getLogger(TaskLogicServiceImpl.class);

    @Resource
    ExamDetailService detailService;

    @Resource
    ExamDetailCourseService detailCourseService;

    @Resource
    ExamPrintPlanService examPrintPlanService;

    @Resource
    ExamTaskService examTaskService;

    @Resource
    ExamTaskDetailService examTaskDetailService;

    @Resource
    ExamCardService examCardService;

    @Resource
    ExamCardDetailService examCardDetailService;

    @Resource
    ExamStudentService examStudentService;

    @Resource
    BasicAttachmentService basicAttachmentService;

    @Resource
    ExamDetailService examDetailService;

//    @Resource
//    OssUtil ossUtil;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    BasicCourseService basicCourseService;

    @Resource
    CreatePdfUtil createPdfUtil;

    @Resource
    RedisTemplate<String, Object> redisTemplate;

    @Resource
    BasicExamRuleService basicExamRuleService;

    @Resource
    TBTaskService tbTaskService;

    @Resource
    BasicCardRuleService basicCardRuleService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    @Resource
    ConvertUtil convertUtil;

    @Autowired
    ExamDetailCourseService examDetailCourseService;

    @Autowired
    BasicStudentService basicStudentService;

    @Autowired
    ExamTaskPrintService examTaskPrintService;

    @Resource
    SysUserService sysUserService;

    @Resource
    FileStoreUtil fileStoreUtil;

    @Resource
    BasicClazzService basicClazzService;

    @Resource
    SysOrgService sysOrgService;

    @Resource
    TCStatisticsService tcStatisticsService;

    @Resource
    TCStatisticsTempService tcStatisticsTempService;

    @Resource
    TSyncExamStudentScoreService tSyncExamStudentScoreService;

    @Resource
    @Lazy
    PrintCommonService printCommonService;

    @Resource
    private BasicExamService basicExamService;

    @Resource
    private DownloadService downloadService;

    @Resource
    private TeachClazzService teachClazzService;

    @Resource
    DictionaryConfig dictionaryConfig;

    /**
     * 创建pdf前置条件
     *
     * @param map
     * @return
     */
    @Override
    @Transactional
    public Map<String, Object> createPdfPrepose(Map<String, Object> map) {
        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        SysUser sysUser = (SysUser) map.get(SystemConstant.USER);
        Long examDetailId = tbTask.getEntityId();
        List<Long> examDetailIds = Objects.nonNull(map.get("examDetailIds")) ? (List<Long>) map.get("examDetailIds") : null;
        //查询printPlan
        ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTask.getPrintPlanId());
        if (Objects.isNull(examPrintPlan)) {
            throw ExceptionResultEnum.EXAM_PRINT_IS_NULL.exception();
        }
        UpdateWrapper<ExamDetail> examDetailQueryWrapper = new UpdateWrapper<>();
        examDetailQueryWrapper.lambda().eq(ExamDetail::getSchoolId, sysUser.getSchoolId())
                .eq(ExamDetail::getPrintPlanId, tbTask.getPrintPlanId());
        if (Objects.nonNull(examDetailId)) {
            examDetailQueryWrapper.lambda().eq(ExamDetail::getId, examDetailId);
        } else if (Objects.nonNull(examDetailIds)) {
            examDetailQueryWrapper.lambda().in(ExamDetail::getId, examDetailIds);
        }
        examDetailQueryWrapper.lambda().set(ExamDetail::getStatus, ExamDetailStatusEnum.NEW)
                .set(ExamDetail::getAttachmentPath, null);
        detailService.update(examDetailQueryWrapper);

        //所有考场都撤回，印刷任务状态改为就绪
        QueryWrapper<ExamDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ExamDetail::getPrintPlanId, tbTask.getPrintPlanId())
                .notIn(ExamDetail::getStatus, ExamDetailStatusEnum.NEW, ExamDetailStatusEnum.READY);
        List<ExamDetail> examDetails = detailService.list(queryWrapper);
        if (CollectionUtils.isEmpty(examDetails)) {
            UpdateWrapper<ExamPrintPlan> printPlanUpdateWrapper = new UpdateWrapper<>();
            printPlanUpdateWrapper.lambda().set(ExamPrintPlan::getStatus, PrintPlanStatusEnum.READY).eq(ExamPrintPlan::getId, tbTask.getPrintPlanId());
            examPrintPlanService.update(printPlanUpdateWrapper);
        }
        return map;
    }

    /**
     * 创建pdf核心逻辑
     *
     * @param examDetailCourseList
     * @param examPrintPlan        印刷计划
     * @param examDetail           考场对象
     * @param sysUser              当前用户
     * @param paperTypeParam       试卷类型
     * @param basicAttachmentList  附件集合
     * @param attachmentIds
     * @param list
     */
    @Transactional
    public List<BasicAttachment> createPdfCoreLogic(List<ExamDetailCourse> examDetailCourseList,
                                                    ExamPrintPlan examPrintPlan,
                                                    ExamDetail examDetail,
                                                    SysUser sysUser,
                                                    String paperTypeParam,
                                                    List<BasicAttachment> basicAttachmentList,
                                                    Set<Long> attachmentIds,
                                                    List<PdfDto>... list
    ) throws Exception {
        if (Objects.nonNull(examDetailCourseList) && examDetailCourseList.size() > 0) {
            Map<Long, BasicCardRule> basicCardRuleMap = new HashMap<>();
            for (ExamDetailCourse examDetailCourse : examDetailCourseList) {
                List<PdfDto> studentPaperPdfList = new ArrayList<>();//所有试卷
                List<PdfDto> studentCardPdfList = new ArrayList<>();//所有题卡
                List<PdfDto> backupPaperPdfList = new ArrayList<>();//备份试卷
                List<PdfDto> backupCardPdfList = new ArrayList<>();//备份题卡

                String printContent = examPrintPlan.getPrintContent();
                if (StringUtils.isBlank(printContent)) {
                    return null;
                }
                //查询试卷
                List<ExamTask> examTaskList = examTaskService.findByFlowStatus(sysUser.getSchoolId(), examDetailCourse.getCourseCode(), examDetailCourse.getCourseName(), examDetailCourse.getPaperNumber(), FlowStatusEnum.FINISH);
                if (Objects.isNull(examTaskList) || examTaskList.size() == 0) {
                    throw ExceptionResultEnum.EXAM_TASK_IS_NULL.exception();
                }
                Set<Long> examTaskIds = examTaskList.stream().map(ExamTask::getId).collect(Collectors.toSet());
                Map<Long, ExamTask> examTaskMap = examTaskList.stream().collect(Collectors.toMap(ExamTask::getId, Function.identity(), (dto1, dto2) -> dto1));

                QueryWrapper<ExamTaskDetail> examTaskDetailQueryWrapper = new QueryWrapper<>();
                examTaskDetailQueryWrapper.lambda().in(ExamTaskDetail::getExamTaskId, examTaskIds).eq(ExamTaskDetail::getEnable, true);
                List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.list(examTaskDetailQueryWrapper);

                JSONObject jsonObject = new JSONObject();
                JSONArray jsonArray = new JSONArray();
                JSONArray stuJsonArray = new JSONArray();
                for (ExamTaskDetail examTaskDetail : examTaskDetailList) {
                    //查询题卡
                    ExamCard examCard = examCardService.getById(examTaskDetail.getCardId());
                    if (Objects.isNull(examCard)) {
                        throw ExceptionResultEnum.EXAM_CARD_IS_NULL.exception();
                    }

                    ExamTask examTask = examTaskMap.get(examTaskDetail.getExamTaskId());

                    //查询题卡规则
                    BasicCardRule basicCardRule = null;
                    if (!basicCardRuleMap.containsKey(examTask.getCardRuleId())) {
                        basicCardRule = basicCardRuleService.getById(examTask.getCardRuleId());
                        BasicCardRule finalBasicCardRule = basicCardRule;
                        basicCardRuleMap.computeIfAbsent(examTask.getCardRuleId(), v -> finalBasicCardRule);
                    } else {
                        basicCardRule = basicCardRuleMap.get(examTask.getCardRuleId());
                    }

                    //拼装key
                    StringJoiner stringJoiner = new StringJoiner("_");
                    stringJoiner.add(String.valueOf(examDetail.getSchoolId()))
                            .add(String.valueOf(examDetail.getExamStartTime()))
                            .add(String.valueOf(examDetail.getExamEndTime()))
                            .add(examDetailCourse.getCourseCode())
                            .add(examDetailCourse.getPaperNumber());
                    String key = stringJoiner.toString();

                    String paperType;
                    if (Objects.nonNull(paperTypeParam)) {
                        paperType = paperTypeParam;
                        CreatePdfCacheUtil.setPaperType(key, paperType);
                    } else {
                        paperType = createPdfUtil.getPaperType(examPrintPlan.getDrawRule(), examTaskDetail, key);//抽取卷型
                    }
                    examTaskDetail.setRelatePaperType(paperType);
                    examDetailCourse.setPaperType(paperType);

                    //查询考生
                    QueryWrapper<ExamStudent> examStudentQueryWrapper = new QueryWrapper<>();
                    examStudentQueryWrapper.lambda().eq(ExamStudent::getExamDetailCourseId, examDetailCourse.getId());
                    List<ExamStudent> examStudentList = examStudentService.list(examStudentQueryWrapper);

                    // 查询考试
                    BasicExam basicExam = basicExamService.getById(examTask.getExamId());
                    //
                    List<String> paperTypes = Arrays.stream(paperType.split(",")).sorted(Comparator.comparing(String::valueOf)).collect(Collectors.toList());
                    int backupCount = examPrintPlan.getBackupCount() != null ? examPrintPlan.getBackupCount() : 0;

                    if (examStudentList != null && examStudentList.size() > 0) {
                        AtomicInteger atomicInteger = new AtomicInteger(0);
                        for (ExamStudent t : examStudentList) {
                            int i1 = atomicInteger.getAndIncrement();
                            int mod = i1 % examTaskDetail.getDrawCount();
                            t.setPaperType(paperTypes.get(mod));
                        }
                    }

                    // 试卷数据组装
                    if (printContent.contains("PAPER")) {
                        List<PaperPdfDto> paperPdfDto = createPdfUtil.getPaperPdfFile(paperType, examTaskDetail);

                        //获取试卷pdf
                        PdfDto pdfDto = createPdfUtil.getPaperPdf(paperPdfDto, backupCount, backupPaperPdfList);
                        if (Objects.nonNull(pdfDto)) {
                            examDetailCourse.setPaperPagesA3(pdfDto.getPageCount());
                        } else {
                            examDetailCourse.setPaperPagesA3(examDetailCourse.getPaperPagesA3());
                        }
                        // 备用试卷
                        list[0].addAll(backupPaperPdfList);

                        if (examStudentList != null && examStudentList.size() > 0) {
                            for (ExamStudent t : examStudentList) {
                                if (Objects.nonNull(pdfDto)) {
                                    PdfDto stuPdfDto = createPdfUtil.getExamStudentPaperPdf(t.getPaperType(), paperPdfDto, studentPaperPdfList);
                                }
                            }
                        } else if (examDetail.getPrintCount() != null) {
                            AtomicInteger atomicInteger = new AtomicInteger(0);
                            int i = 0;
                            while (i < examDetail.getPrintCount()) {
                                int seq = atomicInteger.getAndIncrement();
                                int mod = seq % examTaskDetail.getDrawCount();
                                if (Objects.nonNull(pdfDto)) {
                                    PdfDto stuPdfDto = createPdfUtil.getExamStudentPaperPdf(paperTypes.get(mod), paperPdfDto, studentPaperPdfList);
                                }
                                i++;
                            }
                        } else {
                            throw ExceptionResultEnum.ERROR.exception("数据错误：未找到考生或者印刷数量");
                        }
                        // 考生试卷
                        list[2].addAll(studentPaperPdfList);
                    }

                    // 题卡数据组装
                    basicAttachmentList = Objects.isNull(basicAttachmentList) ? new ArrayList<>() : basicAttachmentList;
                    if (printContent.contains("CARD")) {
                        QueryWrapper<ExamCardDetail> examCardDetailQueryWrapper = new QueryWrapper<>();
                        examCardDetailQueryWrapper.lambda().eq(ExamCardDetail::getCardId, examCard.getId());
                        ExamCardDetail examCardDetail = examCardDetailService.getOne(examCardDetailQueryWrapper);

                        createPdfUtil.getCardAttachmentId(examCardDetail, attachmentIds);

                        //把模板页面上的 ${} 替换成实际内容
                        String cardContent = createPdfUtil.resetHtmlTemplateBar(examCardDetail.getHtmlContent());

                        for (int i = 1; i <= backupCount; i++) {
                            BasicAttachment basicAttachment = createPdfUtil.cardHtml(String.format("%02d", i), cardContent, examDetail, examDetailCourse, jsonArray, sysUser.getId(), backupCardPdfList, basicCardRule);
                            examDetailCourse.setCardPagesA3(basicAttachment.getPages());
                            basicAttachmentList.add(basicAttachment);
                        }
                        // 备用题卡
                        list[1].addAll(backupCardPdfList);

                        if (examStudentList != null && examStudentList.size() > 0) {
                            for (ExamStudent t : examStudentList) {
                                // 用带条码的模板
                                basicAttachmentList.add(createPdfUtil.examStudentHtml(examCardDetail.getHtmlContent(), t, paperType, examDetail, examDetailCourse, sysUser.getId(), studentCardPdfList, basicCardRule));
                            }
                        } else if (examDetail.getPrintCount() != null) {
                            AtomicInteger atomicInteger = new AtomicInteger(0);
                            Map<String, BasicAttachment> stringBasicAttachmentMap = new HashMap<>();
                            int i = 0;
                            while (i < examDetail.getPrintCount()) {
                                int seq = atomicInteger.getAndIncrement();
                                int mod = seq % examTaskDetail.getDrawCount();
                                String tempPaperType = paperTypes.get(mod);
                                BasicAttachment basicAttachment = createPdfUtil.examStudentHtml(cardContent, null, tempPaperType, examDetail, examDetailCourse, sysUser.getId(), studentCardPdfList, basicCardRule);

                                if (!stringBasicAttachmentMap.containsKey(tempPaperType)) {
                                    stringBasicAttachmentMap.put(tempPaperType, basicAttachment);
                                    JSONObject object = new JSONObject();
                                    object.put("name", tempPaperType);
                                    object.put("attachmentId", basicAttachment.getId());
                                    stuJsonArray.add(object);

                                    // 用不带条码的模板
                                    basicAttachmentList.add(basicAttachment);
                                }
                                i++;
                            }
                        } else {
                            throw ExceptionResultEnum.ERROR.exception("数据错误：未找到考生或者印刷数量");
                        }
                        // 题卡
                        list[3].addAll(studentCardPdfList);
                        jsonObject.put("card", jsonArray);
                        examDetailCourse.setAttachmentId(jsonObject.toJSONString());
                        examDetailCourse.setCommonAttachmentId(stuJsonArray.toJSONString());
                    }
                    examStudentService.saveOrUpdateBatch(examStudentList);
                }
                examDetailCourse.setAttachmentId(jsonObject.toJSONString());
                examTaskDetailService.saveOrUpdateBatch(examTaskDetailList);
            }
            detailCourseService.saveOrUpdateBatch(examDetailCourseList);
        }
        return basicAttachmentList;
    }

    /**
     * 创建A4文件
     *
     * @param examPrintPlan
     * @param examDetail
     * @param basicSchool
     * @param ftlList
     * @param examDetailCourseList
     * @param list
     * @throws IOException
     * @throws DocumentException
     */
    @Transactional
    public void createA4File(ExamPrintPlan examPrintPlan, ExamDetail examDetail, BasicSchool basicSchool, Set<File> ftlList, List<ExamDetailCourse> examDetailCourseList, List<PdfDto>... list) throws Exception {
        // 印品
        List<Long> examDetailCourseListIds = examDetailCourseList.stream().map(BaseEntity::getId).collect(Collectors.toList());

        String ordinaryContent = examPrintPlan.getOrdinaryContent();

        if (StringUtils.isNotBlank(ordinaryContent)) {
            //获取普通印品
            JSONArray jsonArrayOrdinary = JSONArray.parseArray(ordinaryContent);
            for (int i = 0; i < jsonArrayOrdinary.size(); i++) {
                JSONObject jsonObjectOrdinary = jsonArrayOrdinary.getJSONObject(i);
                if (Objects.nonNull(jsonObjectOrdinary.get("attachmentId")) && !Objects.equals("", jsonObjectOrdinary.get("attachmentId"))) {
                    Long attachmentId = Long.parseLong((String) jsonObjectOrdinary.get("attachmentId"));
                    BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
                    createPdfUtil.createCheckIn(examDetail, basicAttachment, list[0], (Integer) jsonObjectOrdinary.get("backupCount"));
                }
            }
        }

        String variableContent = examPrintPlan.getVariableContent();

        if (StringUtils.isNotBlank(variableContent)) {
            List<ExamStudentCourseDto> examStudentCourseDtoList = examStudentService.queryBySchoolIdAndExamDetailCourseIds(basicSchool.getId(), examDetailCourseListIds);
            int count = (int) examStudentCourseDtoList.stream().filter(s -> s.getPaperPageA3() != null && s.getPaperPageA3() > 2).count();
            boolean tag = count > 0;

            //获取变量印品
            JSONArray jsonArrayVariable = JSONArray.parseArray(variableContent);
            for (int i = 0; i < jsonArrayVariable.size(); i++) {
                JSONObject jsonObjectVariable = jsonArrayVariable.getJSONObject(i);
                String type = (String) jsonObjectVariable.get("type");
                if (Objects.nonNull(jsonObjectVariable.get("attachmentId")) && !Objects.equals("", jsonObjectVariable.get("attachmentId"))) {
                    Long attachmentId = Long.parseLong((String) jsonObjectVariable.get("attachmentId"));
                    BasicAttachment basicAttachment = basicAttachmentService.getById(attachmentId);
                    ftlList.add(teachcloudCommonService.getFile(basicAttachment.getPath(), false));
                    if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "SIGN")) {//签到表
                        createPdfUtil.createSignBook(basicAttachment, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"), examDetailCourseList);
                    } else if (Objects.nonNull(type) && Objects.equals(type.toUpperCase(), "PACKAGE")) {//卷袋贴
                        createPdfUtil.createPaperPackage(tag, basicAttachment, basicSchool.getName(), examDetail, examStudentCourseDtoList, list[1], (Integer) jsonObjectVariable.get("backupCount"), examDetailCourseList);
                    }
                }
            }
        }

        Collections.sort(list[1], new Comparator<PdfDto>() {
            @Override
            public int compare(PdfDto o1, PdfDto o2) {
                return o1.getSequence() > o2.getSequence() ? 1 : -1;
            }
        });
    }

    /**
     * 创建pdf逻辑
     *
     * @param map
     * @return
     */
    @Override
//    @Transactional
    public Map<String, Object> executeCreatePdfLogic(Map<String, Object> map) throws IOException {
        List<BasicAttachment> basicAttachmentList = null;
        try {
            TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
            SysUser sysUser = (SysUser) map.get(SystemConstant.USER);
            Long examDetailId = tbTask.getEntityId();
            List<Long> examDetailIds = Objects.nonNull(map.get("examDetailIds")) ? (List<Long>) map.get("examDetailIds") : null;
            Long schoolId = tbTask.getSchoolId();
            List<Long> examDetailCourseIds = Objects.nonNull(map.get("examDetailCourseIds")) ? (List<Long>) map.get("examDetailCourseIds") : null;
            String paperTypeParam = Objects.nonNull(map.get("paperType")) ? (String) map.get("paperType") : null;

            //查询printPlan
            ExamPrintPlan examPrintPlan = examPrintPlanService.getById(tbTask.getPrintPlanId());
            if (Objects.isNull(examPrintPlan)) {
                throw ExceptionResultEnum.EXAM_PRINT_IS_NULL.exception();
            }

            BasicSchool basicSchool = commonCacheService.schoolCache(examPrintPlan.getSchoolId());
            BasicExamRule basicExamRule = basicExamRuleService.getBySchoolId(schoolId);
            if (Objects.isNull(basicExamRule)) {
                throw ExceptionResultEnum.EXAM_RULE_IS_NULL.exception();
            }

            //查询examDetail
            QueryWrapper<ExamDetail> examDetailQueryWrapper = new QueryWrapper<>();
            examDetailQueryWrapper.lambda().eq(ExamDetail::getSchoolId, sysUser.getSchoolId())
                    .eq(ExamDetail::getPrintPlanId, tbTask.getPrintPlanId());
            if (Objects.nonNull(examDetailId)) {
                examDetailQueryWrapper.lambda().eq(ExamDetail::getId, examDetailId);
            } else if (Objects.nonNull(examDetailIds)) {
                examDetailQueryWrapper.lambda().in(ExamDetail::getId, examDetailIds);
            }
            List<ExamDetail> examDetailList = detailService.list(examDetailQueryWrapper);
            if (Objects.isNull(examDetailList) || examDetailList.size() == 0) {
                throw ExceptionResultEnum.EXAM_DETAIL_IS_NULL.exception();
            }
            Set<Long> attachmentIds = new HashSet<>();
            Set<File> ftlList = new HashSet<>();
            for (ExamDetail examDetail : examDetailList) {
                tbTask.setObjName(examDetail.getExamRoom() + "-" + examDetail.getExamPlace());
                //查询examDetailCourse
                QueryWrapper<ExamDetailCourse> examDetailCourseQueryWrapper = new QueryWrapper<>();
                if (Objects.nonNull(examDetailCourseIds) && examDetailCourseIds.size() > 0) {
                    examDetailCourseQueryWrapper.lambda().in(ExamDetailCourse::getId, examDetailCourseIds);
                } else {
                    examDetailCourseQueryWrapper.lambda().eq(ExamDetailCourse::getExamDetailId, examDetail.getId());
                }
                List<ExamDetailCourse> examDetailCourseList = detailCourseService.list(examDetailCourseQueryWrapper);
                List<PdfDto> variablePdfList = new ArrayList<>();//变量印品(签到表、卷袋贴)
                List<PdfDto> ordinaryPdfList = new ArrayList<>();//普通印品(登记表)
                List<PdfDto> paperPdfList = new ArrayList<>();//所有试卷
                List<PdfDto> examStudentPdfList = new ArrayList<>();//所有题卡
                List<PdfDto> backupPaperPdfList = new ArrayList<>();//备份试卷
                List<PdfDto> cardPdfList = new ArrayList<>();//备份题卡

                //创建pdf核心逻辑
                basicAttachmentList = createPdfCoreLogic(examDetailCourseList,
                        examPrintPlan,
                        examDetail,
                        sysUser,
                        paperTypeParam,
                        basicAttachmentList,
                        attachmentIds,
                        backupPaperPdfList,
                        cardPdfList,
                        paperPdfList,
                        examStudentPdfList);

                createA4File(examPrintPlan, examDetail, basicSchool, ftlList, examDetailCourseList, ordinaryPdfList, variablePdfList);

                //合并A3（试卷+题卡+备用试卷+备用题卡）
                String dirNameA3 = createPdfUtil.mergeA3Pdf(paperPdfList, examStudentPdfList, backupPaperPdfList, cardPdfList);
                //合并A4（签到表+卷袋贴+登记表）
                String dirNameA4 = createPdfUtil.mergeA4Pdf(variablePdfList, ordinaryPdfList);
                //合并A3（题卡+备用题卡）
                String dirNameCardA3 = createPdfUtil.mergeA3Pdf(examStudentPdfList, cardPdfList);

                List<PdfDto> mergePdfDeleteList = new ArrayList<>();
                mergePdfDeleteList.addAll(examStudentPdfList);
                mergePdfDeleteList.addAll(cardPdfList);
                BasicAttachment attachment = createPdfUtil.mergePdfSaveDb(dirNameA4, dirNameA3, dirNameCardA3, tbTask, sysUser.getId(), examDetail, basicExamRule, mergePdfDeleteList);
                if (basicAttachmentList != null) {
                    basicAttachmentList.add(attachment);
                }

                examDetailService.updateById(examDetail);
            }
            updateExamPrintPlan(basicExamRule, examPrintPlan);
            map.computeIfAbsent("size", v -> examDetailList.size());
            //最后一步删除附件
//            createPdfUtil.deleteAttachment(attachmentIds, ftlList);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
//            if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
            basicAttachmentService.batchDeleteAttachment(basicAttachmentList);
//            }
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return map;
    }

    /**
     * 更新考试计划
     *
     * @param basicExamRule
     * @param examPrintPlan
     */
    @Transactional
    public void updateExamPrintPlan(BasicExamRule basicExamRule, ExamPrintPlan examPrintPlan) {
        if (PrintMethodEnum.AUTO == basicExamRule.getPrintMethod()) {
            examPrintPlan.setStatus(PrintPlanStatusEnum.PRINTING);
            examPrintPlanService.updateById(examPrintPlan);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> executeExaminationLogic(Map<String, Object> map) throws Exception {
        List<ExaminationExportDto> examinationExportDtoList = examDetailService.findExaminationExportDtoDatasource(map);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ExcelUtil.excelMake(ExaminationExportDto.class, examinationExportDtoList, outputStream);
        InputStream in = new ByteArrayInputStream(outputStream.toByteArray());

//        UploadFileEnum.FILE/
        LocalDateTime nowTime = LocalDateTime.now();
        StringJoiner stringJoiner = new StringJoiner("");
        stringJoiner.add(UploadFileEnum.FILE.getTitle()).add(File.separator);

        stringJoiner.add(String.valueOf(nowTime.getYear())).add(File.separator)
                .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                .add(String.format("%02d", nowTime.getDayOfMonth()));

        JSONObject jsonObject = new JSONObject();
        stringJoiner.add(File.separator).add(SystemConstant.getUuid()).add(".").add(SystemConstant.XLSX);

        String dirName = stringJoiner.toString().replaceAll("\\\\", "/");

//        ossUtil.ossUpload(dirName, in, null);
        fileStoreUtil.ossUpload(dirName, in, DigestUtils.md5Hex(new ByteArrayInputStream(outputStream.toByteArray())), fileStoreUtil.getUploadEnumByPath(dirName).getFssType());
        jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
        jsonObject.put(SystemConstant.PATH, dirName);
        jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
        map.put(SystemConstant.PATH, jsonObject.toString());
        map.put(SystemConstant.DATA_COUNT, examinationExportDtoList.size());
        return map;
    }

    @Transactional
    @Override
    public Map<String, Object> executeImportExaminationLogic(Map<String, Object> map) throws Exception {
        SysUser sysUser = (SysUser) map.get(SystemConstant.USER);
        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        InputStream inputStream = (InputStream) map.get("inputStream");
        Long printPlanId = tbTask.getPrintPlanId();
        Long schoolId = tbTask.getSchoolId();
        if (!tbTaskService.countByPrintPlanIdAndEntityId(schoolId, printPlanId, null)) {
            throw ExceptionResultEnum.ERROR.exception("当前印刷计划正在生成pdf,无法导入考务数据");
        }
        Long userId = tbTask.getCreateId();
        ExamPrintPlan examPrintPlan = examPrintPlanService.getById(printPlanId);

        if (examPrintPlan == null) {
            throw ExceptionResultEnum.ERROR.exception("[印刷计划]不存在");
        }

        PrintPlanStatusEnum printPlanStatus = examPrintPlan.getStatus();
        if (PrintPlanStatusEnum.NEW != printPlanStatus && PrintPlanStatusEnum.READY != printPlanStatus) {
            throw ExceptionResultEnum.ERROR.exception(printPlanStatus + "状态下的印刷计划不允许导入");
        }

        String printPlanName = examPrintPlan.getName();

        // 该学校有效考务数据
        List<FieldsDto> fieldsDtoList = examDetailService.findExaminationFields(schoolId);
        if (fieldsDtoList.size() == 0) {
            throw ExceptionResultEnum.ERROR.exception("该学校没有设置考务数据");
        }
        String importFilePath = tbTask.getImportFilePath();
        Map importFilePathMap = JSONObject.parseObject(importFilePath);
        String path = String.valueOf(importFilePathMap.get(SystemConstant.PATH));
        Workbook workbook;
        if (path.endsWith(SystemConstant.XLSX)) {
            workbook = new XSSFWorkbook(inputStream);
        } else if (path.endsWith(SystemConstant.XLS)) {
            workbook = new HSSFWorkbook(inputStream);
        } else {
            throw ExceptionResultEnum.ERROR.exception("文件格式异常");
        }
        // 读取第一个工作表
        Sheet sheet = workbook.getSheetAt(0);
        if (sheet.getLastRowNum() == 0 && sheet.getPhysicalNumberOfRows() == 0) {
            throw ExceptionResultEnum.ERROR.exception("第一个sheet为空,考务数据必须放在第一个sheet（工作表）内");
        }
        // 获取sheet行数
        int totalRows = sheet.getPhysicalNumberOfRows();
        // 获取sheet列数
        int totalCells = 0;
        if (totalRows > 1 && sheet.getRow(0) != null) {
            totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
        }
        // 获取sheet的title
        Row head = sheet.getRow(0);
        List<String> headList = new ArrayList<>();
        // 将必填字段匹配excel解析的表头索引
        for (int i = 0; i < totalCells; i++) {
            String cellValue = String.valueOf(ExcelUtil.convert(head.getCell(i)));
            for (FieldsDto fieldsDto : fieldsDtoList) {
                if (cellValue.equals(fieldsDto.getName())) {
                    // 如果通用规则必填字段和excel表头匹配上了，则为该必选字段设置其在excel中的索引
                    fieldsDto.setIndex(i);
                }
            }
            headList.add(cellValue);
        }

        // 搜索所有有效字段 excel中的表头是否包含
        for (FieldsDto fieldsDto : fieldsDtoList) {
            if (!headList.contains(fieldsDto.getName())) {
                throw ExceptionResultEnum.ERROR.exception("学校考务必填字段 ：'" + fieldsDto.getName() + "' 不存在");
            }
        }
        List<ExaminationImportDto> examinationImportDtoList = new ArrayList<>();
        for (int r = 1; r < totalRows; r++) {
            Row row = sheet.getRow(r);
            if (ExcelUtil.isRowAllCellEmpty(row, head)) {
                // excel中整行为空，直接跳过
                continue;
            }

            List<FieldsDto> secondaryFieldList = new ArrayList<>(); // 备选字段

            ExaminationImportDto examinationImportDto = new ExaminationImportDto();
            Field[] examinationImportDtoFields = examinationImportDto.getClass().getDeclaredFields();
            for (FieldsDto fieldsDto : fieldsDtoList) {
                boolean match = false;
                String name = fieldsDto.getName();
                String code = fieldsDto.getCode();
                int index = fieldsDto.getIndex();
                String level = fieldsDto.getLevel();

                if (Objects.nonNull(row)) {
                    Cell cell = row.getCell(index);
                    if (cell == null) {
                        throw ExceptionResultEnum.ERROR.exception("excel中第[" + (r + 1) + "]行,第[" + (index + 1) + "]列,字段[" + name + "]必填");
                    }
                    String cellValue = String.valueOf(ExcelUtil.convert(cell));
                    if (cellValue == null || cellValue.length() < 1 || cellValue.equals("null")) {
                        throw ExceptionResultEnum.ERROR.exception("excel中第[" + (r + 1) + "]行,第[" + (index + 1) + "]列,字段[" + name + "]必填");
                    }

                    for (Field examinationImportDtoField : examinationImportDtoFields) {
                        ExcelDBFieldDesc excelDBFieldDesc = examinationImportDtoField.getAnnotation(ExcelDBFieldDesc.class);
                        if (excelDBFieldDesc == null) {
                            // 如果没有注解，说明该数据库必须字段不是从excel中获得的，直接跳过
                            continue;
                        }

                        // 如果数据库字段中文名和必填字段中文名称对应，则通过反射为数据库必选字段赋值
                        String dbName = excelDBFieldDesc.name();
                        int dbLength = excelDBFieldDesc.length();
                        if (dbName.equals(name)) {
                            if (dbLength > 0) {
                                SystemConstant.verifyLength(cellValue, dbLength, dbName);
                            }
                            examinationImportDtoField.setAccessible(true);
                            examinationImportDtoField.set(examinationImportDto, cellValue);
                            match = true;
                            break;
                        }
                    }
                    if (!match || "secondary".equals(level)) {
                        // 必选+扩展字段不能匹配到数据库中的字段存放 或者 该字段为扩展字段，则添加到扩展字段中
                        FieldsDto secondaryField = new FieldsDto();
                        secondaryField.setCode(code);
                        secondaryField.setName(name);
                        secondaryField.setEnable(true);
                        secondaryField.setValue(cellValue);
                        secondaryFieldList.add(secondaryField);
                    }
                }
            }
            // 校验试卷编号
            examTaskService.verifyCourseCodeByPaperNumber(schoolId, examinationImportDto.getPaperNumber(), examinationImportDto.getCourseCode());

            // 校验课程信息
            basicCourseService.verifyCourseInfo(schoolId, examinationImportDto.getCourseCode(), examinationImportDto.getCourseName(), userId);

            // 解析时间
            Map<String, Object> timeMap = ConvertUtil.analyzeStartAndEndTime(examinationImportDto.getExamDate(), examinationImportDto.getExamTime());
            String examStartTime = String.valueOf(timeMap.get("startTime"));
            String examEndTime = String.valueOf(timeMap.get("endTime"));

            examinationImportDto.setSecondaryFieldList(secondaryFieldList);
            examinationImportDto.setExamStartTime(examStartTime);
            examinationImportDto.setExamEndTime(examEndTime);
            examinationImportDto.setSchoolId(schoolId);
            examinationImportDto.setPrintPlanId(printPlanId);
            examinationImportDto.setPrintPlanName(printPlanName);
            examinationImportDtoList.add(examinationImportDto);
        }

        // 按考点+开始时间+课程代码+考场排序
        examinationImportDtoList.sort(
                Comparator.comparing(ExaminationImportDto::getExamPlace)
                        .thenComparing(ExaminationImportDto::getExamStartTime)
                        .thenComparing(ExaminationImportDto::getCourseCode)
                        .thenComparing(ExaminationImportDto::getExamRoom)
        );

        // 校验课程代码和试卷编号在印刷计划下是1对1的关系
        List<String> paperNumberList = examinationImportDtoList.stream().map(ExaminationImportDto::getPaperNumber).distinct().collect(Collectors.toList());
        for (String paperNumber : paperNumberList) {
            List<String> tmp = examinationImportDtoList.stream().filter(e -> paperNumber.equals(e.getPaperNumber()))
                    .map(ExaminationImportDto::getCourseCode).distinct().collect(Collectors.toList());
            if (tmp.size() != 1) {
                throw ExceptionResultEnum.ERROR.exception("试卷编号为 " + paperNumber + ",对应多个课程代码 : " + tmp);
            }
        }

        // 删除印刷计划下的考务数据
        examDetailService.deleteExaminationData(printPlanId, null);

        // 卷袋号生成规则
        SerialNumberParams serialNumberParams = new SerialNumberParams("packageCode-" + schoolId, "1", 6);
        String key = serialNumberParams.getModel() + serialNumberParams.getPrefix();
        RedisAtomicLong counter = new RedisAtomicLong(key, Objects.requireNonNull(redisTemplate.getConnectionFactory()));
        Long value = counter.get();
        try {
            // 组装exam_detail数据
            List<Long> examDetailIdList = examDetailService.disposeExamDetailByExaminationExcel(examinationImportDtoList, userId, serialNumberParams, sysUser);
            // 组装exam_detail_course数据
            examDetailService.disposeExamDetailCourseByExaminationExcel(examinationImportDtoList, userId, sysUser);
            // 组装exam_student数据
            examDetailService.disposeExamStudentByExaminationExcel(examinationImportDtoList, userId, sysUser);

            // 更改印刷计划状态
            examPrintPlan.setStatus(PrintPlanStatusEnum.READY);
            examPrintPlanService.updateById(examPrintPlan);

            map.put("examDetailIdList", examDetailIdList);
            map.put("dataCount", examinationImportDtoList.size());
        } catch (Exception e) {
            redisTemplate.opsForValue().set(key, value);
            throw new RuntimeException(e);
        }

        return map;
    }

    /**
     * 下载pdf
     *
     * @param map
     * @return
     * @throws IOException
     */
    @Override
    @Transactional
    public Map<String, Object> executeDownloadPdfLogic(Map<String, Object> map) throws Exception {
        try {
            TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
            JSONArray jsonArray = JSONArray.parseArray(tbTask.getRemark());
            ArraysParams arraysParams = new ArraysParams(jsonArray.toArray(new Long[jsonArray.size()]));
            if (Objects.isNull(arraysParams) || arraysParams.getIds().length == 0) {
                throw ExceptionResultEnum.ERROR.exception("数组id为空");
            }

            //查询examDetail
            List<ExamDetail> examDetailList = examDetailService.listByIds(Arrays.asList(arraysParams.getIds()));
            if (Objects.nonNull(examDetailList)) {
                Set<Long> attachmentIds = new HashSet<>();
                Set<Long> allAttachmentIds = examDetailList.stream().map(ExamDetail::getAttachmentId).collect(Collectors.toSet());
                if (!CollectionUtils.isEmpty(allAttachmentIds)) {
                    attachmentIds.addAll(allAttachmentIds);
                }
                Set<Long> cardAttachmentIds = examDetailList.stream().map(ExamDetail::getCardAttachmentId).collect(Collectors.toSet());
                if (!CollectionUtils.isEmpty(cardAttachmentIds)) {
                    attachmentIds.addAll(cardAttachmentIds);
                }
                List<BasicAttachment> basicAttachmentList = basicAttachmentService.listByIds(attachmentIds);

                if (Objects.nonNull(basicAttachmentList) && basicAttachmentList.size() > 0) {
                    LocalDateTime nowTime = LocalDateTime.now();
                    StringJoiner stringJoiner = new StringJoiner("")
                            .add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
                    StringJoiner dirName = new StringJoiner("")
                            .add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                            .add(String.valueOf(nowTime.getYear())).add(File.separator)
                            .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                            .add(String.format("%02d", nowTime.getDayOfMonth()))
                            .add(File.separator).add(SystemConstant.getUuid()).add(SystemConstant.ZIP_PREFIX);
                    File zipFile = new File(stringJoiner.toString() + dirName.toString());
                    if (!zipFile.getParentFile().exists()) {
                        zipFile.getParentFile().mkdirs();
                        zipFile.createNewFile();
                    }
                    List<File> sourceFiles = new ArrayList<>();
                    for (BasicAttachment basicAttachment : basicAttachmentList) {
                        JSONObject jsonObject = JSONObject.parseObject(basicAttachment.getPath());
                        UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));

                        StringJoiner stringJoinerPdf = new StringJoiner("")
                                .add(SystemConstant.TEMP_FILES_DIR).add(File.separator)
                                .add((String) jsonObject.get(SystemConstant.PATH));
//                        sourceFiles.add(ossUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), stringJoinerPdf.toString()));
                        sourceFiles.add(fileStoreUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), stringJoinerPdf.toString(), uploadFileEnum.getFssType()));
                    }
                    FileUtil.doZip(zipFile, sourceFiles);
                    String ossDirName = dirName.toString().replaceAll("\\\\", "/");
                    fileStoreUtil.ossUpload(ossDirName, zipFile, BinaryUtil.toBase64String(HexUtils.decodeHex(DigestUtils.md5Hex(new FileInputStream(zipFile)))), fileStoreUtil.getUploadEnumByPath(ossDirName).getFssType());
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put(SystemConstant.PATH, ossDirName);
                    jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
                    jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
                    tbTask.setResultFilePath(jsonObject.toJSONString());
                    if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
                        for (File file : sourceFiles) {
                            file.delete();
                        }
                        zipFile.delete();
                    }
                }
                map.computeIfAbsent(SystemConstant.SIZE, v -> attachmentIds.size());
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return map;
    }

    @Override
    @Transactional
    public Map<String, Object> executeExportSampleLogic(Map<String, Object> map) throws Exception {
        int count = 0;
        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        LocalDateTime nowTime = LocalDateTime.now();
        StringJoiner zipJoiner = new StringJoiner("")
                .add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
        StringJoiner dirName = new StringJoiner("")
                .add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                .add(String.valueOf(nowTime.getYear())).add(File.separator)
                .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                .add(String.format("%02d", nowTime.getDayOfMonth()))
                .add(File.separator).add(SystemConstant.getUuid()).add(SystemConstant.ZIP_PREFIX);
        String dirNameTmp = dirName.toString().replaceAll("\\\\", "/");
        File zipFile = new File(zipJoiner.toString() + dirNameTmp);
        if (!zipFile.getParentFile().exists()) {
            zipFile.getParentFile().mkdirs();
            zipFile.createNewFile();
        }

        // 跟文件路径
        String zipLocalRootPath = SystemConstant.TEMP_FILES_DIR + File.separator + System.currentTimeMillis();
        Long[] ids = (Long[]) map.get("ids");
        for (Long id : ids) {
            ExamTask examTask = examTaskService.getById(id);
            if (Objects.isNull(examTask)) {
                throw ExceptionResultEnum.ERROR.exception("未找到命题任务");
            }
            String examTaskSign = examTask.getCourseName() + "-" + examTask.getPaperNumber();
            String firstPath = zipLocalRootPath + File.separator + examTaskSign;
//            List<ExamTaskDetail> examTaskDetailList = examTaskDetailService.list(new QueryWrapper<ExamTaskDetail>().lambda().eq(ExamTaskDetail::getExamTaskId, id));
//            if (examTaskDetailList.size() != 1) {
//                throw ExceptionResultEnum.ERROR.exception("获取命题任务详情失败");
//            }
//            ExamTaskDetail examTaskDetail = examTaskDetailList.get(0);
            ReviewSampleDto reviewSampleDto = examTaskService.findReviewSampleInfoByExamTaskId(id);


            // 处理试卷样品
            List<Map> paperInfo = JSONObject.parseArray(reviewSampleDto.getPaperAttachmentIds(), Map.class);
            if (Objects.isNull(paperInfo)) {
                throw ExceptionResultEnum.ERROR.exception("试卷信息不存在");
            }
            Set<Long> attPaperIds = new HashSet<>();
            for (Map paperMap : paperInfo) {
                if (Objects.nonNull(paperMap.get("attachmentId")) && String.valueOf(paperMap.get("attachmentId")).length() > 0 && !String.valueOf(paperMap.get("attachmentId")).equals("null")) {
                    Long attachmentId = Long.valueOf(String.valueOf(paperMap.get("attachmentId")));
                    attPaperIds.add(attachmentId);
                }
            }
            if (attPaperIds.size() > 0) {
                List<BasicAttachment> paperAttachmentList = basicAttachmentService.listByIds(attPaperIds);
                for (BasicAttachment paperAttachment : paperAttachmentList) {
                    JSONObject jsonObject = JSONObject.parseObject(paperAttachment.getPath());
                    UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));
                    String paperPath = firstPath + File.separator + "试卷" + File.separator + paperAttachment.getName() + paperAttachment.getType();
//                    ossUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), paperPath);
                    fileStoreUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), paperPath, uploadFileEnum.getFssType());
                    count++;
                }
            }

            // 处理审核样品
            List<Map> confirmInfo = JSONObject.parseArray(reviewSampleDto.getPaperConfirmAttachmentIds(), Map.class);
            Set<Long> attConfirmIds = new HashSet<>();
            for (Map confirmMap : confirmInfo) {
                if (Objects.isNull(confirmMap.get("attachmentId"))) {
                    throw ExceptionResultEnum.ERROR.exception("未找到附件id");
                }
                Long attachmentId = Long.valueOf(String.valueOf(confirmMap.get("attachmentId")));
                attConfirmIds.add(attachmentId);
            }
            if (attConfirmIds.size() > 0) {
                List<BasicAttachment> confirmAttachmentList = basicAttachmentService.listByIds(attConfirmIds);
                for (BasicAttachment confirmAttachment : confirmAttachmentList) {
                    JSONObject jsonObject = JSONObject.parseObject(confirmAttachment.getPath());
                    UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));
                    String confirmPath = firstPath + File.separator + "审核样本" + File.separator + confirmAttachment.getName() + confirmAttachment.getType();
//                    ossUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), confirmPath);
                    fileStoreUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), confirmPath, uploadFileEnum.getFssType());
                    count++;
                }
            }

            // 处理题卡
            Long cardId = reviewSampleDto.getCardId();
            ExamCard examCard = examCardService.getById(cardId);
            if (Objects.isNull(examCard)) {
                throw ExceptionResultEnum.ERROR.exception("找不到答题卡");
            }
            MakeMethodEnum makeMethodEnum = examCard.getMakeMethod();
            if (MakeMethodEnum.SELECT.equals(makeMethodEnum) && CardCreateMethodEnum.UPLOAD.equals(examCard.getCreateMethod())) {
                Long attachmentId = examCard.getAttachmentId();
                if (attachmentId == null || attachmentId == 0) {
                    throw ExceptionResultEnum.ERROR.exception("找不到模板对应的附件");
                }
                BasicAttachment cardAttachment = basicAttachmentService.getById(attachmentId);
                if (Objects.isNull(cardAttachment)) {
                    throw ExceptionResultEnum.ERROR.exception("找不到附件");
                }
                JSONObject jsonObject = JSONObject.parseObject(cardAttachment.getPath());
                String cardPath = firstPath + File.separator + "题卡" + File.separator + cardAttachment.getName() + cardAttachment.getType();
                UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));
//                ossUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), cardPath);
                fileStoreUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), cardPath, uploadFileEnum.getFssType());
            } else {
                List<ExamCardDetail> examCardDetailList = examCardDetailService.list(new QueryWrapper<ExamCardDetail>().lambda().eq(ExamCardDetail::getCardId, cardId));
                if (examCardDetailList.size() != 1) {
                    throw ExceptionResultEnum.ERROR.exception("题卡明细信息异常");
                }
                ExamCardDetail examCardDetail = examCardDetailService.getByCardId(cardId);
                String htmlContent = examCardDetail.getHtmlContent();
                byte[] bytes = htmlContent.getBytes();
                String cardPath = firstPath + File.separator + "题卡" + File.separator + examCard.getTitle() + SystemConstant.HTML_PREFIX;
                File localFile = new File(cardPath);
                if (!localFile.getParentFile().exists()) {
                    localFile.getParentFile().mkdirs();
                }
                FileCopyUtils.copy(bytes, localFile);
            }
            count++;
        }
        ZipUtil.zip(zipLocalRootPath, zipFile.getPath(), false);
//        ossUtil.ossUpload(dirNameTmp, zipFile, BinaryUtil.toBase64String(HexUtils.decodeHex(DigestUtils.md5Hex(new FileInputStream(zipFile)))));
        fileStoreUtil.ossUpload(dirNameTmp, zipFile, BinaryUtil.toBase64String(HexUtils.decodeHex(DigestUtils.md5Hex(new FileInputStream(zipFile)))), fileStoreUtil.getUploadEnumByPath(dirNameTmp).getFssType());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(SystemConstant.PATH, dirNameTmp);
        jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
        jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
        tbTask.setResultFilePath(jsonObject.toJSONString());
        ConvertUtil.delFolder(zipLocalRootPath);
        zipFile.delete();
        map.put("count", count);
        return map;
    }

    @Override
    public Map<String, Object> executeExportPaperAndCardLogic(Map<String, Object> map) throws Exception {
        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        String yyyyMMddHH24mmss = DateUtil.format(new Date(), "yyyyMMddHHmmss");
        BasicSchool basicSchool = commonCacheService.schoolCache(tbTask.getSchoolId());
        LocalDateTime nowTime = LocalDateTime.now();
        StringJoiner zipJoiner = new StringJoiner("")
                .add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
        StringJoiner dirName = new StringJoiner("")
                .add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                .add(String.valueOf(nowTime.getYear())).add(File.separator)
                .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                .add(String.format("%02d", nowTime.getDayOfMonth()))
                .add(File.separator)
                .add(yyyyMMddHH24mmss).add("_").add(basicSchool.getName()).add("_").add("试卷导出文件").add(SystemConstant.ZIP_PREFIX);
        String dirNameTmp = dirName.toString().replaceAll("\\\\", "/");

        // 根文件路径
        String zipLocalRootPath = SystemConstant.TEMP_FILES_DIR + File.separator + System.currentTimeMillis();

        List<ExamTaskDetailDto> examTasks = (List<ExamTaskDetailDto>) map.get("examTasks");
        for (ExamTaskDetailDto examTask : examTasks) {
            ExamTaskDetail examTaskDetail = examTaskDetailService.getByExamTaskId(Long.valueOf(examTask.getId()));

            // 试卷
            String paperAttachmentIds = examTaskDetail.getPaperAttachmentIds();
            if (StringUtils.isNotBlank(paperAttachmentIds)) {
                List<Map> paperInfo = JSONObject.parseArray(paperAttachmentIds, Map.class);
                if (Objects.isNull(paperInfo)) {
                    throw ExceptionResultEnum.ERROR.exception("试卷信息不存在");
                }
                for (Map paperMap : paperInfo) {
                    if (Objects.nonNull(paperMap.get("attachmentId")) && String.valueOf(paperMap.get("attachmentId")).length() > 0 && !String.valueOf(paperMap.get("attachmentId")).equals("null")) {
                        String name = paperMap.get("name").toString();
                        Long attachmentId = Long.valueOf(String.valueOf(paperMap.get("attachmentId")));
                        BasicAttachment attachment = basicAttachmentService.getById(attachmentId);
                        if (Objects.nonNull(attachment)) {
                            JSONObject jsonObject = JSONObject.parseObject(attachment.getPath());
                            String paperPath = zipLocalRootPath + File.separator + examTask.getPaperNumber() + File.separator + "试卷" + "_" + examTask.getPaperNumber() + "_" + name + attachment.getType();
                            UploadFileEnum uploadFileEnum = UploadFileEnum.valueOf((String) jsonObject.get(SystemConstant.UPLOAD_TYPE));

//                            ossUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), paperPath);
                            fileStoreUtil.ossDownload((String) jsonObject.get(SystemConstant.PATH), paperPath, uploadFileEnum.getFssType());
                        }
                    }
                }
            }

            // 题卡
            // 处理题卡
            ExamCard examCard = examCardService.getById(examTaskDetail.getCardId());
            if (Objects.isNull(examCard)) {
                throw ExceptionResultEnum.ERROR.exception("找不到答题卡");
            }
            MakeMethodEnum makeMethodEnum = examCard.getMakeMethod();

            String cardPath = zipLocalRootPath + File.separator + examTask.getPaperNumber();
            String cardHtmlPath = cardPath + File.separator + "题卡" + "_" + examTask.getPaperNumber() + SystemConstant.HTML_PREFIX;
            String cardPdfPath = cardPath + File.separator + "题卡" + "_" + examTask.getPaperNumber() + SystemConstant.PDF_PREFIX;
            // 通用题卡
            ExamCardDetail examCardDetail = examCardDetailService.getByCardId(examCard.getId());
            String htmlContent;
            if (MakeMethodEnum.SELECT.equals(makeMethodEnum)) {
                htmlContent = createPdfUtil.resetHtmlTemplateBar(examCardDetail.getHtmlContent());
            } else {
                BasicCardRule basicCardRule = basicCardRuleService.getById(examTask.getCardRuleId());
                htmlContent = createPdfUtil.replaceHtmlCard(examCardDetail, basicCardRule);
            }
            // html
            File localFile = new File(cardHtmlPath);
            if (!localFile.getParentFile().exists()) {
                localFile.getParentFile().mkdirs();
            }
            // 生成html文件
            FileCopyUtils.copy(htmlContent.getBytes(), localFile);
            // 转pdf文件
            File file = new File(cardPdfPath);
            if (!file.exists()) {
                file.createNewFile();
            }
            HtmlToPdfUtil.convert(cardHtmlPath, cardPdfPath, PageSizeEnum.A3);
        }

        File zipFile = new File(zipJoiner.toString() + dirNameTmp);
        if (!zipFile.getParentFile().exists()) {
            zipFile.getParentFile().mkdirs();
        }
        if (!zipFile.exists()) {
            zipFile.createNewFile();
        }

        ZipUtil.zip(zipLocalRootPath, zipFile.getPath(), false);
//        ossUtil.ossUpload(dirNameTmp, zipFile, BinaryUtil.toBase64String(HexUtils.decodeHex(DigestUtils.md5Hex(new FileInputStream(zipFile)))));
        fileStoreUtil.ossUpload(dirNameTmp, zipFile, BinaryUtil.toBase64String(HexUtils.decodeHex(DigestUtils.md5Hex(new FileInputStream(zipFile)))), fileStoreUtil.getUploadEnumByPath(dirNameTmp).getFssType());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(SystemConstant.PATH, dirNameTmp);
        jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
        jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
        tbTask.setResultFilePath(jsonObject.toJSONString());
        ConvertUtil.delFolder(zipLocalRootPath);
        zipFile.delete();
        map.put(SystemConstant.DATA_COUNT, examTasks.size());
        return map;
    }


    @Transactional
    @Override
    public Map<String, Object> executeImportBasicStudentLogic(Map<String, Object> map) throws Exception {
        InputStream inputStream = (InputStream) map.get("inputStream");
        System.out.println(inputStream);
        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(BasicStudentImportDto.class, DescribeImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            List<ExcelError> excelErrorTemp = new ArrayList<>();
            Map<String, String> checkCodeMap = new HashMap<>();
            Map<String, String> checkPhoneMap = new HashMap<>();
            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> basicStudentImportDtoList = excelMap.get(i);
                assert basicStudentImportDtoList != null;
                if (basicStudentImportDtoList.get(0) instanceof DescribeImportDto) {
                    continue;
                }
                for (int y = 0; y < Objects.requireNonNull(basicStudentImportDtoList).size(); y++) {
                    BasicStudentImportDto basicStudentImportDto = (BasicStudentImportDto) basicStudentImportDtoList.get(y);
                    String studentName = basicStudentImportDto.getStudentName();
                    String studentCode = basicStudentImportDto.getStudentCode();
                    String phoneNumber = basicStudentImportDto.getPhoneNumber();
                    String clazzName = basicStudentImportDto.getClazzName();

                    // 检验excel中
                    // 检验学号
                    if (SystemConstant.strNotNull(studentCode)) {
                        if (checkCodeMap.containsKey(studentCode)) {
                            throw ExceptionResultEnum.ERROR.exception("导入的excel中包含在重复的【学生编号】：" + studentCode);
                        } else {
                            checkCodeMap.put(studentCode, studentName);
                        }
                    }
                    // 如果电话有值则检验电话excel中唯一性
                    if (SystemConstant.strNotNull(phoneNumber)) {
                        if (checkPhoneMap.containsKey(phoneNumber)) {
                            throw ExceptionResultEnum.ERROR.exception("导入的excel中包含在重复的【电话号码】：" + phoneNumber);
                        } else {
                            checkPhoneMap.put(phoneNumber, studentCode);
                        }
                    }

                    excelErrorTemp.addAll(ExcelUtil.checkExcelField(basicStudentImportDto, y, i));
                    if (Objects.isNull(studentCode) || studentCode.length() > 30 || !studentCode.matches(SystemConstant.REGULAR_EXPRESSION_OF_CODE)) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[学号]不符合输入规范"));
                    }
                    if (Objects.isNull(studentName) || studentName.length() > 30) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[学生名称]不符合输入规范"));
                    }
                    if (Objects.nonNull(phoneNumber) && !phoneNumber.matches(SystemConstant.REGULAR_EXPRESSION_OF_PHONE)) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[电话号码]不符合输入规范"));
                    }
                }
            }
            if (excelErrorTemp.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(excelErrorTemp));
            }
            return finalExcelList;
        });
        return basicStudentService.executeBasicStudentImportLogic(finalList, map);
    }

    @Transactional
    @Override
    public Map<String, Object> executeImportBasicCourseLogic(Map<String, Object> map) throws Exception {

        InputStream inputStream = (InputStream) map.get("inputStream");
        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(BasicCourseImportDto.class, DescribeImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            List<ExcelError> excelErrorTemp = new ArrayList<>();
            Map<String, BasicCourseImportDto> courseDtoMap = new HashMap<>();
            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> basicCourseImportDtoList = excelMap.get(i);
                assert basicCourseImportDtoList != null;
                if (basicCourseImportDtoList.get(0) instanceof DescribeImportDto) {
                    continue;
                }
                map.put("dataCount", basicCourseImportDtoList.size());
                List<BasicCourseImportDto> duplicateData = new ArrayList<>();
                for (int y = 0; y < Objects.requireNonNull(basicCourseImportDtoList).size(); y++) {
                    BasicCourseImportDto basicCourseImportDto = (BasicCourseImportDto) basicCourseImportDtoList.get(y);
                    String courseName = basicCourseImportDto.getCourseName();
                    String courseCode = basicCourseImportDto.getCourseCode();
                    String teachingRoomName = basicCourseImportDto.getTeachingRoomName();
                    String clazz = basicCourseImportDto.getClazz();

                    if (courseDtoMap.containsKey(courseCode)) {
                        BasicCourseImportDto primaryCell = courseDtoMap.get(courseCode);
                        String primaryName = primaryCell.getCourseName();
                        String primaryTeachingRoomName = primaryCell.getTeachingRoomName();
                        if (!Objects.equals(primaryName, courseName)) {
                            throw ExceptionResultEnum.ERROR.exception("【课程编号】 ： " + courseCode + ",存在不同的【课程名称】");
                        }
                        if (!Objects.equals(primaryTeachingRoomName, teachingRoomName)) {
                            throw ExceptionResultEnum.ERROR.exception("【课程编号】 ： " + courseCode + ",存在不同的【所属教研室】");
                        }
                        String primaryClazz = primaryCell.getClazz();
                        if (SystemConstant.strNotNull(clazz)) {
                            primaryClazz = primaryClazz + SystemConstant.COMMA + clazz;
                            primaryCell.setClazz(primaryClazz);
                        }
                        duplicateData.add(basicCourseImportDto);
                    } else {
                        courseDtoMap.put(courseCode, basicCourseImportDto);
                    }

                    excelErrorTemp.addAll(ExcelUtil.checkExcelField(basicCourseImportDto, y, i));
                    if (Objects.isNull(courseCode) || courseCode.length() > 30 || !courseCode.matches(SystemConstant.REGULAR_EXPRESSION_OF_CODE)) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程编号]不符合输入规范"));
                    }
                    if (Objects.isNull(courseName) || courseName.length() > 30) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[课程名称]不符合输入规范"));
                    }
                }
                // 删除重复的（需要累加的）excel数据
                basicCourseImportDtoList.removeAll(duplicateData);
            }
            if (excelErrorTemp.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(excelErrorTemp));
            }
            return finalExcelList;
        });
        return basicCourseService.executeBasicCourseImportLogic(finalList, map);
    }

    @Transactional
    @Override
    public Map<String, Object> executeImportSysUserLogic(Map<String, Object> map) throws Exception {
        InputStream inputStream = (InputStream) map.get("inputStream");
        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(SysUserImportDto.class, DescribeImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            List<ExcelError> excelErrorTemp = new ArrayList<>();
            Map<String, SysUserImportDto> checkDtoMap = new HashMap<>();

            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> sysUserImportDtoList = excelMap.get(i);
                assert sysUserImportDtoList != null;
                if (sysUserImportDtoList.get(0) instanceof DescribeImportDto) {
                    continue;
                }
                map.put("dataCount", sysUserImportDtoList.size());
                List<SysUserImportDto> duplicateData = new ArrayList<>();
                for (int y = 0; y < Objects.requireNonNull(sysUserImportDtoList).size(); y++) {
                    SysUserImportDto sysUserImportDto = (SysUserImportDto) sysUserImportDtoList.get(y);
                    String name = sysUserImportDto.getName();
                    String code = sysUserImportDto.getCode();
                    String phoneNumber = sysUserImportDto.getPhoneNumber();
                    String orgName = sysUserImportDto.getOrgName();
                    String roleName = sysUserImportDto.getRoleName();

                    if (checkDtoMap.containsKey(code)) {
                        SysUserImportDto primaryCell = checkDtoMap.get(code);
                        String priName = primaryCell.getName();
                        String priPhoneNumber = primaryCell.getPhoneNumber();
                        String priOrgName = primaryCell.getOrgName();
                        if (!Objects.equals(priName, name)) {
                            throw ExceptionResultEnum.ERROR.exception("【工号】 ：" + code + ",的用户存在不同的用户名称异常");
                        }
                        if (!Objects.equals(priPhoneNumber, phoneNumber)) {
                            throw ExceptionResultEnum.ERROR.exception("【工号】 ：" + code + ",的用户存在不同的手机号异常");
                        }
                        if (!Objects.equals(priOrgName, orgName)) {
                            throw ExceptionResultEnum.ERROR.exception("【工号】 ：" + code + ",的用户存在不同的组织架构异常");
                        }
                        String priRoleName = primaryCell.getRoleName();
                        if (SystemConstant.strNotNull(roleName)) {
                            priRoleName = priRoleName + SystemConstant.COMMA + roleName;
                            primaryCell.setRoleName(priRoleName);
                        }
                        duplicateData.add(sysUserImportDto);
                    } else {
                        checkDtoMap.put(code, sysUserImportDto);
                    }

                    excelErrorTemp.addAll(ExcelUtil.checkExcelField(sysUserImportDto, y, i));
                    if (Objects.isNull(code) || code.length() > 30 || !code.matches(SystemConstant.REGULAR_EXPRESSION_OF_CODE)) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[工号]不符合输入规范"));
                    }
                    if (Objects.isNull(name) || name.length() > 30) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[姓名]不符合输入规范"));
                    }
                    if (Objects.nonNull(phoneNumber) && !phoneNumber.matches(SystemConstant.REGULAR_EXPRESSION_OF_PHONE)) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[电话号码]不符合输入规范"));
                    }
                }
                sysUserImportDtoList.removeAll(duplicateData);
            }
            if (excelErrorTemp.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(excelErrorTemp));
            }
            return finalExcelList;
        });
        return sysUserService.executeSysUserImportLogic(finalList, map);
    }

    @Transactional
    @Override
    public Map<String, Object> executeImportBasicClazzLogic(Map<String, Object> map) throws Exception {
        InputStream inputStream = (InputStream) map.get("inputStream");
        System.out.println(inputStream);
        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(BasicClazzImportDto.class, DescribeImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            List<ExcelError> excelErrorTemp = new ArrayList<>();
            Map<String, String> checkNameMap = new HashMap<>();
            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> basicClazzImportDtoList = excelMap.get(i);
                assert basicClazzImportDtoList != null;
                if (basicClazzImportDtoList.get(0) instanceof DescribeImportDto) {
                    continue;
                }
                for (int y = 0; y < Objects.requireNonNull(basicClazzImportDtoList).size(); y++) {
                    BasicClazzImportDto basicClazzImportDto = (BasicClazzImportDto) basicClazzImportDtoList.get(y);
                    String clazzName = basicClazzImportDto.getClazzName();
                    String campusName = basicClazzImportDto.getCampusName();

                    // 检验excel中
                    // 检验学号
                    if (checkNameMap.containsKey(clazzName)) {
                        throw ExceptionResultEnum.ERROR.exception("导入的excel中包含在重复的【班级名称】：" + clazzName);
                    } else {
                        checkNameMap.put(clazzName, campusName);
                    }

                    excelErrorTemp.addAll(ExcelUtil.checkExcelField(basicClazzImportDto, y, i));
                    if (Objects.isNull(clazzName) || clazzName.length() > 50) {
                        excelErrorTemp.add(new ExcelError(y + 1, "excel第" + (i + 1) + "个sheet第" + (y + 1) + "行[学号]不符合输入规范"));
                    }
                }
            }
            if (excelErrorTemp.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(excelErrorTemp));
            }
            return finalExcelList;
        });
        return basicClazzService.executeBasicClazzImportLogic(finalList, map);
    }


    @Override
    @Transactional
    public Map<String, Object> executeImportStatisticsLogic(Map<String, Object> map) throws Exception {
        InputStream inputStream = (InputStream) map.get("inputStream");
        Long examId = SystemConstant.convertIdToLong(String.valueOf(map.get("examId")));
        SysUser sysUser = (SysUser) map.get(SystemConstant.USER);

        List<LinkedMultiValueMap<Integer, Object>> finalList = ExcelUtil.excelReader(inputStream, Lists.newArrayList(StatisticsImportDto.class), (finalExcelList, finalColumnNameList, finalExcelErrorList) -> {
            // 只允许导入一个sheet
            if (finalExcelList.size() > 1) {
                throw ExceptionResultEnum.ERROR.exception("excel中只允许有一个sheet");
            }
            if (finalExcelErrorList.size() > 0) {
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(finalExcelErrorList));
            }
            List<ExcelError> excelErrorTemp = new ArrayList<>();
            // 校验系统中是否存在
            Map<String, SysOrg> collegeOrgMap = new HashMap<>();
            Map<String, SysOrg> teachingRoomMap = new HashMap<>();
            Map<String, BasicCourse> courseMap = new HashMap<>();
            Map<String, DictionaryResult> clazzMap = new HashMap<>();
            String batchNo = SystemConstant.getUuid();
            List<TCStatisticsTemp> tcStatisticsImportTempList = new ArrayList<>();

            for (int i = 0; i < finalExcelList.size(); i++) {
                LinkedMultiValueMap<Integer, Object> excelMap = finalExcelList.get(i);
                List<Object> statisticsTempList = excelMap.get(i);
                for (int y = 0; y < Objects.requireNonNull(statisticsTempList).size(); y++) {
                    StatisticsImportDto statisticsImportDto = (StatisticsImportDto) statisticsTempList.get(y);
                    SysOrg collegeOrg = this.validSysOrgExists(collegeOrgMap, statisticsImportDto.getCollegeName(), sysUser.getSchoolId(), OrgTypeEnum.COLLEGE, excelErrorTemp, (y + 1), (i + 1), "开课学院");
                    SysOrg teachingRoomOrg = this.validSysOrgExists(teachingRoomMap, statisticsImportDto.getTeachingRoomName(), sysUser.getSchoolId(), OrgTypeEnum.TEACHING_ROOM, excelErrorTemp, (y + 1), (i + 1), "开课部门");
                    BasicCourse basicCourse = this.validBasicCourseExists(courseMap, statisticsImportDto.getCourseName(), sysUser.getSchoolId(), statisticsImportDto.getCourseCode(), excelErrorTemp, (y + 1), (i + 1));
                    String teacherName = statisticsImportDto.getTeacherName();
                    String clazzNames = statisticsImportDto.getClazzName();
                    List<DictionaryResult> dictionaryResultList = new ArrayList<>();
                    for (String clazzName : clazzNames.split(",")) {
                        DictionaryResult clazz = this.validBasicClazzExists(clazzMap, clazzName, sysUser.getSchoolId(), excelErrorTemp, (y + 1), (i + 1));
                        dictionaryResultList.add(clazz);
                    }
                    String clazzIds = dictionaryResultList.stream().map(e -> String.valueOf(e.getId())).collect(Collectors.joining(","));


                    if (excelErrorTemp.size() == 0) {

                        TCStatisticsTemp tcStatistics = new TCStatisticsTemp(
                                examId,
                                collegeOrg.getId(),
                                collegeOrg.getName(),
                                teachingRoomOrg.getId(),
                                teachingRoomOrg.getName(),
                                basicCourse.getName(),
                                basicCourse.getCode(),
                                teacherName,
                                clazzIds,
                                clazzNames,
                                batchNo,
                                sysUser.getId());
                        tcStatisticsImportTempList.add(tcStatistics);
                    }
                }
            }
            if (excelErrorTemp.size() > 0) {
                List<String> errors = excelErrorTemp.stream().map(ExcelError::getExcelErrorType).collect(Collectors.toList());
                throw ExceptionResultEnum.ERROR.exception(JSONObject.toJSONString(errors));
            }
            //加入删除(根据考试id和当前登录人)
            tcStatisticsService.removeImportData(examId, sysUser.getId());
            tcStatisticsTempService.saveBatch(tcStatisticsImportTempList);
            map.put("dataCount", tcStatisticsImportTempList.size());
            tcStatisticsService.importJoinData(tcStatisticsImportTempList);
            tcStatisticsTempService.removeByIds(tcStatisticsImportTempList.stream().map(BaseEntity::getId).collect(Collectors.toSet()));
            return finalExcelList;
        });
        return map;
    }

    /**
     * 成绩导出
     *
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> executeExportScoreLogic(Map<String, Object> map) throws Exception {
        ByteArrayOutputStream fos = null;
        try {
            SysUser sysUser = (SysUser) map.get(SystemConstant.USER);
            Long semesterId = null, examId = null, clazzId = null;
            String courseCode = null;
            semesterId = Objects.nonNull(map.get("semesterId")) ? (Long) map.get(semesterId) : null;
            examId = Objects.nonNull(map.get("examId")) ? (Long) map.get(examId) : null;
            clazzId = Objects.nonNull(map.get("clazzId")) ? (Long) map.get("clazzId") : null;
            courseCode = Objects.nonNull(map.get("courseCode")) ? (String) map.get("courseCode") : null;

            fos = new ByteArrayOutputStream();
            List<TSyncExamStudentScoreResult> tSyncExamStudentScoreResultList = tSyncExamStudentScoreService.export(sysUser.getSchoolId(), semesterId, examId, clazzId, courseCode);
            ExcelUtil.excelMake(TSyncExamStudentScoreResult.class, tSyncExamStudentScoreResultList, fos);
            String excelExportFilePath = printCommonService.saveTaskAttachment(fos, (boolean) map.get(SystemConstant.OSS));
            map.computeIfAbsent("count", v -> Objects.isNull(tSyncExamStudentScoreResultList) ? 0 : tSyncExamStudentScoreResultList.size());
            TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
            tbTask.setResultFilePath(excelExportFilePath);
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(fos)) {
                fos.flush();
                fos.close();
            }
        }
        return map;
    }

    /**
     * 成绩轨迹下载
     *
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    @Transactional
    public Map<String, Object> executeDownloadScoreLogic(Map<String, Object> map) throws Exception {
        File zipFile = null;
        List<File> sourceFiles = null;
        List<TSyncExamStudentScore> errorTSyncExamStudentScoreList = null;
        try {
            SysUser sysUser = (SysUser) map.get(SystemConstant.USER);
            Long semesterId = null, examId = null, clazzId = null;
            String courseCode = null;
            semesterId = Objects.nonNull(map.get("semesterId")) ? (Long) map.get("semesterId") : null;
            examId = Objects.nonNull(map.get("examId")) ? (Long) map.get("examId") : null;
            clazzId = Objects.nonNull(map.get("clazzId")) ? (Long) map.get("clazzId") : null;
            courseCode = Objects.nonNull(map.get("courseCode")) ? (String) map.get("courseCode") : null;

            List<TSyncExamStudentScoreResult> tSyncExamStudentScoreResultList = tSyncExamStudentScoreService.export(sysUser.getSchoolId(), semesterId, examId, clazzId, courseCode);
            if (Objects.nonNull(tSyncExamStudentScoreResultList) && tSyncExamStudentScoreResultList.size() > 0) {
                List<TSyncExamStudentScore> tSyncExamStudentScoreList = new Gson().fromJson(JacksonUtil.parseJson(tSyncExamStudentScoreResultList), new TypeToken<List<TSyncExamStudentScore>>() {
                }.getType());
                LocalDateTime nowTime = LocalDateTime.now();
                StringJoiner stringJoiner = new StringJoiner("");
                stringJoiner.add(SystemConstant.TEMP_FILES_DIR).add(File.separator);
                StringJoiner dirZipName = new StringJoiner("");
                dirZipName.add(UploadFileEnum.FILE.getTitle()).add(File.separator)
                        .add(String.valueOf(nowTime.getYear())).add(File.separator)
                        .add(String.format("%02d", nowTime.getMonthValue())).add(File.separator)
                        .add(String.format("%02d", nowTime.getDayOfMonth()))
                        .add(File.separator).add(SystemConstant.getUuid()).add(SystemConstant.ZIP_PREFIX);
                zipFile = new File(stringJoiner.toString() + dirZipName.toString());
                if (!zipFile.exists()) {
                    zipFile.getParentFile().mkdirs();
                    zipFile.createNewFile();
                }
                sourceFiles = new LinkedList<>();
                List<TSyncExamStudentScore> updateTSyncExamStudentScoreList = new ArrayList<>();
                errorTSyncExamStudentScoreList = new ArrayList<>();
                for (TSyncExamStudentScore t : tSyncExamStudentScoreList) {
                    try {
                        boolean update = Objects.isNull(t.getTrajectoryUrls()) ? true : false;
                        t = tSyncExamStudentScoreService.createImageTrajectory(t, ImageTrajectoryEnum.DOWNLOAD);
                        if (Objects.nonNull(t.getTrajectoryFileList())) {
                            File[] files = t.getTrajectoryFileList().get(0).getParentFile().listFiles();
                            List<File> fileList = new ArrayList<>(Arrays.asList(files));
                            fileList.removeAll(t.getTrajectoryFileList());
                            if (Objects.nonNull(dictionaryConfig.sysDomain()) && dictionaryConfig.sysDomain().isOss()) {
                                for (File file : fileList) {
                                    file.delete();
                                }
                            }
                            sourceFiles.add(t.getTrajectoryFileList().get(0).getParentFile());
                        } else {
                            errorTSyncExamStudentScoreList.add(t);
                        }
                        if (update || Objects.isNull(t.getTrajectoryUrls())) {
                            updateTSyncExamStudentScoreList.add(t);
                        }
                    } catch (Exception e) {
                        log.error(SystemConstant.LOG_ERROR, e);
                        errorTSyncExamStudentScoreList.add(t);
                    }
                }
                tSyncExamStudentScoreService.saveOrUpdateBatch(updateTSyncExamStudentScoreList);
                if (Objects.nonNull(sourceFiles) && sourceFiles.size() > 0) {
                    FileUtil.doZip(zipFile, sourceFiles);
                    boolean oss = (boolean) map.get(SystemConstant.OSS);
                    JSONObject jsonObject = new JSONObject();
                    if (oss) {//上传至oss
                        fileStoreUtil.ossUpload(dirZipName.toString(), zipFile, DigestUtils.md5Hex(new FileInputStream(zipFile)), UploadFileEnum.FILE.getFssType());
                        jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
                        jsonObject.put(SystemConstant.PATH, dirZipName.toString());
                    } else {
                        jsonObject.put(SystemConstant.TYPE, SystemConstant.LOCAL);
                        jsonObject.put(SystemConstant.PATH, stringJoiner.toString() + dirZipName.toString());
                    }
                    jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
                    TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
                    tbTask.setResultFilePath(jsonObject.toJSONString());
                }
            }
            map.computeIfAbsent("count", v -> tSyncExamStudentScoreResultList.size());
            if (Objects.nonNull(errorTSyncExamStudentScoreList) && errorTSyncExamStudentScoreList.size() > 0) {
                StringJoiner stringJoiner = new StringJoiner("").add("\r\n");
                for (TSyncExamStudentScore t : errorTSyncExamStudentScoreList) {
                    stringJoiner.add("[").add(t.getName()).add(",").add(t.getExamNumber()).add("]\r\n");
                }
                List<TSyncExamStudentScore> finalErrorTSyncExamStudentScoreList = errorTSyncExamStudentScoreList;
                map.computeIfAbsent("error", v -> "其中未下载成功数据" + finalErrorTSyncExamStudentScoreList.size() + "条:" + stringJoiner.toString());
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
        } finally {
            if (Objects.nonNull(zipFile)) {
                zipFile.delete();
            }
        }
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Map<String, Object> executeDownloadPaperFileBatch(Map<String, Object> map) throws Exception {
        TBTask tbTask = (TBTask) map.get(SystemConstant.TASK);
        DownloadPaperFileParam downloadPaperFileParam = (DownloadPaperFileParam) map.get("downloadPaperFileParam");
        Long schoolId = tbTask.getSchoolId();
        Long semesterId = downloadPaperFileParam.getSemesterId();
        Long examId = downloadPaperFileParam.getExamId();
        Long orgId = downloadPaperFileParam.getOrgId();
        Boolean namedByCourseInfo = downloadPaperFileParam.getNamedByCourseInfo();
        Boolean namedByPaperNumber = downloadPaperFileParam.getNamedByPaperNumber();
        Boolean namedByOriginalFile = downloadPaperFileParam.getNamedByOriginalFile();
        PaperFileDownloadContentEnum paperFileDownloadContent = downloadPaperFileParam.getPaperFileDownloadContentType();
        PaperFileDownloadExposureStatusEnum paperFileDownloadExposureStatus = downloadPaperFileParam.getPaperFileDownloadExposureStatus();
        String specialSuccessMessage = "";
        if (Objects.nonNull(paperFileDownloadExposureStatus)) {
            switch (paperFileDownloadExposureStatus) {
                case EXPOSED_PAPER: // 曝光的
                    specialSuccessMessage = "所选择的命题任务中没有已曝光的试卷";
                    break;
                case UNEXPOSED_PAPER: // 未曝光的
                    specialSuccessMessage = "所选择的命题任务中没有未曝光的试卷";
                    break;
            }
        }

        String courseName = downloadPaperFileParam.getCourseName();
        Set<Long> idSet = downloadPaperFileParam.getIdSet();

        // 如果idSet集合为空且查询条件的机构id也为空，则请求用户的机构id作为机构数据权限带入查询
        SysUser requestUser = (SysUser) map.get(SystemConstant.USER);
        if ((idSet == null || idSet.size() == 0) && !SystemConstant.longNotNull(orgId)) {
            orgId = requestUser.getOrgId();
        }


        LocalDateTime nowTime = LocalDateTime.now();
        String zipJoiner = SystemConstant.TEMP_FILES_DIR + File.separator;
        String dirName = UploadFileEnum.FILE.getTitle() + File.separator +
                nowTime.getYear() + File.separator +
                String.format("%02d", nowTime.getMonthValue()) + File.separator +
                String.format("%02d", nowTime.getDayOfMonth()) +
                File.separator + SystemConstant.getUuid() + SystemConstant.ZIP_PREFIX;
        String dirNameTmp = dirName.replaceAll("\\\\", "/");
        File zipFile = new File(zipJoiner + dirNameTmp);
        if (!zipFile.getParentFile().exists()) {
            boolean mkd = zipFile.getParentFile().mkdirs();
            boolean cf = zipFile.createNewFile();
        }

        // 根文件路径
        String zipLocalRootPath = SystemConstant.TEMP_FILES_DIR + File.separator + System.currentTimeMillis();

        ExamTaskPaperDto examTaskPaperDto = downloadService.findDownloadContent(schoolId, semesterId, examId, orgId, courseName, idSet);
        // 导出文件excel
        List<ExamTaskPaperExportDto> examTaskPaperExportDtoList = examTaskPaperDto.getExamTaskPaperExportDtoList();

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        ExcelUtil.excelMake(ExamTaskPaperExportDto.class, examTaskPaperExportDtoList, outputStream);
        InputStream in = new ByteArrayInputStream(outputStream.toByteArray());

        String excelName = "试卷使用清单";
        if (Objects.nonNull(paperFileDownloadExposureStatus)) {
            excelName = excelName + paperFileDownloadExposureStatus.getDesc();
        }
        String excelLocalPath = zipLocalRootPath + File.separator + excelName + "." + SystemConstant.XLSX;
        convertUtil.saveLocal(in, excelLocalPath);

        // 所有试卷信息
        List<ExamTaskPaperFileDto> examTaskPaperFileDtoList = examTaskPaperDto.getExamTaskPaperFileDtoList();
        if (examTaskPaperFileDtoList.size() == 0) {
            throw ExceptionResultEnum.ERROR.exception("没有找到任何试卷信息");
        }
        // 二级路径 课程
        Set<String> courseSet = examTaskPaperFileDtoList.stream().map(e -> e.getCourseName() + "-" + e.getCourseCode()).collect(Collectors.toSet());
        // 文件数以一级目录文件为准（初始1是excel）
        int count = 1;
        for (String course : courseSet) {
            // 三级路径 课程代码-课程名称/试卷编号
            int courseCount = 0;
            Set<String> paperNumberSet = examTaskPaperFileDtoList
                    .stream()
                    .filter(e -> course.equals(e.getCourseName() + "-" + e.getCourseCode()))
                    .map(ExamTaskPaperFileDto::getPaperNumber)
                    .collect(Collectors.toSet());
            for (String paperNumber : paperNumberSet) {
                // 试卷下文件集
                List<ExamTaskPaperFileDto> paperCellList = examTaskPaperFileDtoList
                        .stream()
                        .filter(e -> paperNumber.equals(e.getPaperNumber()))
                        .collect(Collectors.toList());

                // 文件路径
                String filePath = zipLocalRootPath + File.separator + course + File.separator + paperNumber + File.separator;

                Long examCardId = paperCellList.get(0).getExamCardId();
                Long cardRuleId = paperCellList.get(0).getCardRuleId();
                ExamCard examCard = examCardService.getById(examCardId);
                ExamCardDetail examCardDetail = examCardDetailService.getByCardId(examCardId);
                String htmlContent;
                if (MakeMethodEnum.SELECT.equals(examCard.getMakeMethod()) && CardCreateMethodEnum.UPLOAD.equals(examCard.getCreateMethod())) {
                    htmlContent = createPdfUtil.resetHtmlTemplateBar(examCardDetail.getHtmlContent());
                } else {
                    BasicCardRule basicCardRule = basicCardRuleService.getById(cardRuleId);
                    htmlContent = createPdfUtil.replaceHtmlCard(examCardDetail, basicCardRule);
                }


                byte[] bytes = htmlContent.getBytes();
                String cardName = "题卡-";
                if (namedByCourseInfo) {
                    cardName = cardName + course;
                }
                if (namedByPaperNumber) {
                    cardName = cardName + paperNumber;
                }
                if (namedByOriginalFile) {
                    cardName = cardName + examCardService.getById(examCardId).getTitle();
                }
                String cardLocalHtmlPath = filePath + cardName + SystemConstant.HTML_PREFIX;
                String cardLocalPdfPath = filePath + cardName + SystemConstant.PDF_PREFIX;

                // 试卷文件曝光度筛选
                if (Objects.nonNull(paperFileDownloadExposureStatus)) {
                    switch (paperFileDownloadExposureStatus) {
                        case EXPOSED_PAPER: // 曝光的
                            paperCellList = paperCellList.stream().filter(ExamTaskPaperFileDto::getExposureStatus).collect(Collectors.toList());
                            if (paperCellList.size() > 0) {
                                specialSuccessMessage = "";
                            }
                            break;
                        case UNEXPOSED_PAPER: // 未曝光的
                            paperCellList = paperCellList.stream().filter(e -> !e.getExposureStatus()).collect(Collectors.toList());
                            if (paperCellList.size() > 0) {
                                specialSuccessMessage = "";
                            }
                            break;
                        case ALL_PAPER: // 全部试卷
                            break;
                    }
                }

                if (Objects.isNull(paperFileDownloadContent)) {
                    continue;
                }
                switch (paperFileDownloadContent) {
                    case ONLY_CARD: // 只下载题卡
                        File localFile = new File(cardLocalHtmlPath);
                        if (!localFile.getParentFile().exists()) {
                            boolean mkr = localFile.getParentFile().mkdirs();
                        }
                        FileCopyUtils.copy(bytes, localFile);

                        File pdfFile = new File(cardLocalPdfPath);
                        if (!pdfFile.exists()) {
                            boolean cf = pdfFile.createNewFile();
                        }
                        HtmlToPdfUtil.convert(cardLocalHtmlPath, cardLocalPdfPath, PageSizeEnum.A3);
                        specialSuccessMessage = "";
                        courseCount = 1;
                        break;
                    case ONLY_PAPER: // 只下载试卷
                        for (ExamTaskPaperFileDto examTaskPaperFileDto : paperCellList) {
                            String paperName = "试卷-";
                            if (namedByCourseInfo) {
                                paperName = paperName + course;
                            }
                            if (namedByPaperNumber) {
                                paperName = paperName + paperNumber;
                            }
                            if (namedByOriginalFile) {
                                paperName = paperName + examTaskPaperFileDto.getPaperName();
                            }
                            paperName = paperName + "-" + examTaskPaperFileDto.getPaperType();
                            String paperLocalPath = filePath + paperName + examTaskPaperFileDto.getPaperSuffix();
                            String paperPath = examTaskPaperFileDto.getPaperPath();
                            fileStoreUtil.ossDownload(paperPath, paperLocalPath, fileStoreUtil.getUploadEnumByPath(paperPath).getFssType());
                            courseCount = 1;
                        }
                        break;
                    case PAPER_AND_CARD: // 全部下载
                        // 题卡
                        File localCardFile = new File(cardLocalHtmlPath);
                        if (!localCardFile.getParentFile().exists()) {
                            boolean mkr = localCardFile.getParentFile().mkdirs();
                        }
                        FileCopyUtils.copy(bytes, localCardFile);

                        File cardPdfFile = new File(cardLocalPdfPath);
                        if (!cardPdfFile.exists()) {
                            boolean cf = cardPdfFile.createNewFile();
                        }
                        HtmlToPdfUtil.convert(cardLocalHtmlPath, cardLocalPdfPath, PageSizeEnum.A3);
                        // 试卷
                        for (ExamTaskPaperFileDto examTaskPaperFileDto : paperCellList) {
                            String paperName = "试卷-";
                            if (namedByCourseInfo) {
                                paperName = paperName + course;
                            }
                            if (namedByPaperNumber) {
                                paperName = paperName + paperNumber;
                            }
                            if (namedByOriginalFile) {
                                paperName = paperName + examTaskPaperFileDto.getPaperName();
                            }
                            paperName = paperName + "-" + examTaskPaperFileDto.getPaperType();
                            String paperLocalPath = filePath + paperName + examTaskPaperFileDto.getPaperSuffix();
                            String paperPath = examTaskPaperFileDto.getPaperPath();
                            fileStoreUtil.ossDownload(paperPath, paperLocalPath, fileStoreUtil.getUploadEnumByPath(paperPath).getFssType());
                            courseCount = 1;
                        }
                        break;
                }
            }
            count = count + courseCount;
        }
        ZipUtil.zip(zipLocalRootPath, zipFile.getPath(), false);
        fileStoreUtil.ossUpload(dirNameTmp, zipFile, BinaryUtil.toBase64String(HexUtils.decodeHex(DigestUtils.md5Hex(new FileInputStream(zipFile)))), fileStoreUtil.getUploadEnumByPath(dirNameTmp).getFssType());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(SystemConstant.PATH, dirNameTmp);
        jsonObject.put(SystemConstant.TYPE, SystemConstant.OSS);
        jsonObject.put(SystemConstant.UPLOAD_TYPE, UploadFileEnum.FILE);
        tbTask.setResultFilePath(jsonObject.toJSONString());
        ConvertUtil.delFolder(zipLocalRootPath);
        zipFile.delete();
        map.put("count", count);
        map.put("specialSuccessMessage", specialSuccessMessage);
        return map;
    }


    public String createTempNumber(SerialNumberParams serialNumberParams) {
        return convertUtil.getIncre(serialNumberParams.getPrefix(), serialNumberParams.getModel(), serialNumberParams.getDigit());
    }

    /**
     * 验证机构是否存在
     *
     * @param orgMap         机构map
     * @param key            机构名称
     * @param schoolId       学校id
     * @param orgTypeEnum    机构类型
     * @param excelErrorTemp 错误信息
     * @param row            行
     * @param sheet          区
     * @param cloumnName     cloumnName
     * @return 机构
     */
    private SysOrg validSysOrgExists(Map<String, SysOrg> orgMap,
                                     String key,
                                     Long schoolId,
                                     OrgTypeEnum orgTypeEnum,
                                     List<ExcelError> excelErrorTemp,
                                     int row,
                                     int sheet,
                                     String cloumnName) {
        SysOrg sysOrg = null;
        if (!orgMap.containsKey(key)) {//不存在查询
            QueryWrapper<SysOrg> sysOrgQueryWrapper = new QueryWrapper<>();
            sysOrgQueryWrapper.lambda().eq(SysOrg::getSchoolId, schoolId)
                    .eq(SysOrg::getName, key)
                    .eq(SysOrg::getType, orgTypeEnum)
                    .eq(SysOrg::getEnable, true);
            sysOrg = sysOrgService.getOne(sysOrgQueryWrapper);
        } else {
            sysOrg = orgMap.get(key);
        }
        if (Objects.isNull(sysOrg)) {
            excelErrorTemp.add(new ExcelError(row, "excel第" + sheet + "个sheet第" + row + "行[" + cloumnName + "]不存在"));
        } else {
            SysOrg finalSysOrg = sysOrg;
            orgMap.computeIfAbsent(key, v -> finalSysOrg);
        }
        return sysOrg;
    }

    /**
     * 验证课程是否存在
     *
     * @param courseMap      courseMap
     * @param key            课程名称
     * @param schoolId       学校id
     * @param value          课程编号
     * @param excelErrorTemp 错误信息
     * @param row            行
     * @param sheet          区
     * @return 基础课程
     */
    private BasicCourse validBasicCourseExists(Map<String, BasicCourse> courseMap,
                                               String key,
                                               Long schoolId,
                                               String value,
                                               List<ExcelError> excelErrorTemp,
                                               int row,
                                               int sheet) {
        BasicCourse basicCourse = null;
        if (!courseMap.containsKey(key)) {//不存在查询
            QueryWrapper<BasicCourse> basicCourseQueryWrapper = new QueryWrapper<>();
            basicCourseQueryWrapper.lambda().eq(BasicCourse::getSchoolId, schoolId)
                    .eq(BasicCourse::getName, key)
                    .eq(BasicCourse::getCode, value)
                    .eq(BasicCourse::getEnable, true);
            basicCourse = basicCourseService.getOne(basicCourseQueryWrapper);
        } else {
            basicCourse = courseMap.get(key);
        }
        if (Objects.isNull(basicCourse)) {
            excelErrorTemp.add(new ExcelError(row, "excel第" + sheet + "个sheet第" + row + "行[" + "课程代码" + "]不存在"));
        } else {
            BasicCourse finalBasicCourse = basicCourse;
            courseMap.computeIfAbsent(key, v -> finalBasicCourse);
        }
        return basicCourse;
    }

    /**
     * 验证用户是否存在
     *
     * @param userMap
     * @param key
     * @param schoolId
     * @param excelErrorTemp
     * @param row
     * @param sheet
     * @param cloumnName
     * @return
     */
    private SysUser validSysUserExists(Map<String, SysUser> userMap,
                                       String key,
                                       Long schoolId,
                                       List<ExcelError> excelErrorTemp,
                                       int row,
                                       int sheet,
                                       String cloumnName) {
        SysUser sysUser = null;
        if (!userMap.containsKey(key)) {//不存在查询
            QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
            sysUserQueryWrapper.lambda().eq(SysUser::getSchoolId, schoolId)
                    .eq(SysUser::getRealName, key)
                    .eq(SysUser::getEnable, true);
            sysUser = sysUserService.getOne(sysUserQueryWrapper);
        } else {
            sysUser = userMap.get(key);
        }
        if (Objects.isNull(sysUser)) {
            excelErrorTemp.add(new ExcelError(row, "excel第" + sheet + "个sheet第" + row + "行[" + cloumnName + "]不存在"));
        } else {
            SysUser finalSysUser = sysUser;
            userMap.computeIfAbsent(key, v -> finalSysUser);
        }
        return sysUser;
    }

    /**
     * 验证班级是否存在
     *
     * @param clazzMap       班级map
     * @param key            班级名称
     * @param schoolId       学校id
     * @param excelErrorTemp 错误信息
     * @param row            行
     * @param sheet          区
     * @return 班级信息
     */
    private DictionaryResult validBasicClazzExists(Map<String, DictionaryResult> clazzMap,
                                                   String key,
                                                   Long schoolId,
                                                   List<ExcelError> excelErrorTemp,
                                                   int row,
                                                   int sheet) {
        DictionaryResult clazz = null;
        if (!clazzMap.containsKey(key)) {//不存在查询
            TeachClazz teachClazz = teachClazzService.getOne(new QueryWrapper<TeachClazz>().lambda().eq(TeachClazz::getSchoolId, schoolId).eq(TeachClazz::getTeachClazzName, key));
            if (Objects.nonNull(teachClazz)) {
                clazz = new DictionaryResult();
                clazz.setId(teachClazz.getId());
                clazz.setName(teachClazz.getTeachClazzName());
            } else {
                QueryWrapper<BasicClazz> basicClazzQueryWrapper = new QueryWrapper<>();
                basicClazzQueryWrapper.lambda().eq(BasicClazz::getSchoolId, schoolId)
                        .eq(BasicClazz::getClazzName, key)
                        .eq(BasicClazz::getEnable, true);
                BasicClazz basicClazz = basicClazzService.getOne(basicClazzQueryWrapper);
                if (Objects.nonNull(basicClazz)) {
                    clazz = new DictionaryResult();
                    clazz.setId(basicClazz.getId());
                    clazz.setName(basicClazz.getClazzName());
                }
            }
        } else {
            clazz = clazzMap.get(key);
        }
        if (Objects.isNull(clazz)) {
            excelErrorTemp.add(new ExcelError(row, "excel第" + sheet + "个sheet第" + row + "行[" + "班级名称" + "]不存在"));
        } else {
            DictionaryResult finalClazz = clazz;
            clazzMap.computeIfAbsent(key, v -> finalClazz);
        }
        return clazz;
    }
}
