package com.njcn.csharmonic.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.*;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.FileUtil;
import com.njcn.csdevice.api.CsCommTerminalFeignClient;
import com.njcn.csdevice.api.CsLineFeignClient;
import com.njcn.csdevice.api.WlRecordFeignClient;
import com.njcn.csdevice.pojo.po.CsLinePO;
import com.njcn.csdevice.pojo.po.WlRecord;
import com.njcn.csharmonic.enums.CsHarmonicResponseEnum;
import com.njcn.csharmonic.param.SensitiveUserReportQueryParam;
import com.njcn.csharmonic.pojo.dto.ReportTemplateDTO;
import com.njcn.csharmonic.pojo.param.ReportTemplateParam;
import com.njcn.csharmonic.pojo.po.PqGovernPlan;
import com.njcn.csharmonic.pojo.vo.ReportTemplateDataVO;
import com.njcn.csharmonic.pojo.vo.ReportTreeVO;
import com.njcn.csharmonic.pojo.vo.SysDeptTempVO;
import com.njcn.csharmonic.service.CustomReportService;
import com.njcn.csharmonic.service.ICsSysExcelRelationService;
import com.njcn.csharmonic.service.IPqGovernPlanService;
import com.njcn.csharmonic.utils.DataChangeUtil;
import com.njcn.device.biz.commApi.CommTerminalGeneralClient;
import com.njcn.device.biz.pojo.po.PqsDeviceUnit;
import com.njcn.harmonic.common.mapper.ExcelRptTempMapper;
import com.njcn.harmonic.common.pojo.dto.DeviceUnitCommDTO;
import com.njcn.harmonic.common.pojo.vo.ReportTemplateVO;
import com.njcn.harmonic.common.service.CustomReportTableService;
import com.njcn.harmonic.pojo.param.ReportSearchParam;
import com.njcn.harmonic.pojo.po.ExcelRptTemp;
import com.njcn.influx.constant.InfluxDbSqlConstant;
import com.njcn.influx.pojo.constant.InfluxDBTableConstant;
import com.njcn.influx.utils.InfluxDbUtils;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.enums.OssResponseEnum;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.api.EpdFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.system.pojo.po.EleEpdPqd;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.po.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 自定义报表
 *
 * @author qijian
 * @date 2022/10/15
 */
@Service
@RequiredArgsConstructor
@Slf4j
@DS("sjzx")
public class CustomReportServiceImpl implements CustomReportService {

    private final ExcelRptTempMapper excelRptTempMapper;
    private final EpdFeignClient epdFeignClient;
    private final FileStorageUtil fileStorageUtil;
    private final DicDataFeignClient dicDataFeignClient;
    private final InfluxDbUtils influxDbUtils;
    private final CommTerminalGeneralClient commTerminalGeneralClient;
    private final CsCommTerminalFeignClient csCommTerminalFeignClient;
    private final CustomReportTableService customReportTableService;
    private final WlRecordFeignClient wlRecordFeignClient;
    private final UserFeignClient userFeignClient;
    private final CsLineFeignClient csLineFeignClient;
    private final ICsSysExcelRelationService sysExcelService;
    private final IPqGovernPlanService pqGovernPlanService;
    private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);

    private final JdbcTemplate jdbcTemplate;
    private final String CELL_DATA = "celldata";
    private final String V = "v";
    private final String STR_ONE = "#";
    private final String STR_TWO = "$";
    private final String STR_THREE = "&";
    private final String STR_FOUR = "%";
    private final String STR_FIVE = "~";
    private final String limitTable = "pq_overlimit";

    private final String UVOLTAGE_DEV = "UVOLTAGE_DEV";
    private final String VOLTAGE_DEV = "VOLTAGE_DEV";


    private final String GRID_SIDE_DICT_CODE = "Grid_Side";
    private final String LOAD_SIDE_DICT_CODE = "Load_Side";

    private static final Map<String, String> PHASE_MAPPING = new HashMap<String, String>() {{
        put("AB", "A");
        put("BC", "B");
        put("CA", "C");
        put("M", "T");
    }};

    /**
     * map key转大写
     */
    public <V> Map<String, V> convertKeysToUpperCase(Map<String, V> originalMap) {
        Map<String, V> newMap = new HashMap<>();
        if (CollUtil.isNotEmpty(originalMap)) {
            for (Map.Entry<String, V> entry : originalMap.entrySet()) {
                newMap.put(entry.getKey().toUpperCase(), entry.getValue());
            }
        }

        return newMap;
    }

    public static boolean isInteger(String str) {
        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    @Override
    public void getCustomReport(ReportSearchParam reportSearchParam, HttpServletResponse response) {
        //获取模板id
        String tempId = getTempId(reportSearchParam.getTempId(), reportSearchParam.getLineId());
        //修改模板id
        reportSearchParam.setTempId(tempId);

        //原代码
        TimeInterval timeInterval = new TimeInterval();
        //ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(reportSearchParam.getTempId());
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(tempId);
        if (Objects.isNull(excelRptTemp)) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_ACTIVE);
        }
        if (Objects.isNull(reportSearchParam.getCustomType())) {
            //通用报表
            Map<String,String> map = csLineFeignClient.getCustomDetailByLineId(reportSearchParam.getLineId()).getData();
            Map<String,String> newMap = convertKeysToUpperCase(map);

            PqsDeviceUnit deviceUnit  = csCommTerminalFeignClient.lineUnitDetail(reportSearchParam.getLineId()).getData();
            DeviceUnitCommDTO deviceUnitCommDTO = BeanUtil.copyProperties(deviceUnit, DeviceUnitCommDTO.class);

            customReportTableService.getCustomReport(reportSearchParam,newMap,deviceUnitCommDTO,response);
        } else {
            //浙江无线报表
            analyzeReportZhejiang(reportSearchParam, excelRptTemp, response);
        }

        log.info("报表执行时间{}秒", timeInterval.intervalSecond());
    }

    @Override
    public boolean addCustomReportTemplate(ReportTemplateParam reportTemplateParam) {
        checkName(reportTemplateParam, false);
        MultipartFile fileContent = reportTemplateParam.getFileContent();
        //检验模板json数据规范
        try {
            String content = FileUtil.multipartFileToString(fileContent);
            new JSONArray(content);
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
        reportTemplateParam.setContent(fileStorageUtil.uploadMultipart(fileContent, OssPath.HARMONIC_EXCEL_TEMPLATE));
        //新增模板表
        ExcelRptTemp excelRptTemp = new ExcelRptTemp();
        BeanUtils.copyProperties(reportTemplateParam, excelRptTemp);
        excelRptTemp.setState(DataStateEnum.ENABLE.getCode());
        excelRptTemp.setActivation(DataStateEnum.ENABLE.getCode());
        excelRptTempMapper.insert(excelRptTemp);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateCustomReportTemplate(ReportTemplateParam.UpdateReportTemplateParam reportTemplateParam) {
        checkName(reportTemplateParam, true);
        MultipartFile fileContent = reportTemplateParam.getFileContent();
        //检验模板json数据规范
        try {
            String content = FileUtil.multipartFileToString(fileContent);
            new JSONArray(content);
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }

        //删除之前的文件
        ExcelRptTemp excelRptTempOld = excelRptTempMapper.selectById(reportTemplateParam.getId());
        fileStorageUtil.deleteFile(excelRptTempOld.getContent());
        reportTemplateParam.setContent(fileStorageUtil.uploadMultipart(fileContent, OssPath.HARMONIC_EXCEL_TEMPLATE));
        //修改模板数据
        ExcelRptTemp excelRptTemp = new ExcelRptTemp();
        BeanUtils.copyProperties(reportTemplateParam, excelRptTemp);
        excelRptTemp.setUpdateTime(LocalDateTime.now());
        excelRptTempMapper.updateById(excelRptTemp);

        return true;
    }

    @Override
    public boolean updateBindTemplate(List<ReportSearchParam> reportSearchParams) {

        return true;
    }

    @Override
    public List<SysDeptTempVO> getDataByTempId(String id) {
        return CollUtil.newArrayList();
    }

    @Override
    @DS("sjzx")
    public List<ReportTemplateVO> getTemplateByDept(String id) {
        //List<String> deptIds = deptFeignClient.getDepSonIdtByDeptId(id).getData();
        return excelRptTempMapper.getReportTemplateByDept(new ArrayList<>());
    }

    @Override
    public ExcelRptTemp getCustomReportTemplateById(String id) {
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(id);
        return excelRptTemp;
    }

    @Override
    public void viewCustomReportTemplateById(String id, HttpServletResponse response) {
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(id);
        try {
            fileStorageUtil.downloadStream(response, excelRptTemp.getContent());
        } catch (Exception exception) {
            throw new BusinessException(CsHarmonicResponseEnum.REPORT_TEMPLATE_DOWNLOAD_ERROR);
        }

    }

    @Override
    public void getSensitiveUserReport(SensitiveUserReportQueryParam queryParam, HttpServletResponse response) {
        PqGovernPlan pqGovernPlan = pqGovernPlanService.getById(queryParam.getSensitiveUserId());
        if(Objects.isNull(pqGovernPlan.getGovernBefore()) || Objects.isNull(pqGovernPlan.getGovernAfter())) {
            throw new BusinessException("治理前后监测点缺失，无法生成报告!");
        }
        CsLinePO po1 = csLineFeignClient.getById(pqGovernPlan.getGovernBefore()).getData();
        CsLinePO po2 = csLineFeignClient.getById(pqGovernPlan.getGovernAfter()).getData();
        String tempId = getTempId(queryParam.getTempId(), pqGovernPlan.getGovernAfter());
        queryParam.setTempId(tempId);
        TimeInterval timeInterval = new TimeInterval();
        ExcelRptTemp excelRptTemp = excelRptTempMapper.selectById(tempId);
        if (Objects.isNull(excelRptTemp)) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_ACTIVE);
        }
        String lineName1 = "";
        String lineName2 = "";
        // 模版内容数据
        JSONArray templateData;

        try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) {
            templateData = new JSONArray(new JSONTokener(fileStream, new JSONConfig()));
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }


        //指标数据
        List<ReportTemplateDataVO> indexDataList = new ArrayList<>();
        // 改善率数据
        List<ReportTemplateDataVO> improvementRateDataList = new ArrayList<>();
        // 基础数据
        List<ReportTemplateDataVO> basicDataList = new ArrayList<>();
        parseGovernTemplate(templateData, indexDataList, improvementRateDataList, basicDataList);

        Set<ReportTemplateDataVO> beforeFinalDataList = new HashSet<>();
        Set<ReportTemplateDataVO> afterFinalDataList = new HashSet<>();
        if (CollUtil.isNotEmpty(indexDataList)) {
            //开始组织sql
            indexDataList = new LinkedHashSet<>(indexDataList).stream().sorted(Comparator.comparing(ReportTemplateDataVO::getItemName)).collect(Collectors.toList());
            Map<String, List<ReportTemplateDataVO>> classMap = indexDataList.stream().collect(Collectors.groupingBy(ReportTemplateDataVO::getResourceId));
            //定义存放指标的map
            if (po1 != null) {
                lineName1 = po1.getName();
                List<ReportTemplateDataVO> beforeDataList = fetchDataList(po1, classMap, queryParam);
                beforeFinalDataList.addAll(beforeDataList);
            }
            if (po2 != null) {
                lineName2 = po2.getName();
                List<ReportTemplateDataVO> afterDataList = fetchDataList(po2, classMap, queryParam);
                afterFinalDataList.addAll(afterDataList);
            }
        }
        //进行反向赋值到模板
        //1、根据itemName分组
        Map<String, List<ReportTemplateDataVO>> beforeAssMap = beforeFinalDataList.stream().collect(Collectors.groupingBy(ReportTemplateDataVO::getItemName));
        Map<String, List<ReportTemplateDataVO>> afterAssMap = afterFinalDataList.stream().collect(Collectors.groupingBy(ReportTemplateDataVO::getItemName));
        //处理台账信息，暂时没用到
       /* Map<String, String> finalBasicMap = new HashMap<>();
        if (CollUtil.isNotEmpty(basicDataList)) {
            finalBasicMap.put("LINENAME", lineName);
        }*/
        //2、把itemName的value赋给v和m
        JSONArray finalExcelData = new JSONArray();
        for (Object sheet : templateData) {
            JSONObject sheetData = JSONUtil.parseObj(sheet);
            JSONArray cellDataArray = sheetData.getJSONArray(CELL_DATA);
            JSONArray newCellDataArray = new JSONArray();
            for (Object cell : cellDataArray) {
                Object newCell = cell;
                if (Objects.nonNull(cell) && !"null".equals(cell.toString())) {
                    //获取到1列
                    JSONObject data = JSONUtil.parseObj(cell);
                    JSONObject son = data.getJSONObject(V);
                    if (son.containsKey(V)) {
                        String v = son.getStr(V);
                        if (StrUtil.isNotEmpty(v)) {
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains(STR_ONE)) {
                                String value = "/";
                                List<ReportTemplateDataVO> rDto = beforeAssMap.getOrDefault(v.replace(STR_TWO, "").toUpperCase(), null);
                                if (CollUtil.isNotEmpty(rDto)) {
                                    value = rDto.get(0).getValue();
                                }
                                son.putOpt(V, value);
                            } else if (v.charAt(0) == '~' && v.contains(STR_ONE)) {
                                String value = "/";
                                List<ReportTemplateDataVO> rDto = afterAssMap.getOrDefault(v.replace(STR_FIVE, "").replace(STR_TWO, "").toUpperCase(), null);
                                if (CollUtil.isNotEmpty(rDto)) {
                                    value = rDto.get(0).getValue();
                                }
                                son.putOpt(V, value);
                            } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) {
                                // 改善率计算
                                String value = "/";
                                if (CollUtil.isNotEmpty(improvementRateDataList)) {
                                    String baseItem = v.replace(STR_FOUR, "").toUpperCase();
                                    ReportTemplateDataVO beforeData = beforeFinalDataList.stream().filter(it -> it.getItemName().replace(STR_TWO, "").toUpperCase().startsWith(baseItem)).findFirst().orElse(null);
                                    ReportTemplateDataVO afterData = afterFinalDataList.stream().filter(it -> it.getItemName().replace(STR_FIVE, "").replace(STR_TWO, "").toUpperCase().startsWith(baseItem)).findFirst().orElse(null);
                                    if (afterData != null && beforeData != null) {
                                        String beforeDataValue = beforeData.getValue();
                                        String afterDataValue = afterData.getValue();
                                        if (NumberUtil.isNumber(beforeDataValue) && NumberUtil.isNumber(afterDataValue)) {
                                            // (治理前 - 治理后) / 治理前 * 100
                                            BigDecimal before = new BigDecimal(beforeDataValue);
                                            if (before.compareTo(BigDecimal.ZERO) == 0) {
                                                value = "0.00";
                                            } else {
                                                BigDecimal after = new BigDecimal(afterDataValue);
                                                BigDecimal result = before.subtract(after)
                                                        .divide(before, 4, RoundingMode.HALF_UP)
                                                        .multiply(BigDecimal.valueOf(100))
                                                        .setScale(2, RoundingMode.HALF_UP);
                                                value = result.toString();
                                            }
                                        }



                                    }
                                }

                                son.putOpt(V, value);
                            } else if (v.charAt(0) == '&') {
                                // 基础数据
                                String baseItem = v.replace(STR_THREE, "").toUpperCase();
                                if (baseItem.startsWith("LINENAME1")) {
                                    //台账信息
                                    son.putOpt(V, baseItem.replace("LINENAME1", lineName1));
                                }
                                if (baseItem.startsWith("LINENAME2")) {
                                    //台账信息
                                    son.putOpt(V, baseItem.replace("LINENAME2", lineName2));
                                }
                            } else if (v.contains("start_time") && v.contains("end_time")){
                                //如时间是大于当前时间则用当前时间
                                LocalDate startDate = LocalDateTimeUtil.parseDate(queryParam.getStartTime(), DatePattern.NORM_DATE_PATTERN);
                                LocalDate nowDate = LocalDate.now();
                                if (!nowDate.isAfter(startDate)) {
                                    startDate = LocalDate.now();
                                }
//                                String startTime = LocalDateTimeUtil.format(startDate, DatePattern.NORM_DATE_PATTERN) + InfluxDbSqlConstant.START_TIME;
                                String startTime = LocalDateTimeUtil.format(startDate, DatePattern.NORM_DATE_PATTERN);
                                //如时间是大于当前时间则用当前时间
                                String localTime = InfluxDbSqlConstant.END_TIME;
                                LocalDate endDate = LocalDateTimeUtil.parseDate(queryParam.getEndTime(), DatePattern.NORM_DATE_PATTERN);
                                if (nowDate.isAfter(endDate)) {
                                    localTime = " " + LocalTime.now().format(DatePattern.NORM_TIME_FORMATTER);
                                }
//                                String endTime = queryParam.getEndTime() + localTime;
                                //报表结束时间是当前日的前一天
                                String endTime = LocalDate.parse(queryParam.getEndTime(), DatePattern.NORM_DATE_FORMATTER).minusDays(1).format(DatePattern.NORM_DATE_FORMATTER);
                                String val = v.replace(STR_THREE, "").replace("start_time", startTime).replace("end_time", endTime);
                                son.putOpt(V, val);

                            }
                        }

                    }
                    data.putOpt(V, son);
                    newCell = data;
                }
                newCellDataArray.add(newCell);
            }
            sheetData.putOpt(CELL_DATA, newCellDataArray);
            sheetData.remove("data");
            sheetData.remove("data1");
            finalExcelData.add(sheetData);

        }
        //导出自定义报表
        downReport(finalExcelData, response);

        log.info("报表执行时间{}秒", timeInterval.intervalSecond());
    }

    @Override
    public List<ReportTemplateVO> getTemplateList(ReportSearchParam reportSearchParam) {
        List<ReportTemplateVO> list = excelRptTempMapper.getReportTemplateList(reportSearchParam);
        List<String> updateByList = list.stream().map(ReportTemplateVO::getUpdateBy).distinct().collect(Collectors.toList());
        Map<String, String> userNameMap = userFeignClient.getUserByIdList(updateByList).getData().stream().collect(Collectors.toMap(User::getId, User::getName));
        list.forEach(template -> {
            template.setUpdateBy(userNameMap.getOrDefault(template.getUpdateBy(), ""));
        });
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delTemplate(ReportSearchParam reportSearchParam) {
        excelRptTempMapper.deleteById(reportSearchParam.getTempId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(ReportSearchParam reportSearchParam) {
        return true;
    }

    @Override
    public List<ReportTreeVO> reportChooseTree() {
        List<ReportTreeVO> tree = new ArrayList<>();
        DictData dic = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.CS_DATA_TYPE.getName(), DicDataEnum.PQD.getName()).getData();
        List<EleEpdPqd> epdList = epdFeignClient.dictMarkByDataType(dic.getId()).getData();
        epdList = epdList.stream().filter(it -> StrUtil.isNotBlank(it.getResourcesId())).collect(Collectors.toList());

        if (CollUtil.isEmpty(epdList)) {
            return tree;
        }
        List<DictData> dayTableList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DATA_DAY.getCode()).getData();
        Map<String, String> dayTableMap = dayTableList.stream().collect(Collectors.toMap(DictData::getId, DictData::getName));

        epdList.forEach(item -> item.setResourcesId(dayTableMap.get(item.getResourcesId())));
        epdList.sort(Comparator.comparingInt(EleEpdPqd::getSort));

        Map<String, List<EleEpdPqd>> map = epdList.stream().collect(Collectors.groupingBy(EleEpdPqd::getName, LinkedHashMap::new, Collectors.toList()));

        map.forEach((key, value) -> {
            ReportTreeVO reportTreeVO = new ReportTreeVO();
            reportTreeVO.setName(value.get(0).getOtherName());
            reportTreeVO.setShowName(value.get(0).getShowName());

            //存在1-50次 2-50次情况
            if (Objects.nonNull(value.get(0).getHarmStart()) && Objects.nonNull(value.get(0).getHarmEnd())) {
                List<ReportTreeVO> reHarm = new ArrayList<>();
                for (int i = value.get(0).getHarmStart(); i <= value.get(0).getHarmEnd(); i++) {
                    ReportTreeVO reportTreeCount = new ReportTreeVO();
                    reportTreeCount.setName(value.get(0).getOtherName() + "_" + i);
                    reportTreeCount.setShowName(i + "次" + value.get(0).getShowName());
                    reportTreeVO.setFlag(1);
                    assPhase(value, reportTreeCount, reportTreeCount.getName());
                    reHarm.add(reportTreeCount);
                }
                reportTreeVO.setChildren(reHarm);
            } else {
                assPhase(value, reportTreeVO, value.get(0).getOtherName());
            }
            tree.add(reportTreeVO);
        });
        return tree;
    }

    @Override
    public List<ReportTreeVO> targetLimitChooseTree() {
        List<ReportTreeVO> result = new ArrayList<>();
        DictData dic = dicDataFeignClient.getDicDataByCode(DicDataEnum.PQD.getCode()).getData();


        List<EleEpdPqd> list = epdFeignClient.dictMarkByDataType(dic.getId()).getData()
                .stream().filter(eleEpdPqd -> limitTable.equals(eleEpdPqd.getLimitTable()))
                .sorted(Comparator.comparingInt(EleEpdPqd::getSort)).collect(Collectors.toList());
        Map<String, List<EleEpdPqd>> map = list.stream().collect(Collectors.groupingBy(EleEpdPqd::getLimitName));
        map.forEach((key, val) -> {
            ReportTreeVO reportTreeVO = new ReportTreeVO();
            reportTreeVO.setShowName(val.get(0).getShowName());

            if (Objects.nonNull(val.get(0).getHarmStart()) && Objects.nonNull(val.get(0).getHarmEnd())) {
                String one = val.get(0).getLimitName();
                List<ReportTreeVO> temList = new ArrayList<>();
                for (int i = val.get(0).getHarmStart(); i <= val.get(0).getHarmEnd(); i++) {
                    double count;
                    ReportTreeVO reportTreeItem = new ReportTreeVO();

                    if (val.get(0).getHarmStart() == 1) {
                        count = i + 0.5;
                        reportTreeItem.setShowName(count + "次" + val.get(0).getShowName());
                        reportTreeItem.setName(STR_FOUR + one + count + STR_ONE + val.get(0).getFormula() + STR_ONE + val.get(0).getLimitTable() + STR_FOUR);
                    } else {
                        reportTreeItem.setShowName(i + "次" + val.get(0).getShowName());
                        reportTreeItem.setName(STR_FOUR + one + i + STR_ONE + val.get(0).getFormula() + STR_ONE + val.get(0).getLimitTable() + STR_FOUR);
                    }

                    reportTreeItem.setFlag(1);
                    temList.add(reportTreeItem);
                }
                reportTreeVO.setChildren(temList);
            } else {
                reportTreeVO.setName(STR_FOUR + val.get(0).getLimitName() + STR_ONE + val.get(0).getLimitTable() + STR_FOUR + val.get(0).getFormula() + STR_FOUR);
                reportTreeVO.setFlag(1);
            }

            result.add(reportTreeVO);
        });
        return result;
    }

    @Override
    public List<ReportTreeVO> terminalChooseTree() {
        List<ReportTreeVO> result = new ArrayList<>();
        DictData dic = dicDataFeignClient.getDicDataByCode(DicDataEnum.TERMINAL_SORT.getCode()).getData();
        List<EleEpdPqd> list = epdFeignClient.dictMarkByDataType(dic.getId()).getData();
        list.sort(Comparator.comparingInt(EleEpdPqd::getSort));
        list.forEach(item -> {
            ReportTreeVO reportTreeVO = new ReportTreeVO();
            reportTreeVO.setId(item.getId());
            reportTreeVO.setName(STR_THREE + item.getName() + STR_THREE);
            reportTreeVO.setFlag(1);
            reportTreeVO.setShowName(item.getShowName());
            result.add(reportTreeVO);
        });
        return result;
    }

    /*组装相别*/
    private void assPhase(List<EleEpdPqd> value, ReportTreeVO reportTreeItem, String key) {
        List<ReportTreeVO> phaseTree = new ArrayList<>();
        value.forEach(item -> {
            if (Objects.nonNull(item.getPhase()) && !"T".equals(item.getPhase())) {
                List<ReportTreeVO> statTree = new ArrayList<>();
                ReportTreeVO reportTreePhase = new ReportTreeVO();
                reportTreePhase.setName(item.getPhase());
                reportTreePhase.setShowName(item.getPhase());

                assStatMethod(item, statTree, key, item.getPhase());
                reportTreePhase.setChildren(statTree);
                phaseTree.add(reportTreePhase);
                reportTreeItem.setChildren(phaseTree);

            } else {
                List<ReportTreeVO> statTree = new ArrayList<>();
                assStatMethod(item, statTree, key, "");
                reportTreeItem.setChildren(statTree);
            }
        });

    }

    private void assStatMethod(EleEpdPqd item, List<ReportTreeVO> statTree, String oneKey, String twoKey) {
        //存在相别为M但是Stat_Method不为空
        if (StrUtil.isNotBlank(item.getStatMethod())) {
            String[] arr = item.getStatMethod().split(",");
            List<String> stat = Stream.of(arr).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(stat)) {
                stat.forEach(statItem -> {
                    ReportTreeVO reportTreeStat = new ReportTreeVO();
                    String tem = "";
                    if (Objects.nonNull(item.getLimitName())) {
                        tem = STR_ONE + item.getLimitName();
                    } else {
                        tem = "#NO";
                    }
                    if (StrUtil.isNotBlank(twoKey)) {
                        reportTreeStat.setName(STR_TWO + oneKey + STR_ONE + twoKey + STR_ONE + statItem + STR_ONE + item.getResourcesId().trim() + tem.trim() + STR_TWO);
                    } else {
                        reportTreeStat.setName(STR_TWO + oneKey + STR_ONE + statItem + STR_ONE + item.getResourcesId().trim() + tem.trim() + STR_TWO);
                    }

                    reportTreeStat.setShowName(statItem);
                    statTree.add(reportTreeStat);
                });
            }
        }
    }

    /**
     * 检查名称是否已存在
     *
     * @param reportTemplateParam,isUpdate 参数
     * @return 结果
     */
    private void checkName(ReportTemplateParam reportTemplateParam, boolean isUpdate) {
        LambdaQueryWrapper<ExcelRptTemp> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //条件组合：where state = 1 and name = ?
        lambdaQueryWrapper.eq(ExcelRptTemp::getState, DataStateEnum.ENABLE.getCode()).eq(ExcelRptTemp::getName, reportTemplateParam.getName());

        //and id <> ?
        if (isUpdate) {
            if (reportTemplateParam instanceof ReportTemplateParam.UpdateReportTemplateParam) {
                lambdaQueryWrapper.ne(ExcelRptTemp::getId, ((ReportTemplateParam.UpdateReportTemplateParam) reportTemplateParam).getId());
            }
        }

        //若存在条件数据抛出异常
        int count = excelRptTempMapper.selectCount(lambdaQueryWrapper);
        if (count > 0) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_REPEAT);
        }

    }

    /**
     * 数据单位信息
     *
     * @param reportSearchParam
     * @return
     */
    private Map<String, String> unitMap(ReportSearchParam reportSearchParam) {
        PqsDeviceUnit deviceUnit;
        if (Objects.isNull(reportSearchParam.getResourceType())) {
            deviceUnit = commTerminalGeneralClient.lineUnitDetail(reportSearchParam.getLineId()).getData();
        } else {
            deviceUnit = csCommTerminalFeignClient.lineUnitDetail(reportSearchParam.getLineId()).getData();
        }
        List<DictData> dictData = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEVICE_UNIT.getCode()).getData();
        Map<String, String> unit = new HashMap<>();
        List<String> list = dictData.stream().map(DictData::getCode).collect(Collectors.toList());
        for (String s : list) {
            //有效值
            if (s.equals(DicDataEnum.EFFECTIVE.getCode())) {
                unit.put(s + "#i", deviceUnit.getIeffective());
                unit.put(s + "#v", deviceUnit.getLineVoltage());
            }
            //功率
            if (s.equals(DicDataEnum.POWER.getCode())) {
                unit.put(s + "#p", deviceUnit.getTotalActiveP());
                unit.put(s + "#q", deviceUnit.getTotalNoP());
                unit.put(s + "#s", deviceUnit.getTotalViewP());
            }
            //畸变率
            if (s.equals(DicDataEnum.DISTORTION.getCode())) {
                unit.put(s + "#v", deviceUnit.getVdistortion());
            }
            //电压偏差
            if (s.equals(DicDataEnum.VOLTAGE.getCode())) {
                unit.put(s + "#v", deviceUnit.getVoltageDev());
            }
            //频率
            if (s.equals(DicDataEnum.UNIT_FREQUENCY.getCode())) {
                unit.put(s + "#freq", deviceUnit.getUnitFrequency());
                unit.put(s + "#freqDev", deviceUnit.getUnitFrequencyDev());
            }
            //三项不平衡度
            if (s.equals(DicDataEnum.UNBALANCE.getCode())) {
                unit.put(s + "#v", STR_FOUR);
                unit.put(s + "#vPos", deviceUnit.getPositiveV());
                unit.put(s + "#vNeg", deviceUnit.getNoPositiveV());
                unit.put(s + "#vZero", deviceUnit.getNoPositiveV());
                unit.put(s + "#i", STR_FOUR);
                unit.put(s + "#iPos", "A");
                unit.put(s + "#iNeg", "A");
                unit.put(s + "#iZero", "A");
            }
            //基波
            if (s.equals(DicDataEnum.FUND.getCode())) {
                unit.put(s + "#i", deviceUnit.getIfund());
                unit.put(s + "#v", deviceUnit.getVfundEffective());

            }
        }
        return unit;
    }

    /**
     * @param data         同类型的cell模板
     * @param sql          单个cell模板
     * @param endList      用于返回最终组装好的数据，类似data
     * @param limitMap     指标是否合格模板
     * @param assNoPassMap 用于存储不合格的指标
     * @date 2023/10/20
     */
    private void assSqlNew(List<ReportTemplateDTO> data, StringBuilder sql, List<ReportTemplateDTO> endList, String method, ReportSearchParam reportSearchParam, Map<String, ReportTemplateDTO> limitMap, Map<String, Float> overLimitMap, Map<String, ReportTemplateDTO> assNoPassMap) {
        //sql拼接示例：select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai')


        //cp95函数特殊处理 PERCENTILE(field_key, N)
        if (InfluxDbSqlConstant.CP95.equals(method)) {

            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(InfluxDbSqlConstant.PERCENTILE)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.NUM_95)
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM);
                } else {
                    sql.append(InfluxDbSqlConstant.PERCENTILE)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.NUM_95)
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA);
                }
            }

        } else {

            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM);
                } else {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA);
                }
            }

        }

        sql.append(StrPool.C_SPACE);
        String temS = data.get(0).getResourceId().replace("r_stat_data", "day").replace("_d", "");
        sql.append(InfluxDbSqlConstant.FROM).append(temS);

        sql.append(InfluxDbSqlConstant.WHERE)
                .append(InfluxDBTableConstant.LINE_ID)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(reportSearchParam.getLineId())
                .append(InfluxDbSqlConstant.QM);
        //相别特殊处理
        if (!InfluxDBTableConstant.NO_PHASE.equals(data.get(0).getPhase())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.get(0).getPhase())
                    .append(InfluxDbSqlConstant.QM);
        }


        //data_flicker、data_fluc、data_plt 无 value_type
        if (!InfluxDBTableConstant.DATA_FLICKER.equals(data.get(0).getClassId()) && !InfluxDBTableConstant.DATA_FLUC.equals(data.get(0).getClassId()) && !InfluxDBTableConstant.DATA_PLT.equals(data.get(0).getClassId())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.VALUE_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.get(0).getStatMethod())
                    .append(InfluxDbSqlConstant.QM);
        }

        //频率和频率偏差仅统计T相
        if (data.get(0).getTemplateName().equals("freq_dev") || data.get(0).getTemplateName().equals("freq")) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(InfluxDBTableConstant.PHASE_TYPE_T)
                    .append(InfluxDbSqlConstant.QM);
        }
        //时间范围处理
        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDbSqlConstant.START_TIME).append(InfluxDbSqlConstant.QM)
                .append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM);

        sql.append(InfluxDbSqlConstant.TZ);

        long a = System.currentTimeMillis();
        List<Map<String, Object>> mapList = influxDbUtils.getMapResult(sql.toString());
        long b = System.currentTimeMillis();
        System.out.println(sql);
        System.out.println("当前sql执行了:" + (b - a) + "ms");
        if (CollUtil.isEmpty(mapList)) {
            data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList());
        } else {
            Map<String, Object> map = mapList.get(0);
            for (ReportTemplateDTO item : data) {
                if (Objects.nonNull(map) && map.containsKey(item.getItemName())) {
                    double v = Double.parseDouble(map.get(item.getItemName()).toString());
                    item.setValue(String.format("%.3f", v));

                    if (overLimitMap.containsKey(item.getLimitName())) {
                        Float tagVal = overLimitMap.get(item.getLimitName());
                        if (v > tagVal) {
                            item.setOverLimitFlag(1);
                        } else {
                            item.setOverLimitFlag(0);
                        }
                    }

                    //判断是否越限
                    if (limitMap.size() != 0) {
                        String key = item.getLimitName() + STR_ONE + item.getStatMethod().toLowerCase() + "#pq_overlimit";
                        if (limitMap.containsKey(key)) {
                            ReportTemplateDTO tem = limitMap.get(key);
                            double limitVal = Double.parseDouble(tem.getValue());
                            if (v > limitVal) {
                                tem.setOverLimitFlag(1);
                                assNoPassMap.put(key, tem);
                            } else if (!assNoPassMap.containsKey(key)) {
                                tem.setOverLimitFlag(0);
                                assNoPassMap.put(key, tem);
                            }
                        }
                    }
                } else {
                    item.setValue("/");
                }
            }
        }
        endList.addAll(data);
    }

    /**
     * @param data         同类型的cell模板
     * @param sql          单个cell模板
     * @param endList      用于返回最终组装好的数据，类似data
     * @param limitMap     指标是否合格模板
     * @param assNoPassMap 用于存储不合格的指标
     * @date 2023/10/20
     */

    private void assSqlByMysql(List<ReportTemplateDTO> data, StringBuilder sql, List<ReportTemplateDTO> endList, String method, ReportSearchParam reportSearchParam, Map<String, ReportTemplateDTO> limitMap, Map<String, Float> overLimitMap, Map<String, ReportTemplateDTO> assNoPassMap,List<String> noPhaseList) {
        //sql拼接示例：select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai')
        if (InfluxDbSqlConstant.CP95.equals(method)) {
            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(InfluxDbSqlConstant.MAX)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS)
                            .append("\""+data.get(i).getItemName()+"\"");
                } else {
                    sql.append(InfluxDbSqlConstant.MAX)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS)
                            .append("\""+data.get(i).getItemName()+"\"").append(StrUtil.COMMA);
                }
            }
        } else {
            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS)
                            .append("\""+data.get(i).getItemName()+"\"");
                } else {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS)
                            .append("\""+data.get(i).getItemName()+"\"").append(StrUtil.COMMA);
                }
            }

        }

        //拼接表名
        sql.append(StrPool.C_SPACE)
                .append(InfluxDbSqlConstant.FROM)
                .append(data.get(0).getResourceId());


        sql.append(InfluxDbSqlConstant.WHERE)
                .append(InfluxDBTableConstant.LINE_ID)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(reportSearchParam.getLineId())
                .append(InfluxDbSqlConstant.QM);
        //相别特殊处理
        if (!InfluxDBTableConstant.NO_PHASE.equals(data.get(0).getPhase())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.get(0).getPhase())
                    .append(InfluxDbSqlConstant.QM);
        }

        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDBTableConstant.VALUE_TYPE)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(data.get(0).getStatMethod())
                .append(InfluxDbSqlConstant.QM);


        //频率和频率偏差仅统计T相
        if (noPhaseList.contains(data.get(0).getTemplateName())) {
            if(data.get(0).getTemplateName().equalsIgnoreCase("v_unbalance")){
                System.out.println(44);
            }
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(InfluxDBTableConstant.PHASE_TYPE_T)
                    .append(InfluxDbSqlConstant.QM);
        }
        //时间范围处理
        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getStartTime()).append(InfluxDbSqlConstant.START_TIME).append(InfluxDbSqlConstant.QM)
                .append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(reportSearchParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM);

        System.out.println(sql);

        List<Map<String, Object>> mapList = SqlRunner.DEFAULT.selectList(sql.toString());
        if (CollUtil.isEmpty(mapList) || Objects.isNull(mapList.get(0))) {
            data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList());
        } else {
            //兼容达梦数据库方法
            Map<String, Object> map = convertKeysToUpperCase(mapList.get(0));
            for (ReportTemplateDTO item : data) {
                if (map.containsKey(item.getItemName())) {
                    double v = Double.parseDouble(map.get(item.getItemName()).toString());
                    item.setValue(String.format("%.3f", v));
                    if (overLimitMap.containsKey(item.getLimitName())) {
                        Float tagVal = overLimitMap.get(item.getLimitName());

                        if(item.getLimitName().equalsIgnoreCase(UVOLTAGE_DEV)){
                            //对电压偏差特殊处理
                            Float tagVal_U = overLimitMap.get(UVOLTAGE_DEV);
                            if (v > tagVal || v<tagVal_U) {
                                item.setOverLimitFlag(1);
                            } else {
                                item.setOverLimitFlag(0);
                            }

                        }else {
                            if (v > tagVal) {
                                item.setOverLimitFlag(1);
                            } else {
                                item.setOverLimitFlag(0);
                            }
                        }
                    }

                    //判断是否越限
                    if (!limitMap.isEmpty()) {
                        String key = item.getLimitName() + STR_ONE + item.getStatMethod() + "#PQ_OVERLIMIT";
                        if (limitMap.containsKey(key)) {
                            ReportTemplateDTO tem = limitMap.get(key);
                            double limitVal = Double.parseDouble(tem.getValue());

                            if(VOLTAGE_DEV.equalsIgnoreCase(tem.getLimitName())){
                                //针对电压偏差特殊处理
                                double limitLowVal = Double.parseDouble(tem.getLowValue());

                                if (v > limitVal || v<limitLowVal) {
                                    tem.setOverLimitFlag(1);
                                    assNoPassMap.put(key, tem);
                                } else if (!assNoPassMap.containsKey(key)) {
                                    tem.setOverLimitFlag(0);
                                    assNoPassMap.put(key, tem);
                                }
                            }else {
                                //其他指标
                                if (v > limitVal) {
                                    tem.setOverLimitFlag(1);
                                    assNoPassMap.put(key, tem);
                                } else if (!assNoPassMap.containsKey(key)) {
                                    tem.setOverLimitFlag(0);
                                    assNoPassMap.put(key, tem);
                                }
                            }
                        }
                    }
                } else {
                    item.setValue("/");
                }
            }
        }
        endList.addAll(data);
    }
    private void assSqlByMysqlNew(Map<String,String> tMap, String dataLevel, Double pt, Double ct, List<ReportTemplateDataVO> data, StringBuilder sql, List<ReportTemplateDataVO> finalDataList, String method, SensitiveUserReportQueryParam queryParam, String lineId) {
        //sql拼接示例：select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai')
        if (InfluxDbSqlConstant.CP95.equals(method)) {
            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(InfluxDbSqlConstant.MAX)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(Objects.equals(dataLevel, "Secondary") ? " " + appendData(tMap, data.get(i).getTemplateName()+data.get(i).getPhase()+data.get(0).getResourceId(), pt, ct) : "")
                            .append(InfluxDbSqlConstant.AS)
                            .append("\"" + data.get(i).getItemName() + "\"");
                } else {
                    sql.append(InfluxDbSqlConstant.MAX)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(Objects.equals(dataLevel, "Secondary") ? " " + appendData(tMap, data.get(i).getTemplateName()+data.get(i).getPhase()+data.get(0).getResourceId(), pt, ct) : "")
                            .append(InfluxDbSqlConstant.AS)
                            .append("\"" + data.get(i).getItemName() + "\"").append(StrUtil.COMMA);
                }
            }
        } else {
            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(Objects.equals(dataLevel, "Secondary") ? " " + appendData(tMap, data.get(i).getTemplateName()+data.get(i).getPhase()+data.get(0).getResourceId(), pt, ct) : "")
                            .append(InfluxDbSqlConstant.AS)
                            .append("\"" + data.get(i).getItemName() + "\"");
                } else {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(Objects.equals(dataLevel, "Secondary") ? " " + appendData(tMap, data.get(i).getTemplateName()+data.get(i).getPhase()+data.get(0).getResourceId(), pt, ct) : "")
                            .append(InfluxDbSqlConstant.AS)
                            .append("\"" + data.get(i).getItemName() + "\"").append(StrUtil.COMMA);
                }
            }

        }

        //拼接表名
        sql.append(StrPool.C_SPACE)
                .append(InfluxDbSqlConstant.FROM)
                .append(data.get(0).getResourceId());


        sql.append(InfluxDbSqlConstant.WHERE)
                .append(InfluxDBTableConstant.LINE_ID)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(lineId)
                .append(InfluxDbSqlConstant.QM);
        //相别特殊处理
        if (!InfluxDBTableConstant.NO_PHASE.equals(data.get(0).getPhase())) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(data.get(0).getPhase())
                    .append(InfluxDbSqlConstant.QM);
        }

        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDBTableConstant.VALUE_TYPE)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(data.get(0).getStatMethod())
                .append(InfluxDbSqlConstant.QM);


        //频率和频率偏差仅统计T相
        if (data.get(0).getTemplateName().equals("freq_dev") || data.get(0).getTemplateName().equals("freq")) {
            sql.append(InfluxDbSqlConstant.AND)
                    .append(InfluxDBTableConstant.PHASIC_TYPE)
                    .append(InfluxDbSqlConstant.EQ)
                    .append(InfluxDbSqlConstant.QM)
                    .append(InfluxDBTableConstant.PHASE_TYPE_T)
                    .append(InfluxDbSqlConstant.QM);
        }
        //时间范围处理
        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(queryParam.getStartTime()).append(InfluxDbSqlConstant.START_TIME).append(InfluxDbSqlConstant.QM)
                .append(InfluxDbSqlConstant.AND)
                .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(queryParam.getEndTime()).append(InfluxDbSqlConstant.END_TIME).append(InfluxDbSqlConstant.QM);

        System.out.println(sql);
        List<Map<String, Object>> mapList = Collections.emptyList();
        // 手动切换数据源
        DynamicDataSourceContextHolder.push("sjzx");
        try {
            mapList = jdbcTemplate.queryForList(sql.toString());
        } catch (Exception e) {
            log.error("查询数据源异常", e);
        } finally {
            DynamicDataSourceContextHolder.poll();
        }

        if (CollUtil.isNotEmpty(data)) {
            for (ReportTemplateDataVO item : data) {
                item.setValue("/");
                if (CollUtil.isNotEmpty(mapList)) {
                    Map<String, Object> map = convertKeysToUpperCase(mapList.get(0));
                    Object value = map.getOrDefault(item.getItemName(), 0);
                    if (Objects.nonNull(value)) {
                        double v = Double.parseDouble(value.toString());
                        item.setValue(String.format("%.3f", v));
                    } else {
                        item.setValue("/");
                    }
                }
            }
            finalDataList.addAll(data);
        }


    }

    public String appendData(Map<String,String> tMap,String name, double pt, double ct) {
        String result;
        String format = tMap.get(name);
        if (Objects.equals(format, "*PT")) {
            result = "*"+pt+"/1000";
        } else if (Objects.equals(format, "*CT")) {
            result = "*"+ct;
        } else if (Objects.equals(format, "*PT*CT")) {
            result = "*"+pt+"*"+ct+"/1000";
        } else {
            result = "";
        }
        return result;
    }

    /**
     * 处理
     *
     * @author cdf
     * @date 2023/10/8
     */

    private void analyzeReport(ReportSearchParam reportSearchParam, ExcelRptTemp excelRptTemp, HttpServletResponse response) {
        //定义一个线程集合
        List<Future<?>> futures = new ArrayList<>();
        //指标
        List<ReportTemplateDTO> reportTemplateDTOList = new ArrayList<>();
        //限值
        List<ReportTemplateDTO> reportLimitList = new ArrayList<>();
        //台账
        List<ReportTemplateDTO> terminalList = new ArrayList<>();
        JSONArray jsonArray;
        try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) {
            jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig()));
            parseTemplate(jsonArray, reportTemplateDTOList, reportLimitList, terminalList);
        } catch (Exception e) {
            if (e instanceof BusinessException) {
                throw new BusinessException(e.getMessage());
            } else {
                throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
            }
        }
        //查询不分相别的指标
        DictData dictData = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.EPD.getCode(), DicDataTypeEnum.CS_DATA_TYPE.getCode()).getData();
        if(Objects.isNull(dictData)){
            throw new BusinessException(CommonResponseEnum.FAIL,"字典类型模板缺少!");
        }


        //List<EleEpdPqd> temTargetList = eleEpdMapper.selectList(new LambdaQueryWrapper<EleEpdPqd>().eq(EleEpdPqd::getDataType,dictData.getId()).in(EleEpdPqd::getPhase,Arrays.asList("T", "M")));

        DictData epdDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.EPD.getCode(),DicDataTypeEnum.CS_DATA_TYPE.getCode()).getData();
        List<EleEpdPqd> eleEpdPqdList= epdFeignClient.dictMarkByDataType(epdDic.getId()).getData();
        eleEpdPqdList = eleEpdPqdList.stream().filter(it->"T".equals(it.getPhase())||"M".equals(it.getPhase())).collect(Collectors.toList());
        List<String> noPhaseList = eleEpdPqdList.stream().filter(it->StrUtil.isNotBlank(it.getOtherName())).map(it->it.getOtherName().toUpperCase()).collect(Collectors.toList());

        //处理指标是否合格
        reportLimitList = new LinkedHashSet<>(reportLimitList).stream().sorted(Comparator.comparing(ReportTemplateDTO::getItemName)).collect(Collectors.toList());
        Map<String, Float> limitMap = overLimitDeal(reportLimitList, reportSearchParam);
        //存放限值指标的map
        Map<String, ReportTemplateDTO> limitTargetMapX = reportLimitList.stream().collect(Collectors.toMap(ReportTemplateDTO::getItemName, Function.identity()));

        List<ReportTemplateDTO> endList = new CopyOnWriteArrayList<>();
        if (CollUtil.isNotEmpty(reportTemplateDTOList)) {
            //开始组织sql
            reportTemplateDTOList = new LinkedHashSet<>(reportTemplateDTOList).stream().sorted(Comparator.comparing(ReportTemplateDTO::getItemName)).collect(Collectors.toList());
            Map<String, List<ReportTemplateDTO>> classMap = reportTemplateDTOList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getResourceId));
            //定义存放越限指标的map
            Map<String, ReportTemplateDTO> assNoPassMap = new HashMap<>();

            classMap.forEach((classKey, templateValue) -> {
                Map<String, List<ReportTemplateDTO>> valueTypeMap = templateValue.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getStatMethod));
                //每张表开启一个独立线程查询
                futures.add(executorService.submit(() -> {
                    // 子线程中手动指定数据源（关键）
                    DynamicDataSourceContextHolder.push("sjzx");
                    //avg.max,min,cp95
                    try {
                        valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> {
                            //相别分组
                            Map<String, List<ReportTemplateDTO>> phaseMap = valueTypeVal.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getPhase));
                            phaseMap.forEach((phaseKey, phaseVal) -> {
                                StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);
                                if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) {
                                    assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap,noPhaseList);
                                } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) {
                                    assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap,noPhaseList);
                                } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) {
                                    assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.AVG_WEB, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap,noPhaseList);
                                } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) {
                                    assSqlByMysql(phaseVal, sql, endList, InfluxDbSqlConstant.CP95, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap,noPhaseList);
                                }

                            });
                        });
                    }finally {
                        DynamicDataSourceContextHolder.poll();
                    }
                }));

            });

            // 等待所有任务完成
            for (Future<?> future : futures) {
                try {
                    future.get(); // 这会阻塞直到任务完成或抛出异常
                } catch (InterruptedException | ExecutionException e) {
                    e.printStackTrace();
                    log.error("自定义报表多线程查询流程出错！错误信息{}", e.getMessage());
                }
            }

            //处理指标最终判定合格还是不合格
            dealTargetResult(assNoPassMap, limitTargetMapX, endList);
        }
        if (CollUtil.isNotEmpty(endList)) {
            //数据单位信息
            Map<String, String> unit = unitMap(reportSearchParam);
            //进行反向赋值到模板
            //1、根据itemName分组
            Map<String, List<ReportTemplateDTO>> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName));
            //处理台账信息
            Map<String, String> finalTerminalMap;
            if (CollUtil.isNotEmpty(terminalList)) {
                finalTerminalMap = convertKeysToUpperCase(csLineFeignClient.getCustomDetailByLineId(reportSearchParam.getLineId()).getData());
            } else {
                finalTerminalMap = new HashMap<>();
            }
            //2、把itemName的value赋给v和m
            jsonArray.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
                itemArr.forEach((it) -> {
                    if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                        //获取到1列
                        JSONObject data = (JSONObject) it;
                        JSONObject son = (JSONObject) data.get(V);
                        if (son.containsKey(V)) {
                            String v = son.getStr(V);
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains(STR_ONE)) {
                                String str = "";
                                List<ReportTemplateDTO> rDto = assMap.get(v.replace(STR_TWO, "").toUpperCase());
                                if (Objects.nonNull(rDto)) {
                                    str = rDto.get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set(V, str);
                                    if (Objects.nonNull(rDto.get(0).getOverLimitFlag()) && rDto.get(0).getOverLimitFlag() == 1) {
                                        son.set("fc", "#990000");
                                    }
                                }
                            } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) {
                                //指标合格情况
                                String str = "";
                                List<ReportTemplateDTO> rDto = assMap.get(v.replace(STR_FOUR, "").toUpperCase());
                                if (Objects.nonNull(rDto)) {
                                    str = rDto.get(0).getValue();
                                    //没有值，赋"/"
                                    if (StringUtils.isBlank(str)) {
                                        str = "/";
                                    }
                                    son.set(V, str);
                                    if ("不合格".equals(str)) {
                                        son.set("fc", "#990000");
                                    }
                                }
                            } else if (v.charAt(0) == '&') {
                                //结论
                                String tem = v.replace(STR_THREE, "").toUpperCase();
                                if (Objects.nonNull(finalTerminalMap)) {
                                    if ("STATIS_TIME".equals(tem)) {
                                        //如何时间是大于当前时间则用当前时间
                                        String localTime = InfluxDbSqlConstant.END_TIME;
                                        LocalDate localDate = LocalDateTimeUtil.parseDate(reportSearchParam.getEndTime(), DatePattern.NORM_DATE_PATTERN);
                                        LocalDate nowDate = LocalDate.now();
                                        if (nowDate.isAfter(localDate)) {
                                            son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + localTime);
                                        } else {
                                            localTime = " " + LocalTime.now().format(DatePattern.NORM_TIME_FORMATTER);
                                            son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + nowDate + localTime);
                                        }
                                    } else {
                                        //台账信息
                                        son.set(V, finalTerminalMap.getOrDefault(tem, "/"));
                                    }
                                }
                            }
                            //解决数据单位问题 @指标#类型@
                            if (v.charAt(0) == '@' && v.contains(STR_ONE)) {
                                String replace = v.replace("@", "");
                                son.set(V, unit.getOrDefault(replace, "/"));

                            }
                        }
                    }
                });
            });
        }
        //导出自定义报表
        downReport(jsonArray, response);
    }

    /**
     * 解析模板
     *
     * @author cdf
     * @date 2023/10/20
     */
    private void parseTemplate(JSONArray jsonArray, List<ReportTemplateDTO> reportTemplateDTOList, List<ReportTemplateDTO> reportLimitList, List<ReportTemplateDTO> terminalList) {
        try {
            //通过文件服务器获取
            jsonArray.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
                itemArr.forEach((it) -> {
                    if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                        //获取到1列
                        JSONObject data = (JSONObject) it;
                        JSONObject son = (JSONObject) data.get(V);
                        if (son.containsKey(V)) {
                            String v = son.getStr(V);
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains(STR_ONE)) {
                                //剔除前后$
                                v = v.replace(STR_TWO, "");
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                reportTemplateDTO.setItemName(v.toUpperCase());
                                //根据#分割数据
                                String[] vItem = v.split(STR_ONE);
                                if (vItem.length == 5) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0].toUpperCase());
                                    reportTemplateDTO.setPhase(vItem[1].substring(0, 1).toUpperCase());
                                    reportTemplateDTO.setStatMethod(vItem[2].toUpperCase());
                                    reportTemplateDTO.setResourceId(vItem[3].toUpperCase());
                                    reportTemplateDTO.setLimitName(vItem[4].toUpperCase());
                                } else if (vItem.length == 4) {
                                    //$HA[_25]#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0].toUpperCase());
                                    reportTemplateDTO.setPhase("T");
                                    reportTemplateDTO.setStatMethod(vItem[1].toUpperCase());
                                    reportTemplateDTO.setResourceId(vItem[2].toUpperCase());
                                    reportTemplateDTO.setLimitName(vItem[3].toUpperCase());
                                }

                                reportTemplateDTOList.add(reportTemplateDTO);
                            } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) {
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                v = v.replace(STR_FOUR, "");
                                reportTemplateDTO.setItemName(v.toUpperCase());
                                //根据#分割数据
                                String[] vItem = v.split(STR_ONE);
                                if (vItem.length == 3) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0].toUpperCase());
                                    reportTemplateDTO.setStatMethod(vItem[1].toUpperCase());
                                    reportTemplateDTO.setResourceId(vItem[2].toUpperCase());
                                }
                                reportLimitList.add(reportTemplateDTO);
                            } else if (v.charAt(0) == '&') {
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                v = v.replace(STR_THREE, "");
                                reportTemplateDTO.setItemName(v.toUpperCase());
                                reportTemplateDTO.setTemplateName(v.toUpperCase());
                                terminalList.add(reportTemplateDTO);
                            }
                        }
                    }
                });
            });
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
    }

    /**
     * 解析治理模板
     */
    private void parseGovernTemplate(JSONArray jsonArray, List<ReportTemplateDataVO> indexDataList, List<ReportTemplateDataVO> improvementRateDataList, List<ReportTemplateDataVO> basicDataList) {
        try {
            //通过文件服务器获取
            for (Object item : jsonArray) {
                JSONObject itemJSON = JSONUtil.parseObj(item);
                JSONArray itemArr = itemJSON.getJSONArray(CELL_DATA);
                for (Object it : itemArr) {
                    if (!JSONUtil.isNull(it) && JSONUtil.isJsonObj(it.toString())) {
                        //获取到1列
                        JSONObject data = JSONUtil.parseObj(it);
                        JSONObject son = data.getJSONObject(V);
                        if (son.containsKey(V)) {
                            String v = son.getStr(V);
                            if (StrUtil.isNotEmpty(v)) {
                                //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                                if (v.charAt(0) == '$' && v.contains(STR_ONE)) {
                                    //剔除前后$
                                    v = v.replace(STR_TWO, "");
                                    //封装指标项
                                    ReportTemplateDataVO indexDataVO = new ReportTemplateDataVO();
                                    indexDataVO.setItemName(v.toUpperCase());
                                    //根据#分割数据
                                    String[] vItem = v.split(STR_ONE);
                                    if (vItem.length == 5) {
                                        //$HA[_25]#B#max#classId#no$
                                        indexDataVO.setTemplateName(vItem[0].toUpperCase());
                                        indexDataVO.setPhase(vItem[1].substring(0, 1).toUpperCase());
                                        indexDataVO.setStatMethod(vItem[2].toUpperCase());
                                        indexDataVO.setResourceId(vItem[3].toUpperCase());
                                    } else if (vItem.length == 4) {
                                        //$HA[_25]#max#classId#no$
                                        indexDataVO.setTemplateName(vItem[0].toUpperCase());
                                        indexDataVO.setPhase("T");
                                        indexDataVO.setStatMethod(vItem[1].toUpperCase());
                                        indexDataVO.setResourceId(vItem[2].toUpperCase());
                                    }
                                    indexDataList.add(indexDataVO);
                                } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) {
                                    //封装指标改善率
                                    ReportTemplateDataVO improvementRateDataVO = new ReportTemplateDataVO();
                                    v = v.replace(STR_FOUR, "");
                                    improvementRateDataVO.setItemName(v.toUpperCase());
                                    //根据#分割数据
                                    String[] vItem = v.split(STR_ONE);
                                    if (vItem.length == 3) {
                                        //%vu_dev#A#max%
                                        improvementRateDataVO.setTemplateName(vItem[0].toUpperCase());
                                        improvementRateDataVO.setPhase(vItem[1].substring(0, 1).toUpperCase());
                                        improvementRateDataVO.setStatMethod(vItem[2].toLowerCase());
                                    }
                                    improvementRateDataList.add(improvementRateDataVO);
                                } else if (v.charAt(0) == '&') {
                                    //基础数据
                                    ReportTemplateDataVO basicDataVO = new ReportTemplateDataVO();
                                    v = v.replace(STR_THREE, "");
                                    basicDataVO.setItemName(v.toUpperCase());
                                    basicDataVO.setTemplateName(v.toUpperCase());
                                    basicDataList.add(basicDataVO);
                                } else if (v.charAt(0) == '~' && v.contains(STR_ONE)) {
                                    //~$HA[_25]#B#max#classId#no$ 治理后的
                                    //剔除~再剔除前后$
                                    v = v.replace(STR_FIVE, "").replace(STR_TWO, "");
                                    //封装指标项
                                    ReportTemplateDataVO indexDataVO = new ReportTemplateDataVO();
                                    indexDataVO.setItemName(v.toUpperCase());
                                    //根据#分割数据
                                    String[] vItem = v.split(STR_ONE);
                                    if (vItem.length == 5) {
                                        //~$HA[_25]#B#max#classId#no$
                                        indexDataVO.setTemplateName(vItem[0].toUpperCase());
                                        indexDataVO.setPhase(vItem[1].substring(0, 1).toUpperCase());
                                        indexDataVO.setStatMethod(vItem[2].toUpperCase());
                                        indexDataVO.setResourceId(vItem[3].toUpperCase());
                                    } else if (vItem.length == 4) {
                                        //$HA[_25]#max#classId#no$
                                        indexDataVO.setTemplateName(vItem[0].toUpperCase());
                                        indexDataVO.setPhase("T");
                                        indexDataVO.setStatMethod(vItem[1].toUpperCase());
                                        indexDataVO.setResourceId(vItem[2].toUpperCase());
                                    }
                                    indexDataList.add(indexDataVO);
                                }
                            }

                        }
                    }
                }
            }
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
    }

    /**
     * 获取测点限值
     *
     * @author cdf
     * @date 2023/10/23
     */
    private Map<String, Float> overLimitDeal(List<ReportTemplateDTO> reportLimitList, ReportSearchParam
            reportSearchParam) {
        Map<String, Float> limitMap = new HashMap<>();
        if (CollUtil.isNotEmpty(reportLimitList)) {
            StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);
            for (int i = 0; i < reportLimitList.size(); i++) {
                if (i == reportLimitList.size() - 1) {
                    sql.append(UVOLTAGE_DEV).append(StrUtil.COMMA);
                    sql.append(reportLimitList.get(i).getTemplateName()).append(StrUtil.C_SPACE);
                } else {
                    sql.append(reportLimitList.get(i).getTemplateName()).append(StrUtil.COMMA);
                }
            }

            sql.append(InfluxDbSqlConstant.FROM).append(reportLimitList.get(0).getResourceId()).append(InfluxDbSqlConstant.WHERE).append("id ='").append(reportSearchParam.getLineId()).append("'");
            limitMap = excelRptTempMapper.dynamicSqlMap(sql.toString());
            if (Objects.isNull(limitMap)) {
                throw new BusinessException("当前报表测点限值缺失!");
            }

            for (ReportTemplateDTO item : reportLimitList) {
                if (limitMap.containsKey(item.getTemplateName())) {

                    if(item.getTemplateName().equalsIgnoreCase(VOLTAGE_DEV)){
                        item.setLowValue(limitMap.get(UVOLTAGE_DEV).toString());
                    }
                    item.setValue(limitMap.get(item.getTemplateName()).toString());
                }
            }
        }
        limitMap = convertKeysToUpperCase(limitMap);
        return limitMap;
    }

    /**
     * 报告下载
     */
    private void downReport(JSONArray jsonArray, HttpServletResponse response) {
        InputStream reportStream = IoUtil.toStream(jsonArray.toString(), CharsetUtil.UTF_8);
        response.setContentType("application/octet-stream;charset=UTF-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + "aa");
        OutputStream toClient = null;
        try {
            toClient = new BufferedOutputStream(response.getOutputStream());
            //通过IOUtils对接输入输出流，实现文件下载
            IOUtils.copy(reportStream, toClient);
            toClient.flush();
        } catch (Exception e) {
            throw new BusinessException(OssResponseEnum.DOWNLOAD_FILE_STREAM_ERROR);
        } finally {
            IOUtils.closeQuietly(reportStream);
            IOUtils.closeQuietly(toClient);
        }
    }

    private void analyzeReportZhejiang(ReportSearchParam reportSearchParam, ExcelRptTemp excelRptTemp, HttpServletResponse response) {
        //指标
        List<ReportTemplateDTO> reportTemplateDTOList = new ArrayList<>();
        //限值
        List<ReportTemplateDTO> reportLimitList = new ArrayList<>();
        //台账
        List<ReportTemplateDTO> terminalList = new ArrayList<>();
        JSONArray jsonArray;
        try (InputStream fileStream = fileStorageUtil.getFileStream(excelRptTemp.getContent())) {
            jsonArray = new JSONArray(new JSONTokener(fileStream, new JSONConfig()));
            parseTemplateZhejiang(jsonArray, reportTemplateDTOList, reportLimitList, terminalList);
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }

        DictData pqdDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.PQD.getCode(), DicDataTypeEnum.CS_DATA_TYPE.getCode()).getData();
        List<EleEpdPqd> eleEpdPqdList = epdFeignClient.dictMarkByDataType(pqdDic.getId()).getData()
                .stream().filter(item -> StrUtil.isNotEmpty(item.getPrimaryFormula())).collect(Collectors.toList());
        eleEpdPqdList.sort(Comparator.comparingInt(EleEpdPqd::getSort));
        Map<String, List<EleEpdPqd>> pqdMap = eleEpdPqdList.stream().collect(Collectors.groupingBy(EleEpdPqd::getName));

        //处理指标是否合格
        reportLimitList = new LinkedHashSet<>(reportLimitList)
                .stream()
                .sorted(Comparator.comparing(ReportTemplateDTO::getItemName))
                .collect(Collectors.toList());

        Map<String, Float> limitMap = overLimitDeal(reportLimitList, reportSearchParam);
        //存放限值指标的map
        Map<String, ReportTemplateDTO> limitTargetMapX = reportLimitList.stream().collect(Collectors.toMap(ReportTemplateDTO::getItemName, Function.identity()));

        //组装最后监测点条件
        List<WlRecord> temList = wlRecordFeignClient.getWlAssByWlId(reportSearchParam.getLineId()).getData();
        //List<WlRecord> wlRecordList = temList.stream().filter(it -> it.getType() == 1).collect(Collectors.toList());
        if (CollUtil.isEmpty(temList) && temList.size() == 1) {
            throw new BusinessException("当前测试项无测试数据");
        }

        List<ReportTemplateDTO> endList = new ArrayList<>();
        if (CollUtil.isNotEmpty(reportTemplateDTOList)) {

            //开始组织sql
            reportTemplateDTOList = new LinkedHashSet<>(reportTemplateDTOList)
                    .stream()
                    .sorted(Comparator.comparing(ReportTemplateDTO::getItemName))
                    .collect(Collectors.toList());


            Map<String, List<ReportTemplateDTO>> classMap = reportTemplateDTOList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getResourceId));
            Map<String, ReportTemplateDTO> assNoPassMap = new HashMap<>();
            long deal = System.currentTimeMillis();
            classMap.forEach((classKey, templateValue) -> {
                Map<String, List<ReportTemplateDTO>> valueTypeMap = templateValue.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getStatMethod));

                //avg.max,min,cp95
                valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> {

                    //相别分组
                    Map<String, List<ReportTemplateDTO>> phaseMap = valueTypeVal.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getPhase));
                    phaseMap.forEach((phaseKey, phaseVal) -> {
                        StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);
                        if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) {
                            assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.MAX, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap);
                        } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) {
                            assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.MIN, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap);
                        } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) {
                            assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.AVG, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap);
                        } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) {
                            assSqlZhejiang(phaseVal, sql, endList, InfluxDbSqlConstant.PERCENTILE, reportSearchParam, limitTargetMapX, limitMap, assNoPassMap, temList, pqdMap);
                        }
                    });
                });

            });
            //处理指标最终判定合格还是不合格
            dealTargetResult(assNoPassMap, limitTargetMapX, endList);
            long dealEnd = System.currentTimeMillis();
            System.out.println("查询数据库花费时间" + (dealEnd - deal) / 1000 + "S");
        }
        if (CollUtil.isNotEmpty(endList)) {
            long jie = System.currentTimeMillis();
            //数据单位信息
            Map<String, String> unit = unitMap(reportSearchParam);
            //进行反向赋值到模板
            //1、根据itemName分组
            Map<String, List<ReportTemplateDTO>> assMap = endList.stream().collect(Collectors.groupingBy(ReportTemplateDTO::getItemName));
            //处理台账信息
            Map<String, String> finalTerminalMap;
            if (CollUtil.isNotEmpty(terminalList)) {
                if (Objects.nonNull(reportSearchParam.getCustomType()) && reportSearchParam.getCustomType() == 1) {
                    WlRecord wlRecordMain = temList.stream().filter(it -> it.getType() == 0).collect(Collectors.toList()).get(0);
                    finalTerminalMap = new HashMap<>();
                    finalTerminalMap.put("lineName", wlRecordMain.getItemName());
                    //finalTerminalMap.put("statis_time",wlRecordMain.getStartTime()+"_"+wlRecordMain.getEndTime());
                    finalTerminalMap.put("pt", wlRecordMain.getCt().toString());
                    finalTerminalMap.put("ct", wlRecordMain.getPt().toString());

                    finalTerminalMap.put("Standard_Capacity", wlRecordMain.getCapacitySscb().toString());
                    finalTerminalMap.put("Short_Capacity", wlRecordMain.getCapacitySscmin().toString());
                    finalTerminalMap.put("Deal_Capacity", wlRecordMain.getCapacitySi().toString());
                    finalTerminalMap.put("Dev_Capacity", wlRecordMain.getCapacitySt().toString());
                } else {
                    finalTerminalMap = commTerminalGeneralClient.getCustomDetailByLineId(reportSearchParam.getLineId()).getData();
                }
            } else {
                finalTerminalMap = new HashMap<>();
            }
            //2、把itemName的value赋给v和m
            dealExcelResult(jsonArray, assMap, unit, finalTerminalMap);
            long jieEnd = System.currentTimeMillis();
            System.out.println("组装信息耗时 " + (jieEnd - jie) / 1000 + "S");
        }

        long daochu = System.currentTimeMillis();
        //导出自定义报表
        downReport(jsonArray, response);
        long daochuEnd = System.currentTimeMillis();
        System.out.println("导出耗时 " + (daochuEnd - daochu) / 1000 + "S");
    }

    private void assSqlZhejiang(List<ReportTemplateDTO> data, StringBuilder
            sql, List<ReportTemplateDTO> endList, String method, ReportSearchParam reportSearchParam, Map<String, ReportTemplateDTO> limitMap, Map<String, Float> overLimitMap, Map<String,
            ReportTemplateDTO> assNoPassMap, List<WlRecord> wlRecordList, Map<String, List<EleEpdPqd>> pqdMap) {

        //sql拼接示例：select MAX(IHA2) as IHA2 from power_quality_data where Phase = 'A' and LineId='1324564568' and Stat_Method='max' tz('Asia/Shanghai')
        //cp95函数特殊处理 PERCENTILE(field_key, N)
        if (InfluxDbSqlConstant.PERCENTILE.equals(method)) {
            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(InfluxDbSqlConstant.PERCENTILE)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName()).append(InfluxDbSqlConstant.NUM_95)
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM);
                } else {
                    sql.append(InfluxDbSqlConstant.PERCENTILE)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName()).append(InfluxDbSqlConstant.NUM_95)
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA);
                }
            }
        } else {
            for (int i = 0; i < data.size(); i++) {
                if (i == data.size() - 1) {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM);
                } else {
                    sql.append(method)
                            .append(InfluxDbSqlConstant.LBK)
                            .append(data.get(i).getTemplateName())
                            .append(InfluxDbSqlConstant.RBK)
                            .append(InfluxDbSqlConstant.AS).append(InfluxDbSqlConstant.DQM)
                            .append(data.get(i).getItemName()).append(InfluxDbSqlConstant.DQM).append(StrUtil.COMMA);
                }
            }

        }

        sql.append(StrPool.C_SPACE).append(InfluxDbSqlConstant.FROM).append("pqd_data");
        //相别特殊处理
        sql.append(InfluxDbSqlConstant.WHERE)
                .append(InfluxDBTableConstant.PHASIC_TYPE)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(data.get(0).getPhase())
                .append(InfluxDbSqlConstant.QM);

        //data_flicker、data_fluc、data_plt 无 value_type
        sql.append(InfluxDbSqlConstant.AND)
                .append(InfluxDBTableConstant.VALUE_TYPE)
                .append(InfluxDbSqlConstant.EQ)
                .append(InfluxDbSqlConstant.QM)
                .append(data.get(0).getStatMethod().toLowerCase())
                .append(InfluxDbSqlConstant.QM);

        List<Map<String, Object>> allList = new ArrayList<>();

        WlRecord ceShiItem = wlRecordList.stream().filter(it -> it.getType() == 0).collect(Collectors.toList()).get(0);
        for (WlRecord wlRecord : wlRecordList) {
            if (wlRecord.getType().equals(1)) {
                StringBuilder temSql = new StringBuilder(sql);
                String start = LocalDateTimeUtil.format(wlRecord.getStartTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
                String end = LocalDateTimeUtil.format(wlRecord.getEndTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN));
                temSql.append(" and line_id = '").append(wlRecord.getLineId()).append(InfluxDbSqlConstant.QM)
                        .append(InfluxDbSqlConstant.AND)
                        .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.GE).append(InfluxDbSqlConstant.QM).append(start).append(InfluxDbSqlConstant.QM)
                        .append(InfluxDbSqlConstant.AND)
                        .append(InfluxDbSqlConstant.TIME).append(InfluxDbSqlConstant.LT).append(InfluxDbSqlConstant.QM).append(end).append(InfluxDbSqlConstant.QM)
                        .append(InfluxDbSqlConstant.TZ);

                List<Map<String, Object>> temMapList = influxDbUtils.getMapResult(temSql.toString());
                if (CollUtil.isNotEmpty(temMapList)) {
                    Map<String, Object> tem = temMapList.get(0);
                    //需要吧测点为二次值的转换为一次值
                    if (wlRecord.getDataLevel().equals("Secondary")) {
                        for (Map.Entry<String, Object> entry : tem.entrySet()) {
                            if (Objects.nonNull(entry.getValue()) && !entry.getKey().equals("time")) {
                                String key = entry.getKey();
                                double val = (double) entry.getValue();
                                String zi = key.substring(0, key.indexOf(STR_ONE));
                                String[] temStrArr = zi.split("_");
                                boolean flag = isInteger(temStrArr[temStrArr.length - 1]);
                                if (flag) {
                                    zi = zi.substring(0, zi.lastIndexOf("_"));
                                }
                                if (pqdMap.containsKey(zi)) {
                                    EleEpdPqd eleEpdPqd = pqdMap.get(zi).get(0);
                                    if (!eleEpdPqd.getPrimaryFormula().equals("*CT")) {
                                        val = val / 1000;
                                    }
                                    double vRes = DataChangeUtil.secondaryToPrimary(eleEpdPqd.getPrimaryFormula(), val, (double) ceShiItem.getPt(), (double) ceShiItem.getCt());
                                    entry.setValue(vRes);
                                }
                            }
                        }
                    }

                    allList.add(temMapList.get(0));
                }
            }
        }

        Map<String, Object> resultMap = dealResultMap(method, allList);
        if (resultMap.isEmpty()) {
            data = data.stream().peek(item -> item.setValue("/")).collect(Collectors.toList());
        } else {
            //遍历模板对查询出来的数据进行赋值
            for (ReportTemplateDTO item : data) {
                if (resultMap.containsKey(item.getItemName())) {
                    double v = (Double) resultMap.get(item.getItemName());
                    item.setValue(String.format("%.3f", v));

                    if (overLimitMap.containsKey(item.getLimitName())) {
                        Float tagVal = overLimitMap.get(item.getLimitName());
                        if (v > tagVal) {
                            item.setOverLimitFlag(1);
                        } else {
                            item.setOverLimitFlag(0);
                        }
                    }

                    //结论判断是否越限
                    String key = item.getLimitName() + STR_ONE + item.getStatMethod().toLowerCase() + "#pq_overlimit";
                    if (limitMap.containsKey(key)) {
                        ReportTemplateDTO tem = limitMap.get(key);
                        double limitVal = Double.parseDouble(tem.getValue());
                        if (v > limitVal) {
                            tem.setOverLimitFlag(1);
                            tem.setValue(tem.getValue());
                            assNoPassMap.put(key, tem);
                        } else if (!assNoPassMap.containsKey(key)) {
                            tem.setOverLimitFlag(0);
                            tem.setValue(tem.getValue());
                            assNoPassMap.put(key, tem);
                        }
                    }
                } else {
                    item.setValue("/");
                }
            }
        }

        endList.addAll(data);
    }

    /**
     * 对多测点数据进行计算求出一组数据
     *
     * @param method
     * @param allList
     * @return
     */
    private Map<String, Object> dealResultMap(String method, List<Map<String, Object>> allList) {
        Map<String, Object> resultMap = new HashMap<>();
        // 遍历列表中的每个Map
        if (method.equals(InfluxDbSqlConstant.MIN)) {
            for (Map<String, Object> map : allList) {
                // 遍历当前Map的键值对
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    String key = entry.getKey();
                    if (Objects.nonNull(entry.getValue()) && !key.equals("time")) {
                        double value = (double) entry.getValue();
                        // 检查结果Map中是否已包含该键
                        if (!resultMap.containsKey(key) || (double) resultMap.get(key) > value) {
                            // 如果不包含，或当前值更大，则更新结果Map
                            resultMap.put(key, value);
                        }
                    }
                }
            }
        } else if (method.equals(InfluxDbSqlConstant.MAX) || method.equals(InfluxDbSqlConstant.PERCENTILE)) {
            for (Map<String, Object> map : allList) {
                // 遍历当前Map的键值对
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    String key = entry.getKey();
                    if (Objects.nonNull(entry.getValue()) && !key.equals("time")) {
                        double value = (double) entry.getValue();
                        // 检查结果Map中是否已包含该键
                        if (!resultMap.containsKey(key) || (double) resultMap.get(key) < value) {
                            // 如果不包含，或当前值更大，则更新结果Map
                            resultMap.put(key, value);
                        }
                    }
                }
            }
        } else if (method.equals(InfluxDbSqlConstant.AVG)) {
            Map<String, Double> sumMap = new HashMap<>();
            Map<String, Integer> countMap = new HashMap<>();
            // 遍历列表中的每个Map
            for (Map<String, Object> map : allList) {
                // 遍历当前Map的键值对
                for (Map.Entry<String, Object> entry : map.entrySet()) {
                    String key = entry.getKey();
                    if (Objects.nonNull(entry.getValue()) && !key.equals("time")) {
                        double value = (double) entry.getValue();

                        // 更新累计和
                        sumMap.put(key, sumMap.getOrDefault(key, 0.0) + value);
                        // 更新计数
                        countMap.put(key, countMap.getOrDefault(key, 0) + 1);
                    }
                }
            }

            // 计算平均值并存储到结果Map中
            for (String key : sumMap.keySet()) {
                double sum = sumMap.get(key);
                int count = countMap.get(key);
                double average = BigDecimal.valueOf(sum / count).setScale(3, RoundingMode.HALF_UP).doubleValue();
                resultMap.put(key, average);
            }
        }

        return resultMap;
    }

    private void dealExcelResult(JSONArray
                                         jsonArray, Map<String, List<ReportTemplateDTO>> assMap, Map<String, String> unit, Map<String, String> finalTerminalMap) {
        jsonArray.forEach(item -> {
            JSONObject jsonObject = (JSONObject) item;
            JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
            itemArr.forEach((it) -> {
                if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                    //获取到1列
                    JSONObject data = (JSONObject) it;
                    JSONObject son = (JSONObject) data.get(V);
                    if (son.containsKey(V)) {
                        String v = son.getStr(V);
                        //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                        if (v.charAt(0) == '$' && v.contains(STR_ONE)) {
                            String str = "";
                            List<ReportTemplateDTO> rDto = assMap.get(v.replace(STR_TWO, ""));
                            if (Objects.nonNull(rDto)) {
                                str = rDto.get(0).getValue();
                                //没有值，赋"/"
                                if (StringUtils.isBlank(str)) {
                                    str = "/";
                                }
                                son.set(V, str);
                                if (Objects.nonNull(rDto.get(0).getOverLimitFlag()) && rDto.get(0).getOverLimitFlag() == 1) {
                                    son.set("fc", "#990000");
                                }
                            }
                        } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) {
                            //指标合格情况
                            String str = "";
                            List<ReportTemplateDTO> rDto = assMap.get(v.replace(STR_FOUR, ""));
                            if (Objects.nonNull(rDto)) {
                                str = rDto.get(0).getValue();
                                //没有值，赋"/"
                                if (StringUtils.isBlank(str)) {
                                    str = "/";
                                }
                                son.set(V, str);
                                if ("不合格".equals(str)) {
                                    son.set("fc", "#990000");
                                }
                            }
                        } else if (v.charAt(0) == '&') {
                            //结论
                            String tem = v.replace(STR_THREE, "");
                            if (Objects.nonNull(finalTerminalMap)) {
                                if ("statis_time".equals(tem)) {
                                    // son.set(V, reportSearchParam.getStartTime() + InfluxDbSqlConstant.START_TIME + "_" + reportSearchParam.getEndTime() + InfluxDbSqlConstant.END_TIME);
                                } else {
                                    //台账信息
                                    son.set(V, finalTerminalMap.getOrDefault(tem, "/"));
                                }
                            }
                        } else if (v.charAt(0) == '@' && v.contains(STR_ONE)) {
                            //解决数据单位问题 @指标#类型@
                            String replace = v.replace("@", "");
                            son.set(V, unit.getOrDefault(replace, "/"));

                        }
                    }
                }
            });
        });
    }

    /**
     * 处理指标超标结论
     */
    private void dealTargetResult
    (Map<String, ReportTemplateDTO> assNoPassMap, Map<String, ReportTemplateDTO> limitTargetMapX, List<ReportTemplateDTO> endList) {
        assNoPassMap.forEach((key, val) -> {
            limitTargetMapX.remove(key);
            if ("Freq_Dev".toUpperCase().equals(val.getTemplateName())) {
                val.setValue("±" + val.getValue());
            }

            String expend = "";
            if(Objects.nonNull(val.getLowValue())){
                expend = val.getLowValue()+",";
            }
            if (val.getOverLimitFlag() == 1) {
                val.setValue("不合格 (" + expend+val.getValue() + ")");
            } else {
                val.setValue("合格 (" + expend+val.getValue() + ")");
            }
            endList.add(val);
        });

        limitTargetMapX.forEach((key, val) -> {
            if (Objects.isNull(val.getOverLimitFlag())) {
                val.setValue("/");
            } else {
                val.setValue("合格");
            }
            endList.add(val);
        });
    }


    /**
     * 解析模板
     *
     * @author cdf
     * @date 2023/10/20
     */
    private void parseTemplateZhejiang(JSONArray
                                               jsonArray, List<ReportTemplateDTO> reportTemplateDTOList, List<ReportTemplateDTO> reportLimitList, List<ReportTemplateDTO> terminalList) {
        try {
            //通过文件服务器获取

            jsonArray.forEach(item -> {
                JSONObject jsonObject = (JSONObject) item;
                JSONArray itemArr = (JSONArray) jsonObject.get(CELL_DATA);
                itemArr.forEach((it) -> {
                    if (Objects.nonNull(it) && !"null".equals(it.toString())) {
                        //获取到1列
                        JSONObject data = (JSONObject) it;
                        JSONObject son = (JSONObject) data.get(V);
                        if (son.containsKey(V)) {
                            String v = son.getStr(V);
                            //数据格式：$HA[_25]#B#max#classId$ 或 $HA[_25]#max#classId$
                            if (v.charAt(0) == '$' && v.contains(STR_ONE)) {
                                //剔除前后$
                                v = v.replace(STR_TWO, "");
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                reportTemplateDTO.setItemName(v);
                                //根据#分割数据
                                String[] vItem = v.split(STR_ONE);
                                if (vItem.length == 5) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setPhase(vItem[1]);
                                    reportTemplateDTO.setStatMethod(vItem[2]);
                                    reportTemplateDTO.setResourceId(vItem[3]);
                                    reportTemplateDTO.setLimitName(vItem[4]);
                                } else if (vItem.length == 4) {
                                    //$HA[_25]#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setPhase("T");
                                    reportTemplateDTO.setStatMethod(vItem[1]);
                                    reportTemplateDTO.setResourceId(vItem[2]);
                                    reportTemplateDTO.setLimitName(vItem[3]);
                                }

                                reportTemplateDTOList.add(reportTemplateDTO);
                            } else if (v.charAt(0) == '%' && v.contains(STR_ONE)) {
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();

                                v = v.replace(STR_FOUR, "");
                                reportTemplateDTO.setItemName(v);
                                //根据#分割数据
                                String[] vItem = v.split(STR_ONE);
                                if (vItem.length == 3) {
                                    //$HA[_25]#B#max#classId$
                                    reportTemplateDTO.setTemplateName(vItem[0]);
                                    reportTemplateDTO.setStatMethod(vItem[1]);
                                    reportTemplateDTO.setResourceId(vItem[2]);
                                }
                                reportLimitList.add(reportTemplateDTO);
                            } else if (v.charAt(0) == '&') {
                                //封装ReportTemplateDTO
                                ReportTemplateDTO reportTemplateDTO = new ReportTemplateDTO();
                                v = v.replace(STR_THREE, "");
                                reportTemplateDTO.setItemName(v);
                                reportTemplateDTO.setTemplateName(v);
                                terminalList.add(reportTemplateDTO);
                            }
                        }
                    }
                });
            });
        } catch (Exception e) {
            throw new BusinessException(CsHarmonicResponseEnum.CUSTOM_REPORT_JSON);
        }
    }

    private List<ReportTemplateDataVO> fetchDataList(CsLinePO linePO,
                                                     Map<String, List<ReportTemplateDataVO>> classMap,
                                                     SensitiveUserReportQueryParam queryParam) {
        //获取指标一二次值转换关系
        DictData epdDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.EPD.getCode(),DicDataTypeEnum.CS_DATA_TYPE.getCode()).getData();
        List<EleEpdPqd> eleEpdPqdList= epdFeignClient.dictMarkByDataType(epdDic.getId()).getData();
        Map<String, String> tMap = new HashMap<>();
        eleEpdPqdList.forEach(item->{
            String phase;
            if (Objects.isNull(PHASE_MAPPING.get(item.getPhase()))) {
                phase = item.getPhase();
            } else {
                phase = PHASE_MAPPING.get(item.getPhase());
            }
            if (ObjectUtils.isNotNull(item.getHarmStart()) && ObjectUtils.isNotNull(item.getHarmEnd())) {
                for (int i = item.getHarmStart(); i <= item.getHarmEnd() + 1; i++) {
                    tMap.put((item.getOtherName() + "_" + i + phase + item.getResourcesId()).toUpperCase(), item.getPrimaryFormula());
                }
            } else {
                tMap.put((item.getOtherName() + phase + item.getResourcesId()).toUpperCase(), item.getPrimaryFormula());
            }
        });
        //pt
        double pt = safeDivide(linePO.getPtRatio(), linePO.getPt2Ratio());
        //ct
        double ct = safeDivide(linePO.getCtRatio(), linePO.getCt2Ratio());
        //获取当前监测点是一次值还是二次值
        Map<String,String> map = csLineFeignClient.getCustomDetailByLineId(linePO.getLineId()).getData();
        String dataLevel = map.get("level");

        String lineId = linePO.getLineId();
        List<Future<List<ReportTemplateDataVO>>> futures = new ArrayList<>();

        classMap.forEach((classKey, templateValue) -> {
            Map<String, List<ReportTemplateDataVO>> valueTypeMap = templateValue.stream()
                    .collect(Collectors.groupingBy(ReportTemplateDataVO::getStatMethod));

            futures.add(executorService.submit(() -> {
                List<ReportTemplateDataVO> threadDataList = new ArrayList<>();
                valueTypeMap.forEach((valueTypeKey, valueTypeVal) -> {
                    Map<String, List<ReportTemplateDataVO>> phaseMap = valueTypeVal.stream()
                            .collect(Collectors.groupingBy(ReportTemplateDataVO::getPhase));

                    phaseMap.forEach((phaseKey, phaseVal) -> {
                        // 创建新的数据对象列表，避免引用共享
                        List<ReportTemplateDataVO> newDataList = phaseVal.stream()
                                .map(vo -> {
                                    ReportTemplateDataVO newVo = new ReportTemplateDataVO();
                                    // 复制所有属性
                                    newVo.setItemName(vo.getItemName());
                                    newVo.setTemplateName(vo.getTemplateName());
                                    newVo.setPhase(vo.getPhase());
                                    newVo.setStatMethod(vo.getStatMethod());
                                    newVo.setResourceId(vo.getResourceId());
                                    newVo.setLineId(lineId);
                                    return newVo;
                                })
                                .collect(Collectors.toList());

                        StringBuilder sql = new StringBuilder(InfluxDbSqlConstant.SELECT);

                        if (InfluxDbSqlConstant.MAX.equalsIgnoreCase(valueTypeKey)) {
                            assSqlByMysqlNew(tMap,dataLevel,pt,ct,newDataList, sql, threadDataList, InfluxDbSqlConstant.MAX, queryParam, lineId);
                        } else if (InfluxDbSqlConstant.MIN.equalsIgnoreCase(valueTypeKey)) {
                            assSqlByMysqlNew(tMap,dataLevel,pt,ct,newDataList, sql, threadDataList, InfluxDbSqlConstant.MIN, queryParam, lineId);
                        } else if (InfluxDbSqlConstant.AVG_WEB.equalsIgnoreCase(valueTypeKey)) {
                            assSqlByMysqlNew(tMap,dataLevel,pt,ct,newDataList, sql, threadDataList, InfluxDbSqlConstant.AVG_WEB, queryParam, lineId);
                        } else if (InfluxDbSqlConstant.CP95.equalsIgnoreCase(valueTypeKey)) {
                            assSqlByMysqlNew(tMap,dataLevel,pt,ct,newDataList, sql, threadDataList, InfluxDbSqlConstant.CP95, queryParam, lineId);
                        }
                    });
                });
                return threadDataList;
            }));
        });

        List<ReportTemplateDataVO> dataList = new ArrayList<>();
        for (Future<List<ReportTemplateDataVO>> future : futures) {
            try {
                dataList.addAll(future.get());
            } catch (InterruptedException | ExecutionException e) {
                log.error("自定义报表多线程查询流程出错！错误信息{}", e.getMessage());
            }
        }
        return dataList;
    }

    private double safeDivide(Double dividend, Double divisor) {
        if (divisor == null || divisor == 0.0) {
            divisor = 1.0;
        }
        double dividendValue = dividend != null ? dividend : 0.0;
        return dividendValue / divisor;
    }

    //获取模板id
    public String getTempId(String oldTempId, String lineId) {
        //根据模板类型的id获取模板
        List<ReportTemplateVO> result = sysExcelService.queryList(oldTempId);
        if (CollUtil.isEmpty(result)) {
            throw new BusinessException("未配置相关模板");
        }
        //根据监测点获取接线方式
        CsLinePO po = csLineFeignClient.getById(lineId).getData();
        //根据接线方式获取模板id
        if (Objects.isNull(po.getConType())) {
            throw new BusinessException("监测点缺失接线方式，无法匹配模板");
        }
        int conType = po.getConType();
        DictData dicData;
        //角型
        if (conType == 1) {
            dicData = dicDataFeignClient.getDicDataByCode(DicDataEnum.STAR_TRIANGLE.getCode()).getData();
        }
        //v型
        else if (conType == 2){
            dicData = dicDataFeignClient.getDicDataByCode(DicDataEnum.OPEN_DELTA.getCode()).getData();
        }
        //星型 或 其他
        else {
            dicData = dicDataFeignClient.getDicDataByCode(DicDataEnum.STAR.getCode()).getData();
        }
        String tempId;
        Optional<ReportTemplateVO> vo = result.stream().filter(item -> Objects.equals(dicData.getId(),item.getWiringMethod())).findFirst();
        if (vo.isPresent()) {
            tempId = vo.get().getId();
        } else {
            throw new BusinessException("未找到此接线方式的模板");
        }
        return tempId;
    }


}