package com.mvc.service.aiiden;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.mvc.constant.*;
import com.mvc.dao.TAireadMapper;
import com.mvc.dao.TaskReviewMapper;
import com.mvc.entity.*;
import com.mvc.model.*;
import com.mvc.model.aiiden.NoReviewModel;
import com.mvc.netty.dealconstant.ResourcePath;
import com.mvc.netty.dealconstant.ResourceTag;
import com.mvc.othermodel.TaskReviewTJModel;
import com.mvc.service.TMarkRecordService;
import com.mvc.service.copy.TAireadService;
import com.mvc.service.copy.TServerReadService;
import com.mvc.service.taizhang.StationAccService;
import com.mvc.service.taizhang.TAicbqCfgService;
import com.mvc.utils.*;
import com.mvc.utils.DateUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
@Transactional
public class TaskReviewService {

    @Resource
    private TaskReviewMapper taskReviewMapper;

    @Resource
    private TAireadService tAireadService;

    @Resource
    private TAireadMapper tAireadMapper;

    @Resource
    private TServerReadService tServerReadService;

    @Resource
    private StationAccService stationAccService;

    @Resource
    private TaskReviewPushService taskReviewPushService;

    @Resource
    private Environment env;

    @Resource
    private TAicbqCfgService tAicbqCfgService;

    @Resource
    private TMarkRecordService tMarkRecordService;

    private static final Integer RULE_UNRECOGNIZABLE_DAYS = 30;//系统判定无法辨别的天数

    private static Logger log = LoggerFactory.getLogger(TaskReviewService.class);

    public Map<String, Object> findAllTaskReview(TaskReviewModel queryModel) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskDateEqualTo(queryModel.getTaskDate());

        String finishedFlag = queryModel.getFinishedFlag();
        String sendSlsFlag = queryModel.getSendSlsFlag();
        //finishedFlag经过转换,前台值与库中不一致

        List<String> unitQueryFinishedFlagList = new ArrayList<>();//此List仅在用户查询时使用
        unitQueryFinishedFlagList.add("0");
        unitQueryFinishedFlagList.add("1");
        unitQueryFinishedFlagList.add("2");
        unitQueryFinishedFlagList.add("3");

        if (StringUtils.isNotEmpty(finishedFlag) && !finishedFlag.equals(BaseConstant.INVALID_FLAG)) {
            if (finishedFlag.equals("1")) {
                List<String> qList = new ArrayList<>();
                qList.add("1");
                qList.add("2");
                qList.add("3");
                criteria.andFinishedFlagIn(qList);
                unitQueryFinishedFlagList.clear();
                unitQueryFinishedFlagList.addAll(qList);
            } else if (finishedFlag.equals("2")) {             //前台2代表已审,对应库中的1和2(识别正确和人工修正)
                criteria.andFinishedFlagEqualTo("0");
                unitQueryFinishedFlagList.clear();
                unitQueryFinishedFlagList.add("0");
            } else if (finishedFlag.equals("3")) {
                criteria.andFinishedFlagEqualTo("1");       //识别正确
                unitQueryFinishedFlagList.clear();
                unitQueryFinishedFlagList.add("1");
            } else if (finishedFlag.equals("4")) {
                criteria.andFinishedFlagEqualTo("2");       //审核修正
                unitQueryFinishedFlagList.clear();
                unitQueryFinishedFlagList.add("2");
            } else if (finishedFlag.equals("5")) {
                criteria.andFinishedFlagEqualTo("3");       //无法辨别
                unitQueryFinishedFlagList.clear();
                unitQueryFinishedFlagList.add("3");
            }
        }
        if (StringUtils.isNotEmpty(sendSlsFlag) && !sendSlsFlag.equals(BaseConstant.INVALID_FLAG)) {
            if (sendSlsFlag.equals("1")) {
                criteria.andSendSlsFlagEqualTo("2");
            } else if (sendSlsFlag.equals("2")) {
                criteria.andSendSlsFlagEqualTo("3");
            }
        }

        if (StringUtils.isNotEmpty(queryModel.getSystemReviewFlag())) {
            criteria.andSystemReviewFlagEqualTo(queryModel.getSystemReviewFlag());
        }

        if (StringUtils.isNotEmpty(queryModel.getStationCode())) {
            criteria.andStationCodeEqualTo(queryModel.getStationCode());
        }

        Map<String, Object> resMap = new HashMap<>();
        example.setOrderByClause("STATION_CODE");
        Page<Object> pageObject = PageHelper.startPage(queryModel.getPage(), queryModel.getRows());
        List<TaskReview> taskReviews = null;
        if (StringUtils.isNotEmpty(queryModel.getUnitCode())) {
            String[] arr = unitQueryFinishedFlagList.toArray(new String[unitQueryFinishedFlagList.size()]);
            taskReviews = taskReviewMapper.findCustomReviewList(queryModel.getTaskDate(), queryModel.getUnitCode(), arr);
        } else {
            taskReviews = taskReviewMapper.selectByExample(example);
        }

        List<TaskReviewModel> resList = new ArrayList<>();
        for (TaskReview TaskReview : taskReviews) {
            TaskReviewModel model = new TaskReviewModel();
            BeanUtils.copyProperties(TaskReview, model);

            //MCU结果值与服务侧识别值相差小于1,就代表是匹配的 2022-09-29 guozhao
            String flag = "0";
            if (model.getIdentValue() != null && model.getServerValue() != null) {
                flag = model.getIdentValue().subtract(model.getServerValue()).abs().compareTo(new BigDecimal(1)) < 1 ? "1" : "0";
            }
            model.setValueMatched(flag);

            resList.add(model);
        }
        resMap.put("total", pageObject.getTotal());
        resMap.put("list", resList);
        return resMap;
    }

    public TaskReviewModel saveTaskReview(TaskReviewModel model) {
        model.setTaskId(StringUtil.getUuid());
        TaskReview TaskReview = new TaskReview();
        BeanUtils.copyProperties(model, TaskReview);
        int insert = taskReviewMapper.insert(TaskReview);
        model.setId(TaskReview.getId());
        return model;
    }

    public TaskReviewModel updateTaskReview(TaskReviewModel model) {
        try {
            model.setReviewTime(new Date());
            TaskReview taskReview = taskReviewMapper.selectByPrimaryKey(model.getId());

            //登记推送标记,人工标记FinishedFlag=1时,不需要推送
            if (!model.getFinishedFlag().equals("3")) {
                model.setSendSlsFlag(model.getFinishedFlag());
            }

            dealReviewInfo(model, true);

            BeanUtils.copyProperties(model, taskReview);

            taskReviewMapper.updateByPrimaryKey(taskReview);
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("数据审核发生异常-updateTaskReview", ex);
        }
        return model;
    }

    /**
     * 发送审核报文到水利所(前台手工调用)
     *
     * @param model
     * @return
     * @throws IOException
     */
    public TaskReviewModel sendReviewToSls(TaskReviewModel model) throws InterruptedException, IOException {
        //StoreBlockingQueue.sysReviewQueue.put(model);

        TaskReviewModel res = dealReviewInfo(model, false);
        TaskReview taskReview = taskReviewMapper.selectByPrimaryKey(model.getId());
        BeanUtils.copyProperties(res, taskReview);
        taskReviewMapper.updateByPrimaryKey(taskReview);
        return model;
    }

    /**
     * 处理审核信息
     *
     * @param model
     * @param isUpdateAiRead
     * @return
     * @throws IOException
     * @throws InterruptedException
     */
    public TaskReviewModel dealReviewInfo(TaskReviewModel model, boolean isUpdateAiRead) {
        try {
            TAireadModel tAireadModel = tAireadService.getTaireadByAireadId(model.getAireadId());
            if (tAireadModel == null) {
                log.error("处理审核数据出错:dealReviewInfo->tAireadModel=null,stationCode=" + model.getStationCode());
                return model;
            }

            //更新TAiread中的审核信息
            //tAireadModel.setResultValue(model.getReviewValue());
            if (model.getReviewValue() != null) {//防止被覆盖 2024-01-31 guozhao
                tAireadModel.setResultValue(model.getReviewValue());
            }
            tAireadModel.setReviewValue(model.getReviewValue());
            tAireadModel.setReviewFlag("1");
            tAireadModel.setReviewMan(model.getReviewMan());
            tAireadModel.setReviewTime(model.getReviewTime());
            //修改:统一两张表的flag 2024-09-20 guozhao
            tAireadModel.setReviewResultFlag(model.getFinishedFlag());
            tAireadModel.setTaskReviewId(model.getTaskId());
            if (isUpdateAiRead) {
                //无法辨别的时候,设置resultValue为null 2025-04-28 guozhao
                if(model.getFinishedFlag().equals(ReviewResultType.UNRECOGNIZABLE.getCode())){
                    tAireadModel.setResultValue(null);
                }
                tAireadService.updateTAiread(tAireadModel);
            }

            //非水表无需推送(起因是过滤燃气表) 2024-01-11 guozhao
            //StationAccModel accModel = stationAccService.findStationAccByStationCode(model.getStationCode());
            if (!tAireadModel.getDeviceType().equals(DeviceType.WATER_METER.getCode())) {
                model.setSendSlsFlag("1");
                return model;
            }

            //更新审核状态后,向水利所平台推送值 2022-07-11 guozhao
            if (model.getFinishedFlag().equals(ReviewResultType.REVIEW_REVISE.getCode()) ||
                    StringUtils.isEmpty(model.getSystemReviewFlag()) ||
                    !model.getSystemReviewFlag().equals("0")) {
                //再加一个判断,防止推送给ESP32的设备 2025-01-17 guozhao
                McuSoftVer mcuSoftVer = McuSoftVer.findMcuSoftVerByflag(tAireadModel.getSoftVer());

                //多加了一层限制,防止审核值推送给设备 2024-03-12 guozhao
                if (!tAireadModel.getDeviceType().equals(DeviceType.GAS_METER) &&
                        !tAireadModel.getDeviceType().equals(DeviceType.SERVER_SIDE) &&
                        (mcuSoftVer == null || mcuSoftVer != McuSoftVer.MCU_EC)
                ) {
                    taskReviewPushService.generateTaskReviewPush(model);        //创建IP2的审核推送任务
                }

                //改为定时统一推送 2024-07-02 guozhao
                //==2代表人工修正过
                //log.info("向水利所推送覆盖数据[ID]:" + model.getStationCode());
                tAireadModel.setRawValue(model.getReviewValue());
                tAireadModel.setIdentValue(model.getReviewValue());

                boolean isExistJpg = false;
                String smallUrl = "";
                if (StringUtils.isNotEmpty(model.getServerReadId())) {
                    TServerReadModel tServerReadModel = tServerReadService.findTServerReadByAiServerReadid(model.getServerReadId());

                    if (tServerReadModel != null && StringUtils.isNotEmpty(tServerReadModel.getSmallJpgUrl())) {
                        smallUrl = tServerReadModel.getSmallJpgUrl();
                        tAireadModel.setSmallPicType(tServerReadModel.getSmallJpgType());
                        tAireadModel.setPicHeigth(tServerReadModel.getSmallJpgHeight());
                        tAireadModel.setPicWidth(tServerReadModel.getSmallJpgWidth());
                        smallUrl = convertSmallUrl(smallUrl);         //改https后访问不到本机图片,转为本地路径
                        isExistJpg = true;
                    }
                }

                if (!isExistJpg) {
                    //没有图发空图,尺寸用假数据
                    tAireadModel.setSmallPicType("2");
                    tAireadModel.setPicHeigth(44);
                    tAireadModel.setPicWidth(148);
                }

                //冲水利所的数据时,如果用的是上一次的值,改在今天
                String date = model.getTaskDate() + "160000";
                Date sampleDate = DateUtil.parseTimeStr(date, "yyyyMMddHHmmss");
                tAireadModel.setRptTime(sampleDate);
                tAireadModel.setSampleTime(sampleDate);

                tAireadModel.setTaskReviewId(model.getTaskId());

                tAireadModel.setSmallRawData(getPicRawData(smallUrl));

                handleReviewReviseImage(model);//将审核修正的图片另存一份 2024-08-27 guozhao
                //改为 0 点统一推送
                //StoreBlockingQueue.sysReviewQueue.put(tAireadModel);
            }
        } catch (Exception ex) {
            log.error("dealReviewInfo发生异常", ex);
        }
        return model;
    }

    public int deleteTaskReview(int id) {
        int i = taskReviewMapper.deleteByPrimaryKey(id);
        return i;
    }

    /**
     * 根据遥测站台账数据生成审核数据
     *
     * @param taskDate
     */
    public void generateTaskReviewByStationAcc(String taskDate, String deviceType) {
        String date = taskDate + "160000";
        Date sampleDate = DateUtil.parseTimeStr(date, "yyyyMMddHHmmss");
        Date now = new Date();

        //if (!nowDate.equals(taskDate)) return;           //不是当日
        //if (sampleDate.compareTo(now) == 1) return;        //还未过采样时间

        /* 写法优化,已有获取Map的方法,后面使用不再需要反复遍历了 2024-07-16 guozhao
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskDateEqualTo(taskDate);
        List<TaskReview> curList = taskReviewMapper.selectByExample(example);*/
        Map<String, TaskReview> taskReviewMap = findTaskReviewMapByDate(sampleDate);

        List<StationAccModel> list = getStationAccModels(deviceType);
        if (list == null) return;
        List<TMarkRecordModel> markRecordModels = tMarkRecordService.findUntreatedModels();
        for (StationAccModel model : list) {
            //当日对应站台的审核记录已经产生了
            if (taskReviewMap.containsKey(model.getStationCode())) {
                continue;
            }
            /*if (curList != null) {
                if (curList.stream().filter(taskReview -> taskReview.getStationCode().equals(model.getStationCode())).count() > 0) {
                    continue;
                }
            }*/

            if (model.getStationName().contains("测试") || model.getStationName().toUpperCase().contains("TEST")) {
                continue;               //测试数据不生成审核
            }

            if (!model.getDeviceSetupFlag().equals("1")) {//未安装的不生成
                continue;
            }

            //过滤人工标记的站点(故障的) 2023-03-10 guozhao
            List<TMarkRecordModel> curMarkList = markRecordModels.stream().filter(s -> s.getStationCode().equals(model.getStationCode())).collect(Collectors.toList());
            TMarkRecordModel markRecord = null;
            if (curMarkList != null && curMarkList.size() > 0) {
                if (curMarkList.get(0).getReviewFlag().equals("1")) {
                    System.out.println(curMarkList.get(0));
                }
                if (curMarkList.get(0).getReviewFlag().equals("0")) {
                    log.info(model.getStationCode() + ":因标记跳过审核:" + curMarkList.get(0).getMarkParentName());
                    continue;
                }
                markRecord = curMarkList.get(0);//虽然标记了,但要使用服务器侧值
            }
            TAiread airead = null;
            if (deviceType.equals(DeviceType.GAS_METER.getCode())) {
                airead = getTAiread_GAS(model.getStationCode(), sampleDate);
            } else {
                airead = getTAiread(model.getStationCode(), sampleDate);
            }

            if (airead != null) {
                List<TServerReadModel> serverList = tServerReadService.findTServerReadByAiReadid(airead.getAireadId());
                TServerReadModel serverReadModel = serverList == null || serverList.size() == 0 ? null : serverList.get(0);

                TaskReviewModel taskReviewModel = new TaskReviewModel();
                taskReviewModel.setTaskDate(taskDate);
                taskReviewModel.setDeviceSn(airead.getDeviceSn());
                taskReviewModel.setStationCode(model.getStationCode());
                taskReviewModel.setAireadId(airead.getAireadId());
                taskReviewModel.setSampleTime(airead.getSampleTime());
                taskReviewModel.setIdentValue(airead.getIdentValue());
                taskReviewModel.setRawValue(airead.getRawValue());
                taskReviewModel.setIdenValidFlag(airead.getGoodFlag());

                //调整为大图优先 2024-07-31 guozhao
                if (ImageUtil.isImageByExtension(airead.getBigJpgUrl())) {
                    taskReviewModel.setMcuImageUrl(airead.getBigJpgUrl());
                } else {
                    taskReviewModel.setMcuImageUrl(airead.getSmallJpgUrl());
                }

                taskReviewModel.setIdenValidFlag(airead.getGoodFlag());
                taskReviewModel.setSoftVer(airead.getSoftVer());
                taskReviewModel.setNbVersion(airead.getNbVersion());
                taskReviewModel.setHardVersion(airead.getHardVersion());
                taskReviewModel.setAiVersion(airead.getAiVersion());

                if (serverReadModel != null) {
                    taskReviewModel.setServerReadId(serverReadModel.getServerReadId());
                    taskReviewModel.setServerValue(serverReadModel.getIdentValue());
                    taskReviewModel.setServerImageUrl(serverReadModel.getJpgUrl());
                    taskReviewModel.setServerValidFlag(serverReadModel.getGoodFlag());
                }

                taskReviewModel.setCreateTime(now);
                taskReviewModel.setSendSlsFlag("0");

                //获取上次的审核情况
                TaskReviewModel lastReviewModel = getLastReviewModel(taskReviewModel);
                if (lastReviewModel != null) {
                    taskReviewModel.setLastReviewValue(lastReviewModel.getReviewValue());
                    taskReviewModel.setLastTaskId(lastReviewModel.getTaskId());
                    taskReviewModel.setLastMcuImageUrl(lastReviewModel.getMcuImageUrl());
                    taskReviewModel.setLastSampleTime(lastReviewModel.getSampleTime());
                } else {
                    taskReviewModel.setLastMcuImageUrl("");//防止前台空值
                }

                //StationAccModel stationAccModel = stationAccService.findStationAccByStationCode(taskReviewModel.getStationCode());
                //taskReviewModel.setStationName(stationAccModel == null ? "" : stationAccModel.getStationName());
                taskReviewModel.setStationName(model.getStationName());

                List<TAicbqCfgModel> cfgList = tAicbqCfgService.findTAicbqCfg(airead.getDeviceSn(), "", "1");
                if (cfgList != null && cfgList.size() > 0) {//填充配置项中的数字个数和尾数单位 2022-10-24 guozhao
                    taskReviewModel.setDigitNum(cfgList.get(0).getDigitNum());
                    taskReviewModel.setUnitType(cfgList.get(0).getUnitType());
                }

                NoReviewModel noReviewModel = null;
                //统一改为当日有数就不算历史记录 2024-08-07 guozhao
                String historyFlag = DateUtil.formateDate(airead.getSampleTime(), "yyyyMMdd").equals(taskDate) ? "0" : "1";

                //单独处理燃气表,仅有服务侧值,大图,且采样时间不同 2024-01-11 guozhao
                if (model.getDeviceType().equals(DeviceType.GAS_METER.getCode())) {
                    taskReviewModel.setMcuImageUrl(airead.getBigJpgUrl());
                    //燃气表判断只判断日期部分(只要是当日就不算历史数据),默认是0点的,而不是16点
                    ////historyFlag = DateUtil.formateDate(airead.getSampleTime(), "yyyyMMdd").equals(taskDate) ? "0" : "1";
                    if (serverReadModel != null) {
                        taskReviewModel.setReviewValue(serverReadModel.getIdentValue());
                    }
                } else {
                    noReviewModel = getNoReviewLevel(airead, serverReadModel, sampleDate, markRecord != null);
                    ////historyFlag = sampleDate.compareTo(airead.getSampleTime()) == 1 ? "1" : "0";
                }
                taskReviewModel.setHistoryFlag(historyFlag);

                if (noReviewModel != null) {
                    airead = noReviewModel.getAiread();
                    serverReadModel = noReviewModel.getServerReadModel();
                    taskReviewModel.setSystemReviewFlag(noReviewModel.getNoReviewLevel().toString());
                    if (noReviewModel.getNoReviewLevel() > 0) {//系统审核的
                        taskReviewModel.setFinishedFlag("1");
                        taskReviewModel.setReviewMan(noReviewModel.getLevelName());
                        taskReviewModel.setReviewTime(now);
                        taskReviewModel.setReviewValue(airead.getIdentValue());
                        if (noReviewModel.getNoReviewLevel() == 5) {//使用服务侧值的情况下,将审核值修改为服务侧值 2023-04-18 guozhao
                            taskReviewModel.setReviewValue(serverReadModel.getIdentValue());
                        }
                        if (noReviewModel.getNoReviewLevel() > 2) {
                            taskReviewModel.setSendSlsFlag("1");
                        }
                    } else {
                        taskReviewModel.setFinishedFlag("0");
                    }
                } else {
                    taskReviewModel.setFinishedFlag("0");
                }

                taskReviewModel = saveTaskReview(taskReviewModel);
                //添加条件=WATER_METER才推送至水利所 2024-01-11 guozhao
                if (model.getDeviceType().equals(DeviceType.WATER_METER.getCode()) && taskReviewModel != null) {
                    if (noReviewModel.getNoReviewLevel() > 2) {//三四级免审加入到推送列表中
                        try {
                            //改为0点后统一推送 2024-08-07 guozhao
                            //generateSendSlsAiReadModel(airead, serverReadModel, taskReviewModel);
                            /*TAireadModel aireadModel = new TAireadModel();
                            BeanUtils.copyProperties(airead, aireadModel);
                            aireadModel.setTaskReviewId(taskReviewModel.getTaskId());
                            StoreBlockingQueue.sysReviewQueue.put(aireadModel);*/
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取需要审核的站点台账列表
     *
     * @return
     */
    private List<StationAccModel> getStationAccModels(String deviceType) {
        StationAccExample example = new StationAccExample();
        StationAccExample.Criteria criteria = example.createCriteria();
        if (StringUtils.isNotEmpty(deviceType)) {
            criteria.andDeviceTypeEqualTo(deviceType);
        }
        criteria.andReviewFlagEqualTo(BaseConstant.VALID_FLAG);
        criteria.andUseFlagEqualTo(BaseConstant.VALID_FLAG);

        return stationAccService.findStationaccModelsByExample(example);
    }

    private TAiread getTAiread(String stationCode, Date sampleDate) {
        TAireadExample example = new TAireadExample();
        TAireadExample.Criteria criteria = example.createCriteria();
        criteria.andStationCodeEqualTo(stationCode);
        criteria.andFunCodeEqualTo("32");           //按照中图生成(仅有大图的情况,是没有读数信息的) 2022-09-04 guozhao
        example.setOrderByClause(" SAMPLE_TIME DESC");

        Page<Object> pageObject = PageHelper.startPage(1, 1);
        criteria.andSampleTimeLessThanOrEqualTo(sampleDate);
        List<TAiread> tAireadList = tAireadMapper.selectByExample(example);

        return (tAireadList != null && tAireadList.size() > 0) ? tAireadList.get(0) : null;
    }

    /**
     * 获取读数(燃气表)
     *
     * @param stationCode
     * @param sampleDate
     * @return
     */
    private TAiread getTAiread_GAS(String stationCode, Date sampleDate) {
        //特殊处理原因:燃气表先发0点数据有图,后面因未正常关机或其它未知情况,导致0点后又发了一条(无图),并且采样时间在0点以后,按原来生成规则,会使用后面无图这一条
        TAireadExample example = new TAireadExample();
        TAireadExample.Criteria criteria = example.createCriteria();
        criteria.andStationCodeEqualTo(stationCode);
        criteria.andFunCodeEqualTo("32");
        //正序排列,如果有两条且都有图,可以优先取到整点的 2024-04-01 guozhao
        example.setOrderByClause("SAMPLE_TIME DESC");
        criteria.andSampleTimeLessThanOrEqualTo(sampleDate);

        PageHelper.startPage(1, 5);

        List<TAiread> tAireadList = tAireadMapper.selectByExample(example);

        TAiread tAiread0 = null;//非当日数据
        TAiread tAiread1 = null;//当日0点
        TAiread tAiread2 = null;//当时0点以后

        Date zero = DateUtil.getZeroTimeOfDay(sampleDate);

        for (TAiread temp : tAireadList) {
            if (temp.getSampleTime().compareTo(zero) == 0) {//0点数据正常
                tAiread1 = temp;
            } else if (temp.getSampleTime().compareTo(zero) > 0) {//有当日非0点数据
                tAiread2 = temp;
            } else {//非当日数据
                tAiread0 = temp;
                break;
            }
        }

        if (tAiread1 != null && ImageUtil.isImageByExtension(tAiread1.getBigJpgUrl())) {//优先取当日0点有图
            return tAiread1;
        } else if (tAiread2 != null) {
            if (ImageUtil.isImageByExtension(tAiread2.getBigJpgUrl())) {//0点无图,但0点后有图
                return tAiread2;
            } else if (tAiread1 != null) {//0点和0点后都无图,取0点
                return tAiread1;
            } else {//0点后无图,没有0点数据,取0点后
                return tAiread2;
            }
        } else if (tAiread0 != null) {
            return tAiread0;
        } else {
            if (tAireadList.size() > 0) {//返回最新一条
                return tAireadList.get(tAireadList.size() - 1);
            } else {
                return null;
            }
        }
    }

    public String getPicRawData(String path) throws IOException {
        if (StringUtils.isNotEmpty(path)) {
            if (path.contains("http")) {
                //在线图片有一个跨域问题(用外网地址服务器自己访问不到)
                String src = env.getProperty(ResourceTag.ResourceUrlTag.getTag());
                int index = src.lastIndexOf(":");
                src = src.substring(0, index);

                String tar = env.getProperty(ResourceTag.AiIdenserverUrlTag.getTag());
                index = tar.lastIndexOf(":");
                tar = tar.substring(0, index);

                path = path.replaceAll(src, tar);
                System.out.println(path);
                byte[] bytes = FileUtil.onlineImage2byte(path);
                if (bytes != null && bytes.length > 0) {
                    byte[] res = new byte[bytes.length - 589];
                    System.arraycopy(bytes, 589, res, 0, res.length);
                    return NumberUtil.bytesToHexStr(res);
                }
            } else {
                //转为本地路径的情况
                byte[] bytes = FileUtil.readBytesFile(path);
                if (bytes != null) {
                    byte[] res = new byte[bytes.length - 589];
                    System.arraycopy(bytes, 589, res, 0, res.length);
                    return NumberUtil.bytesToHexStr(res);
                }
            }
        }
        //没有小图,造一个空的
        byte[] res = new byte[500];
        return NumberUtil.bytesToHexStr(res);
    }

    //改https后,服务器本地访问域名和本地ip都会有问题,转成本地
    public String convertSmallUrl(String url) {
        if (url.contains("http")) {
            int index = url.indexOf("//");
            if (index > -1) {
                url = url.substring(index + 2);
                index = url.indexOf("/");
                url = url.substring(index);
                String tar = env.getProperty(ResourceTag.UploadPathTag.getTag());
                url = url.replaceAll(ResourcePath.Image.getPath(), tar);
                return url;
            }
        } else {//处理只存储有效路径的地址(不包含配置文件中的根目录及资源转换的目录) 2023-08-28 guozhao
            return env.getProperty(ResourceTag.UploadPathTag.getTag()) + ResourcePath.Rawdata.getPath() + url;
        }
        return "";
    }

    /**
     * 撤销审核
     *
     * @param id
     * @return
     */
    public TaskReviewModel revokeReview(Integer id) {
        TaskReview taskReview = taskReviewMapper.selectByPrimaryKey(id);
        if (taskReview != null) {
            log.info("撤销审核:id={},旧标记={}", taskReview.getId(), taskReview.getFinishedFlag());
            //是否被审核修正(防止点的审核修正,又修改为其它状态,导致与数据不同步且推送记录未清除) 2024-08-28 guozhao
            boolean isRevise = taskReview.getFinishedFlag().equals(ReviewResultType.REVIEW_REVISE.getCode());
            taskReview.setFinishedFlag(ReviewResultType.UNREVIEW.getCode());
            taskReview.setSendSlsFlag("0");
            taskReview.setFinishedTime(null);
            taskReview.setReviewMan("");
            taskReview.setReviewTime(null);
            taskReview.setSlsReplyMsg("");

            if (taskReviewMapper.updateByPrimaryKey(taskReview) > 0) {
                TaskReviewModel model = new TaskReviewModel();
                BeanUtils.copyProperties(taskReview, model);
                if (isRevise) {
                    syncOhterData(taskReview);
                }
                return model;
            }
        }
        return null;
    }

    /**
     * 同步其它数据(在撤销审核后)
     *
     * @param model
     */
    private void syncOhterData(TaskReview model) {
        TAireadModel tAireadModel = tAireadService.getTaireadByAireadId(model.getAireadId());
        if (tAireadModel != null) {
            tAireadModel.setResultValue(tAireadModel.getIdentValue());//恢复读数记录
            tAireadModel.setReviewMan("");
            tAireadModel.setReviewFlag("");
            tAireadModel.setTaskReviewId("");
            tAireadModel.setReviewResultFlag("");
            tAireadModel.setReviewValue(null);
            tAireadService.updateTAiread(tAireadModel);

            taskReviewPushService.deleteTaskReviewPushByReviewId(model.getTaskId());
        }
    }

    /**
     * 获取指定日期的审核统计
     *
     * @param taskDate
     * @return
     */
    public TaskReviewTJModel getTaskReviewCount(String taskDate) {
        TaskReviewTJModel resModel = new TaskReviewTJModel();
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskDateEqualTo(taskDate);
        List<TaskReview> curList = taskReviewMapper.selectByExample(example);
        return getTaskReviewTJByTaskReviewList(curList);
    }

    /**
     * 根据日期和单位代码获取审核统计数据
     *
     * @param taskDate
     * @param unitCode
     * @return
     */
    public TaskReviewTJModel getTaskReviewCountByUnitCode(String taskDate, String unitCode) {
        String[] arr = {"0", "1", "2", "3"};
        List<TaskReview> taskReviews = taskReviewMapper.findCustomReviewList(taskDate, unitCode, arr);
        return getTaskReviewTJByTaskReviewList(taskReviews);
    }

    /**
     * 根据审核列表获取统计数据
     *
     * @param curList
     * @return
     */
    private TaskReviewTJModel getTaskReviewTJByTaskReviewList(List<TaskReview> curList) {
        TaskReviewTJModel resModel = new TaskReviewTJModel();
        int taskCount = curList == null ? 0 : curList.size();
        int finishedFlag0 = 0;
        int finishedFlag1 = 0;
        int finishedFlag2 = 0;
        int finishedFlag3 = 0;
        int sendSlsCount = 0;
        int sendSlsNum = 0;
        for (TaskReview taskReview : curList) {
            if (taskReview.getFinishedFlag().equals("0")) {
                finishedFlag0++;
            } else if (taskReview.getFinishedFlag().equals("1")) {
                finishedFlag1++;
            } else if (taskReview.getFinishedFlag().equals("2")) {
                finishedFlag2++;
            } else if (taskReview.getFinishedFlag().equals("3")) {
                finishedFlag3++;
            }
            if (taskReview.getSendSlsFlag().equals("2")) {
                sendSlsCount++;
            } else if (taskReview.getSendSlsFlag().equals("3")) {
                sendSlsNum++;
                sendSlsCount++;
            }
        }
        //resModel.setTaskDate(taskDate);
        resModel.setTaskCount(taskCount);
        resModel.setFinishedFlag0(finishedFlag0);
        resModel.setFinishedFlag1(finishedFlag1);
        resModel.setFinishedFlag2(finishedFlag2);
        resModel.setFinishedFlag3(finishedFlag3);
        resModel.setSendSlsCount(sendSlsCount);
        resModel.setSendSlsNum(sendSlsNum);

        return resModel;
    }

    //比对识别数据,系统判定是否需要审核
    /*private boolean ComparisonIdenValue(TAiread tAiread, TServerReadModel tServerReadModel) {
        if (tAiread == null || tServerReadModel == null) return false;
        if (StringUtils.isEmpty(tAiread.getGoodFlag()) || StringUtils.isEmpty(tServerReadModel.getResultCode()))
            return false;
        if (tAiread.getIdentValue() == null || tServerReadModel.getIdentValue() == null) return false;
        //MCU符合1278,服务器侧高概率正确
        if (tAiread.getGoodFlag().equals("1") && tServerReadModel.getResultCode().equals("1")) {
            BigDecimal mcu = tAiread.getIdentValue();
            BigDecimal ser = tServerReadModel.getIdentValue();

            BigDecimal sub = mcu.subtract(ser).abs();
            int cmp = sub.compareTo(new BigDecimal(1));
            if (cmp <= 0) {
                //System.out.println("SN:" + tAiread.getDeviceSn() + ",MCU[" + tAiread.getIdentValue() + "]与服务[" + tServerReadModel.getIdentValue() + "]相差小于1,无需审核");
                return true;
            }
        }
        return false;
    }*/

    /**
     * 获取小于queryModel中采样时间的最近一条审核记录
     *
     * @param queryModel
     * @return
     */
    private TaskReviewModel getLastReviewModel(TaskReviewModel queryModel) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andStationCodeEqualTo(queryModel.getStationCode());
        criteria.andFinishedFlagNotEqualTo("0");
        criteria.andSampleTimeLessThan(queryModel.getSampleTime());
        example.setOrderByClause(" ID DESC");

        List<TaskReview> curList = taskReviewMapper.selectByExample(example);
        if (curList != null && curList.size() > 0) {
            TaskReviewModel model = new TaskReviewModel();
            BeanUtils.copyProperties(curList.get(0), model);
            return model;
        }
        return null;
    }

    /**
     * MCU数据是否可信(符合12原则)
     *
     * @param airead
     * @return
     */
    private boolean isBelievable(TAiread airead) {
        if (airead == null || airead.getSzsbz() == null) {
            return false;
        }
        String[] tsxx = airead.getSzsbz().split(",");
        boolean isGood = false;                                   //数据是否有效
        if (tsxx.length == 12) {
            //新版本MCU程序
            isGood = BaseConstant.IDENT_GOOD_FLAG.contains(tsxx[11]);
        }//长度不是12的,有可能是老版本的MCU程序,数量应该比较少,暂时也加入审核里
        return isGood;
    }

    /**
     * 服务侧是否可信
     *
     * @param model
     * @return
     */
    private boolean serverIsBelievable(TServerReadModel model) {
        return BaseConstant.IDENT_GOOD_FLAG.contains(model.getGoodFlag());
    }

    /**
     * 获取免审等级
     *
     * @param airead
     * @param serverReadModel
     * @param sampleDate
     * @param serverFlag      是否仅使用服务侧判断是否免审 2023-03-10 guozhao
     * @return
     */
    private NoReviewModel getNoReviewLevel(TAiread airead, TServerReadModel serverReadModel, Date sampleDate, boolean serverFlag) {
        NoReviewModel resModel = new NoReviewModel();
        resModel.setNoReviewLevel(0);
        resModel.setAiread(airead);
        resModel.setServerReadModel(serverReadModel);
        if (serverReadModel == null || serverReadModel.getIdentValue() == null) return resModel;     //没有服务侧读数,人工审核
        BigDecimal mcuValue = airead.getIdentValue();
        BigDecimal serverValue = serverReadModel.getIdentValue();

        if (sampleDate.compareTo(airead.getSampleTime()) == 0) {//当日16点数据
            if (serverFlag) {//标记了仅用服务侧识别(仅处理16点的,考虑0点和8点有点麻烦,情况也少) 2023-03-15 guozhao
                if (serverIsBelievable(serverReadModel)) {
                    resModel.setNoReviewLevel(SystemReviewType.LEVEL5.getLevel());//五级免审(只判断服务侧值)
                    resModel.setLevelName(SystemReviewType.LEVEL5.getName());
                }
            } else if (isBelievable(airead)) {//MCU侧可信
                if (mcuValue.compareTo(serverValue) == 0) {//值完全相同
                    resModel.setNoReviewLevel(SystemReviewType.LEVEL1.getLevel());//一级免审(当日16点有数且完全相等)
                    resModel.setLevelName(SystemReviewType.LEVEL1.getName());
                } else if (isLastBitDiff(mcuValue, serverValue)) {
                    resModel.setNoReviewLevel(SystemReviewType.LEVEL2.getLevel());//二级免审(当日16点有数仅最后一位不同)
                    resModel.setLevelName(SystemReviewType.LEVEL2.getName());
                }
            }
        } else {
            String aireadDate = DateUtil.formateDate(airead.getSampleTime(), "yyyyMMdd");
            String nowDate = DateUtil.formateDate(sampleDate, "yyyyMMdd");
            if (!aireadDate.equals(nowDate)) {//非当天数据,加到人工审核
                return resModel;
            }

            if (isBelievable(airead)) {
                if (mcuValue.compareTo(serverValue) == 0) {//值完全相同
                    resModel.setNoReviewLevel(SystemReviewType.LEVEL3.getLevel());//三级免审(非当日16点,且完全相等)
                    resModel.setLevelName(SystemReviewType.LEVEL3.getName());
                } else if (isLastBitDiff(mcuValue, serverValue)) {
                    resModel.setNoReviewLevel(SystemReviewType.LEVEL4.getLevel());//四级免审(非当日16点有数仅最后一位不同)
                    resModel.setLevelName(SystemReviewType.LEVEL4.getName());
                }
            } else {//无16点数据,前面一条也不可信的情况下
                //如果上面判断是8点不符合12原则,找0点,如果是0点不符合免审条件,当天没有合格数据,不符合免审条件(没有写死0点和8点,是为了更灵活,兼容间隔不是8小时的)
                String startTime = DateUtil.formateDate(sampleDate, "yyyyMMdd000000");//当日0点
                String endTime = DateUtil.formateDate(airead.getSampleTime(), "yyyyMMddHHmmss");//当日最后一条为终点
                Map<String, Object> map = tAireadService.findAllTAiread(airead.getDeviceSn(), startTime, endTime, 1, 100);

                List<TAireadModel> tAireadModels = (List<TAireadModel>) map.get("list");
                if (tAireadModels != null) {
                    for (TAireadModel readModel : tAireadModels) {
                        TAiread temp = new TAiread();
                        BeanUtils.copyProperties(readModel, temp);
                        if (!isBelievable(temp)) {
                            continue;
                        }
                        List<TServerReadModel> serList = tServerReadService.findTServerReadByAiReadid(temp.getAireadId());
                        if (serList == null || serList.size() == 0) {//没有服务侧数据
                            continue;
                        }
                        TServerReadModel tempSModel = serList.get(0);
                        if (temp.getIdentValue().compareTo(tempSModel.getIdentValue()) == 0) {//值完全相同
                            resModel.setNoReviewLevel(SystemReviewType.LEVEL3.getLevel());//三级免审(非当日16点,且完全相等)
                            resModel.setAiread(temp);
                            resModel.setServerReadModel(tempSModel);
                            resModel.setLevelName(SystemReviewType.LEVEL3.getName());
                            break;
                        } else if (isLastBitDiff(temp.getIdentValue(), tempSModel.getIdentValue())) {
                            resModel.setNoReviewLevel(SystemReviewType.LEVEL4.getLevel());//四级免审(非当日16点有数仅最后一位不同)
                            resModel.setAiread(temp);
                            resModel.setServerReadModel(tempSModel);
                            resModel.setLevelName(SystemReviewType.LEVEL4.getName());
                            break;
                        }
                    }
                }
            }
        }
        return resModel;
    }

    /**
     * 是否仅最后一位不同
     *
     * @param value1
     * @param value2
     * @return
     */
    private boolean isLastBitDiff(BigDecimal value1, BigDecimal value2) {
        String strVal1 = value1.stripTrailingZeros().toPlainString();
        String strVal2 = value2.stripTrailingZeros().toPlainString();

        int lenCz = Math.abs(strVal1.length() - strVal2.length());

        if (lenCz == 0) {//两个值长度相等
            if (strVal1.length() == 1) {//就一位数的情况下(差值不能大于1)
                return value1.subtract(value2).abs().compareTo(new BigDecimal(1)) <= 0;
            } else {
                return strVal1.substring(0, strVal1.length() - 1).equals(strVal2.substring(0, strVal2.length() - 1));
            }
        } else if (lenCz == 1) {//长度相差一位
            int vl1Scale = value1.stripTrailingZeros().scale();
            int vl2Scale = value2.stripTrailingZeros().scale();

            BigDecimal zsbf1 = value1.setScale(0, RoundingMode.DOWN);
            BigDecimal zsbf2 = value2.setScale(0, RoundingMode.DOWN);

            if (zsbf1.compareTo(zsbf2) != 0) {//长度差1,但整数部分不一样
                return false;
            }
            if (vl1Scale == 0 && vl2Scale == 0) {//两个都是整数,长度不一样
                return false;
            } else if (vl1Scale > 0 && vl2Scale > 0) {//两个都是小数(下面都是整数部分相同前提了)
                int len = strVal1.length() > strVal2.length() ? strVal2.length() : strVal1.length();
                return strVal1.substring(0, len).equals(strVal2.substring(0, len));
            } else {//其中一个是小数,但只有一位,且整数相同,也代表仅最后一位不同
                return true;
            }
        }
        return false;
    }

    /**
     * 重发没有回执的审核数据到水利所
     */
    public void resendNoReceiptData() {
        String taskDate = DateUtil.formateDate(new Date(), "yyyyMMdd");
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskDateEqualTo(taskDate);
        criteria.andFinishedFlagEqualTo("2");
        criteria.andSlsReplyMsgIsNull();

        try {
            List<TaskReview> curList = taskReviewMapper.selectByExample(example);
            for (TaskReview taskReview : curList) {
                TaskReviewModel model = new TaskReviewModel();
                BeanUtils.copyProperties(taskReview, model);
                sendReviewToSls(model);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 根据审核状态返回符合条件的数量
     *
     * @param taskDate
     * @param flag
     * @return
     */
    public Integer findDataNumByFinishedFlag(String taskDate, String flag) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskDateEqualTo(taskDate);
        criteria.andFinishedFlagEqualTo(flag);
        List<TaskReview> curList = taskReviewMapper.selectByExample(example);
        return curList == null ? 0 : curList.size();
    }

    /**
     * 根据SN获取最后一条审核的数据(去除不可辨认的)
     *
     * @param deviceSn
     * @return
     */
    public TaskReviewModel findLastByDeviceSn(String deviceSn) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andDeviceSnEqualTo(deviceSn);
        criteria.andFinishedFlagNotEqualTo(ReviewResultType.UNRECOGNIZABLE.getCode());//不是无法辨别的
        example.setOrderByClause("SAMPLE_TIME desc");
        PageHelper.startPage(1, 1);
        List<TaskReview> list = taskReviewMapper.selectByExample(example);
        if (list != null && list.size() > 0) {
            TaskReviewModel model = new TaskReviewModel();
            BeanUtils.copyProperties(list.get(0), model);
            return model;
        }
        return null;
    }

    /**
     * 根据时间生成所有站点的服务侧读数
     *
     * @param sampleTime
     */
    public void generateServerData(String sampleTime, String deviceType) {
        try {
            Date date = DateUtil.parseTimeStr(sampleTime, "yyyyMMddHHmmss");
            Map<String, Object> mapAcc = stationAccService.findAllStationAcc(1, 1000);
            List<StationAccModel> accList = (List<StationAccModel>) mapAcc.get("list");
            for (StationAccModel acc : accList) {
                if (!acc.getReviewFlag().equals("1") || acc.getStationName().contains("测试") || acc.getStationName().contains("TEST")
                        || !acc.getDeviceSetupFlag().equals("1")) {
                    continue;
                }
                //过滤设备类型
                if (!acc.getDeviceType().equals(deviceType)) {
                    continue;
                }
                TAiread tAiread = tAireadService.findlastTAireadBydatatime(acc.getStationCode(), date);
                if (tAiread == null) continue;
                TAireadModel aireadModel = new TAireadModel();
                BeanUtils.copyProperties(tAiread, aireadModel);
                StoreBlockingQueue.tAireadQueue.put(aireadModel);
            }
        } catch (Exception ex) {

        }
    }

    /**
     * 根据aireadID更新
     *
     * @param taskId
     * @param replayMsg
     */
    public void updateModelByTaskReviewId(String taskId, String replayMsg) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskIdEqualTo(taskId);
        example.setOrderByClause("SAMPLE_TIME desc");
        List<TaskReview> list = taskReviewMapper.selectByExample(example);

        if (list != null && list.size() > 0) {
            TaskReview taskReview = list.get(0);
            taskReview.setSendSlsFlag("3");
            taskReview.setSlsReplyMsg(replayMsg);
            taskReviewMapper.updateByPrimaryKey(taskReview);
        }
    }

    private List<TaskReview> getTaskReviewsByData(Date date) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        String strDate = DateUtil.formateDate(date, "yyyyMMdd");
        criteria.andTaskDateEqualTo(strDate);
        return taskReviewMapper.selectByExample(example);
    }

    /**
     * 下载数据至Excel
     *
     * @param response
     */
    public void downloadExcel(HttpServletResponse response) {
        List<StationAccModel> accModels = getStationAccModels("");
        if (accModels == null || accModels.size() == 0) return;

        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet1 = workbook.createSheet("记录表");
        XSSFSheet sheet2 = workbook.createSheet("差异表");

        Font font = workbook.createFont();
        font.setBold(true);  // 设置字体加粗
        CellStyle style = workbook.createCellStyle();
        style.setFont(font);  // 设置单元格样式

        XSSFRow row0 = sheet1.createRow(0);
        XSSFCell cell0 = row0.createCell(0);
        cell0.setCellValue("序号");
        cell0.setCellStyle(style);

        sheet1.setColumnWidth(1, 11 * 256);
        sheet1.setColumnWidth(2, 30 * 256);
        sheet1.setColumnWidth(3, 11 * 256);
        sheet1.setColumnWidth(4, 20 * 256);

        cell0 = row0.createCell(1);
        cell0.setCellValue("遥测站编码");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(2);
        cell0.setCellValue("遥测站名称");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(3);
        cell0.setCellValue("审核日期");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(4, CellType.STRING);
        cell0.setCellValue("采样时间");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(5);
        cell0.setCellValue("当日16点");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(6);
        cell0.setCellValue("审核状态");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(7);
        cell0.setCellValue("状态编码");
        cell0.setCellStyle(style);

        int num = 1;
        sheet1.createFreezePane(0, 1);//冻结首行
        Date startDate = DateUtil.parseTimeStr("20220712160000", "yyyyMMddHHmmss");
        Date endDate = new Date();

        List<TaskReview> taskReviews = null;

        while (startDate.compareTo(endDate) < 0) {
            taskReviews = getTaskReviewsByData(startDate);

            if (taskReviews == null || taskReviews.size() == 0) {//没有审核数据或未生成
                startDate = DateUtil.getOtherDateByCurrentDate(startDate, 1);
                continue;
            }

            //是否是当天,如果是,判断当天的数据是否均已审核完成
            if (DateUtil.formateDate(startDate, "yyyyMMdd").equals(DateUtil.formateDate(endDate, "yyyyMMdd"))) {
                long yssl = taskReviews.stream().filter(s -> s.getFinishedFlag().equals("0")).count();
                if (yssl > 0) {//当日未审核完成
                    break;
                }
            }

            for (StationAccModel accModel : accModels) {
                String reviewDate = DateUtil.formateDate(startDate, "yyyy-MM-dd");
                //根据站点编码匹配审核记录(兼容新旧站码,旧的站码,输出也转换为新的)
                Optional<TaskReview> optional = taskReviews.stream().filter(s -> s.getStationCode().equals(accModel.getStationCode()) || s.getStationCode().equals(accModel.getWmId())).findFirst();
                TaskReview taskReview = null;
                if (optional.isPresent()) {
                    taskReview = optional.get();
                }
                if (taskReview == null) {
                    continue;
                }

                XSSFRow row = sheet1.createRow(num);
                XSSFCell cell = row.createCell(0);
                cell.setCellValue(num);

                cell = row.createCell(1);
                cell.setCellValue(accModel.getStationCode());

                cell = row.createCell(2);
                cell.setCellValue(accModel.getStationName());

                cell = row.createCell(3);
                cell.setCellValue(reviewDate);//审核日期

                cell = row.createCell(4);
                cell.setCellValue(DateUtil.formateDate(taskReview.getSampleTime(), "yyyy-MM-dd HH:mm:ss"));//采样时间

                cell = row.createCell(5);
                cell.setCellValue((startDate.compareTo(taskReview.getSampleTime()) == 0) ? "是" : "否");//当日16点

                cell = row.createCell(6);
                ReviewResultType reviewResultType = ReviewResultType.findReviewResultTypeByCode(taskReview.getFinishedFlag());
                if (reviewResultType != null) {
                    cell.setCellValue(reviewResultType.getName());
                }

                cell = row.createCell(7);
                cell.setCellValue(taskReview.getFinishedFlag());//状态编码
                num++;
            }
            startDate = DateUtil.getOtherDateByCurrentDate(startDate, 1);//天数加1
        }

        try {
            writeDiffSheet(sheet2, accModels);

            ByteArrayOutputStream os = new ByteArrayOutputStream();
            workbook.write(os);
            byte[] bytes = os.toByteArray();

            String filename = URLEncoder.encode("审核数据" + DateUtil.formateDate(endDate, "yyyyMMdd") + ".xlsx", "UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-disposition", "attachment;filename=" + filename);
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(bytes);
            outputStream.close();
            os.close();
            workbook.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * 写入差异sheet表
     *
     * @param sheet
     * @param accModels
     */
    private void writeDiffSheet(XSSFSheet sheet, List<StationAccModel> accModels) {
        int rowNo = 0;//控制sheet的行号
        int recordSn = 1;//表内序号列

        Date now = new Date();

        Date lastDate = DateUtil.getOtherDateByCurrentDate(now, -1);
        Date prevDate = DateUtil.getOtherDateByCurrentDate(now, -2);

        /*Date lastDate = DateUtil.getOtherDateByCurrentDate(now, -3);
        Date prevDate = DateUtil.getOtherDateByCurrentDate(now, -4);*/

        String strLastDate = DateUtil.formateDate(lastDate, "yyyy-MM-dd");
        String strPrevDate = DateUtil.formateDate(prevDate, "yyyy-MM-dd");

        List<TaskReview> lastList = getTaskReviewsByData(lastDate).stream().filter(s -> s.getFinishedFlag().equals("2") || s.getFinishedFlag().equals("3")).collect(Collectors.toList());//最后一天(不含当日)
        List<TaskReview> prevList = getTaskReviewsByData(prevDate).stream().filter(s -> s.getFinishedFlag().equals("2") || s.getFinishedFlag().equals("3")).collect(Collectors.toList());//前一天

        Font font = sheet.getWorkbook().createFont();
        font.setBold(true);  // 设置字体加粗
        CellStyle style = sheet.getWorkbook().createCellStyle();
        style.setFont(font);  // 设置单元格样式

        XSSFRow row0 = sheet.createRow(0);
        XSSFCell cell0 = row0.createCell(0);
        cell0.setCellValue("序号");
        cell0.setCellStyle(style);

        sheet.setColumnWidth(1, 11 * 256);
        sheet.setColumnWidth(2, 30 * 256);
        sheet.setColumnWidth(3, 11 * 256);
        sheet.setColumnWidth(4, 20 * 256);

        cell0 = row0.createCell(1);
        cell0.setCellValue("遥测站编码");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(2);
        cell0.setCellValue("遥测站名称");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(3);
        cell0.setCellValue("审核日期");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(4, CellType.STRING);
        cell0.setCellValue("采样时间");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(5);
        cell0.setCellValue("当日16点");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(6);
        cell0.setCellValue("审核状态");
        cell0.setCellStyle(style);

        rowNo++;

        XSSFRow row1 = sheet.createRow(rowNo);
        XSSFCell cell1 = row1.createCell(1);
        cell1.setCellValue(DateUtil.formateDate(lastDate, "yyyy-MM-dd") + " | 比昨日新增");
        sheet.addMergedRegion(new CellRangeAddress(rowNo, rowNo, 1, 2));//合并单元格
        cell1.setCellStyle(style);

        rowNo++;

        for (TaskReview review : lastList) {
            if (prevList.stream().filter(s -> s.getStationCode().equals(review.getStationCode())).findFirst().isPresent()) {
                //两天都有
            } else {
                //昨天没有,今天有
                XSSFRow row = sheet.createRow(rowNo);
                XSSFCell cell = row.createCell(0);
                cell.setCellValue(recordSn);

                cell = row.createCell(1);
                cell.setCellValue(review.getStationCode());

                cell = row.createCell(2);
                Stream<StationAccModel> stream = accModels.stream().filter(s -> s.getStationCode().equals(review.getStationCode()) || (s.getWmId() != null && s.getWmId().equals(review.getStationCode())));
                if (stream != null) {
                    Optional<StationAccModel> optional = stream.findFirst();
                    if (optional.isPresent()) {
                        cell.setCellValue(optional.get().getStationName());
                    }
                }

                cell = row.createCell(3);
                cell.setCellValue(strLastDate);//审核日期

                cell = row.createCell(4);
                cell.setCellValue(DateUtil.formateDate(review.getSampleTime(), "yyyy-MM-dd HH:mm:ss"));//采样时间

                cell = row.createCell(5);
                cell.setCellValue((lastDate.compareTo(review.getSampleTime()) == 0) ? "是" : "否");//当日16点

                cell = row.createCell(6);
                ReviewResultType reviewResultType = ReviewResultType.findReviewResultTypeByCode(review.getFinishedFlag());
                if (reviewResultType != null) {
                    cell.setCellValue(reviewResultType.getName());
                }

                rowNo++;
                recordSn++;
            }
        }

        XSSFRow rowT2 = sheet.createRow(rowNo);
        XSSFCell cellT2 = rowT2.createCell(1);
        cellT2.setCellValue(DateUtil.formateDate(lastDate, "yyyy-MM-dd") + " | 比昨日减少");
        sheet.addMergedRegion(new CellRangeAddress(rowNo, rowNo, 1, 2));
        cellT2.setCellStyle(style);
        rowNo++;
        recordSn = 1;
        for (TaskReview review : prevList) {
            if (lastList.stream().filter(s -> s.getStationCode().equals(review.getStationCode())).findFirst().isPresent()) {
                //两天都有
            } else {
                //昨天有，今天没有
                XSSFRow row = sheet.createRow(rowNo);
                XSSFCell cell = row.createCell(0);
                cell.setCellValue(recordSn);

                cell = row.createCell(1);
                cell.setCellValue(review.getStationCode());

                cell = row.createCell(2);

                Stream<StationAccModel> stream = accModels.stream().filter(s -> s.getStationCode().equals(review.getStationCode()) || (s.getWmId() != null && s.getWmId().equals(review.getStationCode())));
                if (stream != null) {
                    Optional<StationAccModel> optional = stream.findFirst();
                    if (optional.isPresent()) {
                        cell.setCellValue(optional.get().getStationName());
                    }
                }

                cell = row.createCell(3);
                cell.setCellValue(strPrevDate);//审核日期

                cell = row.createCell(4);
                cell.setCellValue(DateUtil.formateDate(review.getSampleTime(), "yyyy-MM-dd HH:mm:ss"));//采样时间

                cell = row.createCell(5);
                cell.setCellValue((lastDate.compareTo(review.getSampleTime()) == 0) ? "是" : "否");//当日16点

                cell = row.createCell(6);
                //cell.setCellValue(getReviewResultName(review.getFinishedFlag()));//审核结果
                ReviewResultType reviewResultType = ReviewResultType.findReviewResultTypeByCode(review.getFinishedFlag());
                if (reviewResultType != null) {
                    cell.setCellValue(reviewResultType.getName());
                }

                rowNo++;
                recordSn++;
            }
        }
        sheet.createFreezePane(0, 1);
    }

    /**
     * 根据审核日期获取审核记录Map
     *
     * @param date
     * @return
     */
    public Map<String, TaskReview> findTaskReviewMapByDate(Date date) {
        Map<String, TaskReview> resMap = new HashMap<>();
        String taskDate = DateUtil.formateDate(date, "yyyyMMdd");
        TaskReviewExample example = new TaskReviewExample();
        example.createCriteria().andTaskDateEqualTo(taskDate);
        for (TaskReview taskReview : taskReviewMapper.selectByExample(example)) {
            resMap.put(taskReview.getStationCode(), taskReview);
        }
        return resMap;
    }

    /**
     * 根据日期和审核时间类型生成审核数据
     *
     * @param taskDate
     */
    public void generateReviewDataByTaskDate(String taskDate) {
        try {
            String date = taskDate + "160000";
            Date sampleDate = DateUtil.parseTimeStr(date, DateUtil.PATTERN_DATA_UNSIGNED);
            Date now = new Date();

            Map<String, TaskReview> taskReviewMap = findTaskReviewMapByDate(sampleDate);
            List<StationAccModel> accModels = getStationAccModels(null);

            List<TMarkRecordModel> markRecordModels = tMarkRecordService.findUntreatedModels();

            Map<String, TMarkRecordModel> skipMap = new HashMap<>();
            Map<String, TMarkRecordModel> mustMap = new HashMap<>();

            for (TMarkRecordModel markRecordModel : markRecordModels) {
                if (markRecordModel.getMarkId() < 900) {
                    if (!skipMap.containsKey(markRecordModel.getStationCode())) {
                        skipMap.put(markRecordModel.getStationCode(), markRecordModel);
                    }
                } else {
                    if (!mustMap.containsKey(markRecordModel.getStationCode())) {
                        mustMap.put(markRecordModel.getStationCode(), markRecordModel);
                    }
                }
            }

            int index = 1;
            for (StationAccModel accModel : accModels) {
                String stationCode = accModel.getStationCode();
                log.info("正在处理站点：" + index + " | " + stationCode);
                index++;
                if (taskReviewMap.containsKey(stationCode)) {//已经有记录了
                    continue;
                }

                if (accModel.getStationName().toUpperCase().contains("TEST")) {//排除调试、测试设备
                    continue;
                }

                DeviceType deviceType = DeviceType.findDeviceTypeByCode(accModel.getDeviceType());
                if (deviceType == null) {
                    log.info("站点：" + stationCode + " | 设备类型为空");
                    continue;
                }

                TMarkRecordModel markRecord = null;

                if (skipMap.containsKey(stationCode)) {//存在故障记录
                    if (skipMap.get(stationCode).getReviewFlag().equals("0")) {
                        log.info(stationCode + ":因标记跳过审核:" + skipMap.get(stationCode).getMarkParentName());
                        continue;
                    }
                    markRecord = skipMap.get(stationCode);
                }

                TAiread airead = null;

                if (deviceType == DeviceType.GAS_METER) {
                    airead = getTAiread_GAS(stationCode, sampleDate);
                } else {
                    airead = getTAiread(stationCode, sampleDate);
                }

                if (airead == null) {//没有读数记录
                    continue;
                }

                /*//125版本不需要审核(由2025-06-06会议决定) 2025-06-17
                //此片隐患,受后续版本号的制定(如根据)
                if(airead.getSoftVer().startsWith(BaseConstant.VERSION_NO_REVIEW_REQUIRED)){
                    log.info(stationCode + ":125版本不需要审核");
                    continue;
                }*/

                List<TServerReadModel> serverList = tServerReadService.findTServerReadByAiReadid(airead.getAireadId());
                TServerReadModel serverReadModel = serverList == null || serverList.size() == 0 ? null : serverList.get(0);

                TaskReviewModel taskReviewModel = new TaskReviewModel();
                taskReviewModel.setTaskDate(taskDate);
                taskReviewModel.setDeviceSn(airead.getDeviceSn());
                taskReviewModel.setStationCode(stationCode);
                taskReviewModel.setAireadId(airead.getAireadId());
                taskReviewModel.setSampleTime(airead.getSampleTime());
                taskReviewModel.setIdentValue(airead.getIdentValue());
                taskReviewModel.setRawValue(airead.getRawValue());
                taskReviewModel.setIdenValidFlag(airead.getGoodFlag());
                taskReviewModel.setSystemReviewFlag("0");//添加默认值,非系统审核 2024-09-11 guozhao

                //优先使用大图 2024-07-31 guozhao
                if (ImageUtil.isImageByExtension(airead.getBigJpgUrl())) {
                    taskReviewModel.setMcuImageUrl(airead.getBigJpgUrl());
                } else {
                    taskReviewModel.setMcuImageUrl(airead.getSmallJpgUrl());
                }

                taskReviewModel.setIdenValidFlag(airead.getGoodFlag());
                taskReviewModel.setSoftVer(airead.getSoftVer());
                taskReviewModel.setNbVersion(airead.getNbVersion());
                taskReviewModel.setHardVersion(airead.getHardVersion());
                taskReviewModel.setAiVersion(airead.getAiVersion());

                if (serverReadModel != null) {
                    taskReviewModel.setServerReadId(serverReadModel.getServerReadId());
                    taskReviewModel.setServerValue(serverReadModel.getIdentValue());
                    taskReviewModel.setServerImageUrl(serverReadModel.getJpgUrl());
                    taskReviewModel.setServerValidFlag(serverReadModel.getGoodFlag());
                }

                taskReviewModel.setCreateTime(now);
                taskReviewModel.setSendSlsFlag("0");

                //获取上次的审核情况
                TaskReviewModel lastReviewModel = getLastReviewModel(taskReviewModel);
                if (lastReviewModel != null) {
                    taskReviewModel.setLastReviewValue(lastReviewModel.getReviewValue());
                    taskReviewModel.setLastTaskId(lastReviewModel.getTaskId());
                    taskReviewModel.setLastMcuImageUrl(lastReviewModel.getMcuImageUrl());
                    taskReviewModel.setLastSampleTime(lastReviewModel.getSampleTime());
                } else {
                    taskReviewModel.setLastMcuImageUrl("");//防止前台空值
                }

                taskReviewModel.setStationName(accModel.getStationName());

                List<TAicbqCfgModel> cfgList = tAicbqCfgService.findTAicbqCfg(airead.getDeviceSn(), "", "1");
                TAicbqCfgModel cfgModel = null;
                if (cfgList != null && cfgList.size() > 0) {//填充配置项中的数字个数和尾数单位 2022-10-24 guozhao
                    cfgModel = cfgList.get(0);
                    taskReviewModel.setDigitNum(cfgModel.getDigitNum());
                    taskReviewModel.setUnitType(cfgModel.getUnitType());
                }

                NoReviewModel noReviewModel = null;
                //String historyFlag = "1";
                //统一改为当日有数就不算历史记录 2024-08-07 guozhao
                String historyFlag = DateUtil.formateDate(airead.getSampleTime(), "yyyyMMdd").equals(taskDate) ? "0" : "1";

                //单独处理燃气表,仅有服务侧值,大图,且采样时间不同 2024-01-11 guozhao
                if (deviceType == DeviceType.GAS_METER) {
                    taskReviewModel.setMcuImageUrl(airead.getBigJpgUrl());
                    //燃气表判断只判断日期部分(只要是当日就不算历史数据),默认是0点的,而不是16点
                    //historyFlag = DateUtil.formateDate(airead.getSampleTime(), "yyyyMMdd").equals(taskDate) ? "0" : "1";
                    if (serverReadModel != null) {
                        taskReviewModel.setReviewValue(serverReadModel.getIdentValue());
                    }
                } else if (!mustMap.containsKey(stationCode) && cfgModel != null && cfgModel.getUnitType() == UnitType.UNIT4.getKey()) {//非必审才判断免审 2024-09-02 guozhao
                    noReviewModel = getNoReviewLevel(airead, serverReadModel, sampleDate, markRecord != null);

                    //上面代码添加尾数单位非1的都人工审核 2025-04-02 guozhao
                }
                taskReviewModel.setHistoryFlag(historyFlag);

                if (noReviewModel != null) {
                    airead = noReviewModel.getAiread();
                    serverReadModel = noReviewModel.getServerReadModel();
                    taskReviewModel.setSystemReviewFlag(noReviewModel.getNoReviewLevel().toString());
                    if (noReviewModel.getNoReviewLevel() > 0) {//系统审核的
                        taskReviewModel.setFinishedFlag(ReviewResultType.IDENT_TRUE.getCode());
                        taskReviewModel.setReviewMan(noReviewModel.getLevelName());
                        taskReviewModel.setReviewTime(now);
                        taskReviewModel.setReviewValue(airead.getIdentValue());
                        if (noReviewModel.getNoReviewLevel() == 5) {//使用服务侧值的情况下,将审核值修改为服务侧值 2023-04-18 guozhao
                            taskReviewModel.setReviewValue(serverReadModel.getIdentValue());
                        }
                        if (noReviewModel.getNoReviewLevel() > 2) {
                            taskReviewModel.setSendSlsFlag("1");
                        }
                    } else {
                        handleUnrecognizableDate(taskReviewModel, airead, sampleDate, now);
                    }
                } else {
                    handleUnrecognizableDate(taskReviewModel, airead, sampleDate, now);
                }

                //逻辑添加:不符合免审,且不符合无法辨认的条件,但无当时数据,也无审核必要,放到识别正确中 2024-08-28 guozhao
                if (taskReviewModel.getFinishedFlag().equals(ReviewResultType.UNREVIEW.getCode())
                        && taskReviewModel.getHistoryFlag().equals("1")
                        && lastReviewModel != null
                ) {
                    //taskReviewModel.setFinishedFlag(ReviewResultType.IDENT_TRUE.getCode());//不能武断判定为正常,里面可能包含无法辨别的
                    //非当日数据的延续上次审核状态
                    taskReviewModel.setFinishedFlag(lastReviewModel.getFinishedFlag());
                    taskReviewModel.setSystemReviewFlag(SystemReviewType.LEVEL7.getLevel().toString());
                    taskReviewModel.setReviewMan(SystemReviewType.LEVEL7.getName());
                    taskReviewModel.setReviewTime(now);
                    taskReviewModel.setReviewValue(airead.getResultValue());
                }

                taskReviewModel = saveTaskReview(taskReviewModel);

                //如果是系统免审的,更新airead表审核状态(为后续过滤客户数据做准备) 2024-11-23 guozhao
                if (taskReviewModel != null && StringUtils.isNotEmpty(taskReviewModel.getSystemReviewFlag()) &&
                        !taskReviewModel.getSystemReviewFlag().equals("0")) {
                    airead.setReviewFlag(BaseConstant.VALID_FLAG);
                    airead.setReviewResultFlag(taskReviewModel.getFinishedFlag());
                    airead.setReviewTime(taskReviewModel.getReviewTime());
                    airead.setReviewMan(taskReviewModel.getReviewMan());
                    airead.setTaskReviewId(taskReviewModel.getTaskId());
                    if (taskReviewModel.getFinishedFlag().equals(ReviewResultType.UNRECOGNIZABLE.getCode())) {
                        airead.setReviewValue(null);//无法辨别的最终结果值置为null
                    }
                    TAireadModel aireadModel = new TAireadModel();
                    BeanUtils.copyProperties(airead, aireadModel);
                    tAireadService.updateTAiread(aireadModel);
                }

                //改为0点后统一推送 2024-08-07 guozhao
                //添加条件=WATER_METER才推送至水利所 2024-01-11 guozhao
            /*if (deviceType == DeviceType.WATER_METER && taskReviewModel != null) {
                if (noReviewModel.getNoReviewLevel() > 2) {//三四级免审加入到推送列表中
                    try {
                        generateSendSlsAiReadModel(airead, serverReadModel, taskReviewModel);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }*/
            }
        } catch (Exception e) {
            log.error("生成审核数据异常", e);
        }
    }

    /**
     * 检查是否是无法辨别的数据
     * 1.连续30天无数据;2.连续30天无法辨别
     *
     * @param airead
     * @param date
     * @return
     */
    private boolean checkUnrecognizable(TAiread airead, Date date) {
        TAireadModel latestAireadModel = tAireadService.findLatesTAireadByStationCode(airead.getStationCode());
        if (latestAireadModel == null) {
            return true;
        }

        //最后一条数据距今超过30天
        if (DateUtil.daysBetween(latestAireadModel.getSampleTime(), date) > RULE_UNRECOGNIZABLE_DAYS) {
            log.info(airead.getStationCode() + ":近30天无数据,判定为无法辨别");
            return true;
        }

        //释放机制,防止连续30后,设备恢复后,仍自动判为无法辨别 2024-08-07 guozhao
        if (isBelievable(airead)) {
            return false;
        }

        Date temp = DateUtil.getOtherDateByCurrentDate(date, -RULE_UNRECOGNIZABLE_DAYS);
        String tempStr = DateUtil.formateDate(temp, "yyyyMMdd");
        String dateStr = DateUtil.formateDate(date, "yyyyMMdd");

        //30天都是无法辨别的
        TaskReviewExample example = new TaskReviewExample();
        example.createCriteria().andStationCodeEqualTo(airead.getStationCode()).
                andFinishedFlagEqualTo(ReviewResultType.UNRECOGNIZABLE.getCode()).
                andTaskDateLessThan(dateStr).andTaskDateGreaterThanOrEqualTo(tempStr);
        List<TaskReview> taskReviews = taskReviewMapper.selectByExample(example);
        if (taskReviews.size() >= RULE_UNRECOGNIZABLE_DAYS) {
            log.info(airead.getStationCode() + ":近30天均是无法辨别,判定为无法辨别");
        }

        return taskReviews.size() >= RULE_UNRECOGNIZABLE_DAYS;
    }

    /**
     * 处理无法辨别的(系统判定的)
     *
     * @param taskReviewModel
     * @param airead
     * @param sampleDate
     * @param now
     */
    private void handleUnrecognizableDate(TaskReviewModel taskReviewModel, TAiread airead, Date sampleDate, Date now) {
        if (checkUnrecognizable(airead, sampleDate)) {//符合无法辨别的条件
            taskReviewModel.setFinishedFlag(ReviewResultType.UNRECOGNIZABLE.getCode());
            taskReviewModel.setSystemReviewFlag(SystemReviewType.LEVEL6.getLevel().toString());
            taskReviewModel.setReviewMan(SystemReviewType.LEVEL6.getName());
            taskReviewModel.setReviewTime(now);
            taskReviewModel.setReviewValue(airead.getResultValue());
        } else {
            taskReviewModel.setFinishedFlag(ReviewResultType.UNREVIEW.getCode());
        }
    }

    /**
     * 处理审核修正图片
     * 将处理复制到独立目录
     */
    private void handleReviewReviseImage(TaskReviewModel taskReviewModel) {
        if (!ImageUtil.isImageByExtension(taskReviewModel.getMcuImageUrl())) {//无图片
            return;
        }
        String imgPath = ImageUtil.convertImageUrlToLocalPath(taskReviewModel.getMcuImageUrl(), env.getProperty(ResourceTag.UploadPathTag.getTag()));
        File file = new File(imgPath);
        if (!file.exists()) {//文件不存在了
            return;
        }
        try {
            String destPath = env.getProperty(ResourceTag.UploadPathTag.getTag()) + ResourcePath.ReviewRevise.getPath() + taskReviewModel.getTaskDate();
            File dir = new File(destPath);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            //文件名添加正确的识别结果,供后续验证结果使用 2024-09-20 guozhao
            //00000002695_20240828000418_B.jpg
            String[] fileNameArr = file.getName().split("\\.");
            destPath = String.format("%s%s%s_%s.%s", destPath, File.separator, fileNameArr[0], taskReviewModel.getReviewValue(), fileNameArr[1]);
            Files.copy(Paths.get(imgPath), Paths.get(destPath), StandardCopyOption.REPLACE_EXISTING);
        } catch (Exception e) {
            log.error("处理审核修正图片失败", e);
        }
    }

    /**
     * 根据站码和时间获取有效(正确或修正的)审核记录
     *
     * @param stationCode
     * @param startTime
     * @param endTime
     * @return
     */
    public List<TaskReview> findValidReviewsByStationCodeAndDate(String stationCode, Date startTime, Date endTime) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andStationCodeEqualTo(stationCode)
                .andFinishedFlagLessThanOrEqualTo(ReviewResultType.REVIEW_REVISE.getCode())
                .andFinishedFlagGreaterThanOrEqualTo(ReviewResultType.IDENT_TRUE.getCode());
        if (startTime != null) {
            criteria.andSampleTimeGreaterThanOrEqualTo(startTime);
        }
        if (endTime != null) {
            criteria.andSampleTimeLessThanOrEqualTo(endTime);
        }

        return taskReviewMapper.selectByExample(example);
    }

    /**
     * 根据AireadId获取TaskReview
     *
     * @param aireaId
     * @return
     */
    public TaskReview findTaskReviewByAireadId(String aireaId) {
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andAireadIdEqualTo(aireaId);
        example.setOrderByClause("CREATE_TIME DESC");
        PageHelper.startPage(1, 1);
        List<TaskReview> taskReviews = taskReviewMapper.selectByExample(example);
        return taskReviews.size() > 0 ? taskReviews.get(0) : null;
    }

    /**
     * 根据单位编码等获取审核记录列表
     *
     * @param unitCode
     * @param taskDate
     * @param reviewFlag
     * @return
     */
    public List<TaskReviewModel> findTaskReviewList(String unitCode, String taskDate, String reviewFlag) {
        taskDate = taskDate.replaceAll("-", "");
        List<StationAccModel> stationAccModels = stationAccService.findStationAccByUnitCode(unitCode);
        TaskReviewExample example = new TaskReviewExample();
        TaskReviewExample.Criteria criteria = example.createCriteria();
        criteria.andTaskDateEqualTo(taskDate);
        criteria.andFinishedFlagEqualTo(reviewFlag);
        List<TaskReview> reviews = taskReviewMapper.selectByExample(example);
        List<TaskReviewModel> resList = new ArrayList<>();

        for (StationAccModel stationAccModel : stationAccModels) {
            Optional<TaskReview> optional = reviews.stream().filter(review -> review.getStationCode().equals(stationAccModel.getStationCode())).findFirst();
            if (optional.isPresent()) {
                TaskReviewModel model = new TaskReviewModel();
                BeanUtils.copyProperties(optional.get(), model);
                resList.add(model);
            }
        }

        return resList;
    }

    /**
     * 下载数据至Excel(根据单位代码等)
     *
     * @param response
     */
    public void downloadTaskReviewList(HttpServletResponse response, String unitCode, String taskDate, String reviewFlag) {
        List<TaskReviewModel> list = findTaskReviewList(unitCode, taskDate, reviewFlag);

        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet1 = workbook.createSheet("异常");

        short rowHeight = 10 * 256;//行高

        Font font = workbook.createFont();
        font.setBold(true);  // 设置字体加粗
        CellStyle style = workbook.createCellStyle();
        style.setFont(font);  // 设置单元格样式
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);

        XSSFRow row0 = sheet1.createRow(0);
        XSSFCell cell0 = row0.createCell(0);
        cell0.setCellValue("序号");
        cell0.setCellStyle(style);

        sheet1.setColumnWidth(1, 12 * 256);
        sheet1.setColumnWidth(2, 45 * 256);
        sheet1.setColumnWidth(3, 22 * 256);
        sheet1.setColumnWidth(4, 37 * 256);

        cell0 = row0.createCell(1);
        cell0.setCellValue("遥测站编码");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(2);
        cell0.setCellValue("遥测站名称");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(3, CellType.STRING);
        cell0.setCellValue("采样时间");
        cell0.setCellStyle(style);

        cell0 = row0.createCell(4);
        cell0.setCellValue("图片");
        cell0.setCellStyle(style);

        int num = 1;
        sheet1.createFreezePane(0, 1);//冻结首行

        //画图的顶级管理器，一个sheet只能获取一个（一定要注意这点）
        XSSFDrawing patriarch = sheet1.createDrawingPatriarch();

        for (TaskReviewModel model : list) {
            XSSFRow row = sheet1.createRow(num);
            row.setHeight(rowHeight);
            row.createCell(0).setCellValue(num);
            row.createCell(1).setCellValue(model.getStationCode());
            row.createCell(2).setCellValue(model.getStationName());
            row.createCell(3).setCellValue(DateUtil.formateDate(model.getSampleTime(), "yyyy-MM-dd HH:mm:ss"));

            String localPath = ImageUtil.convertImageUrlToLocalPath(model.getMcuImageUrl(), env.getProperty(ResourceTag.UploadPathTag.getTag()));
            File file = new File(localPath);
            if (!file.exists() || !file.isFile()) {
                num++;
                continue;
            }
            try {
                XSSFCell picCell = row.createCell(4);
                //row.createCell(5);
                FileInputStream fileInputStream = new FileInputStream(file);
                byte[] picbyte = new byte[(int) file.length()];
                fileInputStream.read(picbyte);
                fileInputStream.close();

                XSSFClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, 4, num, 5, num + 1);
                int cmToEmu = 80000;

                // 设置图片的位置和大小
                int dx1 = cmToEmu;
                int dy1 = cmToEmu;
                int dx2 = 37 * 256 - cmToEmu;
                int dy2 = rowHeight - cmToEmu;
                anchor.setDx1(dx1);
                anchor.setDy1(dy1);
                anchor.setDx2(dx2);
                anchor.setDy2(dy2);

                patriarch.createPicture(anchor, workbook.addPicture(picbyte, XSSFWorkbook.PICTURE_TYPE_JPEG));
            } catch (IOException ioe) {

            }
            num++;
        }

        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            workbook.write(os);
            byte[] bytes = os.toByteArray();

            String filename = URLEncoder.encode("异常站点" + taskDate + ".xlsx", "UTF-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-disposition", "attachment;filename=" + filename);
            ServletOutputStream outputStream = response.getOutputStream();
            outputStream.write(bytes);
            outputStream.close();
            os.close();
            workbook.close();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
