package com.njcn.device.common.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.text.StrBuilder;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.dto.SimpleDTO;
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.pojo.response.HttpResult;
import com.njcn.common.utils.LogUtil;
import com.njcn.common.utils.PubUtils;
import com.njcn.device.biz.enums.DeviceResponseEnum;
import com.njcn.device.biz.enums.RunFlagEnum;
import com.njcn.device.biz.pojo.dto.LineDTO;
import com.njcn.device.biz.pojo.po.DeviceBak;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.device.biz.utils.COverlimitUtil;
import com.njcn.device.common.mapper.SuperDataMapper;
import com.njcn.device.common.service.TerminalBaseService;
import com.njcn.device.device.mapper.DevFuctionMapper;
import com.njcn.device.device.mapper.DeviceMapper;
import com.njcn.device.device.service.DeviceBakService;
import com.njcn.device.device.service.DeviceProcessService;
import com.njcn.device.device.service.NodeDeviceService;
import com.njcn.device.device.service.PqDevTypeService;
import com.njcn.device.line.mapper.DeptLineMapper;
import com.njcn.device.line.mapper.LineDetailMapper;
import com.njcn.device.line.mapper.LineMapper;
import com.njcn.device.line.service.LineBakService;
import com.njcn.device.node.service.INodeService;
import com.njcn.device.biz.mapper.OverlimitMapper;
import com.njcn.device.pq.constant.Param;
import com.njcn.device.pq.enums.LineBaseEnum;
import com.njcn.device.pq.enums.PvDeviceResponseEnum;
import com.njcn.device.pq.pojo.bo.BaseLineInfo;
import com.njcn.device.pq.pojo.bo.DeviceType;
import com.njcn.device.pq.pojo.bo.excel.NodeExcel;
import com.njcn.device.pq.pojo.bo.excel.OracleTerminalExcel;
import com.njcn.device.pq.pojo.bo.excel.OverLimitExcel;
import com.njcn.device.pq.pojo.bo.excel.TerminalBaseExcel;
import com.njcn.device.pq.pojo.dto.*;
import com.njcn.device.pq.pojo.param.*;
import com.njcn.device.pq.pojo.param.oracle.*;
import com.njcn.device.pq.pojo.po.*;
import com.njcn.device.pq.pojo.vo.*;
import com.njcn.device.pq.utils.DeviceUtil;
import com.njcn.device.substation.mapper.SubstationMapper;
import com.njcn.device.subvoltage.mapper.VoltageMapper;
import com.njcn.device.terminal.mapper.PqsTerminalLogsMapper;
import com.njcn.device.userledger.service.UserLedgerService;
import com.njcn.device.utils.ExcelStyleUtil;
import com.njcn.device.utils.LineSortHelper;
import com.njcn.message.api.ProduceFeignClient;
import com.njcn.message.constant.DeviceRebootType;
import com.njcn.message.constant.RedisKeyPrefix;
import com.njcn.message.message.DeviceRebootMessage;
import com.njcn.message.message.ProcessRebootMessage;
import com.njcn.message.messagedto.TopicReplyDTO;
import com.njcn.oss.constant.OssPath;
import com.njcn.oss.utils.FileStorageUtil;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.poi.util.PoiUtil;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.supervision.pojo.param.user.UserReportParam;
import com.njcn.supervision.pojo.po.user.UserReportPO;
import com.njcn.supervision.pojo.vo.user.UserLedgerVO;
import com.njcn.system.api.AreaFeignClient;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.pojo.po.Area;
import com.njcn.system.pojo.po.DictData;
import com.njcn.web.utils.RequestUtil;
import com.njcn.web.utils.RestTemplateUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.net.HttpURLConnection;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.njcn.device.pq.enums.LineBaseEnum.*;

/**
 * pqs
 *
 * @author cdf
 * @date 2022/1/4
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TerminalBaseServiceImpl extends ServiceImpl<LineMapper, Line> implements TerminalBaseService {
    private final DeviceMapper deviceMapper;
    private final SuperDataMapper superDataMapper;
    private final PqsTerminalLogsMapper pqsTerminalLogsMapper;
    private final LineMapper lineMapper;
    private final DevFuctionMapper devFuctionMapper;
    private final AreaFeignClient areaFeignClient;
    private final DicDataFeignClient dicDataFeignClient;
    private final SubstationMapper substationMapper;
    private final VoltageMapper voltageMapper;
    private final LineDetailMapper lineDetailMapper;
    private final OverlimitMapper overlimitMapper;
    private final DeptLineMapper deptLineMapper;
    private final INodeService nodeService;
    private final LineBakService lineBakService;
    private final DeviceBakService deviceBakService;
    private final FileStorageUtil fileStorageUtil;
    private final RedisUtil redisUtil;

    private final NodeDeviceService nodeDeviceService;
    private final DeviceProcessService deviceProcessService;
    private final ProduceFeignClient produceFeignClient;
    private final UserLedgerService userLedgerService;
    private final PqDevTypeService pqDevTypeService;
    private final LineSortHelper lineSortHelper;

    @Value("${oracle.isSync}")
    private Boolean isSync;

    @Value("${oracle.syncLedgerLineUrl}")
    private String url;


    @Value("${oracle.syncLedgerUpdateLine}")
    private String updateUrl;

    @Value("${oracle.syncLedgerDeleteLine}")
    private String urlDelete;

    @Value("${devCD:2}")
    private Integer devCD;


    /**
     * 终端新增操作
     *
     * @author cdf
     * @date 2021/7/19
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addTerminal(AddTerminalParam addTerminalParam) {
        String projectIndex = null;
        String provinceIndex = null;
        String gdIndex = null;
        String subIndex = null;
        if (StrUtil.isNotBlank(addTerminalParam.getProjectIndex())) {
            projectIndex = addTerminalParam.getProjectIndex();
            if (Objects.isNull(this.getById(projectIndex))) {
                throw new BusinessException(DeviceResponseEnum.PROJECT_NO);
            }
        }
        if (StrUtil.isNotBlank(addTerminalParam.getProvinceIndex())) {
            provinceIndex = addTerminalParam.getProvinceIndex();
            if (Objects.isNull(this.getById(provinceIndex))) {
                throw new BusinessException(DeviceResponseEnum.PROVINCE_GET_ERROR);
            }
        }
        if (StrUtil.isNotBlank(addTerminalParam.getGdIndex())) {
            gdIndex = addTerminalParam.getGdIndex();
            if (Objects.isNull(this.getById(gdIndex))) {
                throw new BusinessException(DeviceResponseEnum.GD_NO);
            }
        }
        if (StrUtil.isNotBlank(addTerminalParam.getSubIndex())) {
            subIndex = addTerminalParam.getSubIndex();
            if (Objects.isNull(this.getById(subIndex))) {
                throw new BusinessException(DeviceResponseEnum.SUB_NO);
            }
        }

        //项目
        if (Objects.nonNull(addTerminalParam.getProjectParam())) {
            if (StrUtil.isBlank(projectIndex)) {
                checkName(addTerminalParam, PROJECT_LEVEL.getCode(), null);
                Line line = assembleLine(addTerminalParam.getProjectParam().getName(), PROJECT_LEVEL.getCode(), "0", "0", addTerminalParam.getProjectParam().getSort());
                lineSortHelper.handleSort(PROJECT_LEVEL.getCode(),addTerminalParam.getProjectParam().getSort(),line);
                this.baseMapper.insert(line);
                projectIndex = line.getId();
            }
        }
        //省份
        if (Objects.nonNull(addTerminalParam.getProvinceParam())) {
            if (StrUtil.isBlank(provinceIndex) && StrUtil.isNotBlank(projectIndex)) {
                Area result = areaFeignClient.selectIdArea(addTerminalParam.getProvinceParam().getName()).getData();
                if (Objects.isNull(result)) {
                    throw new BusinessException(DeviceResponseEnum.PROVINCE_GET_ERROR);
                }
                LogUtil.njcnDebug(log, "获取区域信息：{}", result.toString());
                checkName(addTerminalParam, PROVINCE_LEVEL.getCode(), projectIndex);
                Line province = assembleLine(result.getId(), PROVINCE_LEVEL.getCode(), projectIndex, projectIndex, addTerminalParam.getProvinceParam().getSort());
                lineSortHelper.handleSort(PROVINCE_LEVEL.getCode(),addTerminalParam.getProvinceParam().getSort(),province);
                this.baseMapper.insert(province);
                provinceIndex = province.getId();
            }
        }

        //供电公司
        if (Objects.nonNull(addTerminalParam.getGdInformationParam())) {
            if (StrUtil.isBlank(gdIndex) && StrUtil.isNotBlank(provinceIndex)) {
                checkName(addTerminalParam, GD_LEVEL.getCode(), provinceIndex);
                Line gdInformation = assembleLine(addTerminalParam.getGdInformationParam().getName(), GD_LEVEL.getCode(), provinceIndex, projectIndex + StrUtil.COMMA + provinceIndex, addTerminalParam.getGdInformationParam().getSort());
                lineSortHelper.handleSort(GD_LEVEL.getCode(),addTerminalParam.getGdInformationParam().getSort(),gdInformation);
                this.baseMapper.insert(gdInformation);
                gdIndex = gdInformation.getId();
            }
        }

        //变电站
        if (Objects.nonNull(addTerminalParam.getSubStationParam())) {
            if (StrUtil.isBlank(subIndex) && StrUtil.isNotBlank(gdIndex)) {
                checkName(addTerminalParam, LineBaseEnum.SUB_LEVEL.getCode(), gdIndex);
                Line subStation = assembleLine(addTerminalParam.getSubStationParam().getName(), LineBaseEnum.SUB_LEVEL.getCode(), gdIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex, addTerminalParam.getSubStationParam().getSort());
                lineSortHelper.handleSort(SUB_LEVEL.getCode(),addTerminalParam.getSubStationParam().getSort(),subStation);
                this.baseMapper.insert(subStation);
                subIndex = subStation.getId();

                //变电站下的经纬度入库
                Substation sub = new Substation();
                sub.setId(subIndex);
                sub.setScale(addTerminalParam.getSubStationParam().getScale());
                sub.setLng(addTerminalParam.getSubStationParam().getLng());
                sub.setLat(addTerminalParam.getSubStationParam().getLat());
                substationMapper.insert(sub);
            }
        }

        //装置
        if (Objects.nonNull(addTerminalParam.getDeviceParam())) {
            List<Line> logsList = new ArrayList<>();
            LambdaQueryWrapper<Line> lineLambdaQueryWrapper = new LambdaQueryWrapper<>();
            if (CollectionUtil.isNotEmpty(addTerminalParam.getDeviceParam()) && StrUtil.isNotBlank(subIndex)) {
                //校验变电站下的装置名称ip是否重复
                checkDevNameAndIp(addTerminalParam, subIndex, lineLambdaQueryWrapper);

                Integer devSort = lineSortHelper.getNextSort(DEVICE_LEVEL.getCode());
                for (DeviceParam deviceParam : addTerminalParam.getDeviceParam()) {
                    //用于记录装置id
                    String devIdIndex;
                    //监测点序号
                    List<Integer> listLineNum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).collect(Collectors.toList());
                    //母线序号
                    List<Integer> listVoltageNum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).collect(Collectors.toList());
                    //标识当前装置下的监测点数量
                    int lineNum = 0, voltageNum = 0;

                    //校验监测点总数不超过10
                    if (CollectionUtil.isNotEmpty(deviceParam.getSubVoltageParam())) {
                        for (SubVoltageParam subVoltage : deviceParam.getSubVoltageParam()) {
                            if (CollectionUtil.isNotEmpty(subVoltage.getLineParam())) {
                                for (LineParam lineValid : subVoltage.getLineParam()) {
                                    if (StrUtil.isBlank(lineValid.getLineIndex())) {
                                        lineNum++;
                                    }
                                }
                            }
                            //一台装置母线最多10路
                            if (StrUtil.isBlank(subVoltage.getSubvIndex())) {
                                voltageNum++;
                            }
                        }
                    }


                    if (StrUtil.isBlank(deviceParam.getDevIndex())) {
                        Line device = assembleLine(deviceParam.getName(), LineBaseEnum.DEVICE_LEVEL.getCode(), subIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex + StrUtil.COMMA + subIndex, deviceParam.getSort());
                        if(Objects.isNull(deviceParam.getSort()) || deviceParam.getSort() == 0){
                            device.setSort(devSort);
                        }
                        this.baseMapper.insert(device);
                        if(Objects.isNull(deviceParam.getSort()) || deviceParam.getSort() == 0){
                            devSort++;
                        }
                        devIdIndex = device.getId();

                        //装置详情
                        Device deviceDetail = new Device();
                        BeanUtils.copyProperties(deviceParam, deviceDetail);
                        deviceDetail.setId(device.getId());
                        deviceDetail.setRunFlag(0);
                        deviceDetail.setCallFlag(0);
                        deviceDetail.setComFlag(0);
                        deviceDetail.setCheckFlag(1);
                        deviceDetail.setThisTimeCheck(PubUtils.localDateFormat(deviceParam.getThisTimeCheck()));
                        deviceDetail.setNextTimeCheck(PubUtils.localDateFormat(deviceParam.getNextTimeCheck()));
                        deviceDetail.setLoginTime(PubUtils.localDateFormat(deviceParam.getLoginTime()));
                        deviceDetail.setUpdateTime(LocalDateTime.now());

                        //处理装置识别码秘钥
                        coderM3d(deviceDetail, false);
                        deviceMapper.insert(deviceDetail);
                        DeviceProcess deviceProcess = new DeviceProcess();
                        deviceProcess.setId(device.getId());
                        deviceProcess.setProcessNo(1);
                        deviceProcessService.saveOrUpdate(deviceProcess);
                        //装置功能
                        List<DictData> funList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_FUN.getName()).getData();
                        if (CollectionUtil.isEmpty(funList)) {
                            throw new BusinessException(DeviceResponseEnum.DIC_GET_EMPTY);
                        }

                        List<DevFuction> insertFunList = new ArrayList<>();
                        for (DictData dicData : funList) {
                            DevFuction devFunction = new DevFuction();
                            devFunction.setLineId(device.getId());
                            devFunction.setFucName(dicData.getId());
                            devFunction.setId(IdUtil.simpleUUID());
                            insertFunList.add(devFunction);
                        }
                        QueryWrapper<DevFuction> funQueryWrapper = new QueryWrapper<>();
                        funQueryWrapper.lambda().eq(DevFuction::getLineId, device.getId());
                        devFuctionMapper.delete(funQueryWrapper);
                        devFuctionMapper.addBatch(insertFunList);
                        logsList.add(device);
                    } else {
                        devIdIndex = deviceParam.getDevIndex();
                        List<LineDetail> lineDetails = lineMapper.getLineDetailByDeviceId(devIdIndex);
                        if (CollectionUtil.isNotEmpty(lineDetails)) {
                            lineNum = lineNum + lineDetails.size();
                            for (LineDetail sline : lineDetails) {
                                listLineNum.removeIf(integer -> sline.getNum().equals(integer));
                            }
                        }
                        //母线
                        List<Voltage> voltageList = lineMapper.getVoltageByDevId(devIdIndex);
                        if (CollectionUtil.isNotEmpty(voltageList)) {
                            voltageNum = voltageNum + voltageList.size();
                            for (Voltage v : voltageList) {
                                listVoltageNum.removeIf(integer -> v.getNum().equals(integer));
                            }
                        }
                    }

                    if (lineNum > 10) {
                        throw new BusinessException(DeviceResponseEnum.DEVICE_LINE_BIG);
                    }
                    if (voltageNum > 10) {
                        throw new BusinessException(DeviceResponseEnum.DEVICE_VOLTAGE_BIG);
                    }

                    //判断设备下是否存在母线
                    if (CollectionUtil.isNotEmpty(deviceParam.getSubVoltageParam())) {
                        //当通过设备节点新增时候需要校验是否存在同名母线名称
                        List<String> subvNameList = deviceParam.getSubVoltageParam().stream()
                                .filter((subv) -> StrUtil.isBlank(subv.getSubvIndex()))
                                .map(SubVoltageParam::getName).collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(subvNameList)) {
                            lineLambdaQueryWrapper.clear();
                            lineLambdaQueryWrapper.eq(Line::getPid, devIdIndex)
                                    .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                                    .in(Line::getName, subvNameList);
                            List<Line> subvRes = this.list(lineLambdaQueryWrapper);
                          /*  if (!subvRes.isEmpty()) {
                                List<String> subvList = subvRes.stream().map(Line::getName).collect(Collectors.toList());
                                throw new BusinessException(DeviceResponseEnum.SUBV_NAME_SAME, String.join(";", subvList));
                            }*/
                        }


                        //母线
                        List<String> voltageName = deviceParam.getSubVoltageParam().stream().filter(item -> StrUtil.isBlank(item.getSubvIndex())).map(SubVoltageParam::getName).collect(Collectors.toList());
                       /* if (CollectionUtil.isNotEmpty(voltageName)) {
                            List<Line> voltageList = this.baseMapper.getVoltageListBySubId(subIndex, voltageName);
                            if (CollectionUtil.isNotEmpty(voltageList)) {
                                throw new BusinessException(DeviceResponseEnum.SUBV_NAME_SAME, voltageList.stream().map(Line::getName).collect(Collectors.joining(";")));
                            }
                        }*/


                        //校验同一变电站下只能有唯一母线名称
                        List<String> addVoltage = deviceParam.getSubVoltageParam().stream().filter(item -> StrUtil.isBlank(item.getSubvIndex())).map(SubVoltageParam::getName).collect(Collectors.toList());
                       /* if (CollectionUtil.isNotEmpty(addVoltage)) {
                            List<Line> voltageListBySubId = this.baseMapper.getVoltageListBySubId(subIndex, addVoltage);
                            if (CollectionUtil.isNotEmpty(voltageListBySubId)) {
                                throw new BusinessException(DeviceResponseEnum.SUBV_NAME_SAME, voltageListBySubId.stream().map(Line::getName).collect(Collectors.joining(";")));
                            }
                        }*/
                        Integer subvSort = lineSortHelper.getNextSort(SUB_V_LEVEL.getCode());
                        for (SubVoltageParam subVoltageParam : deviceParam.getSubVoltageParam()) {
                            //母线id
                            String subvIndex;
                            if (StrUtil.isBlank(subVoltageParam.getSubvIndex()) && StrUtil.isNotBlank(devIdIndex)) {

                                DictData scaleRes = dicDataFeignClient.getDicDataById(subVoltageParam.getScale()).getData();
                                if (Objects.isNull(scaleRes)) {
                                    throw new BusinessException(DeviceResponseEnum.DIC_GET_EMPTY);
                                }
                                //校验母线
                                if (CollectionUtil.isNotEmpty(listVoltageNum)) {
                                    if (!listVoltageNum.contains(subVoltageParam.getNum())) {
                                        throw new BusinessException(DeviceResponseEnum.VOLTAGE_NUM_USE, "母线序号:" + subVoltageParam.getNum());
                                    }
                                } else {
                                    throw new BusinessException(DeviceResponseEnum.DEVICE_VOLTAGE_BIG);
                                }

                                Line subVoltage = assembleLine(subVoltageParam.getName(), LineBaseEnum.SUB_V_LEVEL.getCode(), devIdIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex + StrUtil.COMMA + subIndex + StrUtil.COMMA + devIdIndex, subVoltageParam.getSort());
                                if(Objects.isNull(subVoltageParam.getSort()) || subVoltageParam.getSort() == 0) {
                                    subVoltage.setSort(subvSort);
                                }
                                this.baseMapper.insert(subVoltage);
                                if(Objects.isNull(subVoltageParam.getSort()) || subVoltageParam.getSort() == 0) {
                                    subvSort++;
                                }
                                subvIndex = subVoltage.getId();
                                Voltage voltage = new Voltage();
                                voltage.setId(subVoltage.getId());
                                voltage.setNum(subVoltageParam.getNum());
                                voltage.setScale(scaleRes.getId());
                                voltage.setModel(subVoltageParam.getModel());
                                voltageMapper.insert(voltage);
                            } else {
                                subvIndex = subVoltageParam.getSubvIndex();
                            }

                            //监测点
                            if (CollectionUtil.isNotEmpty(subVoltageParam.getLineParam())) {
                                //校验监测点名称重复
                                List<String> lineNameList = subVoltageParam.getLineParam().stream().filter((line) -> StrUtil.isBlank(line.getLineIndex())).map(LineParam::getName).collect(Collectors.toList());
                                if (CollectionUtil.isNotEmpty(lineNameList)) {
                                    lineLambdaQueryWrapper.clear();
                                    lineLambdaQueryWrapper.eq(Line::getPid, subvIndex)
                                            .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                                            .in(Line::getName, lineNameList);
                                    List<Line> lineList = this.list(lineLambdaQueryWrapper);
                                    if (!lineList.isEmpty()) {
                                        List<String> lineRes = lineList.stream().map(Line::getName).collect(Collectors.toList());
                                        throw new BusinessException(DeviceResponseEnum.LINE_NAME_REPETITION, String.join(";", lineRes));
                                    }
                                }
                                //通用新增监测点
                                Integer lineSort = lineSortHelper.getNextSort(LineBaseEnum.LINE_LEVEL.getCode());
                                for (LineParam lineParam : subVoltageParam.getLineParam()) {
                                    if (StrUtil.isBlank(lineParam.getLineIndex()) && StrUtil.isNotBlank(subvIndex)) {
                                        //判断监测点序号是否重复
                                        if (CollectionUtil.isNotEmpty(listLineNum)) {
                                            if (!listLineNum.contains(lineParam.getNum())) {
                                                throw new BusinessException(DeviceResponseEnum.LINE_NUM_USE, "监测点序号:" + lineParam.getNum());
                                            }
                                        } else {
                                            throw new BusinessException(DeviceResponseEnum.DEVICE_LINE_BIG);
                                        }
                                        //删除与当前线路号重复的项
                                        listLineNum.removeIf(lineNo -> lineNo.equals(lineParam.getNum()));
                                        Line line = assembleLine(lineParam.getName(), LineBaseEnum.LINE_LEVEL.getCode(), subvIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex + StrUtil.COMMA + subIndex + StrUtil.COMMA + devIdIndex + StrUtil.COMMA + subvIndex, lineParam.getSort());
                                        if(Objects.isNull(lineParam.getSort()) || lineParam.getSort() == 0) {
                                            line.setSort(lineSort);
                                        }
                                        this.baseMapper.insert(line);
                                        if(Objects.isNull(lineParam.getSort()) || lineParam.getSort() == 0) {
                                            lineSort++;
                                        }
                                        LineDetail lineDetail = new LineDetail();
                                        BeanUtils.copyProperties(lineParam, lineDetail);
                                        lineDetail.setId(line.getId());
                                        //判断国网监测点id
                                        if (StrUtil.isNotBlank(lineDetail.getMonitorId())) {
                                            lineDetail.setMonitorFlag(1);
                                        } else {
                                            lineDetail.setMonitorFlag(0);
                                        }

                                        if (lineDetail.getPowerFlag() == 1) {
                                            //用户侧，objId不可为空
                                            if (StrUtil.isBlank(lineDetail.getObjId())) {
                                                throw new BusinessException(DeviceResponseEnum.LINE_USER_EMPTY);
                                            }
                                        } else {
                                            if (StrUtil.isNotBlank(lineDetail.getObjId())) {
                                                throw new BusinessException(DeviceResponseEnum.LINE_NO_USER_EMPTY);
                                            }
                                        }
                                        lineDetailMapper.insert(lineDetail);
                                        //通过监测点id获取母线电压等级
                                        Voltage voltage = lineMapper.getVoltageByLineId(line.getId());
                                        //监测点限值
                                        DictData scaleResult = dicDataFeignClient.getDicDataById(voltage.getScale()).getData();
                                        float scaTmp = Float.parseFloat(scaleResult.getValue());
                                        Overlimit overlimit = COverlimitUtil.globalAssemble(scaTmp, lineDetail.getDealCapacity(), lineDetail.getDevCapacity(), lineDetail.getShortCapacity(), lineDetail.getPowerFlag(), 0);

                                        if (Objects.isNull(lineParam.getVoltageDev())) {
                                            overlimit.setVoltageDev(overlimit.getVoltageDev());
                                        } else {
                                            overlimit.setVoltageDev(lineParam.getVoltageDev());
                                        }
                                        if (Objects.isNull(lineParam.getUvoltageDev())) {
                                            overlimit.setUvoltageDev(overlimit.getUvoltageDev());
                                        } else {
                                            overlimit.setUvoltageDev(lineParam.getUvoltageDev());
                                        }
                                        overlimitMapper.deleteById(line.getId());
                                        overlimit.setId(line.getId());
                                        overlimitMapper.insert(overlimit);
                                        logsList.add(line);
                                    }

                                }
                            }
                        }
                    }
                }
            } else {
                throw new BusinessException(CommonResponseEnum.FAIL);
            }

            if (CollUtil.isNotEmpty(logsList)) {
                List<PqsTerminalLogs> pqsTerminalLogsList = new ArrayList<>();
                terminalLogsCat(logsList, Param.ADD, pqsTerminalLogsList, new HashMap<>());
                for (PqsTerminalLogs pqsTerminalLogs : pqsTerminalLogsList) {
                    pqsTerminalLogsMapper.insert(pqsTerminalLogs);
                }
            }
        }
        return true;
    }

    /**
     * 校验装置
     */
    private void checkDevNameAndIp(AddTerminalParam addTerminalParam, String subIndex, LambdaQueryWrapper<Line> lineLambdaQueryWrapper) {
        List<String> devNameList = addTerminalParam.getDeviceParam().stream().filter((dev -> StrUtil.isBlank(dev.getDevIndex()))).map(DeviceParam::getName).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(devNameList)) {
            lineLambdaQueryWrapper.eq(Line::getPid, subIndex).in(Line::getName, devNameList);
            List<Line> deviceListRes = this.list(lineLambdaQueryWrapper);
            //校验当前变电站下是否有同名设备
            if (CollectionUtil.isNotEmpty(deviceListRes)) {
                List<String> stringList = deviceListRes.stream().map(Line::getName).collect(Collectors.toList());
                throw new BusinessException(DeviceResponseEnum.DEVICE_SAME_NAME, String.join(";", stringList));
            }
        }
        //校验当前变电站下的装置是否有相同ip
        List<DeviceParam> devIpList = addTerminalParam.getDeviceParam().stream().filter((dev -> StrUtil.isBlank(dev.getDevIndex()))).collect(Collectors.toList());
        if (CollectionUtil.isNotEmpty(devIpList)) {
            for (DeviceParam deviceParam : devIpList) {
                List<Device> deviceListIpRes = deviceMapper.getDeviceBySubId(subIndex, deviceParam.getIp(), deviceParam.getPort(), null);
                if (CollectionUtil.isNotEmpty(deviceListIpRes)) {
                    throw new BusinessException(DeviceResponseEnum.DEVICE_SAME_IP, deviceListIpRes.get(0).getIp());
                }

            }
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTerminal(UpdateTerminalParam updateTerminalParam) {
        String oldSubName = "";
        String gbName = "";
        LambdaQueryWrapper<Line> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //项目
        if (Objects.nonNull(updateTerminalParam.getProjectUpdateParam())) {
            Line projectRes = this.getById(updateTerminalParam.getProjectUpdateParam().getProjectIndex());
            if (Objects.isNull(projectRes)) {
                throw new BusinessException(DeviceResponseEnum.PROJECT_NO);
            }
            checkUpdateName(updateTerminalParam, 0, null);
            Line project = new Line();
            project.setId(updateTerminalParam.getProjectUpdateParam().getProjectIndex());
            project.setName(updateTerminalParam.getProjectUpdateParam().getName());
            project.setSort(updateTerminalParam.getProjectUpdateParam().getSort());
            this.updateById(project);
        }

        //省份
        if (Objects.nonNull(updateTerminalParam.getProvinceUpdateParam())) {
            Line provinceRes = this.getById(updateTerminalParam.getProvinceUpdateParam().getProvinceIndex());
            if (Objects.isNull(provinceRes)) {
                throw new BusinessException(DeviceResponseEnum.PROVINCE_EMPTY);
            }
            Line province = new Line();
            province.setId(updateTerminalParam.getProvinceUpdateParam().getProvinceIndex());
            province.setName(updateTerminalParam.getProvinceUpdateParam().getName());
            province.setSort(updateTerminalParam.getProvinceUpdateParam().getSort());
            this.updateById(province);
        }

        //供电公司
        if (Objects.nonNull(updateTerminalParam.getGdInformationUpdateParam())) {
            Line gdRes = this.getById(updateTerminalParam.getGdInformationUpdateParam().getGdIndex());
            if (Objects.isNull(gdRes)) {
                throw new BusinessException(DeviceResponseEnum.GD_NO);
            }
            gbName = gdRes.getName();
            Line gdInformation = new Line();
            gdInformation.setId(updateTerminalParam.getGdInformationUpdateParam().getGdIndex());
            gdInformation.setName(updateTerminalParam.getGdInformationUpdateParam().getName());
            gdInformation.setSort(updateTerminalParam.getGdInformationUpdateParam().getSort());

            checkUpdateName(updateTerminalParam, 2, gdRes.getPid());
            this.updateById(gdInformation);
        }
        //变电站
        if (Objects.nonNull(updateTerminalParam.getSubStationUpdateParam())) {
            Line subStationRes = this.getById(updateTerminalParam.getSubStationUpdateParam().getSubIndex());
            if (Objects.isNull(subStationRes)) {
                throw new BusinessException(DeviceResponseEnum.SUB_NO);
            }
            oldSubName = subStationRes.getName();
            Line subStation = new Line();
            subStation.setId(updateTerminalParam.getSubStationUpdateParam().getSubIndex());
            subStation.setName(updateTerminalParam.getSubStationUpdateParam().getName());
            subStation.setSort(updateTerminalParam.getSubStationUpdateParam().getSort());
            checkUpdateName(updateTerminalParam, 3, subStationRes.getPid());

            this.updateById(subStation);
            Substation pqsMap = new Substation();
            BeanUtils.copyProperties(updateTerminalParam.getSubStationUpdateParam(), pqsMap);
            pqsMap.setId(subStation.getId());
            substationMapper.updateById(pqsMap);

        }
        //装置
        if (CollectionUtil.isNotEmpty(updateTerminalParam.getDeviceUpdateParamList())) {
            List<DeviceParam> devList = updateTerminalParam.getDeviceUpdateParamList();
            List<String> devNameList = devList.stream()
                    .filter(item -> item.getUpdateFlag() == 1)
                    .map(DeviceParam::getName).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(devNameList)) {
                long devCount = devNameList.stream().distinct().count();
                if (devCount != devNameList.size()) {
                    throw new BusinessException(DeviceResponseEnum.DEVICE_REPETITION);
                }
            }

            //IP校验
            List<DeviceParam> devIpList = devList.stream()
                    .filter(item -> item.getUpdateFlag() == 1).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(devIpList)) {
                Set<String> set = new HashSet<>();
                devIpList.forEach(item -> set.add(item.getIp() + item.getPort()));
                if (devIpList.size() != set.size()) {
                    throw new BusinessException(DeviceResponseEnum.DEVICE_IP_REPETITION);
                }
            }
            Line deviceValid = this.getById(updateTerminalParam.getDeviceUpdateParamList().get(0).getDevIndex());

            //校验同名设备
            List<String> devIndexList = devList.stream()
                    .filter(item -> item.getUpdateFlag() == 1)
                    .map(DeviceParam::getDevIndex).collect(Collectors.toList());

            if (CollectionUtil.isNotEmpty(devIndexList)) {
                lambdaQueryWrapper.clear();
                lambdaQueryWrapper.in(Line::getName, devNameList)
                        .notIn(Line::getId, devIndexList)
                        .eq(Line::getPid, deviceValid.getPid());
                List<Line> deviceList = this.list(lambdaQueryWrapper);
                if (CollectionUtil.isNotEmpty(deviceList)) {
                    List<String> repeatDevNames = deviceList.stream().map(Line::getName).collect(Collectors.toList());
                    throw new BusinessException(DeviceResponseEnum.DEVICE_SAME_NAME, "重复装置:" + String.join(";", repeatDevNames));
                }
                //校验装置ip
                for (DeviceParam deviceParam : devIpList) {
                    List<Device> deviceIpList = deviceMapper.getDeviceBySubId(deviceValid.getPid(), deviceParam.getIp(), deviceParam.getPort(), deviceParam.getDevIndex());
                    if (CollectionUtil.isNotEmpty(deviceIpList)) {
                        throw new BusinessException(DeviceResponseEnum.DEVICE_SAME_IP, "重复IP:" + deviceIpList.get(0).getIp());
                    }
                }

            }


            //记录终端相关操作日志
            List<PqsTerminalLogs> pqsTerminalLogsList = new ArrayList<>();
            Map<String, DictData> dictDataMap = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_TYPE.getCode()).getData().stream().collect(Collectors.toMap(DictData::getId, Function.identity()));
            DictData dicDataByCode = dicDataFeignClient.getDicDataByCode(DicDataEnum.DEV_PARAMETER.getCode()).getData();
            String userName = RequestUtil.getUserNickname();

            for (DeviceParam updateDeviceParam : devList) {
                if (updateDeviceParam.getUpdateFlag() == 1) {
                    Line devicePO = this.getById(updateDeviceParam.getDevIndex());
                    Line sub = this.getById(devicePO.getPid());
                    Device devDetail = deviceMapper.selectById(updateDeviceParam.getDevIndex());
                    devLogsCat(Param.UPDATE_ZN, updateDeviceParam, devicePO, sub, devDetail, pqsTerminalLogsList, dictDataMap, dicDataByCode, userName);

                    Line device = new Line();
                    BeanUtils.copyProperties(updateDeviceParam, device);
                    device.setId(updateDeviceParam.getDevIndex());
                    Device deviceDetail = new Device();
                    BeanUtils.copyProperties(updateDeviceParam, deviceDetail);
                    deviceDetail.setId(updateDeviceParam.getDevIndex());
                    coderM3d(deviceDetail, true);
                    deviceDetail.setLoginTime(LocalDate.parse(updateDeviceParam.getLoginTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
                    deviceDetail.setThisTimeCheck(LocalDate.parse(updateDeviceParam.getThisTimeCheck(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));
                    deviceDetail.setNextTimeCheck(LocalDate.parse(updateDeviceParam.getNextTimeCheck(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN)));

                    this.updateById(device);
                    deviceMapper.updateById(deviceDetail);
                }

                //母线
                if (CollectionUtil.isNotEmpty(updateDeviceParam.getSubVoltageParam())) {
                    List<SubVoltageParam> subVoltageBOList = updateDeviceParam.getSubVoltageParam();
                    List<SubVoltageParam> useSubVoltageBOList = subVoltageBOList.stream()
                            .filter(item -> item.getUpdateFlag() == 1)
                            .collect(Collectors.toList());
                    if (CollectionUtil.isNotEmpty(useSubVoltageBOList)) {
                        //判断母线名称是否重复
                        List<String> subVNameList = useSubVoltageBOList.stream()
                                .map(SubVoltageParam::getName)
                                .collect(Collectors.toList());
                        if (CollectionUtil.isNotEmpty(subVNameList)) {
                            long subvCount = subVNameList.stream().distinct().count();
                            if (subvCount != subVNameList.size()) {
                                throw new BusinessException(DeviceResponseEnum.SUBV_NAME_REPETITION);
                            }
                            //校验母线名称是否已经存在
                            List<String> subVIndexList = useSubVoltageBOList.stream()
                                    .map(SubVoltageParam::getSubvIndex)
                                    .collect(Collectors.toList());
                            Line voltage = this.getById(subVIndexList.get(0));
                            if (Objects.isNull(voltage)) {
                                throw new BusinessException(DeviceResponseEnum.SUBV_NO);
                            }
                            lambdaQueryWrapper.clear();
                            lambdaQueryWrapper.in(Line::getName, subVNameList)
                                    .notIn(Line::getId, subVIndexList)
                                    .eq(Line::getPid, voltage.getPid());
                            List<Line> subVoltageList = this.list(lambdaQueryWrapper);
                         /*   if (CollectionUtil.isNotEmpty(subVoltageList)) {
                                List<String> repeatSubVNames = subVoltageList.stream().map(Line::getName).collect(Collectors.toList());
                                throw new BusinessException(DeviceResponseEnum.SUBV_NAME_SAME, "已存在母线名称:" + String.join(";", repeatSubVNames));
                            }*/
                        }
                    }

                    for (SubVoltageParam updateSubVoltageParam : subVoltageBOList) {
                        if (updateSubVoltageParam.getUpdateFlag() == 1) {
                            Voltage voltageTem = voltageMapper.selectById(updateSubVoltageParam.getSubvIndex());
                            Line byId = this.getById(updateSubVoltageParam.getSubvIndex());
                            updateSubVoltageParam.setOldName(byId.getName());
                            Line subVoltage = new Line();
                            subVoltage.setId(updateSubVoltageParam.getSubvIndex());
                            subVoltage.setName(updateSubVoltageParam.getName());
                            this.updateById(subVoltage);

                            Voltage voltage = new Voltage();
                            BeanUtils.copyProperties(updateSubVoltageParam, voltage);
                            voltage.setId(updateSubVoltageParam.getSubvIndex());
                            voltageMapper.updateById(voltage);

                            //如果电压等级变化重新计算母线下面监测点的限值
                            if (!voltageTem.getScale().equals(voltage.getScale())) {
                                List<LineDetail> lineList = voltageMapper.getLineDetailByBusBarId(voltage.getId());
                                DictData dictData = dicDataFeignClient.getDicDataById(voltage.getScale()).getData();
                                float voltageLevel = Float.parseFloat(dictData.getValue());
                                if (CollectionUtil.isNotEmpty(lineList)) {
                                    for (LineDetail lineDetail : lineList) {
                                        Overlimit overlimit = COverlimitUtil.globalAssemble(voltageLevel, lineDetail.getDealCapacity(), lineDetail.getDevCapacity(), lineDetail.getShortCapacity(), lineDetail.getPowerFlag(), 0);
                                        overlimit.setId(lineDetail.getId());
                                        overlimitMapper.deleteById(lineDetail.getId());
                                        overlimitMapper.insert(overlimit);
                                    }
                                }
                            }

                        }

                        //监测点
                        if (CollectionUtil.isNotEmpty(updateSubVoltageParam.getLineParam())) {
                            List<LineParam> updateLineBOS = updateSubVoltageParam.getLineParam();
                            Line lineR = this.getById(updateLineBOS.get(0).getLineIndex());
                            if (Objects.isNull(lineR)) {
                                throw new BusinessException(DeviceResponseEnum.LINE_NO);
                            }
                            //校验监测点名称是否已经存在
                            List<LineParam> useLineBOS = updateLineBOS.stream().filter(item -> item.getUpdateFlag() == 1).collect(Collectors.toList());
                            if (CollectionUtil.isNotEmpty(useLineBOS)) {
                                //判断监测点名称是否重复
                                List<String> LineNameList = useLineBOS.stream().map(LineParam::getName).collect(Collectors.toList());
                                long LineCount = LineNameList.stream().distinct().count();
                                if (LineCount != LineNameList.size()) {
                                    throw new BusinessException(DeviceResponseEnum.LINE_NAME_REPETITION);
                                }

                                List<String> lineIndexList = useLineBOS.stream().map(LineParam::getLineIndex).collect(Collectors.toList());
                                lambdaQueryWrapper.clear();
                                lambdaQueryWrapper.in(Line::getName, LineNameList)
                                        .notIn(Line::getId, lineIndexList)
                                        .eq(Line::getPid, lineR.getPid());
                                List<Line> lineList = this.list(lambdaQueryWrapper);
                                if (CollectionUtil.isNotEmpty(lineList)) {
                                    List<String> repeatLineNames = lineList.stream().map(Line::getName).collect(Collectors.toList());
                                    throw new BusinessException(DeviceResponseEnum.LINE_NAME_REPETITION, "已存在监测点名称:" + String.join(";", repeatLineNames));
                                }
                            }

                            for (LineParam updateLineBO : useLineBOS) {
                                String lineId = updateLineBO.getLineIndex();
                                LineDetail lineDetailRes = lineDetailMapper.selectById(lineId);
                                if (Objects.isNull(lineDetailRes)) {
                                    throw new BusinessException(DeviceResponseEnum.LINE_NO);
                                }

                                Line line = new Line();
                                BeanUtils.copyProperties(updateLineBO, line);
                                line.setId(updateLineBO.getLineIndex());
                                this.updateById(line);

                                LineDetail lineDetail = new LineDetail();
                                BeanUtils.copyProperties(updateLineBO, lineDetail);
                                lineDetail.setId(updateLineBO.getLineIndex());
                                //判断国网监测点id
                                if (StrUtil.isNotBlank(lineDetail.getMonitorId())) {
                                    lineDetail.setMonitorFlag(1);
                                } else {
                                    lineDetail.setMonitorFlag(0);
                                }
                                if (lineDetail.getPowerFlag() == 1) {
                                    //用户侧，objId不可为空
                                    if (StrUtil.isBlank(lineDetail.getObjId())) {
                                        throw new BusinessException(DeviceResponseEnum.LINE_USER_EMPTY);
                                    }
                                } else {
                                    if (StrUtil.isNotBlank(lineDetail.getObjId())) {
                                        throw new BusinessException(DeviceResponseEnum.LINE_NO_USER_EMPTY);
                                    }
                                }

                                lineDetailMapper.updateById(lineDetail);

                                Overlimit overlimitTem = overlimitMapper.selectById(lineId);
                                if ((!lineDetailRes.getDevCapacity().equals(lineDetail.getDevCapacity()))
                                        || ((!lineDetailRes.getShortCapacity().equals(lineDetail.getShortCapacity())))
                                        || ((!lineDetailRes.getDealCapacity().equals(lineDetail.getDealCapacity())))
                                        || ((!lineDetailRes.getStandardCapacity().equals(lineDetail.getStandardCapacity())))
                                        || ((!overlimitTem.getVoltageDev().equals(updateLineBO.getVoltageDev()))
                                        || ((!overlimitTem.getUvoltageDev().equals(updateLineBO.getUvoltageDev()))))

                                ) {
                                    //监测点限值
                                    DictData scaleResult = dicDataFeignClient.getDicDataById(updateSubVoltageParam.getScale()).getData();
                                    float scaTmp = Float.parseFloat(scaleResult.getValue());

                                    //监测点限值
                                    Overlimit overlimit = COverlimitUtil.globalAssemble(scaTmp, lineDetail.getDealCapacity(), lineDetail.getDevCapacity(), lineDetail.getShortCapacity(), lineDetail.getPowerFlag(), 0);
                                    if (Objects.isNull(updateLineBO.getVoltageDev())) {
                                        overlimit.setVoltageDev(overlimit.getVoltageDev());
                                    } else {
                                        overlimit.setVoltageDev(updateLineBO.getVoltageDev());
                                    }
                                    if (Objects.isNull(updateLineBO.getUvoltageDev())) {
                                        overlimit.setUvoltageDev(overlimit.getUvoltageDev());
                                    } else {
                                        overlimit.setUvoltageDev(updateLineBO.getUvoltageDev());
                                    }
                                    overlimit.setId(line.getId());
                                    overlimitMapper.deleteById(line.getId());
                                    overlimitMapper.insert(overlimit);
                                }
                                if (!Objects.equals(lineDetail.getCt1(), lineDetailRes.getCt1()) || !Objects.equals(lineDetail.getCt2(), lineDetailRes.getCt2())
                                        || !Objects.equals(lineDetail.getPt1(), lineDetailRes.getPt1()) || !Objects.equals(lineDetail.getPt2(), lineDetailRes.getPt2())
                                        || !Objects.equals(lineDetail.getDevCapacity(), lineDetailRes.getDevCapacity()) || !Objects.equals(lineDetail.getShortCapacity(), lineDetailRes.getShortCapacity())
                                        || !Objects.equals(lineDetail.getStandardCapacity(), lineDetailRes.getStandardCapacity()) || !Objects.equals(lineDetail.getDealCapacity(), lineDetailRes.getDealCapacity())
                                        || !Objects.equals(lineDetail.getPtType(), lineDetailRes.getPtType())) {
                                    //获取用户信息
                                    String index = RequestUtil.getUserIndex();
                                    queryUpdateAndInsertLog(userName, index, lineDetail, lineDetailRes);
                                }
                            }
                        }
                    }
                }
            }
            if (CollUtil.isNotEmpty(pqsTerminalLogsList)) {
                for (PqsTerminalLogs pqsTerminalLogs : pqsTerminalLogsList) {
                    pqsTerminalLogsMapper.insert(pqsTerminalLogs);
                }
            }

        }


        if (isSync) {
            /***
             * oracle http远程调用接口
             */
            SyncLedgerUpdate syncLedger = oracleSyncLedgerUpdate(updateTerminalParam, oldSubName, gbName);
            ResponseEntity<String> userEntity = RestTemplateUtil.post(updateUrl, syncLedger, String.class);
        }
        return true;
    }

    private void coderM3d(Device deviceDetail, Boolean updateFlag) {
        if (updateFlag) {
            Device deviceRes = deviceMapper.selectById(deviceDetail.getId());
            if (!Objects.equals(deviceRes.getDevKey(),deviceDetail.getDevKey())) {
                deviceDetail.setDevKey(DeviceUtil.encodeString(devCD, deviceDetail.getDevKey()));
            }
            if (!Objects.equals(deviceRes.getSeries(),deviceDetail.getSeries())) {
                deviceDetail.setSeries(DeviceUtil.encodeString(devCD, deviceDetail.getSeries()));
            }
        } else {
            if (StrUtil.isNotBlank(deviceDetail.getDevKey())) {
                deviceDetail.setDevKey(DeviceUtil.encodeString(devCD, deviceDetail.getDevKey()));
            }
            if (StrUtil.isNotBlank(deviceDetail.getSeries())) {
                deviceDetail.setSeries(DeviceUtil.encodeString(devCD, deviceDetail.getSeries()));
            }
        }
    }

    private void decoderM3d(Device deviceDetail) {
        if (StrUtil.isNotBlank(deviceDetail.getDevKey())) {
            deviceDetail.setDevKey(DeviceUtil.decoderString(devCD, deviceDetail.getDevKey()));
        }
        if (StrUtil.isNotBlank(deviceDetail.getSeries())) {
            deviceDetail.setSeries(DeviceUtil.decoderString(devCD, deviceDetail.getSeries()));
        }
    }

    /**
     * 查询监测点信息修改处,并新增日志
     *
     * @param userName
     * @param newLine
     * @param oldLine
     * @return
     */
    @Async
    public void queryUpdateAndInsertLog(String userName, String index, LineDetail newLine, LineDetail oldLine) {
        SuperDataParam superDataParam = superDataMapper.getPointSuper(newLine.getId());
        StringBuilder sb = new StringBuilder();
        sb.append(userName).append("修改了").append(superDataParam.getUrbanName()).append(" - ")
                .append(superDataParam.getSubName()).append(" - ").append(superDataParam.getDevName()).append(" - ").append(superDataParam.getPName())
                .append(" - ").append(superDataParam.getMName()).append(" - 监测点的参数;");
        StringBuilder sbNew = new StringBuilder();
        StringBuilder sbOld = new StringBuilder();
        sbNew.append("操作历史,");
        sbOld.append("修改后参数,");
        //pt变化
        if (!Objects.equals(newLine.getPt1(), oldLine.getPt1()) || !Objects.equals(newLine.getPt2(), oldLine.getPt2())) {
            sbNew.append("pt变比: ").append(newLine.getPt1()).append(" : ").append(newLine.getPt2()).append(";");
            sbOld.append("pt变比: ").append(oldLine.getPt1()).append(" : ").append(oldLine.getPt2()).append(";");
        }
        //ct变化
        if (!Objects.equals(newLine.getCt1(), oldLine.getCt1()) || !Objects.equals(newLine.getCt2(), oldLine.getCt2())) {
            sbNew.append("ct变比: ").append(newLine.getCt1()).append(" : ").append(newLine.getCt2()).append(";");
            sbOld.append("ct变比: ").append(oldLine.getCt1()).append(" : ").append(oldLine.getCt2()).append(";");
        }
        //设备容量
        if (!Objects.equals(newLine.getDevCapacity(), oldLine.getDevCapacity())) {
            sbNew.append("设备容量: ").append(newLine.getDevCapacity()).append(";");
            sbOld.append("设备容量: ").append(oldLine.getDevCapacity()).append(";");
        }
        //短路容量
        if (!Objects.equals(newLine.getShortCapacity(), oldLine.getShortCapacity())) {
            sbNew.append("短路容量: ").append(newLine.getShortCapacity()).append(";");
            sbOld.append("短路容量: ").append(oldLine.getShortCapacity()).append(";");
        }
        //基准容量
        if (!Objects.equals(newLine.getStandardCapacity(), oldLine.getStandardCapacity())) {
            sbNew.append("基准容量: ").append(newLine.getStandardCapacity()).append(";");
            sbOld.append("基准容量: ").append(oldLine.getStandardCapacity()).append(";");
        }
        //协议容量
        if (!Objects.equals(newLine.getDealCapacity(), oldLine.getDealCapacity())) {
            sbNew.append("协议容量: ").append(newLine.getDealCapacity()).append(";");
            sbOld.append("协议容量: ").append(oldLine.getDealCapacity()).append(";");
        }
        //接线方式
        if (!Objects.equals(newLine.getPtType(), oldLine.getPtType())) {
            sbNew.append("接线方式: ").append(newLine.getPtType()).append(";");
            sbOld.append("接线方式: ").append(oldLine.getPtType()).append(";");
        }
        sb.append(sbNew).append(sbOld);
        HttpResult<DictData> dicDataByCode = dicDataFeignClient.getDicDataByCode(DicDataEnum.LINE_PARAMETER.getCode());
        DictData data = dicDataByCode.getData();
        //创建对象
        PqsTerminalLogs terminalLogsNew = new PqsTerminalLogs();
        terminalLogsNew.setObjIndex(newLine.getId());
        terminalLogsNew.setTerminalDescribe(sb.toString());
        terminalLogsNew.setTerminalType(LineBaseEnum.LINE_LEVEL.getCode());
        terminalLogsNew.setLogsType(data.getId());
        terminalLogsNew.setState(DataStateEnum.ENABLE.getCode());
        terminalLogsNew.setIsPush(0);
        terminalLogsNew.setOperateType(Param.UPDATE);
        pqsTerminalLogsMapper.insert(terminalLogsNew);
    }

    /**
     * 终端查询操作
     *
     * @param id pq_line表 id
     * @author cdf
     * @date 2021/7/19
     */
    @Override
    public TerminalVO queryTerminal(String id, Integer level) {
        Line obj;
        if (level == 700) {
            obj = new Line();
            UserLedgerVO userLedgerVO = userLedgerService.selectUserInfo(id);
            if (Objects.nonNull(userLedgerVO)) {
                obj.setId(userLedgerVO.getId());
                obj.setLevel(LineBaseEnum.USER_LEVEL.getCode());
                obj.setPid(userLedgerVO.getStationId());
            }
        } else {
            obj = this.getById(id);
        }

        if (Objects.isNull(obj)) {
            throw new BusinessException(CommonResponseEnum.FAIL);
        }
        LambdaQueryWrapper<Line> lineLambdaQueryWrapper = new LambdaQueryWrapper<>();
        TerminalVO terminalVO = new TerminalVO();
        if (obj.getLevel().equals(PROJECT_LEVEL.getCode())) {
            //点击项目节点
            assProject(obj, terminalVO);
        } else if (obj.getLevel().equals(PROVINCE_LEVEL.getCode())) {
            //点击省份节点
            Line project = this.getById(obj.getPid());
            assProject(project, terminalVO);
            assProvince(obj, terminalVO);
        } else if (obj.getLevel().equals(GD_LEVEL.getCode())) {
            //点击供电公司节点
            assGd(obj, terminalVO);
            Line province = this.getById(obj.getPid());
            assProvince(province, terminalVO);
            Line project = this.getById(province.getPid());
            assProject(project, terminalVO);
        } else if (obj.getLevel().equals(LineBaseEnum.SUB_LEVEL.getCode())) {
            //变电站
            assSub(obj, terminalVO);
            Line gdInformation = this.getById(obj.getPid());
            assGd(gdInformation, terminalVO);

            Line province = this.getById(gdInformation.getPid());
            assProvince(province, terminalVO);

            Line project = this.getById(province.getPid());
            assProject(project, terminalVO);


            //展示所有下级装置母线监测点
            lineLambdaQueryWrapper.clear();
            lineLambdaQueryWrapper.eq(Line::getPid, id)
                    .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                    .orderByAsc(Line::getSort);
            List<Line> devList = this.list(lineLambdaQueryWrapper);
            List<DeviceVO> deviceDTOList = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(devList)) {
                for (Line device : devList) {
                    DeviceVO deviceVO = new DeviceVO();
                    BeanUtils.copyProperties(device, deviceVO);


                    Device deviceDetail = deviceMapper.selectById(device.getId());
                    //解密
                    //decoderM3d(deviceDetail);
                    BeanUtils.copyProperties(deviceDetail, deviceVO);
                    deviceVO.setDevIndex(device.getId());
                    //母线
                    lineLambdaQueryWrapper.clear();
                    lineLambdaQueryWrapper.eq(Line::getPid, device.getId())
                            .orderByAsc(Line::getSort)
                            .eq(Line::getState, DataStateEnum.ENABLE.getCode());

                    List<Line> subVoltageList = this.list(lineLambdaQueryWrapper);
                    if (CollectionUtil.isNotEmpty(subVoltageList)) {
                        List<SubVoltageVO> subVoltageVOS = new ArrayList<>();
                        for (Line subVoltage : subVoltageList) {
                            SubVoltageVO subVoltageVO = new SubVoltageVO();
                            BeanUtils.copyProperties(subVoltage, subVoltageVO);

                            Voltage voltage = voltageMapper.selectById(subVoltage.getId());
                            BeanUtils.copyProperties(voltage, subVoltageVO);
                            subVoltageVO.setSubvIndex(subVoltage.getId());
                            //监测点
                            lineLambdaQueryWrapper.clear();
                            lineLambdaQueryWrapper.eq(Line::getPid, subVoltage.getId())
                                    .eq(Line::getState, DataStateEnum.ENABLE.getCode());
                            List<Line> lineList = this.list(lineLambdaQueryWrapper);
                            if (CollectionUtil.isNotEmpty(lineList)) {
                                List<LineVO> lineVOS = new ArrayList<>();
                                for (Line line : lineList) {
                                    LineVO lineVO = new LineVO();
                                    BeanUtils.copyProperties(line, lineVO);
                                    LineDetail lineDetail = lineDetailMapper.selectById(line.getId());
                                    BeanUtils.copyProperties(lineDetail, lineVO);

                                    Overlimit overLimit = overlimitMapper.selectById(line.getId());
                                    lineVO.setVoltageDev(overLimit.getVoltageDev());
                                    lineVO.setUvoltageDev(overLimit.getUvoltageDev());
                                    lineVO.setLineIndex(line.getId());
                                    lineVOS.add(lineVO);
                                }
                                subVoltageVO.setLineVO(lineVOS);
                            }

                            subVoltageVOS.add(subVoltageVO);
                        }
                        deviceVO.setSubVoltageVOList(subVoltageVOS);
                    }
                    deviceDTOList.add(deviceVO);
                }
            }
            terminalVO.setDeviceVO(deviceDTOList);

        } else if (obj.getLevel().equals(LineBaseEnum.USER_LEVEL.getCode())) {
            //点击用户节点

            //查询所有子级装置
            LambdaQueryWrapper<LineDetail> detailLambdaQueryWrapper = new LambdaQueryWrapper<>();
            detailLambdaQueryWrapper.eq(LineDetail::getObjId, id);
            List<LineDetail> lineDetailList = lineDetailMapper.selectList(detailLambdaQueryWrapper);
            List<String> ids = lineDetailList.stream().map(LineDetail::getId).distinct().collect(Collectors.toList());

            lineLambdaQueryWrapper.clear();
            lineLambdaQueryWrapper.in(Line::getId, ids)
                    .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                    .orderByAsc(Line::getSort);
            List<Line> temLineList = this.list(lineLambdaQueryWrapper);
            List<String> devIds = temLineList.stream().map(it -> it.getPids().split(StrUtil.COMMA)[4]).collect(Collectors.toList());

            lineLambdaQueryWrapper.clear();
            lineLambdaQueryWrapper.in(Line::getId, devIds)
                    .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                    .orderByAsc(Line::getSort);
            List<Line> devList = this.list(lineLambdaQueryWrapper);

            List<DeviceVO> deviceDTOList = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(devList)) {
                for (Line device : devList) {
                    DeviceVO deviceVO = new DeviceVO();
                    BeanUtils.copyProperties(device, deviceVO);


                    Device deviceDetail = deviceMapper.selectById(device.getId());
                    //解密
                    //decoderM3d(deviceDetail);
                    BeanUtils.copyProperties(deviceDetail, deviceVO);
                    deviceVO.setDevIndex(device.getId());
                    //母线
                    lineLambdaQueryWrapper.clear();
                    lineLambdaQueryWrapper.eq(Line::getPid, device.getId())
                            .orderByAsc(Line::getSort)
                            .eq(Line::getState, DataStateEnum.ENABLE.getCode());

                    List<Line> subVoltageList = this.list(lineLambdaQueryWrapper);
                    if (CollectionUtil.isNotEmpty(subVoltageList)) {
                        List<SubVoltageVO> subVoltageVOS = new ArrayList<>();
                        for (Line subVoltage : subVoltageList) {
                            SubVoltageVO subVoltageVO = new SubVoltageVO();
                            BeanUtils.copyProperties(subVoltage, subVoltageVO);

                            Voltage voltage = voltageMapper.selectById(subVoltage.getId());
                            BeanUtils.copyProperties(voltage, subVoltageVO);
                            subVoltageVO.setSubvIndex(subVoltage.getId());
                            //监测点
                            lineLambdaQueryWrapper.clear();
                            lineLambdaQueryWrapper.eq(Line::getPid, subVoltage.getId())
                                    .eq(Line::getState, DataStateEnum.ENABLE.getCode());
                            List<Line> lineList = this.list(lineLambdaQueryWrapper);
                            if (CollectionUtil.isNotEmpty(lineList)) {
                                List<LineVO> lineVOS = new ArrayList<>();
                                for (Line line : lineList) {
                                    LineVO lineVO = new LineVO();
                                    BeanUtils.copyProperties(line, lineVO);
                                    LineDetail lineDetail = lineDetailMapper.selectById(line.getId());
                                    BeanUtils.copyProperties(lineDetail, lineVO);

                                    Overlimit overLimit = overlimitMapper.selectById(line.getId());
                                    lineVO.setVoltageDev(overLimit.getVoltageDev());
                                    lineVO.setUvoltageDev(overLimit.getUvoltageDev());
                                    lineVO.setLineIndex(line.getId());
                                    lineVOS.add(lineVO);
                                }
                                subVoltageVO.setLineVO(lineVOS);
                            }

                            subVoltageVOS.add(subVoltageVO);
                        }
                        deviceVO.setSubVoltageVOList(subVoltageVOS);
                    }
                    deviceDTOList.add(deviceVO);
                }
            }
            terminalVO.setDeviceVO(deviceDTOList);

            commTerminalValue(terminalVO, obj.getPid());

        } else if (obj.getLevel().equals(LineBaseEnum.DEVICE_LEVEL.getCode())) {
            //点击装置节点

            List<DeviceVO> deviceList = new ArrayList<>();
            DeviceVO deviceVO = new DeviceVO();
            deviceVO.setName(obj.getName());
            deviceVO.setSort(obj.getSort());

            Device deviceDetail = deviceMapper.selectById(obj.getId());
            //解密
            //decoderM3d(deviceDetail);
            BeanUtils.copyProperties(deviceDetail, deviceVO);
            deviceVO.setDevIndex(obj.getId());
//            DeviceProcess deviceProcess = deviceProcessService.lambdaQuery().eq(DeviceProcess::getId, obj.getId()).one();
//            if(Objects.nonNull(deviceProcess)){
//                deviceVO.setProcessNum(deviceProcess.getProcessNo());
//            }

            lineLambdaQueryWrapper.clear();
            lineLambdaQueryWrapper.eq(Line::getPid, obj.getId())
                    .orderByAsc(Line::getSort)
                    .eq(Line::getState, DataStateEnum.ENABLE.getCode());
            List<Line> subvList = this.list(lineLambdaQueryWrapper);

            if (CollectionUtil.isNotEmpty(subvList)) {
                List<SubVoltageVO> subVList = new ArrayList<>();
                for (Line subVoltage : subvList) {

                    SubVoltageVO subVoltageVO = new SubVoltageVO();
                    BeanUtils.copyProperties(subVoltage, subVoltageVO);

                    Voltage voltage = voltageMapper.selectById(subVoltage.getId());
                    BeanUtils.copyProperties(voltage, subVoltageVO);
                    subVoltageVO.setSubvIndex(subVoltage.getId());

                    lineLambdaQueryWrapper.clear();
                    lineLambdaQueryWrapper.eq(Line::getPid, subVoltage.getId())
                            .orderByAsc(Line::getSort)
                            .eq(Line::getState, DataStateEnum.ENABLE.getCode());
                    List<Line> lineList = this.list(lineLambdaQueryWrapper);
                    if (CollectionUtil.isNotEmpty(lineList)) {
                        List<LineVO> lineVOList = new ArrayList<>();
                        for (Line line : lineList) {
                            LineVO lineVO = new LineVO();
                            BeanUtils.copyProperties(line, lineVO);

                            LineDetail lineDetail = lineDetailMapper.selectById(line.getId());
                            BeanUtils.copyProperties(lineDetail, lineVO);
                            lineVO.setLineIndex(line.getId());

                            Overlimit overLimit = overlimitMapper.selectById(line.getId());
                            lineVO.setVoltageDev(overLimit.getVoltageDev());
                            lineVO.setUvoltageDev(overLimit.getUvoltageDev());
                            lineVOList.add(lineVO);
                        }
                        subVoltageVO.setLineVO(lineVOList);
                    }

                    subVList.add(subVoltageVO);

                }
                deviceVO.setSubVoltageVOList(subVList);
            }
            deviceList.add(deviceVO);
            terminalVO.setDeviceVO(deviceList);

            commTerminalValue(terminalVO, obj.getPid());

        } else if (obj.getLevel().equals(LineBaseEnum.SUB_V_LEVEL.getCode())) {
            //点击母线节点
            SubVoltageVO subVoltageVO = new SubVoltageVO();
            subVoltageVO.setName(obj.getName());
            subVoltageVO.setSort(obj.getSort());
            Voltage voltage = voltageMapper.selectById(obj.getId());
            BeanUtils.copyProperties(voltage, subVoltageVO);
            subVoltageVO.setSubvIndex(obj.getId());

            lineLambdaQueryWrapper.clear();
            lineLambdaQueryWrapper.eq(Line::getPid, obj.getId())
                    .orderByAsc(Line::getSort)
                    .eq(Line::getState, DataStateEnum.ENABLE.getCode());
            List<Line> lineList = this.list(lineLambdaQueryWrapper);
            if (CollectionUtil.isNotEmpty(lineList)) {
                List<LineVO> lineVOS = new ArrayList<>();
                for (Line line : lineList) {
                    LineVO lineVO = new LineVO();
                    lineVO.setName(line.getName());
                    lineVO.setSort(line.getSort());
                    LineDetail lineDetail = lineDetailMapper.selectById(line.getId());
                    BeanUtils.copyProperties(lineDetail, lineVO);
                    lineVO.setLineIndex(line.getId());

                    Overlimit overlimit = overlimitMapper.selectById(line.getId());
                    lineVO.setVoltageDev(overlimit.getVoltageDev());
                    lineVO.setUvoltageDev(overlimit.getUvoltageDev());
                    lineVOS.add(lineVO);
                }
                subVoltageVO.setLineVO(lineVOS);
            }
            List<SubVoltageVO> subvList = new ArrayList<>();
            subvList.add(subVoltageVO);

            Line device = this.getById(obj.getPid());
            List<DeviceVO> deviceVOList = new ArrayList<>();
            if (Objects.nonNull(device)) {
                DeviceVO deviceVO = new DeviceVO();
                deviceVO.setName(device.getName());
                deviceVO.setSort(device.getSort());
                Device deviceDetail = deviceMapper.selectById(device.getId());
                //解密
                //decoderM3d(deviceDetail);
                BeanUtils.copyProperties(deviceDetail, deviceVO);
                deviceVO.setDevIndex(device.getId());
//                DeviceProcess deviceProcess = deviceProcessService.lambdaQuery().eq(DeviceProcess::getId, device.getId()).one();
//                if(Objects.nonNull(deviceProcess)){
//                    deviceVO.setProcessNum(deviceProcess.getProcessNo());
//                }


                deviceVO.setSubVoltageVOList(subvList);
                deviceVOList.add(deviceVO);
                terminalVO.setDeviceVO(deviceVOList);

                commTerminalValue(terminalVO, device.getPid());

            }


        } else if (obj.getLevel().equals(LineBaseEnum.LINE_LEVEL.getCode())) {

            //点击监测点
            DeviceVO deviceVO = new DeviceVO();

            LineVO lineVO = new LineVO();
            BeanUtils.copyProperties(obj, lineVO);
            LineDetail lineDetail = lineDetailMapper.selectById(id);
            if (Objects.nonNull(lineDetail)) {
                List<LineVO> lineVOS = new ArrayList<>();

                BeanUtils.copyProperties(lineDetail, lineVO);
                lineVO.setLineIndex(obj.getId());
                Overlimit overlimit = overlimitMapper.selectById(obj.getId());
                lineVO.setVoltageDev(overlimit.getVoltageDev());
                lineVO.setUvoltageDev(overlimit.getUvoltageDev());

                lineVOS.add(lineVO);

                Line subVoltage = this.getById(obj.getPid());
                if (Objects.nonNull(subVoltage)) {
                    List<SubVoltageVO> subVoltageVOS = new ArrayList<>();
                    SubVoltageVO subVoltageVO = new SubVoltageVO();
                    BeanUtils.copyProperties(subVoltage, subVoltageVO);
                    Voltage voltage = voltageMapper.selectById(subVoltage.getId());
                    subVoltageVO.setSubvIndex(subVoltage.getId());
                    BeanUtils.copyProperties(voltage, subVoltageVO);
                    subVoltageVO.setLineVO(lineVOS);
                    subVoltageVOS.add(subVoltageVO);


                    Line device = this.getById(subVoltage.getPid());
                    List<DeviceVO> deviceVOList = new ArrayList<>();
                    if (Objects.nonNull(device)) {
                        BeanUtils.copyProperties(device, deviceVO);

                        Device deviceDetail = deviceMapper.selectById(device.getId());
                        //解密
                        //decoderM3d(deviceDetail);
                        BeanUtils.copyProperties(deviceDetail, deviceVO);
                        deviceVO.setDevIndex(device.getId());
//                        DeviceProcess deviceProcess = deviceProcessService.lambdaQuery().eq(DeviceProcess::getId, device.getId()).one();
//                        if(Objects.nonNull(deviceProcess)){
//                            deviceVO.setProcessNum(deviceProcess.getProcessNo());
//                        }


                        deviceVO.setSubVoltageVOList(subVoltageVOS);
                        deviceVOList.add(deviceVO);
                        terminalVO.setDeviceVO(deviceVOList);
                        //公共操作
                        commTerminalValue(terminalVO, device.getPid());
                    }


                }

            }

        }

        return terminalVO;

    }

    @Override
    public Line queryTerminalByName(String devName) {
        Line one = this.lambdaQuery().eq(Line::getName, devName).one();
        return one;
    }


    private void deleteProjectAndChildren(Line project, List<Line> ledgerList, List<PqsTerminalLogs> logsList, Map<String, Node> nodeMap) {
        // 1. 删除项目本身
        this.removeById(project.getId());

        // 2. 查询并删除所有省份
        List<Line> provinces = findChildren(project.getId());
        if (CollectionUtil.isEmpty(provinces)) {
            return;
        }

        List<String> provinceIds = provinces.stream()
                .map(Line::getId)
                .collect(Collectors.toList());

        this.removeByIds(provinceIds);

        // 3. 对每个省份删除其下级
        provinceIds.forEach(it -> deleteProvinceAndChildren(it, ledgerList, logsList, nodeMap));
    }

    private void deleteProvinceAndChildren(String provinceId, List<Line> ledgerList, List<PqsTerminalLogs> logsList, Map<String, Node> nodeMap) {
        this.removeById(provinceId);

        // 1. 查询并删除所有供电公司
        List<Line> powerCompanies = findChildren(provinceId);
        if (CollectionUtil.isEmpty(powerCompanies)) {
            return;
        }

        List<String> companyIds = powerCompanies.stream()
                .map(Line::getId)
                .collect(Collectors.toList());

        this.removeByIds(companyIds);

        // 2. 对每个供电公司删除其下级
        companyIds.forEach(it -> deletePowerCompanyAndChildren(it, ledgerList, logsList, nodeMap));
    }

    private void deletePowerCompanyAndChildren(String companyId, List<Line> ledgerList, List<PqsTerminalLogs> logsList, Map<String, Node> nodeMap) {
        this.removeById(companyId);
        // 1. 查询并删除所有变电站
        List<Line> substations = findChildren(companyId);
        if (CollectionUtil.isEmpty(substations)) {
            return;
        }
        ledgerList.addAll(substations);

        List<String> substationIds = substations.stream()
                .map(Line::getId)
                .collect(Collectors.toList());


        this.removeByIds(substationIds);
        substationMapper.deleteBatchIds(substationIds);

        // 2. 对每个变电站删除其下级
        substationIds.forEach(it -> deleteSubstationAndChildren(it, ledgerList, logsList, nodeMap));
    }

    private void deleteSubstationAndChildren(String substationId, List<Line> ledgerList, List<PqsTerminalLogs> logsList, Map<String, Node> nodeMap) {
        this.removeById(substationId);
        substationMapper.deleteById(substationId);
        // 1. 查询并删除所有装置
        List<Line> devices = findChildren(substationId);
        if (CollectionUtil.isEmpty(devices)) {
            return;
        }
        ledgerList.addAll(devices);


        List<String> deviceIds = devices.stream()
                .map(Line::getId)
                .collect(Collectors.toList());

        // 2. 对每个装置删除其下级
        deviceIds.forEach(it -> deleteDeviceAndChildren(it, ledgerList, logsList, nodeMap));
    }

    private void deleteDeviceAndChildren(String deviceId, List<Line> ledgerList, List<PqsTerminalLogs> logsList, Map<String, Node> nodeMap) {
        Device device = deviceMapper.selectById(deviceId);
        Node node = nodeService.getNodeById(device.getNodeId());
        nodeMap.put(device.getId(), node);

        this.removeById(deviceId);
        deviceMapper.deleteById(deviceId);
        devFuctionMapper.delete(new LambdaQueryWrapper<DevFuction>().eq(DevFuction::getLineId, deviceId));

        // 1. 查询并删除所有母线
        List<Line> busbars = findChildren(deviceId);
        if (CollectionUtil.isEmpty(busbars)) {
            return;
        }
        List<String> busbarIds = busbars.stream()
                .map(Line::getId)
                .collect(Collectors.toList());
        this.removeByIds(busbarIds);
        voltageMapper.deleteBatchIds(busbarIds);

        // 2. 对每条母线删除其下级
        busbarIds.forEach(it -> deleteBusbarAndChildren(it, ledgerList, logsList));

    }

    private void deleteBusbarAndChildren(String busbarId, List<Line> ledgerList, List<PqsTerminalLogs> logsList) {
        this.removeById(busbarId);
        voltageMapper.deleteById(busbarId);
        // 1. 查询并删除所有监测点
        List<Line> monitoringPoints = findChildren(busbarId);
        if (CollectionUtil.isEmpty(monitoringPoints)) {
            return;
        }
        ledgerList.addAll(monitoringPoints);

        List<String> pointIds = monitoringPoints.stream()
                .map(Line::getId)
                .collect(Collectors.toList());
        deleteMonitoringPoints(pointIds);
    }

    private void deleteMonitoringPoints(List<String> pointIds) {
        this.removeByIds(pointIds);
        lineDetailMapper.deleteBatchIds(pointIds);
        overlimitMapper.deleteBatchIds(pointIds);
        LambdaQueryWrapper<DeptLine> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(DeptLine::getLineId, pointIds);
        deptLineMapper.delete(wrapper);
    }

    private void deleteMonitoringPoint(String pointId) {
        this.removeById(pointId);
        lineDetailMapper.deleteById(pointId);
        overlimitMapper.deleteById(pointId);
        deptLineMapper.deleteById(pointId);
    }

    private List<Line> findChildren(String pid) {
        LambdaQueryWrapper<Line> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Line::getPid, pid)
                .eq(Line::getState, DataStateEnum.ENABLE.getCode());
        return this.list(wrapper);
    }

    private void syncToExternalSystem(Line obj) {
        SyncLedgerDelete delete = oracleSyncLedgerDelete(obj);
        RestTemplateUtil.post(urlDelete, delete, String.class);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delTerminal(String id) {
        //存放所有需要记录日志的台账信息
        List<Line> logsLedger = new ArrayList<>();
        //用于存放最终日志信息
        List<PqsTerminalLogs> allLogs = new ArrayList<>();
        //用于记录删除终端的前置信息
        Map<String, Node> nodeMap = new HashMap<>();
        Line obj = this.getById(id);
        if (Objects.isNull(obj)) {
            throw new BusinessException(CommonResponseEnum.FAIL);
        }
        logsLedger.add(obj);
        LineBaseEnum lineBaseEnum = LineBaseEnum.getLineBaseEnumByCode(obj.getLevel());
        // 根据层级选择删除策略
        switch (lineBaseEnum) {
            case PROJECT_LEVEL:
                deleteProjectAndChildren(obj, logsLedger, allLogs, nodeMap);
                break;
            case PROVINCE_LEVEL:
                deleteProvinceAndChildren(obj.getId(), logsLedger, allLogs, nodeMap);
                break;
            case GD_LEVEL:
                deletePowerCompanyAndChildren(obj.getId(), logsLedger, allLogs, nodeMap);
                break;
            case SUB_LEVEL:
                deleteSubstationAndChildren(obj.getId(), logsLedger, allLogs, nodeMap);
                break;
            case DEVICE_LEVEL:
                Line sub = this.getById(obj.getPid());
                logsLedger.add(sub);
                deleteDeviceAndChildren(obj.getId(), logsLedger, allLogs, nodeMap);
                break;
            case SUB_V_LEVEL:
                Line subTwo = this.getById(obj.getPids().split(StrUtil.COMMA)[SUB_LEVEL.getCode()]);
                logsLedger.add(subTwo);
                deleteBusbarAndChildren(obj.getId(), logsLedger, allLogs);
                break;
            case LINE_LEVEL:
                Line subThree = this.getById(obj.getPids().split(StrUtil.COMMA)[SUB_LEVEL.getCode()]);
                logsLedger.add(subThree);
                deleteMonitoringPoint(obj.getId());
                break;
            default:
                throw new BusinessException(CommonResponseEnum.FAIL);
        }
        if (CollUtil.isNotEmpty(logsLedger)) {
            terminalLogsCat(logsLedger, Param.DEL, allLogs, nodeMap);
            for (PqsTerminalLogs pqsTerminalLogs : allLogs) {
                pqsTerminalLogsMapper.insert(pqsTerminalLogs);
            }
        }
        return true;
    }

    @Override
    public List<Line> getSubstationByIds(List<String> substationIds, List<String> scale) {
        return this.baseMapper.getSubStations(substationIds, scale);
    }

    @Override
    public List<Line> getLineById(List<String> lineIds) {
        return this.lambdaQuery()
                .in(!CollectionUtils.isEmpty(lineIds), Line::getId, lineIds)
                .eq(Line::getLevel, 6)
                .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                .list();
    }

    @Deprecated
    @Override
    public List<Line> getDeviceById(List<String> devIds, DeviceType deviceType) {
        return this.baseMapper.getDeviceById(devIds, deviceType);
    }

    @Override
    public List<TerminalBaseVO> getDeviceByIdOnOrOff(List<String> devIds, DeviceType deviceType, Integer comFlag) {
        List<TerminalBaseVO> deviceByIdOnOrOff = this.baseMapper.getDeviceByIdOnOrOff(devIds, deviceType, comFlag);
        if (CollUtil.isNotEmpty(deviceByIdOnOrOff)) {
            List<DictData> devTypeDic = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_TYPE.getCode()).getData();
            Map<String, String> devTypeDicMap = devTypeDic.stream().collect(Collectors.toMap(DictData::getId, DictData::getName));
            for (TerminalBaseVO terminalBaseVO : deviceByIdOnOrOff) {
                if (devTypeDicMap.containsKey(terminalBaseVO.getDevType())) {
                    terminalBaseVO.setDevType(devTypeDicMap.get(terminalBaseVO.getDevType()));
                }
            }
        }
        return deviceByIdOnOrOff;
    }


    @Override
    public List<Line> getSubstationById(List<String> list) {
        return this.lambdaQuery().in(Line::getId, list).list();
    }

    @Override
    public List<Line> getLineByCondition(List<String> ids, DeviceInfoParam deviceInfoParam) {
        if(StrUtil.isNotBlank(deviceInfoParam.getSearchValue())){
            return this.baseMapper.getLineByConditionBySearchValue(ids, deviceInfoParam);
        }
        return this.baseMapper.getLineByCondition(ids, deviceInfoParam);
    }

    @Override
    public List<Line> getDeviceByCondition(List<String> devIds, DeviceType deviceType, DeviceInfoParam manufacturer) {
        return this.baseMapper.getDeviceByCondition(devIds, deviceType, manufacturer);
    }

    @Override
    public List<Line> getVoltageByCondition(List<String> voltageIds, List<SimpleDTO> scale) {
        return this.baseMapper.getVoltageByCondition(voltageIds, scale);
    }

    @Override
    public List<Line> getSubByCondition(List<String> subIds, List<SimpleDTO> scale) {
        return this.baseMapper.getSubByCondition(subIds, scale);
    }

    @Override
    public List<String> getVoltageIdByScale(List<String> voltageIds, String scale) {
        return this.baseMapper.getVoltageIdByScale(voltageIds, scale);
    }

    @Override
    public List<String> getSubIdByScale(List<String> subIds, String scale) {
        return this.baseMapper.getSubIdByScale(subIds, scale);
    }

    @Override
    public List<String> getLineIdByLoadType(List<String> lineIds, String loadType) {
        return this.baseMapper.getLineIdByLoadType(lineIds, loadType);
    }

    @Override
    public List<String> getDeviceIdByManufacturer(List<String> deviceIds, String manufacturer) {
        return this.baseMapper.getDeviceIdByManufacturer(deviceIds, manufacturer);
    }

    @Override
    public List<String> getDeviceIdByPowerFlag(List<String> lineIds, Integer manufacturer) {
        return this.baseMapper.getDeviceIdByPowerFlag(lineIds, manufacturer);
    }

    @Override
    public List<String> getDeviceIdByJbPowerFlag(List<String> lineIds, Integer powerFlag) {
        return this.baseMapper.getDeviceIdByJbPowerFlag(lineIds, powerFlag);
    }

    @Override
    public List<BaseLineInfo> getBaseLineInfo(List<String> lineIndex) {
        return this.baseMapper.getBaseLineInfo(lineIndex);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importOracleTerminalData(MultipartFile file, HttpServletResponse response) {
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        params.setTitleRows(1);
        params.setNeedVerify(true);
        //第一个sheet为台账信息
        params.setStartSheetIndex(0);
        params.setSheetNum(1);
        try {
            ExcelImportResult<OracleTerminalExcel> terminalExcelExcelImportResult = ExcelImportUtil.importExcelMore(file.getInputStream(), OracleTerminalExcel.class, params);
            //第二个sheet为前置信息
            params.setStartSheetIndex(1);
            ExcelImportResult<NodeExcel> nodeExcelExcelImportResult = ExcelImportUtil.importExcelMore(file.getInputStream(), NodeExcel.class, params);
            //第三个sheet为限值信息
            params.setStartSheetIndex(2);
            ExcelImportResult<OverLimitExcel> overLimitExcelExcelImportResult = ExcelImportUtil.importExcelMore(file.getInputStream(), OverLimitExcel.class, params);
            //如果存在非法数据，将不合格的数据导出
            if (terminalExcelExcelImportResult.isVerifyFail()) {
                PoiUtil.exportFileByWorkbook(terminalExcelExcelImportResult.getFailWorkbook(), "非法台账信息.xlsx", response);
            } else {
                //执行前置机信息导入
                nodeService.saveBatchNodeInfo(nodeExcelExcelImportResult.getList());
                //执行台账信息导入（不考虑，存在监测点却不存在限值信息）
                return saveTerminalInfo(terminalExcelExcelImportResult.getList(), overLimitExcelExcelImportResult.getList());
            }
        } catch (Exception e) {
            throw new BusinessException(DeviceResponseEnum.IMPORT_ORACLE_EXCEPTION);
        }
        return null;
    }

    @Override
    public List<TerminalBaseExcel> exportTerminalBase() {
        return this.baseMapper.getTerminalBaseExcel();
    }

    @Override
    public void downTerminalTemplate(HttpServletResponse response) {
        ExportParams exportParams = new ExportParams("批量导入模板（请严格按照模板标准填入数据）", "台账信息");
        exportParams.setStyle(ExcelStyleUtil.class);
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, TerminalBaseExcel.class, new ArrayList<TerminalBaseExcel>());
        List<DictData> businessList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.BUSINESS_TYPE.getName()).getData();
        List<DictData> loadTypeList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName()).getData();
        List<DictData> manufacturerList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_MANUFACTURER.getName()).getData();
//        List<DictData> devTypeList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_TYPE.getName()).getData();
        List<PqDevType> devTypeList = pqDevTypeService.list(new LambdaQueryWrapper<PqDevType>()
                        .eq(PqDevType::getState, DataStateEnum.ENABLE.getCode())
                        .orderByDesc(PqDevType::getCreateTime));
        List<DictData> frontList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.FRONT_TYPE.getName()).getData();
        List<DictData> scaleList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_VOLTAGE_STAND.getName()).getData();
        List<UserLedgerVO> userLedgerVOS = userLedgerService.selectUserList(new UserReportParam());
        List<Node> nodeList = nodeService.nodeAllList();

        ExcelUtil.selectList(workbook, 4, 4, scaleList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 40, 40, userLedgerVOS.stream().map(UserLedgerVO::getProjectName).collect(Collectors.toList()).toArray(new String[]{}));

        //这里是自己加的 带下拉框的代码
        ExcelUtil.selectList(workbook, 8, 8, new String[]{"虚拟设备", "实际设备", "离线设备"});
        ExcelUtil.selectList(workbook, 9, 9, new String[]{"暂态系统", "稳态系统", "双系统"});
        ExcelUtil.selectList(workbook, 10, 10, new String[]{"投运", "热备用", "停运"});
        ExcelUtil.selectList(workbook, 11, 11, manufacturerList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 12, 12, devTypeList.stream().map(PqDevType::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 17, 17, new String[]{"周期触发", "变为触发"});
        ExcelUtil.selectList(workbook, 18, 18, nodeList.stream().map(Node::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 19, 19, frontList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));

        /*母线序号*/
        ExcelUtil.selectList(workbook, 23, 23, new String[]{"1", "2", "3", "3", "4", "5", "6"});
        ExcelUtil.selectList(workbook, 24, 24, scaleList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 25, 25, new String[]{"虚拟母线", "实际母线"});
        ExcelUtil.selectList(workbook, 27, 27, new String[]{"1", "2", "3", "3", "4", "5", "6"});
        ExcelUtil.selectList(workbook, 28, 28, new String[]{"极重要", "重要", "普通", "不重要"});
        ExcelUtil.selectList(workbook, 35, 35, new String[]{"星型接法", "三角型接法", "开口三角型接法"});
        ExcelUtil.selectList(workbook, 36, 36, new String[]{"3", "5", "10"});
        ExcelUtil.selectList(workbook, 37, 37, loadTypeList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 38, 38, businessList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 41, 41, new String[]{"电网侧", "非电网侧"});
        ExcelUtil.selectList(workbook, 42, 42, new String[]{"不参与统计", "参与统计"});
        PoiUtil.exportFileByWorkbook(workbook, "台账导入模板.xlsx", response);


    }

    @Override
    public void downTerminalAutonomeTemplate(HttpServletResponse response) {
        ExportParams exportParams = new ExportParams("批量导入模板（请严格按照模板标准填入数据）", "台账信息");
        exportParams.setStyle(ExcelStyleUtil.class);
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, TerminalBaseExcel.class, new ArrayList<TerminalBaseExcel>());
        List<DictData> businessList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.BUSINESS_TYPE.getName()).getData();
        List<DictData> loadTypeList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName()).getData();
        List<DictData> manufacturerList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_MANUFACTURER.getName()).getData();
        List<DictData> devTypeList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_TYPE.getName()).getData();
        List<DictData> frontList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.FRONT_TYPE.getName()).getData();
        List<DictData> scaleList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_VOLTAGE_STAND.getName()).getData();
        List<Node> nodeList = nodeService.nodeAllList();


        //这里是自己加的 带下拉框的代码
        ExcelUtil.selectList(workbook, 8, 8, new String[]{"离线设备"});
        ExcelUtil.selectList(workbook, 9, 9, new String[]{"暂态系统", "稳态系统", "双系统"});
        ExcelUtil.selectList(workbook, 10, 10, new String[]{"投运", "热备用", "停运"});
        ExcelUtil.selectList(workbook, 11, 11, manufacturerList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 12, 12, devTypeList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 17, 17, new String[]{"周期触发", "变为触发"});
        ExcelUtil.selectList(workbook, 18, 18, nodeList.stream().map(Node::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 19, 19, frontList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));

        /*母线序号*/
        ExcelUtil.selectList(workbook, 23, 23, new String[]{"1", "2", "3", "3", "4", "5", "6"});
        ExcelUtil.selectList(workbook, 24, 24, scaleList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 25, 25, new String[]{"虚拟母线", "实际母线"});
        ExcelUtil.selectList(workbook, 27, 27, new String[]{"1", "2", "3", "3", "4", "5", "6"});
        ExcelUtil.selectList(workbook, 28, 28, new String[]{"极重要", "重要", "普通", "不重要"});
        ExcelUtil.selectList(workbook, 35, 35, new String[]{"星型接法", "三角型接法", "开口三角型接法"});
        ExcelUtil.selectList(workbook, 36, 36, new String[]{"3", "5", "10"});
        ExcelUtil.selectList(workbook, 37, 37, loadTypeList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 38, 38, businessList.stream().map(DictData::getName).collect(Collectors.toList()).toArray(new String[]{}));
        ExcelUtil.selectList(workbook, 41, 41, new String[]{"电网侧", "非电网侧"});
        ExcelUtil.selectList(workbook, 42, 42, new String[]{"不参与统计", "参与统计"});
        PoiUtil.exportFileByWorkbook(workbook, "台账导入模板.xlsx", response);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importTerminalBase(MultipartFile file, HttpServletResponse response) {
        ImportParams params = new ImportParams();
        params.setHeadRows(1);
        params.setTitleRows(1);
        params.setNeedVerify(true);
        //第一个sheet为台账信息
        params.setStartSheetIndex(0);
        params.setSheetNum(1);
        try {
            ExcelImportResult<TerminalBaseExcel> terminalBaseList = ExcelImportUtil.importExcelMore(file.getInputStream(), TerminalBaseExcel.class, params);
            //如果存在非法数据，将不合格的数据导出
            if (terminalBaseList.isVerifyFail()) {
                PoiUtil.exportFileByWorkbook(terminalBaseList.getFailWorkbook(), "非法台账信息.xlsx", response);
            } else {
                saveTerminalBase(terminalBaseList.getList());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Integer updatePqOverLimit() {
        List<LineDetail> lineDetailList = lineDetailMapper.selectList(new LambdaQueryWrapper<>());

        int count = 0;
        for (LineDetail lineDetail : lineDetailList) {
            overlimitMapper.deleteById(lineDetail.getId());
            Line line = lineMapper.selectById(lineDetail.getId());
            if (Objects.nonNull(line)) {
                Voltage voltage = voltageMapper.selectById(line.getPid());
                //监测点限值
                DictData scaleResult = dicDataFeignClient.getDicDataById(voltage.getScale()).getData();
                System.out.println("======================" + scaleResult);
                System.out.println("======================" + scaleResult.getValue());
                if (Objects.isNull(scaleResult)) {
                    throw new BusinessException(CommonResponseEnum.DIC_DATA);
                }


                if (StrUtil.isBlank(voltage.getScale())) {
                    System.out.println(111);
                }

                float voltageLevel = Float.parseFloat(scaleResult.getValue());
                Overlimit overlimit = COverlimitUtil.globalAssemble(voltageLevel, lineDetail.getDealCapacity(), lineDetail.getDevCapacity(), lineDetail.getShortCapacity(), lineDetail.getPowerFlag(), 0);
                overlimit.setId(lineDetail.getId());
                overlimitMapper.insert(overlimit);
                count++;
            }
        }
        return count;
    }

    @Override
    public Boolean wiringDiagramUpload(MultipartFile[] files, String lineId) {

        LineDetail lineDetailValid = lineDetailMapper.selectById(lineId);
        if (Objects.isNull(lineDetailValid)) {
            throw new BusinessException(DeviceResponseEnum.LINE_NO);
        }
        String[] urls = new String[0];
        if (StrUtil.isNotBlank(lineDetailValid.getWiringDiagram())) {
            urls = lineDetailValid.getWiringDiagram().split(StrUtil.COMMA);
        }

        if (urls.length + files.length > 2) {
            throw new BusinessException(DeviceResponseEnum.LINE_WIRING_MORE);
        }

        List<String> list = new ArrayList<>(Arrays.asList(urls));
        StrBuilder strBuilder = new StrBuilder();
        Arrays.stream(files).map(file -> fileStorageUtil.uploadMultipart(file, OssPath.WIRING_DIAGRAM)).forEach(list::add);

        for (int i = 0; i < list.size(); i++) {
            if (i == list.size() - 1) {
                strBuilder.append(list.get(i));
            } else {
                strBuilder.append(list.get(i)).append(StrUtil.COMMA);
            }
        }

        LineDetail lineDetail = new LineDetail();
        lineDetail.setWiringDiagram(strBuilder.toString());
        lineDetail.setId(lineId);
        lineDetailMapper.updateById(lineDetail);
        return true;
    }

    @Override
    public List<LineWiringDiagramVO> wiringDiagramShow(String lineId) {
        List<LineWiringDiagramVO> result = new ArrayList<>();
        LineDetail detail = lineDetailMapper.selectById(lineId);
        if (Objects.isNull(detail)) {
            throw new BusinessException(DeviceResponseEnum.LINE_NO);
        }
        if (StrUtil.isBlank(detail.getWiringDiagram())) {
            return result;
        }

        String[] urlStr = detail.getWiringDiagram().split(StrUtil.COMMA);
        for (String url : urlStr) {
            LineWiringDiagramVO lineWiringDiagramVO = new LineWiringDiagramVO();
            String realUrl = fileStorageUtil.getFileUrl(url);
            lineWiringDiagramVO.setLineId(detail.getId());
            lineWiringDiagramVO.setWiringDiagramName(url);
            lineWiringDiagramVO.setUrl(realUrl);
            result.add(lineWiringDiagramVO);
        }
        return result;
    }

    @Override
    public boolean wiringDiagramChange(MultipartFile file, String lineId, String wiringDiagramName) {
        LineDetail detail = lineDetailMapper.selectById(lineId);
        if (Objects.isNull(detail)) {
            throw new BusinessException(DeviceResponseEnum.LINE_NO);
        }
        if (StrUtil.isBlank(detail.getWiringDiagram())) {
            throw new BusinessException(DeviceResponseEnum.LINE_WIRING_DEL);
        }
        if (!detail.getWiringDiagram().contains(wiringDiagramName)) {
            throw new BusinessException(DeviceResponseEnum.LINE_WIRING_NO);
        }

        String[] urlArr = detail.getWiringDiagram().split(StrUtil.COMMA);
        List<String> newUrlList = Arrays.stream(urlArr).filter(s -> !s.equalsIgnoreCase(wiringDiagramName)).collect(Collectors.toList());

        if (newUrlList.size() > 1) {
            throw new BusinessException(DeviceResponseEnum.LINE_WIRING_MORE);
        }

        fileStorageUtil.deleteFile(wiringDiagramName);
        String url = fileStorageUtil.uploadMultipart(file, OssPath.WIRING_DIAGRAM);
        newUrlList.add(url);

        StrBuilder strBuilder = new StrBuilder();
        for (int i = 0; i < newUrlList.size(); i++) {
            if (i == newUrlList.size() - 1) {
                strBuilder.append(newUrlList.get(i));
            } else {
                strBuilder.append(newUrlList.get(i)).append(StrUtil.COMMA);
            }
        }

        LineDetail lineDetail = new LineDetail();
        lineDetail.setId(detail.getId());
        lineDetail.setWiringDiagram(strBuilder.toString());
        lineDetailMapper.updateById(lineDetail);
        return true;
    }

    @Override
    public boolean wiringDiagramDel(String lineId, String wiringDiagramName) {
        LineDetail detail = lineDetailMapper.selectById(lineId);
        if (Objects.isNull(detail)) {
            throw new BusinessException(DeviceResponseEnum.LINE_NO);
        }
        if (StrUtil.isBlank(detail.getWiringDiagram())) {
            throw new BusinessException(DeviceResponseEnum.LINE_WIRING_DEL);
        }
        if (!detail.getWiringDiagram().contains(wiringDiagramName)) {
            throw new BusinessException(DeviceResponseEnum.LINE_WIRING_NO);
        }
        fileStorageUtil.deleteFile(wiringDiagramName);

        String[] urlArr = detail.getWiringDiagram().split(StrUtil.COMMA);
        List<String> newUrlList = Arrays.stream(urlArr).filter(s -> !s.equalsIgnoreCase(wiringDiagramName)).collect(Collectors.toList());
        StrBuilder strBuilder = new StrBuilder();
        for (int i = 0; i < newUrlList.size(); i++) {
            if (i == newUrlList.size() - 1) {
                strBuilder.append(newUrlList.get(i));
            } else {
                strBuilder.append(newUrlList.get(i)).append(StrUtil.COMMA);
            }
        }
        LineDetail lineDetail = new LineDetail();
        lineDetail.setId(detail.getId());
        lineDetail.setWiringDiagram(strBuilder.toString());
        lineDetailMapper.updateById(lineDetail);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String terminalSync(SyncTerminalParam syncTerminalParam) {
        if (isSync) {
            /***
             * oracle http远程调用接口
             */
            SyncLedger syncLedger = oracleSyncLedger(syncTerminalParam);
            ResponseEntity<Map> userEntity = RestTemplateUtil.post(url, syncLedger, Map.class);
            if (HttpURLConnection.HTTP_OK == userEntity.getStatusCodeValue()) {
                //获取返回体
                Map body = userEntity.getBody();
                Integer oracleLineId = Integer.valueOf(body.get("oracleLineId").toString());
                Integer oracleDevId = Integer.valueOf(body.get("oracleDevId").toString());
                syncTerminalParam.setOracleLineId(oracleLineId);
                syncTerminalParam.setOracleDevId(oracleDevId);

                Map<String, String> DevIdMapping = new HashMap<>();
                Map<String, String> LineIdMapping = new HashMap<>();
                List<LineBak> resultList = lineBakService.list();
                for (LineBak row : resultList) {
                    String id = row.getId();
                    String lineId = row.getLineId() + "";
                    LineIdMapping.put(lineId, id);
                }
                redisUtil.saveByKey("LineIdMapping", LineIdMapping);
                List<DeviceBak> list = deviceBakService.list();
                for (DeviceBak row : list) {
                    String id = row.getId();
                    String devId = row.getDevId() + "";
                    DevIdMapping.put(devId, id);
                }
                redisUtil.saveByKey("DevIdMapping", DevIdMapping);
            }
        }
        String projectIndex = null;
        String provinceIndex = null;
        String gdIndex = null;
        String subIndex = null;
        if (StrUtil.isNotBlank(syncTerminalParam.getProjectIndex())) {
            projectIndex = syncTerminalParam.getProjectIndex();
            if (Objects.isNull(this.getById(projectIndex))) {
                throw new BusinessException(DeviceResponseEnum.PROJECT_NO);
            }
        }
        if (StrUtil.isNotBlank(syncTerminalParam.getProvinceIndex())) {
            provinceIndex = syncTerminalParam.getProvinceIndex();
            if (Objects.isNull(this.getById(provinceIndex))) {
                throw new BusinessException(DeviceResponseEnum.PROVINCE_GET_ERROR);
            }
        }
        if (StrUtil.isNotBlank(syncTerminalParam.getGdIndex())) {
            gdIndex = syncTerminalParam.getGdIndex();
            if (Objects.isNull(this.getById(gdIndex))) {
                throw new BusinessException(DeviceResponseEnum.GD_NO);
            }
        }
        if (StrUtil.isNotBlank(syncTerminalParam.getSubIndex())) {
            subIndex = syncTerminalParam.getSubIndex();
            if (Objects.isNull(this.getById(subIndex))) {
                throw new BusinessException(DeviceResponseEnum.SUB_NO);
            }
        }


        //变电站 todo 可能新建电站
        if (Objects.nonNull(syncTerminalParam.getSubStationParam())) {
            if (StrUtil.isBlank(subIndex) && StrUtil.isNotBlank(gdIndex)) {
                Line substation = this.lambdaQuery().eq(Line::getName, syncTerminalParam.getSubStationParam().getName()).one();
                if (Objects.isNull(substation)) {
                    Line subStation = assembleLine(syncTerminalParam.getSubStationParam().getName(), LineBaseEnum.SUB_LEVEL.getCode(), gdIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex, syncTerminalParam.getSubStationParam().getSort());
                    this.baseMapper.insert(subStation);
                    subIndex = subStation.getId();

                    //变电站下的经纬度入库
                    Substation sub = new Substation();
                    sub.setId(subIndex);
                    sub.setScale(syncTerminalParam.getSubStationParam().getScale());
                    sub.setLng(syncTerminalParam.getSubStationParam().getLng());
                    sub.setLat(syncTerminalParam.getSubStationParam().getLat());
                    substationMapper.insert(sub);
                } else {
                    subIndex = substation.getId();

                }

            }
        }

        //装置

        //查询该设备是否已经同步到表如何存在则之前同步监测点时同步过了，不用同步设备了，反之同步
        DeviceParam deviceParam = syncTerminalParam.getDeviceParam();
        Line deviceLine = this.baseMapper.selectById(syncTerminalParam.getDeviceParam().getDevIndex());
        if (Objects.isNull(deviceLine)) {
            Line device = assembleLine(deviceParam.getName(), LineBaseEnum.DEVICE_LEVEL.getCode(), subIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex + StrUtil.COMMA + subIndex, deviceParam.getSort());
            device.setId(deviceParam.getDevIndex());
            this.baseMapper.insert(device);

            //装置详情
            Device deviceDetail = new Device();
            BeanUtils.copyProperties(deviceParam, deviceDetail);
            deviceDetail.setId(device.getId());
            deviceDetail.setRunFlag(3);
            deviceDetail.setCallFlag(0);
            deviceDetail.setComFlag(0);
            deviceDetail.setCheckFlag(1);
            deviceDetail.setThisTimeCheck(PubUtils.localDateFormat(deviceParam.getThisTimeCheck()));
            deviceDetail.setNextTimeCheck(PubUtils.localDateFormat(deviceParam.getNextTimeCheck()));
            deviceDetail.setLoginTime(PubUtils.localDateFormat(deviceParam.getLoginTime()));
            deviceDetail.setUpdateTime(LocalDateTime.now());

            //处理终端oracle关系
            if (ObjectUtil.isNotNull(syncTerminalParam.getOracleDevId())) {
                DeviceBak back = new DeviceBak();
                back.setId(deviceDetail.getId());
                back.setDevId(syncTerminalParam.getOracleDevId());
                deviceBakService.saveOrUpdate(back);
            }
            //处理装置识别码秘钥
            deviceMapper.insert(deviceDetail);
            //装置功能 todo确定devFuction
//                        List<DictData> funList = dicDataFeignClient.getDicDataByTypeName(DicDataTypeEnum.DEV_FUN.getName()).getData();
//                        if (CollectionUtil.isEmpty(funList)) {
//                            throw new BusinessException(DeviceResponseEnum.DIC_GET_EMPTY);
//                        }
//
//                        List<DevFuction> insertFunList = new ArrayList<>();
//                        for (DictData dicData : funList) {
//                            DevFuction devFunction = new DevFuction();
//                            devFunction.setLineId(device.getId());
//                            devFunction.setFucName(dicData.getId());
//                            devFunction.setId(IdUtil.simpleUUID());
//                            insertFunList.add(devFunction);
//                        }
//                        QueryWrapper<DevFuction> funQueryWrapper = new QueryWrapper<>();
//                        funQueryWrapper.lambda().eq(DevFuction::getLineId, device.getId());
//                        devFuctionMapper.delete(funQueryWrapper);
//                        devFuctionMapper.addBatch(insertFunList);
        }

        //处理母线
        SubVoltageParam subVoltageParam = syncTerminalParam.getSubVoltageParam();
        String subvIndex = null;
        //如果电站下存在同名母线则将监测点挂在下面反之新建母线
        //同一变电站下只能有唯一母线名称
        Line SubVoltage = this.lambdaQuery().eq(Line::getName, subVoltageParam.getName()).like(Line::getPids, syncTerminalParam.getSubIndex()).one();

        if (Objects.isNull(SubVoltage)) {
            //新建母线
            Line subVoltage = assembleLine(subVoltageParam.getName(), LineBaseEnum.SUB_V_LEVEL.getCode(), deviceParam.getDevIndex(), projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex + StrUtil.COMMA + subIndex + StrUtil.COMMA + deviceParam.getDevIndex(), subVoltageParam.getSort());
            this.baseMapper.insert(subVoltage);
            subvIndex = subVoltage.getId();
            Voltage voltage = new Voltage();
            voltage.setId(subVoltage.getId());
            voltage.setNum(subVoltageParam.getNum());
            DictData scaleRes = dicDataFeignClient.getDicDataById(subVoltageParam.getScale()).getData();

            voltage.setScale(scaleRes.getId());
            voltage.setModel(subVoltageParam.getModel());
            voltageMapper.insert(voltage);
        } else {
            subvIndex = SubVoltage.getId();
        }

        //处理监测点
        LineParam lineParam = syncTerminalParam.getLineParam();

        Line line = assembleLine(lineParam.getName(), LineBaseEnum.LINE_LEVEL.getCode(), subvIndex, projectIndex + StrUtil.COMMA + provinceIndex + StrUtil.COMMA + gdIndex + StrUtil.COMMA + subIndex + StrUtil.COMMA + deviceParam.getDevIndex() + StrUtil.COMMA + subvIndex, lineParam.getSort());
        line.setId(lineParam.getLineIndex());
        this.baseMapper.insert(line);
        LineDetail lineDetail = new LineDetail();
        BeanUtils.copyProperties(lineParam, lineDetail);
        lineDetail.setId(line.getId());
        lineDetail.setRunFlag(3);
        //判断国网监测点id
        if (StrUtil.isNotBlank(lineDetail.getMonitorId())) {
            lineDetail.setMonitorFlag(1);
        } else {
            lineDetail.setMonitorFlag(0);
        }

        lineDetailMapper.insert(lineDetail);
        //处理终端oracle关系
        if (ObjectUtil.isNotNull(syncTerminalParam.getOracleLineId())) {
            LineBak back = new LineBak();
            back.setId(lineDetail.getId());
            back.setLineId(syncTerminalParam.getOracleLineId());
            lineBakService.saveOrUpdate(back);
        }
        //通过监测点id获取母线电压等级
        Voltage voltage = lineMapper.getVoltageByLineId(line.getId());
        //监测点限值
        DictData scaleResult = dicDataFeignClient.getDicDataById(voltage.getScale()).getData();
        float scaTmp = Float.parseFloat(scaleResult.getValue());
        Overlimit overlimit = COverlimitUtil.globalAssemble(scaTmp, lineDetail.getDealCapacity(), lineDetail.getDevCapacity(), lineDetail.getShortCapacity(), lineDetail.getPowerFlag(), 0);

        if (Objects.isNull(lineParam.getVoltageDev())) {
            overlimit.setVoltageDev(overlimit.getVoltageDev());
        } else {
            overlimit.setVoltageDev(lineParam.getVoltageDev());
        }
        if (Objects.isNull(lineParam.getUvoltageDev())) {
            overlimit.setUvoltageDev(overlimit.getUvoltageDev());
        } else {
            overlimit.setUvoltageDev(lineParam.getUvoltageDev());
        }
        overlimitMapper.deleteById(line.getId());
        overlimit.setId(line.getId());
        overlimitMapper.insert(overlimit);
        DeptLine deptLine = new DeptLine();
        deptLine.setId(syncTerminalParam.getDeptId());
        deptLine.setLineId(line.getId());
        deptLineMapper.insert(deptLine);
        return subIndex;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean terminalSyncRunFly(String lineId) {
        LineDTO lineDTO = this.baseMapper.selectLineDetail(lineId);
        if (ObjectUtil.isNotNull(lineDTO)) {
            lineDetailMapper.update(null, new LambdaUpdateWrapper<LineDetail>()
                    .set(LineDetail::getRunFlag, 0)
                    .eq(LineDetail::getId, lineDTO.getLineId())
            );

            deviceMapper.update(null, new LambdaUpdateWrapper<Device>()
                    .set(Device::getRunFlag, 0)
                    .eq(Device::getId, lineDTO.getDevId())
            );
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean terminalSyncDeleteFly(String lineId) {
        LineDTO lineDTO = this.baseMapper.selectLineDetail(lineId);
        if (ObjectUtil.isNotNull(lineDTO)) {
            //删除监测点详细信息
            lineDetailMapper.updateLineRunFlag(lineDTO.getLineId(), RunFlagEnum.QUIT.getStatus());
            //todo 删除监测点信息
            this.removeById(lineDTO.getLineId());
            //todo 删除部门监测点关系
            deptLineMapper.delete(new LambdaQueryWrapper<DeptLine>()
                    .eq(DeptLine::getLineId, lineDTO.getLineId()));
        }
        return false;
    }


    private String saveTerminalInfo(List<OracleTerminalExcel> oracleTerminalExcels, List<OverLimitExcel> overLimitExcels) {
        List<OracleTerminalExcel.OracleTerminalExcelMsg> oracleTerminalExcelMsg = new ArrayList<>();
        //任意集合数据为空，不处理
        if (CollectionUtil.isNotEmpty(oracleTerminalExcels)) {
            Line temp;
            List<String> pids = new ArrayList<>();
            for (OracleTerminalExcel oracleTerminalExcel : oracleTerminalExcels) {
                //清空父id集合
                pids.clear();
                LambdaQueryWrapper<Line> lineLambdaQueryWrapper = new LambdaQueryWrapper<>();
                /*
                 * 处理项目,判断数据库中是否已存在，存在则保留其索引，不存在则插入新纪录
                 */
                String projectName = oracleTerminalExcel.getProjectName();
                temp = queryLine(lineLambdaQueryWrapper, projectName, "0", PROJECT_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(projectName, PROJECT_LEVEL.getCode(), "0", Stream.of("0").collect(Collectors.toList()));
                    this.baseMapper.insert(temp);
                }
                //添加项目索引
                pids.add(temp.getId());
                /*
                 * 处理省会
                 * 1、根据省会名称从sys_area中查询对应的id
                 * 2、再根据省会id去pq_line中查询是否存在省会记录
                 * 注：如果sys_ara不存在该省会，记录到oracleTerminalExcelMsg中，稍后导出给用户查看
                 */
                Area area = areaFeignClient.selectAreaByName(oracleTerminalExcel.getProvinceName()).getData();
                if (Objects.isNull(area)) {
                    oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "省会名称不存在，请联系管理员"));
                    continue;
                }
                temp = queryLine(lineLambdaQueryWrapper, area.getId(), pids.get(PROJECT_LEVEL.getCode()), PROVINCE_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(area.getId(), PROVINCE_LEVEL.getCode(), pids.get(PROJECT_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                }
                //添加省会索引
                pids.add(temp.getId());
                /*
                 * 处理供电公司,判断数据库中是否已存在，存在则保留其索引，不存在则插入新纪录
                 */
                String gdName = oracleTerminalExcel.getGdName();
                temp = queryLine(lineLambdaQueryWrapper, gdName, pids.get(PROVINCE_LEVEL.getCode()), GD_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(gdName, GD_LEVEL.getCode(), pids.get(PROVINCE_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                }
                //添加供电公司索引
                pids.add(temp.getId());
                /*
                 * 处理变电站
                 * 1、判断是否存在，不存在则插入
                 * 2、变电站的电压等级，如果字典表不存在，则自动录入
                 */
                String substationName = oracleTerminalExcel.getSubstationName();
                temp = queryLine(lineLambdaQueryWrapper, substationName, pids.get(GD_LEVEL.getCode()), LineBaseEnum.SUB_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(substationName, LineBaseEnum.SUB_LEVEL.getCode(), pids.get(GD_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                    //处理电压等级字典表
                    DictData substationScale = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_VOLTAGE_STAND.getName(), oracleTerminalExcel.getSubStationScale()).getData();
                    if (Objects.isNull(substationScale)) {
                        //在电压等级内新增一条记录
                        substationScale = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_VOLTAGE.getName(), oracleTerminalExcel.getSubStationScale()).getData();
                    }
                    Substation substation = new Substation();
                    substation.setId(temp.getId());
                    substation.setScale(substationScale.getId());
                    substation.setLng(oracleTerminalExcel.getLng());
                    substation.setLat(oracleTerminalExcel.getLat());
                    substationMapper.insert(substation);
                } else {
                    //避免漏掉oracle项目中变电站经纬度的更改
                    Substation substation = substationMapper.selectById(temp.getId());
                    substation.setLng(oracleTerminalExcel.getLng());
                    substation.setLat(oracleTerminalExcel.getLat());
                    substationMapper.updateById(substation);
                }
                //添加变电站索引
                pids.add(temp.getId());
                /*
                 * 处理装置
                 * 1、判断是否存在，不存在则插入
                 * 2、终端厂家字典表中如果不存在，则自动录入
                 * 3、终端类型字典表中如果不存在，则自动录入
                 * 4、通讯类型需要截取，再做判断 CLD MMS PQDIF
                 * 5、当前变电站下的终端ip地址需要保持唯一，因为需要先插入终端，如果ip不唯一，需要删除插入的数据，并收集到错误信息列表中
                 */
                String deviceName = oracleTerminalExcel.getDeviceName();
                temp = queryLine(lineLambdaQueryWrapper, deviceName, pids.get(LineBaseEnum.SUB_LEVEL.getCode()), LineBaseEnum.DEVICE_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    //判断是否因为改了终端名称导致没有查到数据
                    LambdaQueryWrapper<DeviceBak> deviceBakLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    deviceBakLambdaQueryWrapper.eq(DeviceBak::getDevId, oracleTerminalExcel.getDeviceId());
                    List<DeviceBak> deviceBaks = deviceBakService.list(deviceBakLambdaQueryWrapper);

                    List<String> devIds = deviceBaks.stream().map(DeviceBak::getId).collect(Collectors.toList());
                    List<Line> devList = new ArrayList<>();
                    if (!CollectionUtil.isEmpty(devIds)) {
                        LambdaQueryWrapper<Line> devLambda = new LambdaQueryWrapper<>();
                        devLambda.in(Line::getId, devIds)
                                .orderByAsc(Line::getCreateTime)
                                .eq(Line::getState, DataStateEnum.ENABLE.getCode());
                        devList = lineMapper.selectList(devLambda);
                    }
                    if (CollectionUtil.isEmpty(deviceBaks) || CollectionUtil.isEmpty(devList)) {
                        temp = assembleLine(deviceName, LineBaseEnum.DEVICE_LEVEL.getCode(), pids.get(LineBaseEnum.SUB_LEVEL.getCode()), pids);
                        this.baseMapper.insert(temp);
                        List<Device> existIp = deviceMapper.getDeviceBySubId(pids.get(LineBaseEnum.SUB_LEVEL.getCode()), oracleTerminalExcel.getIp(), oracleTerminalExcel.getPort(), null);
                        if (CollectionUtil.isNotEmpty(existIp)) {
                            Device device = existIp.get(0);
                            if (!device.getId().equalsIgnoreCase(temp.getId())) {
                                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "IP地址：" + oracleTerminalExcel.getIp() + "已存在"));
                                //删除刚刚新增装置信息
                                this.baseMapper.deleteById(temp.getId());
                                continue;
                            }
                        }
                        //处理终端厂家
                        DictData manufacturer = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_MANUFACTURER.getName(), oracleTerminalExcel.getManufacturer()).getData();
                        if (Objects.isNull(manufacturer)) {
                            //在终端厂家字典内新增一条记录
                            manufacturer = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_MANUFACTURER.getName(), oracleTerminalExcel.getManufacturer()).getData();
                        }
                        Device device = new Device();
                        BeanUtils.copyProperties(oracleTerminalExcel, device);
                        device.setId(temp.getId());
                        device.setManufacturer(manufacturer.getId());
                        device.setIp(oracleTerminalExcel.getIp());
                        //处理前置ID
                        Node node = nodeService.getNodeByNodeName(oracleTerminalExcel.getNodeName());
                        if (Objects.isNull(node)) {
                            oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "前置名：" + oracleTerminalExcel.getNodeName() + "不存在"));
                            //删除刚刚新增装置信息
                            this.baseMapper.deleteById(temp.getId());
                            continue;
                        }
                        device.setNodeId(node.getId());
                        String oracleDevType = oracleTerminalExcel.getDevType().toUpperCase();
                        String frontType = getComType(oracleDevType);
                        if (StringUtils.isBlank(frontType)) {
                            oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "前置类型不存在"));
                            //删除刚刚新增装置信息
                            this.baseMapper.deleteById(temp.getId());
                            continue;
                        }
                        //处理前置类型
                        DictData frontTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.FRONT_TYPE.getName(), frontType).getData();
                        if (Objects.isNull(frontTypeDicData)) {
                            //在通讯类型字典内新增一条记录
                            frontTypeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.FRONT_TYPE.getName(), frontType).getData();
                        }
                        device.setFrontType(frontTypeDicData.getId());
                        String devType = oracleDevType.replace("_" + frontType, "");
                        //处理终端类型
                        DictData devTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_TYPE.getName(), devType).getData();
                        if (Objects.isNull(devTypeDicData)) {
                            //在终端类型字典内新增一条记录
                            devTypeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_TYPE.getName(), devType).getData();
                        }
                        device.setDevType(devTypeDicData.getId());
                        deviceMapper.insert(device);
                        //插入新旧终端ID中间表
                        DeviceBak deviceBak = new DeviceBak();
                        deviceBak.setId(temp.getId());
                        deviceBak.setDevId(oracleTerminalExcel.getDeviceId());
                        deviceBakService.saveOrUpdate(deviceBak);
                    } else {
                        if (CollectionUtil.isNotEmpty(devList)) {
                            //仅保留最早创建的记录
                            List<String> ids = new ArrayList<>();
                            if (devList.size() > 2) {
                                for (int i = 1; i < devList.size(); i++) {
                                    ids.add(devList.get(i).getId());
                                }
                                //删除错误关系和错误数据，避免丢失influx数据，保留最早的终端记录
                                lineMapper.deleteBatchIds(ids);
                                deviceMapper.deleteBatchIds(ids);
                                LambdaQueryWrapper<DeviceBak> deviceBakLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                                deviceBakLambdaQueryWrapper1.in(DeviceBak::getId, ids);
                                deviceBakService.remove(deviceBakLambdaQueryWrapper1);
                            } else if (devList.size() == 1) {
                                temp = lineMapper.selectById(devList.get(0).getId());
                            }
                        }
                    }
                } else {
                    //先查询终端id是否存在，存在则修改，不存在这添加
                    //判断是否因为改了终端名称导致没有查到数据
//                    LambdaQueryWrapper<DeviceBak> deviceBakLambdaQueryWrapper = new LambdaQueryWrapper<>();
//                    deviceBakLambdaQueryWrapper.eq(DeviceBak::getDevId, temp.getId());
//                    DeviceBak byId = deviceBakService.getById(deviceBakLambdaQueryWrapper);
//                    if(Objects.isNull(byId)){
                    //插入新旧终端ID中间表
                    DeviceBak deviceBak = new DeviceBak();
                    deviceBak.setId(temp.getId());
                    deviceBak.setDevId(oracleTerminalExcel.getDeviceId());
                    deviceBakService.saveOrUpdate(deviceBak);
//                    }else{
//                        if(!byId.getDevId().equals(oracleTerminalExcel.getDeviceId())){
//                            oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "终端关系，数据存入Oracle和excl不一样：" + oracleTerminalExcel.getLineNum() + "需要排查"));
//                            continue;
//                        }
//                    }
                    //更新终端信息
//                    List<Device> existIp = deviceMapper.getDeviceBySubId(pids.get(LineBaseEnum.SUB_LEVEL.getCode()), oracleTerminalExcel.getIp(), oracleTerminalExcel.getPort(), null);
//                    if (CollectionUtil.isNotEmpty(existIp)) {
//                        Device device = existIp.get(0);
//                        if (!device.getId().equalsIgnoreCase(temp.getId())) {
//                            oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "IP地址：" + oracleTerminalExcel.getIp() + "已存在"));
//                            //删除刚刚新增装置信息
//                            this.baseMapper.deleteById(temp.getId());
//                            continue;
//                        }
//                    }
                    //处理终端厂家
                    DictData manufacturer = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_MANUFACTURER.getName(), oracleTerminalExcel.getManufacturer()).getData();
                    if (Objects.isNull(manufacturer)) {
                        //在终端厂家字典内新增一条记录
                        manufacturer = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_MANUFACTURER.getName(), oracleTerminalExcel.getManufacturer()).getData();
                    }
                    Device device = new Device();
                    BeanUtils.copyProperties(oracleTerminalExcel, device);
                    device.setId(temp.getId());
                    device.setManufacturer(manufacturer.getId());
                    device.setIp(oracleTerminalExcel.getIp());
                    //处理前置ID
                    Node node = nodeService.getNodeByNodeName(oracleTerminalExcel.getNodeName());
                    if (Objects.isNull(node)) {
                        oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "前置名：" + oracleTerminalExcel.getNodeName() + "不存在"));
                        //删除刚刚新增装置信息
                        this.baseMapper.deleteById(temp.getId());
                        continue;
                    }
                    device.setNodeId(node.getId());
                    String oracleDevType = oracleTerminalExcel.getDevType().toUpperCase();
                    String frontType = getComType(oracleDevType);
                    if (StringUtils.isBlank(frontType)) {
                        oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "前置类型不存在"));
                        //删除刚刚新增装置信息
                        this.baseMapper.deleteById(temp.getId());
                        continue;
                    }
                    //处理前置类型
                    DictData frontTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.FRONT_TYPE.getName(), frontType).getData();
                    if (Objects.isNull(frontTypeDicData)) {
                        //在通讯类型字典内新增一条记录
                        frontTypeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.FRONT_TYPE.getName(), frontType).getData();
                    }
                    device.setFrontType(frontTypeDicData.getId());
                    String devType = oracleDevType.replace("_" + frontType, "");
                    //处理终端类型
                    DictData devTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_TYPE.getName(), devType).getData();
                    if (Objects.isNull(devTypeDicData)) {
                        //在终端类型字典内新增一条记录
                        devTypeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_TYPE.getName(), devType).getData();
                    }
                    device.setDevType(devTypeDicData.getId());
                    deviceMapper.updateById(device);
                }
                //添加终端索引
                pids.add(temp.getId());
                /*
                 * 处理母线
                 * 1、判断是否存在，不存在则插入
                 * 2、判断线路号是否已被占用，被占用，返回错误信息
                 * 3、处理母线电压等级
                 */
                String subvName = oracleTerminalExcel.getSubvName();
                temp = queryLine(lineLambdaQueryWrapper, subvName, pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), LineBaseEnum.SUB_V_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(subvName, LineBaseEnum.SUB_V_LEVEL.getCode(), pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                    //判断线路号，不判断母线号了
                    Integer subvNum = oracleTerminalExcel.getSubvNum();
//                    List<Voltage> voltages = voltageMapper.getVoltageByNum(pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), Stream.of(subvNum).collect(Collectors.toList()));
//                    if (CollectionUtil.isNotEmpty(voltages)) {
//                        Voltage voltage = voltages.get(0);
//                        if (!voltage.getId().equalsIgnoreCase(temp.getId())) {
//                            oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "母线线路号：" + subvNum + "已存在"));
//                            //删除刚刚新增母线信息
//                            this.baseMapper.deleteById(temp.getId());
//                            continue;
//                        }
//                    }
                    Voltage voltage = new Voltage();
                    voltage.setNum(subvNum);
                    voltage.setId(temp.getId());
                    voltage.setModel(oracleTerminalExcel.getSubvModel());
                    //处理电压等级字典表
                    DictData subvScale = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_VOLTAGE_STAND.getName(), oracleTerminalExcel.getSubvScale()).getData();
                    if (Objects.isNull(subvScale)) {
                        //在电压等级内新增一条记录
                        subvScale = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_VOLTAGE.getName(), oracleTerminalExcel.getSubvScale()).getData();
                    }
                    voltage.setScale(subvScale.getId());
                    voltageMapper.insert(voltage);
                }
                //添加母线索引
                pids.add(temp.getId());


                /*
                 * 处理监测点
                 * 1、判断是否存在，不存在则插入
                 * 2、监测点线路号排重
                 * 3、干扰源类型字典判断
                 * 4、行业类型字典判断
                 * 5、终端等级字典判断
                 */
                String lineName = oracleTerminalExcel.getLineName();
                temp = queryLine(lineLambdaQueryWrapper, lineName, pids.get(LineBaseEnum.SUB_V_LEVEL.getCode()), LineBaseEnum.LINE_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.nonNull(temp)) {
//                    oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "监测点名称重复，请联系管理员"));
                    LineBak lineBak = new LineBak();
                    lineBak.setId(temp.getId());
                    lineBak.setLineId(oracleTerminalExcel.getId());
                    lineBakService.saveOrUpdate(lineBak);
                    //修改监测点信息
                    LineDetail lineDetail = new LineDetail();
                    BeanUtils.copyProperties(oracleTerminalExcel, lineDetail);
                    lineDetail.setId(temp.getId());
                    //判断监测点号是否已被占用
//                    List<LineDetail> lineDetails = lineDetailMapper.getLineDetail(pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), Stream.of(oracleTerminalExcel.getLineNum()).collect(Collectors.toList()));
//                    if (CollectionUtil.isNotEmpty(lineDetails)) {
//                        LineDetail lineDetail1 = lineDetails.get(0);
//                        if (lineDetail1.getId().equalsIgnoreCase(temp.getId())) {
//                            oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "监测点线路号：" + oracleTerminalExcel.getLineNum() + "已存在"));
//                            //删除刚刚新增装置信息
//                            this.baseMapper.deleteById(temp.getId());
//                            continue;
//                        }
//                    }
                    //获取该监测点的限值数据
//                    List<OverLimitExcel> overLimitList = overLimitExcels.stream()
//                            .filter(overLimitExcel -> overLimitExcel.getId().equals(oracleTerminalExcel.getId()))
//                            .collect(Collectors.toList());
//                    if (CollectionUtil.isEmpty(overLimitList)) {
//                        oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "没有找到该监测点的限值数据"));
//                        //删除刚刚新增装置信息
//                        this.baseMapper.deleteById(temp.getId());
//                        continue;
//                    }
                    lineDetail.setNum(oracleTerminalExcel.getLineNum());
                    //干扰源类型
                    DictData loadTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName(), oracleTerminalExcel.getLoadType()).getData();
                    if (Objects.isNull(loadTypeDicData)) {
                        //在电压等级内新增一条记录
                        loadTypeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName(), oracleTerminalExcel.getLoadType()).getData();
                    }
                    lineDetail.setLoadType(loadTypeDicData.getId());
                    //行业类型
                    DictData businessDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.BUSINESS_TYPE.getName(), oracleTerminalExcel.getBusinessType()).getData();
                    if (Objects.isNull(businessDicData)) {
                        //在电压等级内新增一条记录
                        businessDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.BUSINESS_TYPE.getName(), oracleTerminalExcel.getBusinessType()).getData();
                    }
                    lineDetail.setBusinessType(businessDicData.getId());
                    if (StringUtils.isBlank(oracleTerminalExcel.getMonitorId())) {
                        lineDetail.setMonitorFlag(0);
                    } else {
                        lineDetail.setMonitorFlag(1);
                    }
                    //终端等级,为空不处理，可以为空
                    if (StringUtils.isNotBlank(oracleTerminalExcel.getLineGrade())) {
                        DictData lineGradeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_LEVEL.getName(), oracleTerminalExcel.getLineGrade()).getData();
                        if (Objects.isNull(lineGradeDicData)) {
                            //在电压等级内新增一条记录
                            lineGradeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_LEVEL.getName(), oracleTerminalExcel.getLineGrade()).getData();
                        }
                        lineDetail.setLineGrade(lineGradeDicData.getId());
                    }
                    lineDetailMapper.updateById(lineDetail);
                } else {
                    //判断是否因为改了终端名称导致没有查到数据
                    LambdaQueryWrapper<LineBak> lineBakLambdaQueryWrapper = new LambdaQueryWrapper<>();
                    lineBakLambdaQueryWrapper.eq(LineBak::getLineId, oracleTerminalExcel.getId());
                    List<LineBak> lineBaks = lineBakService.list(lineBakLambdaQueryWrapper);
                    List<String> lineIds = lineBaks.stream().map(LineBak::getId).collect(Collectors.toList());
                    List<Line> lineList = new ArrayList<>();
                    if (CollectionUtil.isNotEmpty(lineIds)) {
                        LambdaQueryWrapper<Line> devLambda = new LambdaQueryWrapper<>();
                        devLambda.in(Line::getId, lineIds)
                                .orderByAsc(Line::getCreateTime)
                                .eq(Line::getState, DataStateEnum.ENABLE.getCode());
                        lineList = lineMapper.selectList(devLambda);
                    }
                    if (CollectionUtil.isEmpty(lineBaks) || CollectionUtil.isEmpty(lineList)) {
                        temp = assembleLine(lineName, LineBaseEnum.LINE_LEVEL.getCode(), pids.get(LineBaseEnum.SUB_V_LEVEL.getCode()), pids);
                        this.baseMapper.insert(temp);
                        LineDetail lineDetail = new LineDetail();
                        BeanUtils.copyProperties(oracleTerminalExcel, lineDetail);
                        lineDetail.setId(temp.getId());
                        //判断监测点号是否已被占用
                        List<LineDetail> lineDetails = lineDetailMapper.getLineDetail(pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), Stream.of(oracleTerminalExcel.getLineNum()).collect(Collectors.toList()));
                        if (CollectionUtil.isNotEmpty(lineDetails)) {
                            LineDetail lineDetail1 = lineDetails.get(0);
                            if (lineDetail1.getId().equalsIgnoreCase(temp.getId())) {
                                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "监测点线路号：" + oracleTerminalExcel.getLineNum() + "已存在"));
                                //删除刚刚新增装置信息
                                this.baseMapper.deleteById(temp.getId());
                                continue;
                            }
                        }
                        //获取该监测点的限值数据
//                    List<OverLimitExcel> overLimitList = overLimitExcels.stream()
//                            .filter(overLimitExcel -> overLimitExcel.getId().equals(oracleTerminalExcel.getId()))
//                            .collect(Collectors.toList());
//                    if (CollectionUtil.isEmpty(overLimitList)) {
//                        oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "没有找到该监测点的限值数据"));
//                        //删除刚刚新增装置信息
//                        this.baseMapper.deleteById(temp.getId());
//                        continue;
//                    }
                        lineDetail.setNum(oracleTerminalExcel.getLineNum());
                        //干扰源类型
                        DictData loadTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName(), oracleTerminalExcel.getLoadType()).getData();
                        if (Objects.isNull(loadTypeDicData)) {
                            //在电压等级内新增一条记录
                            loadTypeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.INTERFERENCE_SOURCE_TYPE.getName(), oracleTerminalExcel.getLoadType()).getData();
                        }
                        lineDetail.setLoadType(loadTypeDicData.getId());
                        //行业类型
                        DictData businessDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.BUSINESS_TYPE.getName(), oracleTerminalExcel.getBusinessType()).getData();
                        if (Objects.isNull(businessDicData)) {
                            //在电压等级内新增一条记录
                            businessDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.BUSINESS_TYPE.getName(), oracleTerminalExcel.getBusinessType()).getData();
                        }
                        lineDetail.setBusinessType(businessDicData.getId());
                        if (StringUtils.isBlank(oracleTerminalExcel.getMonitorId())) {
                            lineDetail.setMonitorFlag(0);
                        } else {
                            lineDetail.setMonitorFlag(1);
                        }
                        //终端等级,为空不处理，可以为空
                        if (StringUtils.isNotBlank(oracleTerminalExcel.getLineGrade())) {
                            DictData lineGradeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_LEVEL.getName(), oracleTerminalExcel.getLineGrade()).getData();
                            if (Objects.isNull(lineGradeDicData)) {
                                //在电压等级内新增一条记录
                                lineGradeDicData = dicDataFeignClient.addDicData(DicDataTypeEnum.DEV_LEVEL.getName(), oracleTerminalExcel.getLineGrade()).getData();
                            }
                            lineDetail.setLineGrade(lineGradeDicData.getId());
                        }

                        lineDetailMapper.insert(lineDetail);
                        LineBak lineBak = new LineBak();
                        lineBak.setId(temp.getId());
                        lineBak.setLineId(oracleTerminalExcel.getId());
                        lineBakService.save(lineBak);
//                    OverLimitExcel overLimitExcel = overLimitList.get(0);
//                    Overlimit overlimit = new Overlimit();
//                    BeanUtils.copyProperties(overLimitExcel, overlimit);
//                    overlimit.setId(temp.getId());
//                    overlimitMapper.insert(overlimit);
                    } else {
                        if (CollectionUtil.isNotEmpty(lineList)) {
                            //仅保留最早创建的记录
                            List<String> ids = new ArrayList<>();
                            if (lineList.size() > 2) {
                                for (int i = 1; i < lineList.size(); i++) {
                                    ids.add(lineList.get(i).getId());
                                }
                                //删除错误关系和错误数据，避免丢失influx数据，保留最早的终端记录
                                lineMapper.deleteBatchIds(ids);
                                lineDetailMapper.deleteBatchIds(ids);
                                LambdaQueryWrapper<LineBak> lineBakLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
                                lineBakLambdaQueryWrapper1.in(LineBak::getId, ids);
                                lineBakService.remove(lineBakLambdaQueryWrapper1);
                            }
                        }
                    }
                }
            }
        }
        //错误信息不为空，则以excel的形式输出到前台
        this.updatePqOverLimit();
        if (CollectionUtil.isNotEmpty(oracleTerminalExcelMsg)) {
            ExcelUtil.exportExcel("失败列表.xlsx", OracleTerminalExcel.OracleTerminalExcelMsg.class, oracleTerminalExcelMsg);
            return null;
        }
        return CommonResponseEnum.SUCCESS.getMessage();
    }


    /**
     * 终端台账批量导入
     *
     * @author cdf
     * @date 2022/5/18
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveTerminalBase(List<TerminalBaseExcel> terminalBaseExcels) {
        List<TerminalBaseExcel.TerminalBaseExcelMsg> terminalBaseExcelMsgs = new ArrayList<>();
        //任意集合数据为空，不处理
        if (CollectionUtil.isNotEmpty(terminalBaseExcels)) {
            Line temp;
            List<String> pids = new ArrayList<>();
            for (TerminalBaseExcel terminalBaseExcel : terminalBaseExcels) {
                //清空父id集合
                pids.clear();
                LambdaQueryWrapper<Line> lineLambdaQueryWrapper = new LambdaQueryWrapper<>();
                /*
                 * 处理项目,判断数据库中是否已存在，存在则保留其索引，不存在则插入新纪录
                 */
                String projectName = terminalBaseExcel.getProjectName();
                temp = queryLine(lineLambdaQueryWrapper, projectName, "0", PROJECT_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(projectName, PROJECT_LEVEL.getCode(), "0", Stream.of("0").collect(Collectors.toList()));
                    this.baseMapper.insert(temp);
                }
                //添加项目索引
                pids.add(temp.getId());
                /*
                 * 处理省会
                 * 1、根据省会名称从sys_area中查询对应的id
                 * 2、再根据省会id去pq_line中查询是否存在省会记录
                 * 注：如果sys_ara不存在该省会，记录到oracleTerminalExcelMsg中，稍后导出给用户查看
                 */
                Area area = areaFeignClient.selectAreaByName(terminalBaseExcel.getProvinceName()).getData();
                if (Objects.isNull(area)) {
                    terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "省会名称不存在，请联系管理员"));
                    continue;
                }
                temp = queryLine(lineLambdaQueryWrapper, area.getId(), pids.get(PROJECT_LEVEL.getCode()), PROVINCE_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(area.getId(), PROVINCE_LEVEL.getCode(), pids.get(PROJECT_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                }
                //添加省会索引
                pids.add(temp.getId());
                /*
                 * 处理供电公司,判断数据库中是否已存在，存在则保留其索引，不存在则插入新纪录
                 */
                String gdName = terminalBaseExcel.getGdName();
                temp = queryLine(lineLambdaQueryWrapper, gdName, pids.get(PROVINCE_LEVEL.getCode()), GD_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(gdName, GD_LEVEL.getCode(), pids.get(PROVINCE_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                }
                //添加供电公司索引
                pids.add(temp.getId());
                /*
                 * 处理变电站
                 * 1、判断是否存在，不存在则插入
                 */
                String substationName = terminalBaseExcel.getSubstationName();
                temp = queryLine(lineLambdaQueryWrapper, substationName, pids.get(GD_LEVEL.getCode()), LineBaseEnum.SUB_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(substationName, LineBaseEnum.SUB_LEVEL.getCode(), pids.get(GD_LEVEL.getCode()), pids);
                    //处理电压等级字典表
                    DictData substationScale = dicDataFeignClient.getDicDataByNameAndType(terminalBaseExcel.getSubStationScale(), DicDataTypeEnum.DEV_VOLTAGE_STAND.getName()).getData();
                    if (Objects.isNull(substationScale)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "字典电压等级不存在"));
                        continue;
                    }
                    this.baseMapper.insert(temp);
                    Substation substation = new Substation();
                    substation.setId(temp.getId());
                    substation.setScale(substationScale.getId());
                    substation.setLng(terminalBaseExcel.getLng());
                    substation.setLat(terminalBaseExcel.getLat());
                    substationMapper.insert(substation);
                }
                //添加变电站索引
                pids.add(temp.getId());
                /*
                 * 处理装置
                 * 1、判断是否存在，不存在则插入
                 * 2、终端厂家字典表中如果不存在，则自动录入
                 * 3、终端类型字典表中如果不存在，则自动录入
                 * 4、通讯类型需要截取，再做判断 CLD MMS PQDIF
                 * 5、当前变电站下的终端ip地址需要保持唯一，因为需要先插入终端，如果ip不唯一，需要删除插入的数据，并收集到错误信息列表中
                 */
                String deviceName = terminalBaseExcel.getDeviceName();
                temp = queryLine(lineLambdaQueryWrapper, deviceName, pids.get(LineBaseEnum.SUB_LEVEL.getCode()), LineBaseEnum.DEVICE_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(deviceName, LineBaseEnum.DEVICE_LEVEL.getCode(), pids.get(LineBaseEnum.SUB_LEVEL.getCode()), pids);

                    List<Device> existIp = lineMapper.getDeviceBySubId(pids.get(LineBaseEnum.SUB_LEVEL.getCode()), Stream.of(terminalBaseExcel.getIp()).collect(Collectors.toList()));
                    if (CollectionUtil.isNotEmpty(existIp)) {
                        Device device = existIp.get(0);
                        if (!device.getId().equalsIgnoreCase(temp.getId())) {
                            terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "IP地址：" + terminalBaseExcel.getIp() + "已存在"));
                            continue;
                        }
                    }
                    //处理终端厂家
                    DictData manufacturer = dicDataFeignClient.getDicDataByName(terminalBaseExcel.getManufacturer()).getData();
                    if (Objects.isNull(manufacturer)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "终端厂家：" + terminalBaseExcel.getManufacturer() + "不存在"));
                        continue;
                    }
                    //处理前置ID
                    Node node = nodeService.getNodeByNodeName(terminalBaseExcel.getNodeName());
                    if (Objects.isNull(node)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "前置名：" + terminalBaseExcel.getNodeName() + "不存在"));
                        continue;
                    }
                    //处理前置类型
                    DictData frontTypeDicData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.FRONT_TYPE.getName(), terminalBaseExcel.getFrontType()).getData();
                    if (Objects.isNull(frontTypeDicData)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "前置类型不存在"));
                        continue;
                    }
                    //处理终端类型
                    DictData devTypeDicData = dicDataFeignClient.getDicDataByName(terminalBaseExcel.getDevType()).getData();
                    PqDevType one = new PqDevType();
                    if (Objects.isNull(devTypeDicData)) {
                        //上边逻辑不删兼容旧版本，新版本查询pq_dev_type
                        one = pqDevTypeService.lambdaQuery().eq(PqDevType::getName, terminalBaseExcel.getDevType()).eq(PqDevType::getState, DataStateEnum.ENABLE.getCode()).one();
                        if(Objects.isNull(one)){
                            terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "字典装置型号不存在"));
                            continue;
                        }

                    }
                    this.baseMapper.insert(temp);
                    Device device = new Device();
                    BeanUtils.copyProperties(terminalBaseExcel, device);
                    device.setId(temp.getId());
                    device.setManufacturer(manufacturer.getId());
                    device.setIp(terminalBaseExcel.getIp());
                    device.setNodeId(node.getId());
                    device.setFrontType(frontTypeDicData.getId());
                    device.setDevType(Objects.isNull(devTypeDicData)?one.getId():devTypeDicData.getId());
                    device.setComFlag(0);
                    device.setCheckFlag(1);
                    device.setLoginTime(LocalDate.now());
                    device.setThisTimeCheck(LocalDate.now());
                    device.setNextTimeCheck(LocalDate.now().plusYears(3));
                    device.setUpdateTime(LocalDateTime.now());
                    device.setElectroplate(0);
                    device.setOnTime(1);
                    //处理装置识别码秘钥
                    coderM3d(device, false);
                    deviceMapper.insert(device);
                    //分配前置进程
                    nodeDeviceService.oneKeyDistribution(node.getId());
                }
                //添加终端索引
                pids.add(temp.getId());
                /*
                 * 处理母线
                 * 1、判断是否存在，不存在则插入
                 * 2、判断线路号是否已被占用，被占用，返回错误信息
                 * 3、处理母线电压等级
                 */
                String subvName = terminalBaseExcel.getSubvName();
                temp = queryLine(lineLambdaQueryWrapper, subvName, pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), LineBaseEnum.SUB_V_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.isNull(temp)) {
                    temp = assembleLine(subvName, LineBaseEnum.SUB_V_LEVEL.getCode(), pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), pids);

                    //判断线路号
                    Integer subvNum = terminalBaseExcel.getSubvNum();
                    List<Voltage> voltages = voltageMapper.getVoltageByNum(pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), Stream.of(subvNum).collect(Collectors.toList()));
                    if (CollectionUtil.isNotEmpty(voltages)) {
                        Voltage voltage = voltages.get(0);
                        if (!voltage.getId().equalsIgnoreCase(temp.getId())) {
                            terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "母线线路号：" + subvNum + "已存在"));
                            continue;
                        }
                    }
                    //处理电压等级字典表
                    DictData subvScale = dicDataFeignClient.getDicDataByNameAndType(terminalBaseExcel.getSubvScale(), DicDataTypeEnum.DEV_VOLTAGE_STAND.getName()).getData();

                    if (Objects.isNull(subvScale)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "字典电压等级：" + terminalBaseExcel.getSubStationScale() + "不存在"));
                        continue;
                    }
                    this.baseMapper.insert(temp);
                    Voltage voltage = new Voltage();
                    voltage.setNum(subvNum);
                    voltage.setId(temp.getId());
                    voltage.setModel(terminalBaseExcel.getSubvModel());
                    voltage.setScale(subvScale.getId());
                    voltageMapper.insert(voltage);
                }
                //添加母线索引
                pids.add(temp.getId());
                /*
                 * 处理监测点
                 * 1、判断是否存在，不存在则插入
                 * 2、监测点线路号排重
                 * 3、干扰源类型字典判断
                 * 4、行业类型字典判断
                 * 5、终端等级字典判断
                 */
                String lineName = terminalBaseExcel.getLineName();
                temp = queryLine(lineLambdaQueryWrapper, lineName, pids.get(LineBaseEnum.SUB_V_LEVEL.getCode()), LineBaseEnum.LINE_LEVEL.getCode(), DataStateEnum.ENABLE.getCode());
                if (Objects.nonNull(temp)) {
                    terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "监测点名称重复，请联系管理员"));
                } else {
                    //判断监测点号是否已被占用
                    List<LineDetail> lineDetails = lineDetailMapper.getLineDetail(pids.get(LineBaseEnum.DEVICE_LEVEL.getCode()), Stream.of(terminalBaseExcel.getLineNum()).collect(Collectors.toList()));
                    if (CollectionUtil.isNotEmpty(lineDetails)) {
                        LineDetail lineDetail1 = lineDetails.get(0);
                        if (lineDetail1.getId().equalsIgnoreCase(temp.getId())) {
                            terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "监测点线路号：" + terminalBaseExcel.getLineNum() + "已存在"));
                            continue;
                        }
                    }
                    temp = assembleLine(lineName, LineBaseEnum.LINE_LEVEL.getCode(), pids.get(LineBaseEnum.SUB_V_LEVEL.getCode()), pids);
                    this.baseMapper.insert(temp);
                    LineDetail lineDetail = new LineDetail();
                    BeanUtils.copyProperties(terminalBaseExcel, lineDetail);
                    //干扰源类型
                    DictData loadTypeDicData = dicDataFeignClient.getDicDataByName(terminalBaseExcel.getLoadType()).getData();
                    if (Objects.isNull(loadTypeDicData)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "字典干扰源类型：" + terminalBaseExcel.getLoadType() + "不存在"));
                        continue;
                    }
                    //行业类型
                    DictData businessDicData = dicDataFeignClient.getDicDataByName(terminalBaseExcel.getBusinessType()).getData();
                    if (Objects.isNull(businessDicData)) {
                        terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "字典行业类型：" + terminalBaseExcel.getBusinessType() + "不存在"));
                        continue;
                    }
                    //终端等级,为空不处理，可以为空
                    if (StringUtils.isNotBlank(terminalBaseExcel.getLineGrade())) {
                        DictData lineGradeDicData = dicDataFeignClient.getDicDataByName(terminalBaseExcel.getLineGrade()).getData();
                        if (Objects.isNull(lineGradeDicData)) {
                            terminalBaseExcelMsgs.add(assembleBaseMsg(terminalBaseExcel, "字典终端等级：" + terminalBaseExcel.getLineGrade() + "不存在"));
                            continue;
                        }
                        lineDetail.setLineGrade(lineGradeDicData.getId());
                    }

                    lineDetail.setId(temp.getId());
                    lineDetail.setNum(terminalBaseExcel.getLineNum());
                    lineDetail.setLoadType(loadTypeDicData.getId());
                    lineDetail.setBusinessType(businessDicData.getId());
                    if (StringUtils.isBlank(terminalBaseExcel.getMonitorId())) {
                        lineDetail.setMonitorFlag(0);
                    } else {
                        lineDetail.setMonitorFlag(1);
                    }
                    String[] pt = terminalBaseExcel.getPt().split("/");
                    String[] ct = terminalBaseExcel.getCt().split("/");
                    lineDetail.setPt1(Float.valueOf(pt[0]));
                    lineDetail.setPt2(Float.valueOf(pt[1]));
                    lineDetail.setCt1(Float.valueOf(ct[0]));
                    lineDetail.setCt2(Float.valueOf(ct[1]));
                    if(StringUtils.isNoneBlank(terminalBaseExcel.getObjName())){
                        UserReportPO one = userLedgerService.lambdaQuery().eq(UserReportPO::getProjectName, terminalBaseExcel.getObjName())
                                .eq(UserReportPO::getState, DataStateEnum.ENABLE.getCode()).one();
                        if(Objects.nonNull(one)){
                            lineDetail.setObjId(one.getId());

                        }

                    }

                    DictData dictData = dicDataFeignClient.getDicDataByNameAndType(terminalBaseExcel.getSubvScale(), DicDataTypeEnum.DEV_VOLTAGE_STAND.getName()).getData();

                    lineDetailMapper.insert(lineDetail);
                    Overlimit overlimit = COverlimitUtil.globalAssemble(Float.parseFloat(dictData.getValue()), terminalBaseExcel.getDealCapacity(), terminalBaseExcel.getDevCapacity(), terminalBaseExcel.getShortCapacity(), terminalBaseExcel.getPowerFlag(), 0);
                    overlimit.setId(temp.getId());
                    overlimitMapper.insert(overlimit);
                }
            }
        }
        //错误信息不为空，则以excel的形式输出到前台
        if (CollectionUtil.isNotEmpty(terminalBaseExcelMsgs)) {
            ExcelUtil.exportExcel("失败列表.xlsx", TerminalBaseExcel.TerminalBaseExcelMsg.class, terminalBaseExcelMsgs);
        }
    }


    /**
     * 根据条件查询出台账信息
     *
     * @param name  名称
     * @param pid   父id
     * @param level 层级
     * @param state 状态 0 删除 1 正常
     * @return 终端信息
     */
    private Line queryLine(LambdaQueryWrapper<Line> lineLambdaQueryWrapper, String name, String pid, Integer level, Integer state) {
        lineLambdaQueryWrapper.clear();
        lineLambdaQueryWrapper.eq(Line::getName, name)
                .eq(Line::getPid, pid)
                .eq(Line::getLevel, level)
                .eq(Line::getState, state);
        return this.baseMapper.selectOne(lineLambdaQueryWrapper);
    }

    /**
     * 组装台账信息，稍后入库
     *
     * @param name  名称
     * @param level 等级
     * @param pid   父ID
     * @param pids  上层所有ID
     */
    private Line assembleLine(String name, Integer level, String pid, List<String> pids) {
        Line line = new Line();
        line.setName(name);
        line.setLevel(level);
        line.setPid(pid);
        line.setPids(String.join(",", pids));
        line.setSort(0);
        line.setState(DataStateEnum.ENABLE.getCode());
        return line;
    }

    private Line assembleLine(String name, Integer level, String pid, String pids, Integer sort) {
        Line line = new Line();
        line.setName(name);
        line.setLevel(level);
        line.setPid(pid);
        line.setPids(pids);
        line.setSort(sort);
        line.setState(DataStateEnum.ENABLE.getCode());
        return line;
    }

    /**
     * 组装不能正常插入的记录，稍后导出给用户
     *
     * @param oracleTerminalExcel 记录信息
     * @param msg                 错误信息
     */
    private OracleTerminalExcel.OracleTerminalExcelMsg assembleMsg(OracleTerminalExcel oracleTerminalExcel, String msg) {
        OracleTerminalExcel.OracleTerminalExcelMsg oracleTerminalExcelMsg = new OracleTerminalExcel.OracleTerminalExcelMsg();
        BeanUtils.copyProperties(oracleTerminalExcel, oracleTerminalExcelMsg);
        oracleTerminalExcelMsg.setMsg(msg);
        return oracleTerminalExcelMsg;
    }

    private TerminalBaseExcel.TerminalBaseExcelMsg assembleBaseMsg(TerminalBaseExcel terminalBaseExcel, String msg) {
        TerminalBaseExcel.TerminalBaseExcelMsg terminalBaseExcelMsg = new TerminalBaseExcel.TerminalBaseExcelMsg();
        BeanUtils.copyProperties(terminalBaseExcel, terminalBaseExcelMsg);
        terminalBaseExcelMsg.setMsg(msg);
        return terminalBaseExcelMsg;
    }

    /**
     * 根据oracle中的终端类型获取 通讯类型
     * 目前常见的有：_CLD _MMS _PQDIF
     *
     * @param oracleDevType oracle库中的终端类型
     * @return 通讯类型
     */
    private String getComType(String oracleDevType) {
        if (oracleDevType.contains("_CLD")) {
            return "CLD";
        } else if (oracleDevType.contains("_MMS")) {
            return "MMS";
        } else if (oracleDevType.contains("_PQDIF")) {
            return "PQDIF";
        }
        return "";
    }


    /**
     * 校验参数，检查是否存在相同名称
     * param
     */
    private void checkName(AddTerminalParam addTerminalParam, Integer level, String pid) {
        LambdaQueryWrapper<Line> lineLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LineBaseEnum lineBaseEnum = LineBaseEnum.getLineBaseEnumByCode(level);
        switch (lineBaseEnum) {
            case PROJECT_LEVEL:
                lineLambdaQueryWrapper.eq(Line::getName, addTerminalParam.getProjectParam().getName())
                        .eq(Line::getLevel, lineBaseEnum.getCode());
                break;
            case PROVINCE_LEVEL:
                lineLambdaQueryWrapper
                        .eq(Line::getName, addTerminalParam.getProvinceParam().getName())
                        .eq(Line::getPid, pid);
                break;
            case GD_LEVEL:
                lineLambdaQueryWrapper.eq(Line::getName, addTerminalParam.getGdInformationParam().getName())
                        .eq(Line::getPid, pid);
                break;
            case SUB_LEVEL:
                lineLambdaQueryWrapper.eq(Line::getName, addTerminalParam.getSubStationParam().getName())
                        .eq(Line::getPid, pid);
                break;
            default:
                throw new BusinessException(DeviceResponseEnum.INVALID_LEVEL);
        }

        lineLambdaQueryWrapper.eq(Line::getState, DataStateEnum.ENABLE.getCode());

        int countByAccount = this.count(lineLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            switch (lineBaseEnum) {
                case PROJECT_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.PROJECT_SAME_NAME);
                case PROVINCE_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.PROVINCE_SAME_NAME);
                case GD_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.GD_SAME_NAME);
                case SUB_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.SUB_SAME_NAME);
                default:
                    throw new BusinessException(DeviceResponseEnum.INVALID_LEVEL);
            }
        }
    }


    /**
     * 校验参数，检查是否存在相同名称
     * param
     */
    private void checkUpdateName(UpdateTerminalParam updateTerminalParam, Integer level, String pid) {
        LambdaQueryWrapper<Line> lineLambdaQueryWrapper = new LambdaQueryWrapper<>();
        LineBaseEnum lineBaseEnum = LineBaseEnum.getLineBaseEnumByCode(level);
        switch (lineBaseEnum) {
            case PROJECT_LEVEL:
                lineLambdaQueryWrapper.eq(Line::getName, updateTerminalParam.getProjectUpdateParam().getName())
                        .eq(Line::getLevel, lineBaseEnum.getCode())
                        .ne(Line::getId, (updateTerminalParam.getProjectUpdateParam()).getProjectIndex());
                break;
            case GD_LEVEL:
                lineLambdaQueryWrapper.eq(Line::getName, updateTerminalParam.getGdInformationUpdateParam().getName())
                        .eq(Line::getPid, pid)
                        .ne(Line::getId, (updateTerminalParam.getGdInformationUpdateParam()).getGdIndex());
                break;
            case SUB_LEVEL:
                lineLambdaQueryWrapper.eq(Line::getName, updateTerminalParam.getSubStationUpdateParam().getName())
                        .eq(Line::getPid, pid)
                        .ne(Line::getId, (updateTerminalParam.getSubStationUpdateParam()).getSubIndex());
                break;
            default:
                throw new BusinessException(DeviceResponseEnum.INVALID_LEVEL);
        }
        lineLambdaQueryWrapper.eq(Line::getState, DataStateEnum.ENABLE.getCode());
        int countByAccount = this.count(lineLambdaQueryWrapper);
        //大于等于1个则表示重复
        if (countByAccount >= 1) {
            switch (lineBaseEnum) {
                case PROJECT_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.PROJECT_SAME_NAME);
                case GD_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.GD_SAME_NAME);
                case SUB_LEVEL:
                    throw new BusinessException(DeviceResponseEnum.SUB_SAME_NAME);
                default:
                    throw new BusinessException(DeviceResponseEnum.INVALID_LEVEL);
            }
        }
    }


    /**
     * 组装台账信息
     *
     * @author cdf
     * @date 2022/2/14
     */
    private TerminalVO commTerminalValue(TerminalVO terminalVO, String subId) {
        if (StrUtil.isBlank(subId) || Objects.isNull(terminalVO)) {
            log.error("赋值出错");
            return null;
        }

        Line subStation = this.getById(subId);
        if (Objects.nonNull(subStation)) {
            assSub(subStation, terminalVO);

            Line gdInformation = this.getById(subStation.getPid());
            assGd(gdInformation, terminalVO);

            Line province = this.getById(gdInformation.getPid());
            assProvince(province, terminalVO);

            Line project = this.getById(province.getPid());
            assProject(project, terminalVO);

            return terminalVO;
        } else {
            throw new BusinessException(DeviceResponseEnum.SUB_NO);
        }

    }

    /**
     * 组装项目
     */
    private void assProject(Line project, TerminalVO terminalVO) {
        ProjectVO projectVO = new ProjectVO();
        projectVO.setProjectIndex(project.getId());
        projectVO.setName(project.getName());
        projectVO.setSort(project.getSort());
        terminalVO.setProjectVO(projectVO);

    }

    /**
     * 组装省份
     */
    private void assProvince(Line province, TerminalVO terminalVO) {
        ProvinceVO provinceVO = new ProvinceVO();
        provinceVO.setProvinceIndex(province.getId());
        provinceVO.setName(province.getName());
        provinceVO.setSort(province.getSort());
        terminalVO.setProvinceVO(provinceVO);
    }

    /**
     * 组装供电公司
     */
    private void assGd(Line gdInformation, TerminalVO terminalVO) {
        GdInformationVO gdInformationVO = new GdInformationVO();
        gdInformationVO.setGdIndex(gdInformation.getId());
        gdInformationVO.setName(gdInformation.getName());
        gdInformationVO.setSort(gdInformation.getSort());
        terminalVO.setGdInformationVO(gdInformationVO);
    }

    /**
     * 组装变电站
     */
    private void assSub(Line subStation, TerminalVO terminalVO) {
        Substation substation = substationMapper.selectById(subStation.getId());
        SubStationVO subStationVO = new SubStationVO();
        subStationVO.setSubIndex(subStation.getId());
        subStationVO.setName(subStation.getName());
        subStationVO.setSort(subStation.getSort());
        BeanUtils.copyProperties(substation, subStationVO);
        terminalVO.setSubStationVO(subStationVO);
    }

    private SyncLedgerDelete oracleSyncLedgerDelete(Line obj) {
        SyncLedgerDelete delete = new SyncLedgerDelete();
        delete.setLevel(obj.getLevel());
        /**
         * 3-变电站；4-终端；5-母线；6-监测点
         */
        switch (obj.getLevel()) {
            case 3:
                Line byId = this.getById(obj.getPid());
                if (Objects.isNull(byId)) {
                    throw new BusinessException(CommonResponseEnum.NO_DATA);
                }
                delete.setSuperName(byId.getName());
                delete.setName(obj.getName());
                break;
            case 4:
                DeviceBak deviceBak = deviceBakService.getById(obj.getId());
                delete.setId(deviceBak.getDevId());
                delete.setName(obj.getName());
                break;
            case 5:
                DeviceBak bak = deviceBakService.getById(obj.getPid());
                delete.setName(obj.getName());
                delete.setSuperId(bak.getDevId());
                break;
            case 6:
                LineBak lineBak = lineBakService.getById(obj.getId());
                delete.setId(lineBak.getLineId());
                delete.setName(obj.getName());
                break;
        }
        return delete;
    }

    private SyncLedgerUpdate oracleSyncLedgerUpdate(UpdateTerminalParam param, String oldSubName, String gdName) {
        SyncLedgerUpdate update = new SyncLedgerUpdate();
        /**
         * 先更新变电站信息，然后根据变电站信息查询终端信息
         */
        //变电站信息
        SubStationParam.SubStationUpdateParam sub = param.getSubStationUpdateParam();
        List<DeviceParam> deviceUpdateParamList = param.getDeviceUpdateParamList();
        PqSubstation substation = new PqSubstation();
        if (ObjectUtil.isNull(sub)) {
            //因为查出来的数据电压等级是转换过的所有不需要替换
            Line byId = this.getById(deviceUpdateParamList.get(0).getDevIndex());
            PollutionSubstationDTO substationInfo = lineMapper.getSubstationInfo(byId.getPid());
            sub = new SubStationParam.SubStationUpdateParam();
            sub.setName(substationInfo.getName());
            oldSubName = substationInfo.getName();
            sub.setLng(substationInfo.getLng());
            sub.setLat(substationInfo.getLat());
            sub.setSubIndex(substationInfo.getId());
            substation.setScale(substationInfo.getVoltageLevel());
        } else {
            substation.setScale(dictName(sub.getScale()));
        }
        substation.setName(sub.getName());
        substation.setOldName(oldSubName);
        if (StrUtil.isNotBlank(gdName)) {
            substation.setGdName(gdName);
        } else {
            Line byId = this.getById(sub.getSubIndex());
            Line byId1 = this.getById(byId.getPid());
            if (ObjectUtil.isNull(byId1)) {
                throw new BusinessException(PvDeviceResponseEnum.GD_OR_NOT);
            }
            substation.setGdName(byId1.getName());
        }
        update.setPqSubstation(substation);
        PqsMap pqsMap = new PqsMap();
        pqsMap.setLongitude(sub.getLng().doubleValue());
        pqsMap.setLatitude(sub.getLat().doubleValue());
        update.setPqsMap(pqsMap);

        //修改终端信息
        List<PqDevice> deviceList = new ArrayList<>();
        List<PqDevicedetail> deviceDetailList = new ArrayList<>();
        List<PqLinedetail> lineDeatailList = new ArrayList<>();

        List<String> devMysqlIds = deviceUpdateParamList.stream().map(DeviceParam::getDevIndex).collect(Collectors.toList());
        List<DeviceBak> deviceBaks = deviceBakService.listByIds(devMysqlIds);
        Map<String, Integer> deviceBakMap = deviceBaks.stream().collect(Collectors.toMap(DeviceBak::getId, DeviceBak::getDevId));


        for (DeviceParam device : deviceUpdateParamList) {
            String devIndex = device.getDevIndex();
            if (deviceBakMap.containsKey(devIndex)) {
                Integer devOracleId = deviceBakMap.get(devIndex);
                //终端
                PqDevice pqDevice = new PqDevice();
                pqDevice.setDevIndex(devOracleId);
                pqDevice.setName(device.getName());
                pqDevice.setStatus(1);
                pqDevice.setDevtype(dictName(device.getDevType()));
                pqDevice.setLogontime(device.getLoginTime());
                pqDevice.setUpdatetime(device.getLoginTime());
                Node node = nodeService.getNodeById(device.getNodeId());
                if (ObjectUtil.isNotNull(node)) {
                    pqDevice.setNodeName(node.getName());
                }
                pqDevice.setPortid(device.getPort());
                pqDevice.setDevflag(0);
                pqDevice.setDevSeries(device.getSeries());
                pqDevice.setDevKey(device.getDevKey());
                pqDevice.setIp(device.getIp());
                pqDevice.setDevmodel(device.getDevModel());
                pqDevice.setCallflag(device.getCallFlag());
                pqDevice.setDatatype(device.getDevDataType());

                //终端详细信息
                PqDevicedetail pqDevicedetail = new PqDevicedetail();
                pqDevicedetail.setDevIndex(devOracleId);
                pqDevicedetail.setManufacturer(dictName(device.getManufacturer()));
                pqDevicedetail.setThistimecheck(device.getThisTimeCheck());
                pqDevicedetail.setNexttimecheck(device.getNextTimeCheck());
                pqDevicedetail.setElectroplate(device.getElectroplate());
                pqDevicedetail.setContract(device.getContract());
                pqDevicedetail.setSim(device.getSim());
                pqDevicedetail.setDevCatena(device.getDevSeries());
                pqDevicedetail.setDevLocation(device.getDevLocation());
                pqDevicedetail.setDevNo(device.getDevNo());
                pqDevicedetail.setIsAlarm(device.getIsAlarm());
                deviceDetailList.add(pqDevicedetail);

                //处理母线信息
                List<PqSubvoltage> pqSubVoltages = new ArrayList<>();
                for (SubVoltageParam subVoltage : device.getSubVoltageParam()) {
                    //母线
                    PqSubvoltage pqSubvoltage = new PqSubvoltage();
                    pqSubvoltage.setName(subVoltage.getName());
                    pqSubvoltage.setOldName(subVoltage.getOldName());
                    pqSubvoltage.setSubvNum(subVoltage.getNum());
                    pqSubvoltage.setScale(dictName(subVoltage.getScale()));
                    pqSubvoltage.setSubvmodel(subVoltage.getModel());
                    pqSubVoltages.add(pqSubvoltage);
                    //监测点
                    List<PqLine> pqLines = new ArrayList<>();
                    for (LineParam line : subVoltage.getLineParam()) {
                        LineBak byId = lineBakService.getById(line.getLineIndex());
                        if (ObjectUtil.isNotNull(byId)) {
                            //监测点
                            PqLine pqLine = new PqLine();
                            pqLine.setLineIndex(byId.getLineId());
                            pqLine.setName(line.getName());
                            pqLine.setPt1(line.getPt1().doubleValue());
                            pqLine.setPt2(line.getPt2().doubleValue());
                            pqLine.setCt1(line.getCt1().doubleValue());
                            pqLine.setCt2(line.getCt2().doubleValue());
                            pqLine.setDevcmp(line.getDevCapacity().doubleValue());
                            pqLine.setDlcmp(line.getShortCapacity().doubleValue());
                            pqLine.setJzcmp(line.getStandardCapacity().doubleValue());
                            pqLine.setXycmp(line.getDealCapacity().doubleValue());
                            pqLine.setScale(dictName(subVoltage.getScale()));
                            pqLine.setStatus(0);
                            pqLines.add(pqLine);

                            PqLinedetail pqLinedetail = new PqLinedetail();
                            pqLinedetail.setLineIndex(byId.getLineId());
                            pqLinedetail.setLineName(line.getName());
                            pqLinedetail.setPttype(line.getPtType());
                            pqLinedetail.setLastTime(device.getLoginTime());
                            pqLinedetail.setTinterval(line.getTimeInterval());
                            pqLinedetail.setLoadtype(dictName(line.getLoadType()));
                            pqLinedetail.setBusinesstype(dictName(line.getBusinessType()));
                            pqLinedetail.setRemark(line.getRemark());
                            pqLinedetail.setMonitorId(line.getMonitorId());
                            pqLinedetail.setPowerid(line.getPowerFlag());
                            pqLinedetail.setObjname(line.getObjName());
                            pqLinedetail.setStatflag(line.getStatFlag());
                            pqLinedetail.setPowerSubstationName(line.getPowerSubstationName());
                            pqLinedetail.setHangLine(line.getHangLine());
                            pqLinedetail.setOwner(line.getOwner());
                            pqLinedetail.setOwnerDuty(line.getOwnerDuty());
                            pqLinedetail.setOwnerTel(line.getOwnerTel());
                            pqLinedetail.setSuperiorsSubstation(line.getSuperiorsSubstation());
                            pqLinedetail.setClassificationGrade(line.getCalssificationGrade());
                            pqLinedetail.setIsGridPoint(1);
                            lineDeatailList.add(pqLinedetail);
                        }
                    }
                    pqSubvoltage.setPqLine(pqLines);

                }
                pqDevice.setPqSubvoltage(pqSubVoltages);
                deviceList.add(pqDevice);
            }

        }
        update.setPqDevice(deviceList);
        update.setPqDevicedetail(deviceDetailList);
        update.setPqLinedetail(lineDeatailList);
        return update;
    }

    /**
     * oracle远程台账同步
     *
     * @param param
     * @return
     */
    private SyncLedger oracleSyncLedger(SyncTerminalParam param) {
        SyncLedger ledger = new SyncLedger();
        List<Line> data = lineMapper.selectList(new LambdaQueryWrapper<Line>()
                .eq(Line::getState, DataStateEnum.ENABLE.getCode())
                .in(Line::getId, Arrays.asList(param.getProjectIndex(),
                        param.getProvinceIndex(),
                        param.getGdIndex()))
        );

        //项目信息表
        PqProject pqProject = new PqProject();
        List<Line> project = data.stream().filter(x -> x.getId().equals(param.getProjectIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(project)) {
            pqProject.setName(project.get(0).getName());
        } else {
            throw new BusinessException(PvDeviceResponseEnum.PROJECT_OR_NOT);
        }
        ledger.setPqProject(pqProject);


        //省级项目表
        PqProvince pqProvince = new PqProvince();
        List<Line> province = data.stream().filter(x -> x.getId().equals(param.getProvinceIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(province)) {
            Area area = areaFeignClient.selectIdArea(province.get(0).getName()).getData();
            pqProvince.setName(area.getName());
        } else {
            throw new BusinessException(PvDeviceResponseEnum.PROVINCE_OR_NOT);
        }
        ledger.setPqProvince(pqProvince);

        //供电公司表
        PqGdinformation pqGdinformation = new PqGdinformation();
        List<Line> gd = data.stream().filter(x -> x.getId().equals(param.getGdIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(gd)) {
            pqGdinformation.setName(gd.get(0).getName());
        } else {
            throw new BusinessException(PvDeviceResponseEnum.GD_OR_NOT);
        }
        ledger.setPqGdinformation(pqGdinformation);

        //变电站
        PqSubstation pqSubstation = new PqSubstation();
        SubStationParam subStation = param.getSubStationParam();
        if (ObjectUtil.isNull(subStation)) {
            //因为查出来的数据电压等级是转换过的所有不需要替换
            PollutionSubstationDTO sub = lineMapper.getSubstationInfo(param.getSubIndex());
            subStation = new SubStationParam();
            subStation.setName(sub.getName());
            subStation.setScale(sub.getVoltageLevel());
            subStation.setLng(sub.getLng());
            subStation.setLat(sub.getLat());
        }
        pqSubstation.setName(subStation.getName());
        pqSubstation.setScale(subStation.getScale());
        ledger.setPqSubstation(pqSubstation);
        PqsMap pqsMap = new PqsMap();
        pqsMap.setLongitude(subStation.getLng().doubleValue());
        pqsMap.setLatitude(subStation.getLat().doubleValue());
        pqsMap.setState(1);
        ledger.setPqsMap(pqsMap);

        //终端
        PqDevice pqDevice = new PqDevice();
        DeviceParam device = param.getDeviceParam();
        pqDevice.setName(device.getName());
        pqDevice.setStatus(1);
        pqDevice.setDevtype(dictName(device.getDevType()));
        pqDevice.setLogontime(device.getLoginTime());
        pqDevice.setUpdatetime(device.getLoginTime());
        Node node = nodeService.getNodeById(device.getNodeId());
        if (ObjectUtil.isNotNull(node)) {
            pqDevice.setNodeName(node.getName());
        }
        pqDevice.setPortid(device.getPort());
        pqDevice.setDevflag(0);
        pqDevice.setDevSeries(device.getSeries());
        pqDevice.setDevKey(device.getDevKey());
        pqDevice.setIp(device.getIp());
        pqDevice.setDevmodel(device.getDevModel());
        pqDevice.setCallflag(device.getCallFlag());
        pqDevice.setDatatype(device.getDevDataType());
        ledger.setPqDevice(pqDevice);

        PqDevicedetail pqDevicedetail = new PqDevicedetail();
        pqDevicedetail.setManufacturer(dictName(device.getManufacturer()));
        pqDevicedetail.setThistimecheck(device.getThisTimeCheck());
        pqDevicedetail.setNexttimecheck(device.getNextTimeCheck());
        pqDevicedetail.setElectroplate(device.getElectroplate());
        pqDevicedetail.setContract(device.getContract());
        pqDevicedetail.setSim(device.getSim());
        pqDevicedetail.setDevCatena(device.getDevSeries());
        pqDevicedetail.setDevLocation(device.getDevLocation());
        pqDevicedetail.setDevNo(device.getDevNo());
        pqDevicedetail.setIsAlarm(device.getIsAlarm());
//        pqDevicedetail.setOnlineratetj();
//        pqDevicedetail.setDataplan();
//        pqDevicedetail.setNewtraffic();
//        pqDevicedetail.setOntime();
//        pqDevicedetail.setCheckflag();
        ledger.setPqDevicedetail(pqDevicedetail);

        //母线
        PqSubvoltage pqSubvoltage = new PqSubvoltage();
        SubVoltageParam subVoltage = param.getSubVoltageParam();
        pqSubvoltage.setName(subVoltage.getName());
        pqSubvoltage.setSubvNum(subVoltage.getNum());
        pqSubvoltage.setScale(dictName(subVoltage.getScale()));
        pqSubvoltage.setSubvmodel(subVoltage.getModel());
        ledger.setPqSubvoltage(pqSubvoltage);

        //监测点
        PqLine pqLine = new PqLine();
        LineParam line = param.getLineParam();
        pqLine.setName(line.getName());
        pqLine.setPt1(line.getPt1().doubleValue());
        pqLine.setPt2(line.getPt2().doubleValue());
        pqLine.setCt1(line.getCt1().doubleValue());
        pqLine.setCt2(line.getCt2().doubleValue());
        pqLine.setDevcmp(line.getDevCapacity().doubleValue());
        pqLine.setDlcmp(line.getShortCapacity().doubleValue());
        pqLine.setJzcmp(line.getStandardCapacity().doubleValue());
        pqLine.setXycmp(line.getDealCapacity().doubleValue());
        pqLine.setScale(dictName(subVoltage.getScale()));
        pqLine.setStatus(0);
        ledger.setPqLine(pqLine);
        PqLinedetail pqLinedetail = new PqLinedetail();
        pqLinedetail.setLineName(line.getName());
        pqLinedetail.setPttype(line.getPtType());
        pqLinedetail.setLastTime(device.getLoginTime());
        pqLinedetail.setTinterval(line.getTimeInterval());
        pqLinedetail.setLoadtype(dictName(line.getLoadType()));
        pqLinedetail.setBusinesstype(dictName(line.getBusinessType()));
        pqLinedetail.setRemark(line.getRemark());
        pqLinedetail.setMonitorId(line.getMonitorId());
        pqLinedetail.setPowerid(line.getPowerFlag());
        pqLinedetail.setObjname(line.getObjName());
        pqLinedetail.setStatflag(line.getStatFlag());
        pqLinedetail.setPowerSubstationName(line.getPowerSubstationName());
        pqLinedetail.setHangLine(line.getHangLine());
        pqLinedetail.setOwner(line.getOwner());
        pqLinedetail.setOwnerDuty(line.getOwnerDuty());
        pqLinedetail.setOwnerTel(line.getOwnerTel());
        pqLinedetail.setSuperiorsSubstation(line.getSuperiorsSubstation());
        pqLinedetail.setClassificationGrade(line.getCalssificationGrade());
        pqLinedetail.setIsGridPoint(1);
//        pqLinedetail.setLineGrade();
//        pqLinedetail.setWiringDiagram();
        ledger.setPqLinedetail(pqLinedetail);
        ledger.setLineNum(line.getNum());
        return ledger;
    }

    private String dictName(String dicId) {
        try {
            DictData data = dicDataFeignClient.getDicDataById(dicId).getData();
            return data.getName();
        } catch (Exception e) {
            throw new BusinessException("字典转换异常");
        }

    }


    //    @Override
    public void askRestartProcess(String guid, String nodeId, Integer processNum, String processType, String processRebootType) {

        ProcessRebootMessage procesRebootMessage = new ProcessRebootMessage();
        procesRebootMessage.setIndex(processNum);

        procesRebootMessage.setFun(processType);
        procesRebootMessage.setProcessNum(processNum);
        procesRebootMessage.setFrontType(processRebootType);
        procesRebootMessage.setNodeId(nodeId);
        procesRebootMessage.setProcessNo(processNum);
        procesRebootMessage.setGuid(guid);
        produceFeignClient.askRestartProcess(procesRebootMessage);


    }


    //    @Override
//    @Async
    public void askRestartDevice(String guid, String nodeId, List<String> devId, String deviceRebootType, Integer processNum) {


        DeviceRebootMessage deviceRebootMessage = new DeviceRebootMessage();
        deviceRebootMessage.setCode(deviceRebootType);
        deviceRebootMessage.setGuid(guid);
        deviceRebootMessage.setNodeId(nodeId);
        deviceRebootMessage.setProcessNo(processNum);
        if (Objects.equals(deviceRebootType, DeviceRebootType.DELETE_TERMINAL)) {
            List<DeviceRebootMessage.DeviceInfo> list = new ArrayList<>();

            devId.forEach(temp -> {
                DeviceRebootMessage.DeviceInfo deviceInfo = new DeviceRebootMessage.DeviceInfo();
                deviceInfo.setId(temp);
                list.add(deviceInfo);
            });

            deviceRebootMessage.setData(list);
            deviceRebootMessage.setIndex(processNum);
            produceFeignClient.askRestartDevice(deviceRebootMessage);
            //删除设备进程关系
            deviceProcessService.removeByIds(devId);

        } else {
            List<DeviceRebootMessage.DeviceInfo> list = new ArrayList<>();

            devId.forEach(temp -> {
                NodeDeviceParam nodeDeviceParam = new NodeDeviceParam();
                nodeDeviceParam.setDevId(temp);
                List<DeviceInfo> deviceInfos = nodeDeviceService.nodeDeviceList(nodeDeviceParam);
                if (CollectionUtil.isNotEmpty(deviceInfos)) {
                    deviceRebootMessage.setIndex(processNum);
                    DeviceInfo deviceInfo = deviceInfos.get(0);
                    DeviceRebootMessage.DeviceInfo deviceInfo1 = new DeviceRebootMessage.DeviceInfo();
                    BeanUtils.copyProperties(deviceInfo, deviceInfo1);
                    deviceInfo1.setProcessNo(processNum);
                    List<DeviceRebootMessage.DeviceInfo.MonitorInfo> monitorInfoList = deviceInfo.getMonitorData().stream().map(tempMonitorInfo -> {
                        DeviceRebootMessage.DeviceInfo.MonitorInfo m = new DeviceRebootMessage.DeviceInfo.MonitorInfo();
                        BeanUtils.copyProperties(tempMonitorInfo, m);
                        return m;
                    }).collect(Collectors.toList());
                    deviceInfo1.setMonitorData(monitorInfoList);
                    list.add(deviceInfo1);
                }
            });
            deviceRebootMessage.setData(list);
            produceFeignClient.askRestartDevice(deviceRebootMessage);
        }
    }


    @Override
    public List<PreCommandDTO> ledgerChangePush() {
        List<PreCommandDTO> preCommandDTOList = new ArrayList<>();
        DictData dataDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.PROCESS_PARMETER.getCode(), DicDataTypeEnum.DEV_OPS.getCode()).getData();

        QueryWrapper<PqsTerminalLogs> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(PqsTerminalLogs::getState, 1).eq(PqsTerminalLogs::getIsPush, 0).in(PqsTerminalLogs::getTerminalType, Stream.of(4, 6).collect(Collectors.toList()));
        //涉及进程修改的直接重启进程
        List<DeviceProcess> deviceProcesses = deviceProcessService.lambdaQuery().list();
        Map<String, Integer> deviceProcesseMap = deviceProcesses.stream().collect(Collectors.toMap(DeviceProcess::getId, DeviceProcess::getProcessNo));
        List<PqsTerminalLogs> list = pqsTerminalLogsMapper.selectList(queryWrapper);
        //获取所有监测点
        List<Line> lineById = this.lineMapper.selectList(null);
        Map<String, Line> lineMap = lineById.stream().collect(Collectors.toMap(Line::getId, Function.identity()));

        //监测点终端集合
        Map<String, String> lineDeviceMap = lineById.stream().filter(temp -> Objects.equals(temp.getLevel(), 6)).collect(Collectors.toMap(Line::getId, item -> item.getPids().split(",")[4]));
        List<Device> devices = deviceMapper.selectList(null);
        Map<String, Device> deviceMap = devices.stream().collect(Collectors.toMap(Device::getId, Function.identity()));
        List<Node> nodes = nodeService.nodeAllList();
        Map<String, Node> nodeMap = nodes.stream().collect(Collectors.toMap(Node::getId, Function.identity()));
        Map<String, Node> nodeNameMap = nodes.stream().collect(Collectors.toMap(Node::getName, Function.identity()));

        List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList = new ArrayList<>();
        List<String> addAndDelteId = new ArrayList<>();
        //异常标志
        Boolean exFlag= false;
        if (!CollectionUtils.isEmpty(list)) {
            List<PqsTerminalLogs> list1 = new ArrayList<>();
            try {
                //前置层修改
                list1 = list.stream().filter(temp -> temp.getTerminalDescribe().contains("终端所属前置机由")).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(list1)) {
                    for (PqsTerminalLogs temp : list1) {
                        String temLos = "%s终端所属前置机由 %s 改为> %s;";
                        List<String> strings = this.parseTemplateValues(temLos, temp.getTerminalDescribe());
                        String node1 = strings.get(1); // 第一个前置
                        String node2 = strings.get(2); // 第二个前置
                        if (deviceProcesseMap.containsKey(temp.getObjIndex())) {
                            Integer processNum = deviceProcesseMap.get(temp.getObjIndex());
                            PqsTerminalPushLogDTO pqsTerminalPushLogDTO = new PqsTerminalPushLogDTO();
                            pqsTerminalPushLogDTO.setId(temp.getId());
                            String deviceId = temp.getObjIndex();
                            pqsTerminalPushLogDTO.setDevId(deviceId);
                            pqsTerminalPushLogDTO.setDevName(lineMap.containsKey(deviceId) ? lineMap.get(deviceId).getName() : "删除设备");
                            pqsTerminalPushLogDTO.setNodeId(node1);
                            pqsTerminalPushLogDTO.setNodeName(nodeMap.get(node1).getName());
                            pqsTerminalPushLogDTO.setProcessUpdateFlag(true);
                            pqsTerminalPushLogDTO.setProcessNum(processNum);
                            pqsTerminalPushLogDTOList.add(pqsTerminalPushLogDTO);

                            PqsTerminalPushLogDTO pqsTerminalPushLogDTO2 = new PqsTerminalPushLogDTO();
                            pqsTerminalPushLogDTO2.setId(temp.getId());
                            pqsTerminalPushLogDTO2.setDevId(deviceId);
                            pqsTerminalPushLogDTO2.setDevName(lineMap.containsKey(deviceId) ? lineMap.get(deviceId).getName() : "删除设备");
                            pqsTerminalPushLogDTO2.setNodeId(node2);
                            pqsTerminalPushLogDTO2.setNodeName(nodeMap.get(node2).getName());
                            pqsTerminalPushLogDTO2.setProcessUpdateFlag(true);
                            pqsTerminalPushLogDTO2.setProcessNum(processNum);
                            pqsTerminalPushLogDTOList.add(pqsTerminalPushLogDTO2);

                        }
                    }
                }

                list.removeAll(list1);
                if (!CollectionUtils.isEmpty(list)) {
                    //终端层面和检测点层面修改
                    list.forEach(temp -> {
                        PqsTerminalPushLogDTO pqsTerminalPushLogDTO = new PqsTerminalPushLogDTO();
                        if (Objects.equals(temp.getTerminalType(), 6)) {
                            pqsTerminalPushLogDTO.setId(temp.getId());
                            String deviceId;
                            //如果不存在该设备id,说明监测点删除
                            if (!lineDeviceMap.containsKey(temp.getObjIndex())) {
                                String temLos = "%s监测点名称: %s";
                                List<String> strings = this.parseTemplateValues(temLos, temp.getTerminalDescribe());
                                String[] lineName = strings.get(1).split("->");
                                List<Line> devList = lineById.stream().filter(line -> Objects.equals(line.getName(), lineName[1])).collect(Collectors.toList());
                                if (CollectionUtils.isEmpty(devList)) {
                                    //如果不存在该设备说明设备也被删除，直接走下边删除设备逻辑;
                                    return;
                                } else {
                                    Line sub = lineById.stream().filter(line -> Objects.equals(line.getName(), lineName[0])).collect(Collectors.toList()).get(0);
                                    Line tempDev = devList.stream().filter(dev -> dev.getPid().equals(sub.getId())).collect(Collectors.toList()).get(0);
                                    deviceId = tempDev.getId();
                                }

                            } else {
                                deviceId = lineDeviceMap.get(temp.getObjIndex());

                            }

                            pqsTerminalPushLogDTO.setDevId(deviceId);
                            pqsTerminalPushLogDTO.setDevName(lineMap.get(deviceId).getName());
                            String nodeId = deviceMap.get(deviceId).getNodeId();
                            pqsTerminalPushLogDTO.setNodeId(nodeId);
                            //如果前置删了直接返回
                            if (!nodeMap.containsKey(nodeId)) {
                                return;
                            }
                            pqsTerminalPushLogDTO.setNodeName(nodeMap.get(nodeId).getName());
                            pqsTerminalPushLogDTO.setProcessUpdateFlag(false);
                            if (deviceProcesseMap.containsKey(deviceId)) {
                                pqsTerminalPushLogDTO.setProcessNum(deviceProcesseMap.get(deviceId));
                            } else {
                                throw new BusinessException("存在终端未设置进程号，请在前置管理页面设置进程号在进行此操作");
                            }
                            pqsTerminalPushLogDTO.setOperateType(DeviceRebootType.LEDGER_MODIFY);
                            pqsTerminalPushLogDTOList.add(pqsTerminalPushLogDTO);

                        } else if (Objects.equals(temp.getTerminalType(), 4)) {
                            String deviceId = temp.getObjIndex();
                            if(!deviceMap.containsKey(deviceId)){
                                //说明设备被删除
                                String temLos = "%s名称:%s;前置信息:%s";
                                List<String> strings = this.parseTemplateValues(temLos, temp.getTerminalDescribe());
                                String devName = strings.get(1); // 设备名称
                                String nodeName = strings.get(2); // 进程名称
                                pqsTerminalPushLogDTO.setDevName(devName);
                                //如果前置删了直接返回
                                if(!nodeNameMap.containsKey(nodeName)){
                                    return;
                                }
                                String nodeId = nodeNameMap.get(nodeName).getId();
                                pqsTerminalPushLogDTO.setNodeId(nodeId);
                                pqsTerminalPushLogDTO.setNodeName(nodeName);
                            }

                            //如果是修改进程操作记录2个进程日志;
                            if (temp.getLogsType().equals(dataDic.getId())) {
                                String temLos = "%s进行更新终端进程操作;终端名称 ：%s,由进程%s修改成进程%s";
                                List<String> strings = this.parseTemplateValues(temLos, temp.getTerminalDescribe());
                                String num1 = strings.get(2); // 第一个进程
                                String num2 = strings.get(3); // 第二个进程
                                int processId1 = Integer.parseInt(num1);
                                int processId2 = Integer.parseInt(num2);
                                pqsTerminalPushLogDTO.setId(temp.getId());
//                            String deviceId = temp.getObjIndex();
                                pqsTerminalPushLogDTO.setDevId(deviceId);
                                pqsTerminalPushLogDTO.setDevName(lineMap.containsKey(deviceId) ? lineMap.get(deviceId).getName() : "删除设备");
                                String nodeId = deviceMap.get(deviceId).getNodeId();
                                pqsTerminalPushLogDTO.setNodeId(nodeId);
                                pqsTerminalPushLogDTO.setNodeName(nodeMap.get(nodeId).getName());
                                pqsTerminalPushLogDTO.setProcessUpdateFlag(true);
                                pqsTerminalPushLogDTO.setProcessNum(processId1);
                                pqsTerminalPushLogDTOList.add(pqsTerminalPushLogDTO);
                                PqsTerminalPushLogDTO pqsTerminalPushLogDTO1 = new PqsTerminalPushLogDTO();

                                pqsTerminalPushLogDTO1.setId(temp.getId());
                                pqsTerminalPushLogDTO1.setDevId(deviceId);
                                pqsTerminalPushLogDTO1.setDevName(lineMap.get(deviceId).getName());
                                pqsTerminalPushLogDTO1.setNodeId(nodeId);
                                pqsTerminalPushLogDTO1.setNodeName(nodeMap.get(nodeId).getName());
                                pqsTerminalPushLogDTO1.setProcessUpdateFlag(true);
                                pqsTerminalPushLogDTO1.setProcessNum(processId2);
                                pqsTerminalPushLogDTOList.add(pqsTerminalPushLogDTO1);

                            } else {
                                pqsTerminalPushLogDTO.setId(temp.getId());
//                            String deviceId = temp.getObjIndex();
                                pqsTerminalPushLogDTO.setDevId(deviceId);
                                //区分删除操作，新增和其他操作
                                String operate = DeviceRebootType.LEDGER_MODIFY;

                                if (Objects.equals(temp.getOperateType(), Param.DEL)) {
                                    operate = DeviceRebootType.DELETE_TERMINAL;


                                } else if (Objects.equals(temp.getOperateType(), Param.ADD)) {
                                    operate = DeviceRebootType.ADD_TERMINAL;

                                }
                                //设备删除找不到设备名称,重日志截取
                                if (Objects.equals(temp.getOperateType(), Param.DEL)) {
                                    //删除有2种情况，1.设备删除，2，设备状态修改；
                                    if (lineMap.containsKey(deviceId)) {
                                        pqsTerminalPushLogDTO.setDevName(lineMap.get(deviceId).getName());
                                        String nodeId = deviceMap.get(deviceId).getNodeId();
                                        pqsTerminalPushLogDTO.setNodeId(nodeId);
                                        pqsTerminalPushLogDTO.setNodeName(nodeMap.containsKey(nodeId)?nodeMap.get(nodeId).getName():"删除前置");

                                    }else {
                                        if(temp.getTerminalDescribe().contains("前置信息")){
                                            String temLos = "%s名称:%s;前置信息:%s";
                                            List<String> strings = this.parseTemplateValues(temLos, temp.getTerminalDescribe());
                                            String devName = strings.get(1); // 设备名称
                                            String nodeName = strings.get(2); // 进程名称
                                            pqsTerminalPushLogDTO.setDevName(devName);
                                            String nodeId = nodeNameMap.get(nodeName).getId();
                                            pqsTerminalPushLogDTO.setNodeId(nodeId);
                                            pqsTerminalPushLogDTO.setNodeName(nodeName);
                                        }else {
                                            return;
                                        }

                                    }

                                } else {
                                    //如果存在说明设备未被删除，不存在说明有一条删除日志，直接return；
                                    if (lineMap.containsKey(deviceId)) {
                                        pqsTerminalPushLogDTO.setDevName(lineMap.get(deviceId).getName());
                                    } else {
                                        pqsTerminalPushLogDTO.setDevName("删除设备");

                                    }
                                    //如果新增的没有，说明该新增设备在本次也删除了，
                                    if (deviceMap.containsKey(deviceId)) {
                                        String nodeId = deviceMap.get(deviceId).getNodeId();
                                        pqsTerminalPushLogDTO.setNodeId(nodeId);
                                        pqsTerminalPushLogDTO.setNodeName(nodeMap.containsKey(nodeId)?nodeMap.get(nodeId).getName():"删除前置");
                                    } else {
                                        addAndDelteId.add(deviceId);
                                        return;
                                    }


                                }

                                pqsTerminalPushLogDTO.setProcessUpdateFlag(false);
                                if (deviceProcesseMap.containsKey(deviceId)) {
                                    pqsTerminalPushLogDTO.setProcessNum(deviceProcesseMap.get(deviceId));
                                } else {
                                    throw new BusinessException("存在终端未设置进程号，请在前置管理页面设置进程号在进行此操作");
                                }

                                pqsTerminalPushLogDTO.setOperateType(operate);
                                pqsTerminalPushLogDTOList.add(pqsTerminalPushLogDTO);
                            }


                        }

                    });
                }


                Map<String, Map<Integer, List<PqsTerminalPushLogDTO>>> collect2 = pqsTerminalPushLogDTOList.stream().filter(temp -> !addAndDelteId.contains(temp.getDevId())).collect(Collectors.groupingBy(PqsTerminalPushLogDTO::getNodeId, Collectors.groupingBy(PqsTerminalPushLogDTO::getProcessNum)));
                collect2.forEach((nodeId, pqsTerminalPushLogDTOMap) -> {
                    pqsTerminalPushLogDTOMap.forEach((processId, tempPqsTerminalPushLogDTOList) -> {

                        PqsTerminalPushLogDTO pqsTerminalPushLogDTO = tempPqsTerminalPushLogDTOList.get(0);
                        //如果存在终端变更进程的记录直接重启进程
                        boolean processUpdateFlag = tempPqsTerminalPushLogDTOList.stream().map(PqsTerminalPushLogDTO::getProcessUpdateFlag).anyMatch(b -> b != null && b);
                        if (processUpdateFlag) {
                            PreCommandDTO preCommandDTO = new PreCommandDTO();
                            String guid = IdUtil.simpleUUID();
                            String command = "重启前置机：" + pqsTerminalPushLogDTO.getNodeName() + "下进程：" + processId;
                            preCommandDTO.setGuid(guid);
                            preCommandDTO.setCommand(command);
                            preCommandDTO.setResult("2");
                            //调用重启进程接口
                            this.askRestartProcess(guid, pqsTerminalPushLogDTO.getNodeId(), processId, "delete", "all");
                            preCommandDTOList.add(preCommandDTO);
                        } else {
                            List<String> deviceIds = tempPqsTerminalPushLogDTOList.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                            //如果一个进程上涉及10个以上的设备修改，直接重启进程，否则重启设备
                            if (CollectionUtil.isNotEmpty(deviceIds) && deviceIds.size() > 10) {
                                PreCommandDTO preCommandDTO = new PreCommandDTO();
                                String guid = IdUtil.simpleUUID();
                                String command = "重启前置机：" + pqsTerminalPushLogDTO.getNodeName() + "下进程：" + processId;
                                preCommandDTO.setGuid(guid);
                                preCommandDTO.setCommand(command);
                                preCommandDTO.setResult("2");

                                //调用重启进程接口
                                this.askRestartProcess(guid, pqsTerminalPushLogDTO.getNodeId(), processId, "delete", "all");
                                preCommandDTOList.add(preCommandDTO);

                            } else {
                                //调用重启设备接口先删除设备，在新增，在修改在重启设备
                                List<String> deleteDevIds = new ArrayList<>();
                                List<String> addDevIds = new ArrayList<>();
                                List<String> modifyDevIds = new ArrayList<>();
                                Map<String, List<PqsTerminalPushLogDTO>> collect = tempPqsTerminalPushLogDTOList.stream().collect(Collectors.groupingBy(PqsTerminalPushLogDTO::getOperateType));
                                if (collect.containsKey(DeviceRebootType.DELETE_TERMINAL)) {
                                    List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList1 = collect.get(DeviceRebootType.DELETE_TERMINAL);
                                    deleteDevIds = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                                }
                                if (collect.containsKey(DeviceRebootType.ADD_TERMINAL)) {
                                    List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList1 = collect.get(DeviceRebootType.ADD_TERMINAL);
                                    addDevIds = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                                }
                                if (collect.containsKey(DeviceRebootType.LEDGER_MODIFY)) {
                                    List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList1 = collect.get(DeviceRebootType.LEDGER_MODIFY);
                                    modifyDevIds = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                                }
                                if (collect.containsKey(DeviceRebootType.DELETE_TERMINAL)) {
                                    List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList1 = collect.get(DeviceRebootType.DELETE_TERMINAL);
                                    List<String> finalAddDevIds = addDevIds;
                                    //过滤本次新增的设备，因为前置那边还没有新增该装备
                                    pqsTerminalPushLogDTOList1 = pqsTerminalPushLogDTOList1.stream().filter(temp -> !finalAddDevIds.contains(temp.getDevId())).distinct().collect(Collectors.toList());
                                    if (!CollectionUtils.isEmpty(pqsTerminalPushLogDTOList1)) {
                                        String devNameString = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevName).distinct().collect(Collectors.joining(","));
                                        List<String> resultDevIds = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                                        PreCommandDTO preCommandDTO = new PreCommandDTO();
                                        String guid = IdUtil.simpleUUID();

                                        String command = "删除前置机：" + pqsTerminalPushLogDTO.getNodeName() + "下进程：" + processId + "下终端" + devNameString;
                                        preCommandDTO.setGuid(guid);
                                        preCommandDTO.setCommand(command);
                                        preCommandDTO.setResult("2");

                                        //调用重启设备接口
                                        this.askRestartDevice(guid, pqsTerminalPushLogDTO.getNodeId(), resultDevIds, DeviceRebootType.DELETE_TERMINAL, processId);
                                        preCommandDTOList.add(preCommandDTO);
                                    }


                                }
                                if (collect.containsKey(DeviceRebootType.ADD_TERMINAL)) {
                                    List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList1 = collect.get(DeviceRebootType.ADD_TERMINAL);
                                    List<String> finalDeleteDevIds = deleteDevIds;
                                    pqsTerminalPushLogDTOList1 = pqsTerminalPushLogDTOList1.stream().filter(temp -> !finalDeleteDevIds.contains(temp.getDevId())).distinct().collect(Collectors.toList());

                                    if (!CollectionUtils.isEmpty(pqsTerminalPushLogDTOList1)) {
                                        String devNameString = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevName).distinct().collect(Collectors.joining(","));
                                        List<String> resultDevIds = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                                        PreCommandDTO preCommandDTO = new PreCommandDTO();
                                        String guid = IdUtil.simpleUUID();
                                        String command = "新增前置机：" + pqsTerminalPushLogDTO.getNodeName() + "下进程：" + processId + "下终端" + devNameString;
                                        preCommandDTO.setGuid(guid);
                                        preCommandDTO.setCommand(command);
                                        preCommandDTO.setResult("2");

                                        //调用重启进程接口
                                        this.askRestartDevice(guid, pqsTerminalPushLogDTO.getNodeId(), resultDevIds, DeviceRebootType.ADD_TERMINAL, processId);

                                        preCommandDTOList.add(preCommandDTO);
                                    }

                                }
                                if (collect.containsKey(DeviceRebootType.LEDGER_MODIFY)) {
                                    List<PqsTerminalPushLogDTO> pqsTerminalPushLogDTOList1 = collect.get(DeviceRebootType.LEDGER_MODIFY);
                                    List<String> finalDeleteDevIds1 = deleteDevIds;
                                    List<String> finalAddDevIds1 = addDevIds;
                                    pqsTerminalPushLogDTOList1 = pqsTerminalPushLogDTOList1.stream().filter(temp -> !finalDeleteDevIds1.contains(temp.getDevId()) && !finalAddDevIds1.contains(temp.getDevId())).distinct().collect(Collectors.toList());

                                    if (!CollectionUtils.isEmpty(pqsTerminalPushLogDTOList1)) {
                                        String devNameString = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevName).distinct().collect(Collectors.joining(","));
                                        List<String> resultDevIds = pqsTerminalPushLogDTOList1.stream().map(PqsTerminalPushLogDTO::getDevId).distinct().collect(Collectors.toList());
                                        PreCommandDTO preCommandDTO = new PreCommandDTO();
                                        String guid = IdUtil.simpleUUID();
                                        String command = "修改前置机：" + pqsTerminalPushLogDTO.getNodeName() + "下进程：" + processId + "下终端" + devNameString;
                                        preCommandDTO.setGuid(guid);
                                        preCommandDTO.setCommand(command);
                                        preCommandDTO.setResult("2");
                                        //调用重启进程接口
                                        this.askRestartDevice(guid, pqsTerminalPushLogDTO.getNodeId(), resultDevIds, DeviceRebootType.LEDGER_MODIFY, processId);
                                        preCommandDTOList.add(preCommandDTO);
                                    }

                                }


                            }
                        }

                    });
                });
            } catch (Exception e) {
                log.info("台账同步推送异常：" + e);
                //出现异常，直接重启整个前置
                exFlag=true;
                for (Node node : nodes) {
                    RestartParam restartParam = new RestartParam();
                    restartParam.setDeviceRebootType("1");
                    restartParam.setNodeId(node.getId());

                    askRestartProcess(restartParam);
                }

            }

            if (!CollectionUtils.isEmpty(list1)) {
                list1.forEach(temp -> {
                    temp.setIsPush(1);

                    pqsTerminalLogsMapper.updateById(temp);
                });
            }
            if (!CollectionUtils.isEmpty(list)) {
                list.forEach(temp -> {
                    temp.setIsPush(1);

                    pqsTerminalLogsMapper.updateById(temp);
                });
            }


        } else {
            throw new BusinessException("暂无变动的装置测点推送");
        }
        if(exFlag){
            throw new BusinessException("存在未知错误，重启前置");

        }
        if (CollectionUtils.isEmpty(preCommandDTOList)) {
            throw new BusinessException("暂无变动的装置测点推送");
        }
        return preCommandDTOList;
    }

    @Override


    public PushResultDTO getPushResult(String guid) {
        PushResultDTO pushResultDTO = new PushResultDTO();
        String stringByKey = redisUtil.getStringByKey(RedisKeyPrefix.TOPIC_REPLY.concat(guid));
        if (Objects.isNull(stringByKey)) {
            pushResultDTO.setCode("2");
            pushResultDTO.setResult("");
        } else {
            TopicReplyDTO topicReplyDTO = JSONObject.parseObject(stringByKey, TopicReplyDTO.class);
            pushResultDTO.setCode("1");
            pushResultDTO.setResult(topicReplyDTO.getResult());


        }
        return pushResultDTO;
    }

    @Override
    public void askRestartProcess(RestartParam restartParam) {

        ProcessRebootMessage procesRebootMessage = new ProcessRebootMessage();

        Node nodeById = nodeService.getNodeById(restartParam.getNodeId());
        procesRebootMessage.setIndex(restartParam.getProcessNo());
        if (Objects.equals("1", restartParam.getDeviceRebootType())) {
            procesRebootMessage.setFun("reset");
            procesRebootMessage.setProcessNum(nodeById.getMaxProcessNum());
            procesRebootMessage.setProcessNo(1);

        } else {
            procesRebootMessage.setFun("delete");
            procesRebootMessage.setProcessNo(restartParam.getProcessNo());

        }
        procesRebootMessage.setFrontType("all");
        procesRebootMessage.setNodeId(restartParam.getNodeId());
        String guid = IdUtil.simpleUUID();

        procesRebootMessage.setGuid(guid);
        produceFeignClient.askRestartProcess(procesRebootMessage);

    }

    //反解析日志
    public List<String> parseTemplateValues(String template, String actualString) {
        List<String> values = new ArrayList<>();

        // 分割模板字符串，以%s为分隔符
        String[] templateParts = template.split("%s", -1);  // -1保留末尾空字符串

        int currentPos = 0;
        for (int i = 0; i < templateParts.length - 1; i++) {
            String part = templateParts[i];

            // 在原始字符串中找到当前模板部分的位置
            int partIndex = actualString.indexOf(part, currentPos);
            if (partIndex == -1) {
                throw new IllegalArgumentException("字符串不匹配模板");
            }

            // 计算值开始位置
            int valueStart = partIndex + part.length();

            // 找到下一个模板部分的位置来确定值结束位置
            String nextPart = templateParts[i + 1];
            int nextPartIndex;
            if (nextPart.isEmpty()) {
                // 如果下一个部分是空字符串，则值到字符串末尾
                nextPartIndex = actualString.length();
            } else {
                nextPartIndex = actualString.indexOf(nextPart, valueStart);
                if (nextPartIndex == -1) {
                    throw new IllegalArgumentException("字符串不匹配模板");
                }
            }

            // 提取值
            String value = actualString.substring(valueStart, nextPartIndex);
            values.add(value);

            currentPos = nextPartIndex;
        }

        return values;
    }


    /**
     * 终端日志记录(只记录新增删除)
     */
    private void terminalLogsCat(List<Line> logsList, String operateType, List<PqsTerminalLogs> pqsTerminalLogsList, Map<String, Node> nodeMap) {
        String op;
        Map<String, Line> subMap = new HashMap<>();
        List<Line> temList = logsList.stream().filter(it -> it.getLevel().equals(LINE_LEVEL.getCode()) || it.getLevel().equals(DEVICE_LEVEL.getCode())).collect(Collectors.toList());
        if (CollUtil.isEmpty(temList)) {
            return;
        }
        switch (operateType) {
            case Param.ADD:
                op = Param.ADD_ZN;
                List<String> stationIds = temList.stream().map(it -> it.getPids().split(StrUtil.COMMA)[SUB_LEVEL.getCode()]).distinct().collect(Collectors.toList());
                List<Line> subList = this.listByIds(stationIds);
                subMap = subList.stream().collect(Collectors.toMap(Line::getId, Function.identity()));
                break;
            case Param.DEL:
                op = Param.DEL_ZN;
                List<Line> stationList = logsList.stream().filter(it -> it.getLevel().equals(SUB_LEVEL.getCode())).collect(Collectors.toList());
                subMap = stationList.stream().collect(Collectors.toMap(Line::getId, Function.identity()));

                break;
            default:
                op = Param.UNKONOW;
                break;
        }
        DictData monitorDataDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.LINE_PARAMETER.getCode(), DicDataTypeEnum.DEV_OPS.getCode()).getData();
        DictData devDataDic = dicDataFeignClient.getDicDataByCodeAndType(DicDataEnum.DEV_PARAMETER.getCode(), DicDataTypeEnum.DEV_OPS.getCode()).getData();
        String name = RequestUtil.getUserNickname();
        if (CollUtil.isNotEmpty(temList)) {
            for (Line line : temList) {
                PqsTerminalLogs pqsTerminalLogs = new PqsTerminalLogs();
                pqsTerminalLogs.setTerminalType(line.getLevel());
                if (line.getLevel().equals(LINE_LEVEL.getCode())) {
                    pqsTerminalLogs.setLogsType(monitorDataDic.getId());
                } else if (line.getLevel().equals(DEVICE_LEVEL.getCode())) {
                    pqsTerminalLogs.setLogsType(devDataDic.getId());
                }
                String subName;
                String levelOperate;
                String tem;
                String nodeName = "";
                if (line.getLevel().equals(LINE_LEVEL.getCode())) {
                    levelOperate = LINE_LEVEL.getMessage();
                } else {
                    levelOperate = DEVICE_LEVEL.getMessage();
                    if (nodeMap.containsKey(line.getId())) {
                        nodeName = ";前置信息:" + nodeMap.get(line.getId()).getName();
                    }

                }
                subName = subMap.get(line.getPids().split(StrUtil.COMMA)[SUB_LEVEL.getCode()]).getName();
                String temLos = "%s进行%s%s操作;详细信息: %s名称: %s";
                if (line.getLevel().equals(LINE_LEVEL.getCode())) {
                    String devId=line.getPids().split(StrUtil.COMMA)[DEVICE_LEVEL.getCode()];
                    Line byId = this.getById(devId);
                    String devName="";
                    //设备已删除
                    if(Objects.nonNull(byId)){
                        devName= byId.getName();
                    }else{
                        List<Line> device = logsList.stream().filter(temp -> Objects.equals(temp.getId(), devId)).collect(Collectors.toList());
                        if(!CollectionUtils.isEmpty(device)){
                            devName =device.get(0).getName();
                        }else {
                            devName = "已删除设备";

                        }
                    }
                    tem = String.format(temLos, name, op, levelOperate, levelOperate, subName + "->" + devName + "->" + line.getName() + nodeName);
                } else {
                    tem = String.format(temLos, name, op, levelOperate, levelOperate, subName + "->" + line.getName() + nodeName);


                }
                pqsTerminalLogs.setTerminalDescribe(tem);
                pqsTerminalLogs.setState(DataStateEnum.ENABLE.getCode());
                pqsTerminalLogs.setIsPush(0);
                pqsTerminalLogs.setOperateType(operateType);
                pqsTerminalLogs.setObjIndex(line.getId());
                pqsTerminalLogsList.add(pqsTerminalLogs);
            }

        }
    }


    /**
     * 终端日志记录(记录修改)
     *
     * @param op
     * @param updateDeviceParam
     * @param devicePO
     * @param sub
     * @param devDetail
     * @param pqsTerminalLogsList
     * @param dictDataMap
     * @param dicDataByCode
     * @param userName
     */
    public void devLogsCat(String op, DeviceParam updateDeviceParam, Line devicePO, Line sub, Device devDetail, List<PqsTerminalLogs> pqsTerminalLogsList, Map<String, DictData> dictDataMap, DictData dicDataByCode, String userName) {
        StringBuilder stringBuilder = new StringBuilder(String.format("%s进行%s装置(%s_%s)操作,详细信息:", userName, op, sub.getName(), devicePO.getName()));

        if (Param.DEL_ZN.equals(op)) {
            Node node = nodeService.getById(devDetail.getNodeId());
            String info = sub.getName() + "_" + devicePO.getName() + ";前置信息:" + node.getName();
            stringBuilder.append(info);
            PqsTerminalLogs pqsTerminalLogs = new PqsTerminalLogs();
            pqsTerminalLogs.setOperateType(Param.DEL);
            pqsTerminalLogs.setTerminalType(DEVICE_LEVEL.getCode());
            pqsTerminalLogs.setState(DataStateEnum.ENABLE.getCode());
            pqsTerminalLogs.setObjIndex(devicePO.getId());
            pqsTerminalLogs.setIsPush(0);
            pqsTerminalLogs.setLogsType(dicDataByCode.getId());
            pqsTerminalLogs.setTerminalDescribe(stringBuilder.toString());
            pqsTerminalLogsList.add(pqsTerminalLogs);
        } else if (Param.UPDATE_ZN.equals(op)) {

            boolean flag = false;
            // 比较装置名称
            flag |= compareAndAppend(stringBuilder, devicePO.getName(), updateDeviceParam.getName(), "终端名称");

            // 比较装置 IP
            flag |= compareAndAppend(stringBuilder, devDetail.getIp(), updateDeviceParam.getIp(), "终端ip");

            // 比较装置 所属前置
            flag |= compareAndAppend(stringBuilder, devDetail.getNodeId(), updateDeviceParam.getNodeId(), "终端所属前置机");
            //如果前置机切换，可能装置在进程2上，但是切换后前置机只有一个进程，因此修改装置进程表设为默认进程1
            if(!Objects.equals(updateDeviceParam.getNodeId(), devDetail.getNodeId())){
                deviceProcessService.lambdaUpdate().eq(DeviceProcess::getId,devDetail.getId()).set(DeviceProcess::getProcessNo,1).update();
            }

            // 比较装置端口号
            flag |= compareAndAppend(stringBuilder, devDetail.getPort(), updateDeviceParam.getPort(), "终端端口号");
            // 比较装置端口号
            flag |= compareAndAppend(stringBuilder, devDetail.getDevKey(), updateDeviceParam.getDevKey(), "终端识别码");
            // 比较装置端口号
            flag |= compareAndAppend(stringBuilder, devDetail.getSeries(), updateDeviceParam.getSeries(), "终端秘钥");
            // 比较装置型号
            if (updateDeviceParam.getDevType() != null) {
                String oldDevTypeName = dictDataMap.get(devDetail.getDevType()) != null ? dictDataMap.get(devDetail.getDevType()).getName() : null;
                String newDevTypeName = dictDataMap.get(updateDeviceParam.getDevType()) != null ? dictDataMap.get(updateDeviceParam.getDevType()).getName() : null;
                flag |= compareAndAppend(stringBuilder, oldDevTypeName, newDevTypeName, "终端型号");
            }
            if (flag) {
                PqsTerminalLogs pqsTerminalLogs = new PqsTerminalLogs();
                pqsTerminalLogs.setOperateType(Param.UPDATE);
                pqsTerminalLogs.setTerminalType(DEVICE_LEVEL.getCode());
                pqsTerminalLogs.setState(DataStateEnum.ENABLE.getCode());
                pqsTerminalLogs.setObjIndex(devicePO.getId());
                pqsTerminalLogs.setIsPush(0);
                pqsTerminalLogs.setLogsType(dicDataByCode.getId());
                pqsTerminalLogs.setTerminalDescribe(stringBuilder.toString());
                pqsTerminalLogsList.add(pqsTerminalLogs);
            }
        }
    }

    private boolean compareAndAppend(StringBuilder sb, String oldValue, String newValue, String fieldName) {
        if (oldValue != null && !oldValue.equals(newValue)) {
            sb.append(String.format("%s由 %s 改为> %s;", fieldName, oldValue, newValue));
            return true;
        }
        return false;
    }

    private boolean compareAndAppend(StringBuilder sb, Integer oldValue, Integer newValue, String fieldName) {
        if (oldValue != null && !oldValue.equals(newValue)) {
            sb.append(String.format("%s由 %s 改为> %s;", fieldName, oldValue, newValue));
            return true;
        }
        return false;
    }
}
