package com.yeejoin.equipmanage.service.impl;

import cn.hutool.core.util.StrUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
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.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.interceptors.PermissionInterceptorContext;
import com.yeejoin.amos.boot.biz.common.utils.RedisUtils;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.systemctl.model.MessageModel;
import com.yeejoin.equipmanage.common.datasync.entity.FireEquipment;
import com.yeejoin.equipmanage.common.datasync.vo.FireEquipmentVO;
import com.yeejoin.equipmanage.common.dto.EquipmentSpecificDto;
import com.yeejoin.equipmanage.common.dto.FireFightingSystemDto;
import com.yeejoin.equipmanage.common.dto.UserDto;
import com.yeejoin.equipmanage.common.entity.*;
import com.yeejoin.equipmanage.common.entity.dto.EquipTypeAmountPageDTO;
import com.yeejoin.equipmanage.common.entity.dto.EquipmentSpecificDTO;
import com.yeejoin.equipmanage.common.entity.vo.*;
import com.yeejoin.equipmanage.common.enums.*;
import com.yeejoin.equipmanage.common.exception.BaseException;
import com.yeejoin.equipmanage.common.utils.CommonResponseUtil;
import com.yeejoin.equipmanage.common.utils.DateUtils;
import com.yeejoin.equipmanage.common.utils.QRCodeUtil;
import com.yeejoin.equipmanage.common.utils.StringUtil;
import com.yeejoin.equipmanage.common.vo.*;
import com.yeejoin.equipmanage.fegin.IdxFeign;
import com.yeejoin.equipmanage.fegin.IotFeign;
import com.yeejoin.equipmanage.fegin.SystemctlFeign;
import com.yeejoin.equipmanage.mapper.*;
import com.yeejoin.equipmanage.remote.RemoteSecurityService;
import com.yeejoin.equipmanage.service.*;
import com.yeejoin.equipmanage.utils.RelationRedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.Resource;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.component.emq.EmqKeeper;
import org.typroject.tyboot.core.foundation.utils.Bean;
import org.typroject.tyboot.core.foundation.utils.DateTimeUtil;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static org.apache.poi.Version.getProduct;
import static org.typroject.tyboot.core.foundation.context.RequestContext.getAppKey;
import static org.typroject.tyboot.core.foundation.context.RequestContext.getToken;
import static org.typroject.tyboot.core.foundation.utils.DateTimeUtil.ISO8601_DATE_HOUR_MIN_SEC;

/**
 * @author ZeHua Li
 * @date 2020/10/29 16:58
 * @since v2.0
 */
@Service
//@EnableAsync
@Slf4j
public class EquipmentSpecificSerivceImpl extends ServiceImpl<EquipmentSpecificMapper, EquipmentSpecific> implements IEquipmentSpecificSerivce {

    @Value("${auth-key-auth-enabled:}")
    private String authKey;
    private final String injection = "{\n" +
            "\n" +
            "        \"items\": [\n" +
            "\n" +
            "          { \"key\": \"巡检点\", \"value\": \"主楼一层 L06D003 烟感探测器\" },\n" +
            "\n" +
            "          { \"key\": \"巡检周期\", \"value\": \"1周\" },\n" +
            "\n" +
            "          { \"key\": \"巡检人员\", \"value\": \"王某某\" },\n" +
            "\n" +
            "          { \"key\": \"巡检单位\", \"value\": \"王某某公司\" },\n" +
            "\n" +
            "           { \"key\": \"巡检依据\", \"value\": \"烟感报警器巡检规范\" }\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"inspectionApi\": \"http://172.16.11.36:8100/equip/equipSpecific/getMaintenanceInfo\",\n" +
            "\t\t\"inspectionParams\": [\"checkDate\"],\n" +
            "\n" +
            "        \"inspectionPeriod\": {\n" +
            "\n" +
            "          \"items\": [\n" +
            "\n" +
            "            { \"key\": \"巡检时间\", \"value\": \"2020-11-27  10:00:02\" },\n" +
            "\n" +
            "            { \"key\": \"巡检结果\", \"value\": \"正常\" }\n" +
            "\n" +
            "          ],\n" +
            "\n" +
            "          \"modelName\":\"巡检\",\n" +
            "\n" +
            "          \"picUrl\": [\"http://39.98.246.31:8888/group1/M00/00/34/rBq-8F-FHRCAbU9GAAACvViVp0w113.png\"],\n" +
            "\n" +
            "          \"videoUrl\": [\"xxx.xxx\"]\n" +
            "\n" +
            "        },\n" +
            "\n" +
            "        \"colums\": [\n" +
            "\n" +
            "          {\"key\": \"inspectionRequire\", \"value\": \"巡检要求\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionMethod\", \"value\": \"巡检方法\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionResult\", \"value\": \"巡检结果\"}\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"tableList\": [\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"1\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"2\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"3\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"4\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          }\n" +
            "\n" +
            "        ]\n" +
            "\n" +
            "      }";
    private final String maintenance = "{\n" +
            "\n" +
            "        \"items\": [\n" +
            "\n" +
            "          { \"key\": \"巡检点\", \"value\": \"主楼一层 L06D003 烟感探测器\" },\n" +
            "\n" +
            "          { \"key\": \"巡检周期\", \"value\": \"1周\" },\n" +
            "\n" +
            "          { \"key\": \"巡检人员\", \"value\": \"王某某\" },\n" +
            "\n" +
            "          { \"key\": \"巡检单位\", \"value\": \"王某某公司\" },\n" +
            "\n" +
            "          { \"key\": \"巡检依据\", \"value\": \"烟感报警器巡检规范\" }\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"inspectionApi\": \"http://172.16.11.36:8100/equip/equipSpecific/getMaintenanceInfo\",\n" +
            "\t\t\"inspectionParams\": [\"checkDate\"],\n" +
            "\n" +
            "        \"inspectionPeriod\": {\n" +
            "\n" +
            "          \"items\": [\n" +
            "\n" +
            "            { \"key\": \"维保时间\", \"value\": \"2020-11-27  10:00:02\" },\n" +
            "\n" +
            "            { \"key\": \"维保结果\", \"value\": \"正常\" }\n" +
            "\n" +
            "          ],\n" +
            "\n" +
            "          \"modelName\":\"维保\",\n" +
            "\n" +
            "          \"picUrl\": [\"http://39.98.246.31:8888/group1/M00/00/34/rBq-8F-FHRCAbU9GAAACvViVp0w113.png\"],\n" +
            "\n" +
            "          \"videoUrl\": [\"xxx.xxx\"]\n" +
            "\n" +
            "        },\n" +
            "\n" +
            "        \"colums\": [\n" +
            "\n" +
            "          {\"key\": \"inspectionRequire\", \"value\": \"维保要求\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionMethod\", \"value\": \"维保方法\"},\n" +
            "\n" +
            "          {\"key\": \"inspectionResult\", \"value\": \"维保结果\"}\n" +
            "\n" +
            "        ],\n" +
            "\n" +
            "        \"tableList\": [\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"1\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"2\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"3\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          },\n" +
            "\n" +
            "          {\n" +
            "\n" +
            "            \"id\": \"4\",\n" +
            "\n" +
            "            \"inspectionRequire\": \"外观应完好，无明显损伤\",\n" +
            "\n" +
            "            \"inspectionMethod\": \"目测、手动检查\",\n" +
            "\n" +
            "            \"inspectionResult\": \"正常\"\n" +
            "\n" +
            "          }\n" +
            "\n" +
            "        ]\n" +
            "\n" +
            "      }";
    @Autowired
    protected EmqKeeper emqKeeper;
    @Autowired
    IStockDetailService stockDetailService;
    @Autowired
    @Lazy
    IStockService stockService;
    @Autowired
    @Lazy
    IEquipmentSpecificIndexSerivce equipmentSpecificIndexSerivce;
    @Autowired
    IStockBillDetailService stockBillDetailService;
    @Autowired
    IStockBillService stockBillService;
    @Autowired
    EquipmentSpecificAlarmMapper equipmentSpecificAlarmMapper;
    @Autowired
    UploadFileMapper uploadFileMapper;

    @Autowired
    IEquipmentDetailService equipmentDetailService;
    @Autowired
    IWarehouseService warehouseService;
    @Autowired
    IWarehouseStructureService warehouseStructureService;
    @Autowired
    @Lazy
    IEquipmentService equipmentService;


    @Autowired
    IFireFightingSystemService iFireFightingSystemService;
    @Autowired
    IEquipmentSystemSourceStatisticsService equipmentSystemSourceStatisticsService;

    @Autowired
    IEquipmentIndexService iEquipmentIndexService;

    @Value("${equipment.type}")
    String equipmentCategoryLeftTypeCode;
    @Value("${equipment.scrap.day}")
    String equipmentScrapDay;

    @Autowired
    FireFightingSystemMapper fireFightingSystemMapper;
    @Autowired
    IEquipmentSpecificAlarmService equipmentSpecificAlarmService;
    @Autowired
    WarehouseStructureMapper warehouseStructureMapper;
    @Autowired
    FormInstanceMapper formInstanceMapper;
    @Autowired
    FormInstanceEquipMapper formInstanceEquipMapper;
    @Autowired
    EquipmentSpecificIndexMapper equipmentSpecificIndexMapper;
    @Autowired
    private RemoteSecurityService remoteSecurityService;
    @Autowired
    private SystemctlFeign systemctlFeign;
    @Autowired
    private Sequence sequence;
    @Autowired
    private IUploadFileService iUploadFileService;
    @Autowired
    private EquipmentSpecificMapper equipmentSpecificMapper;
    @Autowired
    private IVideoService videoService;
    @Autowired
    private ICarService carService;
    @Autowired
    private IVideoEquipmentSpecificService videoEquipmentSpecificService;
    @Autowired
    private IFormInstanceService formInstanceService;
    @Autowired
    private IFormInstanceEquipService formInstanceEquipService;
    @Value("${systemctl.dict.iot-core-param}")
    private String iotCoreParam;
    @Value("${equipment.filter.code}")
    private String codes;
    @Autowired
    private ISyncDataService syncDataService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private RelationRedisUtil relationRedisUtil;
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private IdxFeign idxFeign;
    @Value("${systemctl.sync.switch}")
    private Boolean syncSwitch;
    @Value("classpath:/json/equipmentCode.json")
    private Resource equipmentCode;
    @Value("${equipment.pressurepump.start}")
    private String pressurePumpStart;

    @Autowired
    IotFeign iotFeign;


    private StockBill buildStockBills(EquipmentSpecific equipmentSpecific, ReginParams reginParams, AgencyUserModel agencyUserModel) {
        StockBill stockBill = new StockBill();
        stockBill.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
        stockBill.setCreatorName(agencyUserModel.getRealName());
        stockBill.setCompanyName(reginParams.getCompany().getCompanyName());
        stockBill.setDepartmentName(reginParams.getDepartment().getDepartmentName());
        stockBill.setDepartmentOrgcode(String.valueOf(reginParams.getDepartment().getDeptOrgCode()));
        stockBill.setOrgCode(reginParams.getCompany().getOrgCode());
        stockBill.setWarehouseId(equipmentSpecific.getStockDetail().getWarehouseId());
        stockBill.setBillCode(stockBillService.generateQrCode("RK"));
        stockBill.setBillType(StockBillTypeEnum.DBRK.getValue());
        return stockBill;
    }

    private List<EquipmentDetail> saveEquipmentDetailBatch(EquipmentDetail equipmentDetailVo, int loopTime) {
        List<EquipmentDetail> equipmentDetails = new ArrayList<>();
        for (int i = 0; i < loopTime; i++) {
            EquipmentDetail equipmentDetail = new EquipmentDetail();
            Bean.copyExistPropertis(equipmentDetailVo, equipmentDetail);
            equipmentDetail.setId(equipmentDetail.getId() == null ? sequence.nextId() : equipmentDetail.getId());
            equipmentDetails.add(equipmentDetail);
            List<UploadFile> fileList = new ArrayList<>();
            fileList.addAll(fillFileList(equipmentDetail.getImg(), equipmentDetail.getId(), FileTypeEnum.image.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getVideo(), equipmentDetail.getId(), FileTypeEnum.video.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getCertification(), equipmentDetail.getId(), FileTypeEnum.certificate.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getInstruction(), equipmentDetail.getId(), FileTypeEnum.instruction.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getQuality(), equipmentDetail.getId(), FileTypeEnum.quality.toString()));
            fileList.addAll(fillFileList(equipmentDetail.getOperation(), equipmentDetail.getId(), FileTypeEnum.operation.toString()));
            iUploadFileService.saveBatch(fileList);
        }
        equipmentDetailService.saveOrUpdateBatch(equipmentDetails);
        return equipmentDetails;
    }

    private List<UploadFile> fillFileList(List<UploadFile> list, Long id, String type) {
        if (list == null) {
            return new ArrayList<UploadFile>();
        }
        list.forEach(item -> {
            item.setUrl(item.getUrl());
            item.setId(sequence.nextId());
            item.setFileType(type);
            item.setObjectType(BillContentEnum.ZB.getKey());
            item.setObjectId(id);
        });
        return list;
    }

    @Override
    public IPage<ComplementCodeVO> selectEquipmentSpecific(EquipmentSpecificDTO equipmentSpecific) {
        return this.baseMapper.selectEquipmentSpecific(equipmentSpecific.getPage(), equipmentSpecific);
    }

    @Override
    public IPage<Map<String,Object>> selectZJEquipmentSpecificWWX(EquipmentSpecificDTO equipmentSpecific) {
        return this.baseMapper.selectZJEquipmentSpecificWWX(equipmentSpecific.getPage(), equipmentSpecific);
    }

    @Override
    public List<Map<String,Object>> selectZJEquipmentSpecificWWXByIds(String bussIds) {
        return this.baseMapper.selectZJEquipmentSpecificWWXByIds( bussIds);
    }

    @Override
    public EquipmentSpecific updateEquipmentSpecific(EquipmentSpecific equipmentSpecific, ReginParams reginParams, AgencyUserModel agencyUserModel) {
        SimpleDateFormat stf = new SimpleDateFormat("yyyy-MM-dd");
//         @TableField(updateStrategy = FieldStrategy.IGNORED) 置空不生效 为空单独设置 by kongfm 2021-09-10
        this.update(new LambdaUpdateWrapper<EquipmentSpecific>().set(EquipmentSpecific::getAgencyId, equipmentSpecific.getAgencyId()).set(EquipmentSpecific::getTeamId, equipmentSpecific.getTeamId()).eq(EquipmentSpecific::getId, equipmentSpecific.getId()));
        if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
            equipmentSpecific.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());

            // 更新alarm表没有复位的装备位置信息
            LambdaQueryWrapper<EquipmentSpecificAlarm> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(EquipmentSpecificAlarm::getEquipmentSpecificId, equipmentSpecific.getId());
            queryWrapper.ne(EquipmentSpecificAlarm::getStatus, AlarmStatusEnum.HF.getCode());
            List<EquipmentSpecificAlarm> alarms = equipmentSpecificAlarmService.getBaseMapper().selectList(queryWrapper);
            if (0 < alarms.size()) {
                alarms.stream().map(x -> x.setLocation(equipmentSpecific.getPosition() + " "
                        + (null == equipmentSpecific.getStockDetail().getDescription() ? "" : equipmentSpecific.getStockDetail().getDescription()))).collect(Collectors.toList());
                equipmentSpecificAlarmService.updateBatchById(alarms);
            }
        }
        boolean updateById = this.updateById(equipmentSpecific);
        if (updateById) {
            relationRedisUtil.delSysRedisKey(equipmentSpecific.getSystemId());
        }
        if (syncSwitch) {
            //AST数据同步
            FireEquipment specificDetail = getEquipSpecificDetail(equipmentSpecific);
            syncDataService.syncCreatedEquipmentSpecific(specificDetail);
        }
        if (equipmentSpecific.getStock() != null && equipmentSpecific.getStock().getId() != null) {
            stockService.updateById(equipmentSpecific.getStock());
            stockDetailService.updateById(equipmentSpecific.getStockDetail());
        } else {

            //如果位置不为空，入库
            if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {

                //没传仓库的情况下，默认单个仓库
                if (equipmentSpecific.getStock().getWarehouseId() == null) {
                    List<Warehouse> warehouseslist = warehouseService.list();
                    if (warehouseslist.size() > 0) {
                        equipmentSpecific.getStock().setWarehouseId(warehouseslist.get(0).getId());
                    } else {
                        equipmentSpecific.getStock().setWarehouseId(0L);
                    }
                }
                List<EquipmentSpecific> list = new ArrayList<>();
                list.add(equipmentSpecific);
                initEquipmentSystemSourceStatistics(list);
                //插入库存
                equipmentSpecific.getStock().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStock().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStock().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStock().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStock().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                equipmentSpecific.getStock().setCreateDate(new Date());
                stockService.save(equipmentSpecific.getStock());

                //库存详情
                equipmentSpecific.getStockDetail().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStockDetail().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStockDetail().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStockDetail().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStockDetail().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStockDetail().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                equipmentSpecific.getStockDetail().setStockId(equipmentSpecific.getStock().getId());
                equipmentSpecific.getStockDetail().setStatus(StockBillTypeEnum.DBRK.getValue());
                equipmentSpecific.getStockDetail().setUpdateDate(new Date());
                equipmentSpecific.getStockDetail().setWarehouseId(equipmentSpecific.getStock().getWarehouseId());
                equipmentSpecific.getStockDetail().setQrCode(equipmentSpecific.getQrCode());
                equipmentSpecific.getStockDetail().setEquipmentSpecificId(equipmentSpecific.getId());
                EquipmentDetail detail = equipmentDetailService
                        .getOne(new QueryWrapper<EquipmentDetail>().eq("id", equipmentSpecific.getEquipmentDetailId()));
                equipmentSpecific.getStockDetail().setDescription(detail.getArea());
                stockDetailService.save(equipmentSpecific.getStockDetail());

                //生成入库单
                StockBill stockBill = buildStockBills(equipmentSpecific, reginParams, agencyUserModel);
                stockBillService.save(stockBill);

                StockBillDetail stockBillDetail = new StockBillDetail();
                stockBillDetail.setAmount(equipmentSpecific.getStockDetail().getAmount());
                stockBillDetail.setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                stockBillDetail.setStockDetailId(equipmentSpecific.getStockDetail().getId());
                stockBillDetail.setBatchNum(stf.format(new Date()));
                stockBillDetail.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
                stockBillDetail.setSingleEquipCode(equipmentSpecific.getStockDetail().getQrCode());
                stockBillDetail.setStockBillId(stockBill.getId());
                stockBillDetail.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
                stockBillDetailService.save(stockBillDetail);
            }
        }
        return equipmentSpecific;
    }


    @Override
    public Map<String, Object> getAll(Long id) {
        QueryWrapper<EquipmentSpecificAlarm> wrapper = new QueryWrapper<>();
        wrapper.eq("equipment_specific_id", id);
        wrapper.orderByDesc("create_date");
        List<EquipmentSpecificAlarm> equipmentSpecifics = equipmentSpecificAlarmMapper.selectList(wrapper);

        // 当前告警信息拼接
        CurrAlaramVO currAlaram = new CurrAlaramVO();
        if (equipmentSpecifics.size() > 0) {
            currAlaram.setNum("1");
            currAlaram.setAlarmName(equipmentSpecifics.get(0).getEquipmentSpecificIndexName());
            currAlaram.setAlarmTime(DateUtils.convertDateToString(equipmentSpecifics.get(0).getCreateDate(), DateUtils.DATE_TIME_PATTERN));
        }
        DevInfoVO devInfo = new DevInfoVO();

        Map<String, Object> inspectionMaintenanceMap = new HashMap<>();
        inspectionMaintenanceMap.put("value", "巡检信息");
        inspectionMaintenanceMap.put("inspectionInfo", JSONObject.parseObject(injection));
        devInfo.setInspection(inspectionMaintenanceMap);

        Map<String, Object> MaintenanceMap = new HashMap<>();
        MaintenanceMap.put("value", "维保信息");
        MaintenanceMap.put("maintenanceInfo", JSONObject.parseObject(maintenance));
        devInfo.setMaintenance(MaintenanceMap);

        AlarmInfoVO alarmInfo = new AlarmInfoVO();
        devInfo.setAlarmInfo(alarmInfo);
        alarmInfo.setValue("告警信息");
        List<AlarmVO> alarmVOS = new ArrayList<>();
        equipmentSpecifics.forEach(x -> {
            AlarmVO alarmVO = new AlarmVO();
            alarmVO.setId(x.getId());
            if (EquipmentRiskTypeEnum.HZGJ.getCode().equals(x.getType())) {
                alarmVO.setType(EquipmentRiskTypeEnum.HZGJ.getType());
            } else if (EquipmentRiskTypeEnum.GZ.getCode().equals(x.getType())) {
                alarmVO.setType(EquipmentRiskTypeEnum.GZ.getType());
            } else {
                alarmVO.setType(EquipmentRiskTypeEnum.QT.getType());
            }
            alarmVO.setStatus(x.getStatus() == 0 ? "复位" : "报警");
            alarmVO.setAlarmName(x.getEquipmentSpecificIndexName());
            alarmVO.setAlarmTime(DateUtils.convertDateToString(x.getCreateDate(), DateUtils.DATE_TIME_PATTERN));
            alarmVOS.add(alarmVO);
        });
        alarmInfo.setTableList(alarmVOS);

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

        Map<String, Object> alarmcolums2 = new LinkedHashMap<>();
        alarmcolums2.put("key", "alarmTime");
        alarmcolums2.put("value", "告警时间");
        Map<String, Object> alarmcolums3 = new LinkedHashMap<>();
        alarmcolums3.put("key", "alarmName");
        alarmcolums3.put("value", "告警名称");
        Map<String, Object> alarmcolums4 = new LinkedHashMap<>();
        alarmcolums4.put("key", "type");
        alarmcolums4.put("value", "类型");
        colums.add(alarmcolums2);
        colums.add(alarmcolums3);
        colums.add(alarmcolums4);
        alarmInfo.setColums(colums);

        List<EquipmentSpecificIndex> equipmentSpecificIndices = equipmentSpecificIndexSerivce.getEquipmentSpeIndexByEquipmentSecificId(id);
        List<Map<String, Object>> equipmentSpecificIndicesMaps = new ArrayList<>();
        if (equipmentSpecificIndices != null && equipmentSpecificIndices.size() != 0) {
            equipmentSpecificIndices.forEach(x -> {
                Map<String, Object> equipmentSpecificIndicesMap = new HashMap<>();
                if ("故障".equals(x.getNameKey())) {
                    if (("true").equals(x.getValue())) {
                        equipmentSpecificIndicesMap.put("value", "false");
                    } else {
                        equipmentSpecificIndicesMap.put("value", "true");
                    }
                } else if ("火灾告警".equals(x.getNameKey())) {
                    if (("true").equals(x.getValue())) {
                        equipmentSpecificIndicesMap.put("value", "false");
                    } else {
                        equipmentSpecificIndicesMap.put("value", "true");
                    }
                } else {
                    equipmentSpecificIndicesMap.put("value", x.getValue());
                }
                equipmentSpecificIndicesMap.put("key", x.getNameKey());
                equipmentSpecificIndicesMaps.add(equipmentSpecificIndicesMap);
            });
        }
        alarmInfo.setLoTInfo(equipmentSpecificIndicesMaps);

        //周边视频拼接
        List<Video> videos = equipmentSpecificIndexSerivce.getVideoByEquipmentSecificId(id);
        SurrVideoVO surrVideoVO = new SurrVideoVO();
        List<VideoVO> videoVOS = new ArrayList<>();
        videos.forEach(x -> {
            VideoVO video = new VideoVO();
            video.setName(x.getName());
            video.setTokens(x.getToken());
            video.setUrl(x.getUrl());
            video.setIp(x.getIp());
            video.setPort(x.getPort());
            videoVOS.add(video);
        });
        surrVideoVO.setVideos(videoVOS);
        surrVideoVO.setValue("周边视频");
        devInfo.setSurrVideo(surrVideoVO);

        //设备信息
        EquipmentSecificDetailVO equipmentSecificDetail = equipmentSpecificIndexSerivce.getEquipmentDetailBySecificId(id);
        DevOverviewVO devOverview = new DevOverviewVO();
        devOverview.setQrCode(equipmentSecificDetail.getQrCode());
        List<Map<String, Object>> devOverviewMapList = new ArrayList();
        Map<String, Object> devOverviewMap1 = new HashMap<>();
        devOverviewMap1.put("key", "设备名称");
        devOverviewMap1.put("value", equipmentSecificDetail.getEquipmentName());
        devOverviewMapList.add(devOverviewMap1);

        Map<String, Object> devOverviewMap2 = new HashMap<>();
        devOverviewMap2.put("key", "编码");
        devOverviewMap2.put("value", equipmentSecificDetail.getCode());
        devOverviewMapList.add(devOverviewMap2);

        Map<String, Object> devOverviewMap3 = new HashMap<>();
        devOverviewMap3.put("key", "器材分类");
        devOverviewMap3.put("value", equipmentSecificDetail.getCategoryName());
        devOverviewMapList.add(devOverviewMap3);

        Map<String, Object> devOverviewMap4 = new HashMap<>();
        devOverviewMap4.put("key", "所属系统");
        devOverviewMap4.put("value", equipmentSecificDetail.getSystemName());
        devOverviewMapList.add(devOverviewMap4);

        Map<String, Object> devOverviewMap5 = new HashMap<>();
        devOverviewMap5.put("key", "安装位置");
        devOverviewMap5.put("value", equipmentSecificDetail.getWarehouseName());
        devOverviewMapList.add(devOverviewMap5);

        Map<String, Object> devOverviewMap6 = new HashMap<>();
        devOverviewMap6.put("key", "负责人");
        devOverviewMap6.put("value", "王某某");
        devOverviewMapList.add(devOverviewMap6);

        devOverview.setItems(devOverviewMapList);

        PartDetailVO partDetail = new PartDetailVO();
        partDetail.setValue("部件详情");

        devOverview.setOperaState(StringUtil.isNotEmpty(equipmentSecificDetail.getStatus()) ? equipmentSecificDetail.getStatus() : "1");
        Map<String, Object> operaStateMap = new HashMap<>();
        operaStateMap.put("1", "正常");
        operaStateMap.put("2", "报警");
        operaStateMap.put("3", "故障");
        operaStateMap.put("4", "无信号");
        devOverview.setOperaStateObj(operaStateMap);

        devOverview.setInjectionState("1");
        Map<String, Object> injectionStateMap = new HashMap<>();
        injectionStateMap.put("1", "正常");
        injectionStateMap.put("2", "逾期");
        injectionStateMap.put("3", "临近");
        devOverview.setInjectionStateObj(injectionStateMap);
        Map<String, Object> maintenanceStateMap = new HashMap<>();
        maintenanceStateMap.put("1", "正常");
        maintenanceStateMap.put("2", "逾期");
        maintenanceStateMap.put("3", "临近");
        devOverview.setMaintenanceState("1");
        devOverview.setMaintenanceStateObj(maintenanceStateMap);
        partDetail.setDevOverview(devOverview);

        ProductInfoVO productInfo = new ProductInfoVO();
        List<Map<String, Object>> productInfoMapList = new ArrayList<>();
        Map<String, Object> productInfoMap1 = new HashMap<>();
        productInfoMap1.put("key", "名称");
        productInfoMap1.put("value", equipmentSecificDetail.getEquipmentName());
        productInfoMapList.add(productInfoMap1);
        Map<String, Object> productInfoMap2 = new HashMap<>();
        productInfoMap2.put("key", "规格型号");
        productInfoMap2.put("value", equipmentSecificDetail.getBrand());
        productInfoMapList.add(productInfoMap2);
        Map<String, Object> productInfoMap3 = new HashMap<>();
        productInfoMap3.put("key", "进口/国产");
        productInfoMap3.put("value", Boolean.valueOf(equipmentSecificDetail.getIsImport()) == true ? "进口" : "国产");
        productInfoMapList.add(productInfoMap3);
        Map<String, Object> productInfoMap4 = new HashMap<>();
        productInfoMap4.put("key", "维保周期");
        productInfoMap4.put("value", equipmentSecificDetail.getMaintenanceCycle() + "月");
        productInfoMapList.add(productInfoMap4);
        Map<String, Object> productInfoMap5 = new HashMap<>();
        productInfoMap5.put("key", "报废年限");
        productInfoMap5.put("value", "5年");
        productInfoMapList.add(productInfoMap5);
        Map<String, Object> productInfoMap6 = new HashMap<>();
        productInfoMap6.put("key", "计量单位");
        productInfoMap6.put("value", equipmentSecificDetail.getUnitName());
        productInfoMapList.add(productInfoMap6);
        Map<String, Object> productInfoMap7 = new HashMap<>();
        productInfoMap7.put("key", "品牌");
        productInfoMap7.put("value", equipmentSecificDetail.getStandard());
        productInfoMapList.add(productInfoMap7);
        Map<String, Object> productInfoMap8 = new HashMap<>();
        productInfoMap8.put("key", "国别");
        productInfoMap8.put("value", equipmentSecificDetail.getCountry());
        productInfoMapList.add(productInfoMap8);
        Map<String, Object> productInfoMap9 = new HashMap<>();
        productInfoMap9.put("key", "巡检频率");
        productInfoMap9.put("value", "每天");
        productInfoMapList.add(productInfoMap9);
        Map<String, Object> productInfoMap10 = new HashMap<>();
        productInfoMap10.put("key", "备注");
        productInfoMap10.put("value", equipmentSecificDetail.getRemark());
        productInfoMapList.add(productInfoMap10);
        QueryWrapper<UploadFile> imgUploadFileQueryWrapper = new QueryWrapper<>();
        imgUploadFileQueryWrapper.eq("file_type", "image");
        imgUploadFileQueryWrapper.eq("object_type", "equipment");
        imgUploadFileQueryWrapper.eq("object_id", equipmentSecificDetail.getEquipDetailId());
        List<UploadFile> imgUploadFiles = uploadFileMapper.selectList(imgUploadFileQueryWrapper);
        List<String> images = new ArrayList<>();
        imgUploadFiles.forEach(x -> {
            images.add(x.getUrl());
        });
        productInfo.setItems(productInfoMapList);
        productInfo.setPic(images);
        productInfo.setPicName("产品图片");
        partDetail.setProductInfo(productInfo);

        //资料
        TechInfoVO techInfo = new TechInfoVO();
        QueryWrapper<UploadFile> instructionUploadFileQueryWrapper = new QueryWrapper<>();
        instructionUploadFileQueryWrapper.eq("file_type", "instruction");
        instructionUploadFileQueryWrapper.eq("object_type", "equipment");
        instructionUploadFileQueryWrapper.eq("object_id", equipmentSecificDetail.getEquipId());
        List<UploadFile> instructionUploadFiles = uploadFileMapper.selectList(instructionUploadFileQueryWrapper);
        List<TechInfoListVO> techInfoListVOS = new ArrayList<>();
        instructionUploadFiles.forEach(x -> {
            TechInfoListVO techInfoListVO = new TechInfoListVO();
            techInfoListVO.setName(x.getName());
            techInfoListVO.setUrl(x.getUrl());
            techInfoListVOS.add(techInfoListVO);
        });
        techInfo.setInfoLists(techInfoListVOS);
        QueryWrapper<UploadFile> videoUploadFileQueryWrapper = new QueryWrapper<>();
        videoUploadFileQueryWrapper.eq("file_type", "video");
        videoUploadFileQueryWrapper.eq("object_type", "equipment");
        videoUploadFileQueryWrapper.eq("object_id", equipmentSecificDetail.getEquipId());
        UploadFile videoUploadFiles = uploadFileMapper.selectOne(videoUploadFileQueryWrapper);
        if (videoUploadFiles != null) {
            techInfo.setVideoName(videoUploadFiles.getName());
            List<String> videoUrls = new ArrayList<>();
            videoUrls.add(videoUploadFiles.getUrl());
            techInfo.setVideoUrl(videoUrls);
        }

        //核心参数
        partDetail.setCoreParams(equipmentSpecificIndexSerivce.selectEquProperty(id));

        ManufacturerVO manufacturerVO = new ManufacturerVO();
        manufacturerVO.setPic(equipmentSecificDetail.getImg());
        manufacturerVO.setCompanyName(equipmentSecificDetail.getManufacturerName());
        List<Map<String, Object>> manufacturerMapList = new ArrayList<>();
        Map<String, Object> manufacturerMap1 = new HashMap<>();
        manufacturerMap1.put("key", "杜广锋");
        manufacturerMap1.put("value", "杜广锋");

        Map<String, Object> manufacturerMap2 = new HashMap<>();
        manufacturerMap2.put("key", "手机号");
        manufacturerMap2.put("value", equipmentSecificDetail.getSalesTel());

        Map<String, Object> manufacturerMap3 = new HashMap<>();
        manufacturerMap3.put("key", "固定电话");
        manufacturerMap3.put("value", equipmentSecificDetail.getServiceTel());

        Map<String, Object> manufacturerMap4 = new HashMap<>();
        manufacturerMap4.put("key", "邮箱");
        manufacturerMap4.put("value", "duguangfeng@yeejoin.com");

        Map<String, Object> manufacturerMap5 = new HashMap<>();
        manufacturerMap5.put("key", "网址");
        manufacturerMap5.put("value", "http://www.yeejoin.com");

        Map<String, Object> manufacturerMap6 = new HashMap<>();
        manufacturerMap6.put("key", "地址");
        manufacturerMap6.put("value", equipmentSecificDetail.getAddress());

        manufacturerMapList.add(manufacturerMap1);
        manufacturerMapList.add(manufacturerMap2);
        manufacturerMapList.add(manufacturerMap3);
        manufacturerMapList.add(manufacturerMap4);
        manufacturerMapList.add(manufacturerMap5);
        manufacturerMapList.add(manufacturerMap6);
        manufacturerVO.setItems(manufacturerMapList);
        partDetail.setManufacturer(manufacturerVO);

        ManufacturerVO supplier = new ManufacturerVO();
        manufacturerVO.setPic(equipmentSecificDetail.getImg());
        manufacturerVO.setCompanyName(equipmentSecificDetail.getManufacturerName());
        List<Map<String, Object>> supplierMapList = new ArrayList<>();
        Map<String, Object> supplierMap1 = new HashMap<>();
        supplierMap1.put("key", "联系人");
        supplierMap1.put("value", "杜广锋");

        Map<String, Object> supplierMap2 = new HashMap<>();
        supplierMap2.put("key", "手机号");
        supplierMap2.put("value", "18092840417");

        Map<String, Object> supplierMap3 = new HashMap<>();
        supplierMap3.put("key", "固定电话");
        supplierMap3.put("value", "010-67889346");

        Map<String, Object> supplierMap4 = new HashMap<>();
        supplierMap4.put("key", "邮箱");
        supplierMap4.put("value", "duguangfeng@yeejoin.com");

        Map<String, Object> supplierMap5 = new HashMap<>();
        supplierMap5.put("key", "网址");
        supplierMap5.put("value", "http://www.yeejoin.com");

        Map<String, Object> supplierMap6 = new HashMap<>();
        supplierMap6.put("key", "地址");
        supplierMap6.put("value", "北京市北京经济技术开发区中和街16好5号楼1层、5层");

        supplierMapList.add(supplierMap1);
        supplierMapList.add(supplierMap2);
        supplierMapList.add(supplierMap3);
        supplierMapList.add(supplierMap4);
        supplierMapList.add(supplierMap5);
        supplierMapList.add(supplierMap6);
        supplier.setItems(supplierMapList);
        partDetail.setSupplier(supplier);

        ManufacturerVO maintenanceUnit = new ManufacturerVO();
        manufacturerVO.setPic(equipmentSecificDetail.getImg());
        manufacturerVO.setCompanyName(equipmentSecificDetail.getManufacturerName());
        List<Map<String, Object>> maintenanceUnitList = new ArrayList<>();
        Map<String, Object> maintenanceUnitMap1 = new HashMap<>();
        maintenanceUnitMap1.put("key", "联系人");
        maintenanceUnitMap1.put("value", "杜广锋");

        Map<String, Object> maintenanceUnitMap2 = new HashMap<>();
        maintenanceUnitMap2.put("key", "手机号");
        maintenanceUnitMap2.put("value", "18092840417");

        Map<String, Object> maintenanceUnitMap3 = new HashMap<>();
        maintenanceUnitMap3.put("key", "固定电话");
        maintenanceUnitMap3.put("value", "010-67889346");

        Map<String, Object> maintenanceUnitMap4 = new HashMap<>();
        maintenanceUnitMap4.put("key", "邮箱");
        maintenanceUnitMap4.put("value", "duguangfeng@yeejoin.com");

        Map<String, Object> maintenanceUnitMap5 = new HashMap<>();
        maintenanceUnitMap5.put("key", "网址");
        maintenanceUnitMap5.put("value", "http://www.yeejoin.com");

        Map<String, Object> maintenanceUnitMap6 = new HashMap<>();
        maintenanceUnitMap6.put("key", "地址");
        maintenanceUnitMap6.put("value", "北京市北京经济技术开发区中和街16好5号楼1层、5层");

        maintenanceUnitList.add(maintenanceUnitMap1);
        maintenanceUnitList.add(maintenanceUnitMap2);
        maintenanceUnitList.add(maintenanceUnitMap3);
        maintenanceUnitList.add(maintenanceUnitMap4);
        maintenanceUnitList.add(maintenanceUnitMap5);
        maintenanceUnitList.add(maintenanceUnitMap6);
        maintenanceUnit.setItems(maintenanceUnitList);
        partDetail.setManufacturer(maintenanceUnit);
        devInfo.setPartDetail(partDetail);
        //全部信息
        Map<String, Object> res = new LinkedHashMap<>();

        res.put("currAlaram", currAlaram);
        res.put("devInfo", devInfo);

        return res;
    }

    @Override
    public Map<String, Object> getMaintenanceInfo(String checkDate) {
        return JSONObject.parseObject(maintenance);
    }

    /**
     * 或者设备id判断装备是否单件录入 false:批量 true单件
     *
     * @param qrCode
     * @return
     */
    @Override
    public boolean equipmentgetIsSingleByQrcode(String qrCode, Long equipmentSpecifticId) {
        EquipmentSpecific equipmentSpecific;
        if (StringUtils.isBlank(qrCode)) {
            QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
            wrapper.eq("equipment_specific_id", equipmentSpecifticId);
            equipmentSpecific = this.baseMapper.selectOne(wrapper);
        } else {
            QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
            wrapper.eq("qr_code", qrCode);
            equipmentSpecific = this.baseMapper.selectOne(wrapper);

        }
        if (equipmentSpecific == null) {
            return false;
        } else {
            return equipmentSpecific.getSingle();
        }

    }

    @Override
    public EquipmentSpecific equipmentByQrcode(String qrCode) {
        EquipmentSpecific equipmentSpecific;
        QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
        wrapper.eq("qr_code", qrCode);
        equipmentSpecific = this.baseMapper.selectOne(wrapper);
        return equipmentSpecific;
    }

    @Override
    public Boolean delEquipmentSpecific(Long id) {
        EquipmentSpecific equipmentSpecific = this.baseMapper.selectById(id);
        QueryWrapper<StockDetail> stockDetailQueryWrapper = new QueryWrapper<>();
        stockDetailQueryWrapper.eq("equipment_specific_id", equipmentSpecific.getId());
        if (stockDetailService.count(stockDetailQueryWrapper) > 0) {
            throw new RuntimeException("设备已入库，无法删除");
        }
        String code = this.getSystemCodeBySpeId(equipmentSpecific.getSystemId());
        int res = this.baseMapper.deleteById(id);
        if (StringUtil.isNotEmpty(code)) {
            this.integrationPageSysDataRefresh(code);
        }
        if (res > 0 && syncSwitch) {
            //数据同步
            delEquipmentSpecificSyncData(id);
        }
        //判断装备表剩余数量，无剩余删除模板
        QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
        wrapper.eq("equipment_detail_id", equipmentSpecific.getEquipmentDetailId());
        List<String> sys = this.baseMapper.selectSystemList(id);
        List<String> build = this.baseMapper.selectBuildList(id);
        String sysErrorMeg = "";
        String buildErrorMeg = "";
        if (sys.size() > 0 || build.size() > 0) {
            for (String s : sys) {
                sysErrorMeg = sysErrorMeg.equals("") ? s : sysErrorMeg + "," + s;
            }
            for (String s : build) {
                buildErrorMeg = buildErrorMeg.equals("") ? s : buildErrorMeg + "," + s;
            }
            sysErrorMeg = sysErrorMeg.equals("") ? sysErrorMeg : "系统：" + sysErrorMeg + ",";
            buildErrorMeg = buildErrorMeg.equals("") ? buildErrorMeg : "建筑：" + buildErrorMeg + ",";
            throw new RuntimeException("设备与" + sysErrorMeg + buildErrorMeg + "存在绑定关系，无法删除");
        }
        if (this.baseMapper.selectCount(wrapper) == 0) {
            equipmentDetailService.removeById(equipmentSpecific.getEquipmentDetailId());
        }
        if (res > 0) {
            equipmentSpecificAlarmMapper.clearAlarmData(id);
            // 删除设备动态表单扩展属性
            return formInstanceEquipService.deleteInstanceById(id);
        } else {
            return false;
        }
    }

    @Override
    public Boolean delEquipmentSpecificByIdNew(EquipmentSpecific equipmentSpecific) {
        Long id = equipmentSpecific.getId();
        QueryWrapper<StockDetail> stockDetailQueryWrapper = new QueryWrapper<>();
        stockDetailQueryWrapper.eq("equipment_specific_id", equipmentSpecific.getId());
        if (stockDetailService.count(stockDetailQueryWrapper) > 0) {
            throw new BadRequest("所选设备中存在已入库设备，无法删除，请重新选择，装备名称：" + equipmentSpecific.getName());
        }
        String code = this.getSystemCodeBySpeId(equipmentSpecific.getSystemId());
        int res = this.baseMapper.deleteById(id);
        if (StringUtil.isNotEmpty(code)) {
            this.integrationPageSysDataRefresh(code);
        }
        if (res > 0 && Boolean.TRUE.equals(syncSwitch)) {
            //数据同步
            delEquipmentSpecificSyncData(id);
        }
        //判断装备表剩余数量，无剩余删除模板
        QueryWrapper<EquipmentSpecific> wrapper = new QueryWrapper<>();
        wrapper.eq("equipment_detail_id", equipmentSpecific.getEquipmentDetailId());
        List<String> sys = this.baseMapper.selectSystemList(id);
        List<String> build = this.baseMapper.selectBuildList(id);
        String sysErrorMeg = "";
        String buildErrorMeg = "";
        if (!CollectionUtils.isEmpty(sys) || !CollectionUtils.isEmpty(build)) {
            for (String s : sys) {
                sysErrorMeg = sysErrorMeg.equals("") ? s : sysErrorMeg + "," + s;
            }
            for (String s : build) {
                buildErrorMeg = buildErrorMeg.equals("") ? s : buildErrorMeg + "," + s;
            }
            sysErrorMeg = sysErrorMeg.equals("") ? sysErrorMeg : "系统：" + sysErrorMeg + ",";
            buildErrorMeg = buildErrorMeg.equals("") ? buildErrorMeg : "建筑：" + buildErrorMeg + ",";
            throw new BadRequest("所选设备中有与" + sysErrorMeg + buildErrorMeg + "存在绑定关系，无法删除，装备名称：" + equipmentSpecific.getName());
        }
        if (this.baseMapper.selectCount(wrapper) == 0) {
            equipmentDetailService.removeById(equipmentSpecific.getEquipmentDetailId());
        }
        if (res > 0) {
            // 删除设备动态表单扩展属性
            return formInstanceEquipService.deleteInstanceById(id);
        } else {
            return false;
        }
    }

    private String getSystemCodeBySpeId(String sysIds) {
        if (StringUtil.isNotEmpty(sysIds)) {
            List<FireFightingSystemEntity> sys = fireFightingSystemMapper.getFightingSysByIds(sysIds.split(","));
            return sys.stream().map(FireFightingSystemEntity::getCode).collect(Collectors.joining(","));
        } else {
            return null;
        }
    }


    public void delEquipmentSpecificSyncData(Long id) {
        //数据同步
        syncDataService.syncDeletedEquipmentSpecific(Arrays.asList(id));
        List<EquipmentIndexVO> indexBySpecificIdIn = equipmentSpecificIndexSerivce.getEquipIndexBySpecificIdIn(Arrays.asList(String.valueOf(id)));
        if (!indexBySpecificIdIn.isEmpty()) {
            List<Long> fireEquipmentInfoCollect = indexBySpecificIdIn.stream().filter(vo -> 0 == vo.getIsIot()).map(EquipmentIndexVO::getId).collect(Collectors.toList());
            List<Long> fireEquipMeasurementCollect = indexBySpecificIdIn.stream().filter(vo -> 1 == vo.getIsIot()).map(EquipmentIndexVO::getId).collect(Collectors.toList());
            syncDataService.syncDeletedEquipmentSpecificInfo(fireEquipmentInfoCollect);
            syncDataService.syncDeletedFireEquipMeasurement(fireEquipMeasurementCollect);
        }
    }

    @Override
    public Object getOneCard(Long id, String type) {
        if (BitmapEnum.video.getKey().equals(type)) {
            AlamVideoVO video = videoMapper.getVideoById(id);
            if (!ObjectUtils.isEmpty(video)) {
                video.setUrl(videoService.getVideoUrl(video.getName(), video.getPresetPosition(), video.getUrl(), video.getCode()));
                video.setId(id);
                video.setVedioFormat(video.getVideoType());
            }
            return video;
        } else {
            DetailPaneVO detailPaneVO = new DetailPaneVO();
            Map<String, String> map = this.baseMapper.getQrCodeAndPic(id);
            if (ObjectUtils.isEmpty(map)) {
                return detailPaneVO;
            }
            detailPaneVO.setQrCode(map.get("qrCode"));
            detailPaneVO.setPic(map.get("pic"));
            detailPaneVO.setItems(this.baseMapper.getOneCard(id));
            return detailPaneVO;
        }
    }

    @Override
    public SourceNameByEquipSpeIdVO getSourceNameByEquipSpeId(Long id) {
        return this.baseMapper.getSourceNameByEquipSpeId(id);
    }

    @Override
    public IPage<SourceNameByEquipSpeIdVO> getSourceNameList(IPage page, Long warehouseStructureId, Long sourceId, String equipmentName, String equipmentCode) {
        return this.baseMapper.getSourceNameList(page, warehouseStructureId, sourceId, equipmentName, equipmentCode);
    }

    @Override
    public List<FireEquipment> getEquipSpecificDetailsByEquipmentId(Long equipmentId) {
        List<FireEquipment> detailsByEquipmentId = equipmentSpecificMapper.getEquipSpecificDetailsByEquipmentId(equipmentId);
        if (detailsByEquipmentId != null && !detailsByEquipmentId.isEmpty()) {
            return detailsByEquipmentId;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<EquipmentSpecific3dVo> get3dFightingSysEquipList(Long id, Integer status, String name) {
        List<EquipmentSpecific3dVo> list = equipmentSpecificMapper.get3dFightingSysEquipList(id, name);
        if (!CollectionUtils.isEmpty(list)) {
            if (status != null) {
                return list.stream().filter(x -> status.equals(x.getStatus())).collect(Collectors.toList());
            }
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public Page<EquipmentSpecific3dVo> listPage(Page<EquipmentSpecific3dVo> pageBean, EquipFor3DVO equipment) {
        List<EquipmentSpecific3dVo> list = equipmentSpecificMapper.listPage(equipment, pageBean.offset(), pageBean.getSize());
        int count = equipmentSpecificMapper.listCount(equipment);
        Page<EquipmentSpecific3dVo> page = new Page<>(pageBean.getCurrent(), pageBean.getSize());
        page.setRecords(list);
        page.setTotal(count);
        return page;
    }

    @Override
    public List<LinkedHashMap> get3dFightingSysEquipCount(Long id, Integer status, String name) {
        List<LinkedHashMap> map = equipmentSpecificMapper.get3dFightingSysEquipCount(id, status, name);
        if (!CollectionUtils.isEmpty(map)) {
            return map;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<EquipmentOnCarVo> getAirEquipSpecificList(String like, String notLike, Integer status) {
        String[] split = null;
        if (StringUtil.isNotEmpty(notLike)) {
            split = notLike.split(",");
        }
        List<EquipmentOnCarVo> list = equipmentSpecificMapper.getAirEquipSpecificList(like, split, status);
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public IPage<EquipmentOnCarVo> onCarVoIPage(EquipmentSpecificDto equipmentSpecificDto) {
        String[] strs = null;
        if (StringUtil.isNotEmpty(codes)) {
            strs = codes.split(",");
        }
        equipmentSpecificDto.setCodes(strs);
        String categoryCode = equipmentSpecificDto.getCategoryCode();
//        List<String> categoryCodeList = null;
//        if (StringUtils.isNotEmpty(categoryCode)) {
//            QueryWrapper<EquipmentCategory> queryWrapper = new QueryWrapper<>();
//            EquipmentCategory categoryEntity = iEquipmentCategoryService.getOne(queryWrapper.eq("code", categoryCode).eq("industry_code", equipmentCategoryLeftTypeCode));
//            List<EquipmentCategory> categoryList = equipmentCategoryService.getEquipmentCategoryList(Integer.valueOf(equipmentCategoryLeftTypeCode));
//            Collection<EquipmentCategory> categorieTree = TreeBuilder.buildByRecursive(categoryList, categoryEntity.getId());
//            List<EquipmentCategory> categorieChildren = TreeUtil.getAllChildren(categorieTree);
//            categoryCodeList = categorieChildren.stream().map(category -> category.getCode()).collect(Collectors.toList());
//            categoryCodeList.add(categoryCode);
//        }
//        String str = org.apache.commons.lang.StringUtils.join(categoryCodeList.toArray(), ",");
//        equipmentSpecificDto.setCategories("(" + str + ")");
        equipmentSpecificDto.setCategories(categoryCode);
        return this.baseMapper.onCarVoIPage(equipmentSpecificDto.getPage(), equipmentSpecificDto);
    }

    @Override
    public EquipmentDetailVo getAirEquipSpecificDetail(Long stockDetailId) {
        return equipmentSpecificMapper.getAirEquipSpecificDetail(stockDetailId);
    }

    @Override
    public List<UserDto> getEquipSpecificLocationInfo(Long equipmentSpecificId, String[] fieldName) {
        return equipmentSpecificMapper.getEquipSpecificLocationInfo(equipmentSpecificId, fieldName);
    }

    public Map<String, Double> getEquipLocationInfo(Long equipmentSpecificId) {
        // 权限处理
        PermissionInterceptorContext.setDataAuthRule(authKey);
        return equipmentSpecificMapper.getEquipLocationInfo(equipmentSpecificId);
    }

    @Override
    @Async("equipAsyncExecutor")
    public void equipSpecificDataSync(Long equipmentId) {
        //  TODO 放大范围，根据equipment_id同步
        List<FireEquipment> specificDetails = getEquipSpecificDetailsByEquipmentId(equipmentId);
        if (specificDetails.size() > 0) {
            syncDataService.syncCreatedEquipmentSpecific(specificDetails);
            List<String> specificIds = new ArrayList<>();
            specificDetails.stream().forEach(x -> specificIds.add(x.getId()));
            List<EquipmentIndexVO> specificIndexList = equipmentSpecificIndexSerivce.getEquipIndexBySpecificIdIn(specificIds);
            List<EquipmentIndexVO> fireEquipmentInfoCollect = specificIndexList.stream().filter(vo -> 0 == vo.getIsIot()).collect(Collectors.toList());
            List<EquipmentIndexVO> fireEquipMeasurementCollect = specificIndexList.stream().filter(vo -> 1 == vo.getIsIot()).collect(Collectors.toList());
            syncDataService.syncCreatedEquipmentSpecificInfo(fireEquipmentInfoCollect);
            syncDataService.syncCreatedFireEquipMeasurement(fireEquipMeasurementCollect);
        }
    }

    @Override
    @Transactional
    public EquipmentDate equipmentSpecificCreate(EquipmentDate equipmentData, ReginParams reginParams, AgencyUserModel agencyUserModel) {
        StringBuilder fireFightSysIdsBuffer = new StringBuilder();
        EquipmentSpecific equipmentSpecific = equipmentData.getEquipmentSpecific();
        equipmentSpecific.setStock(new Stock().setWarehouseId(0L));
        EquipmentDetail equipmentDetail = equipmentData.getEquipmentDetail();
        Equipment equipment = equipmentService.getById(equipmentDetail.getEquipmentId());
        if (equipment != null) {
            String equipmentCode = equipment.getCode();
            equipmentDetail.setCode(equipmentCode);
            equipmentDetail.setEquipmentName(equipment.getName());
            equipmentSpecific.setEquipmentCode(equipmentCode);
            equipmentSpecific.setName(equipmentDetail.getName());

            if (StringUtil.isNotEmpty(equipmentDetail.getArea())) {
                String[] addressData = equipmentDetail.getArea().split("@address@");
                if (addressData.length > 1) {
                    equipmentDetail.setArea(addressData[0]);
                    JSONObject langLatObj = JSON.parseObject(addressData[1]);
                    if (StringUtil.isNotEmpty(langLatObj.getString("longitude"))) {
                        equipmentDetail.setLongitude(Double.valueOf(langLatObj.getString("longitude")));
                    }
                    if (StringUtil.isNotEmpty(langLatObj.getString("latitude"))) {
                        equipmentDetail.setLatitude(Double.valueOf(langLatObj.getString("latitude")));
                    }
                }
            }
        }
        Long warehouseStructureId = null;
        if (!ObjectUtils.isEmpty(equipmentSpecific.getStockDetail())) {
            warehouseStructureId = equipmentSpecific.getStockDetail().getWarehouseStructureId();
        }
        if (warehouseStructureId != null) {
            WarehouseStructure warehouseStructure = warehouseStructureService.getById(warehouseStructureId);
            if (!ObjectUtils.isEmpty(warehouseStructure)) {
                equipmentSpecific.setPosition(warehouseStructure.getFullName());
            }
        }
        if (!equipmentSpecific.getSingle()) {
            //TODO 非单件管理逻辑
            //1.数据制码
            equipmentDetail = equipmentDetailService.saveOne(equipmentDetail);
            String qrCode = QRCodeUtil.generateQRCode();
            //2.插入设备数据
            equipmentSpecific.setStock(new Stock().setWarehouseId(0L));
            equipmentSpecific.setEquipmentDetailId(equipmentDetail.getId());
            equipmentSpecific.setQrCode(qrCode);
            equipmentSpecific.setOrgCode(reginParams.getCompany().getOrgCode());
            if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                equipmentSpecific.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
            }
            boolean save = this.save(equipmentSpecific);
            if (save) {
                fireFightSysIdsBuffer.append(equipmentSpecific.getSystemId() + ",");
            }
            List<EquipmentSpecific> equipmentSpecifics = Collections.singletonList(equipmentSpecific);
            //没传仓库的情况下，默认单个仓库
            if (equipmentSpecific.getStock().getWarehouseId() == null) {
                List<Warehouse> list = warehouseService.list();
                if (list.size() > 0) {
                    equipmentSpecific.getStock().setWarehouseId(list.get(0).getId());
                } else {
                    equipmentSpecific.getStock().setWarehouseId(0L);
                }
            }

            //4.如果位置不为空，入库
            if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {

                //3.初始化物理监控查询数据
                initEquipmentSystemSourceStatistics(equipmentSpecifics);

                //4.1插入库存
                equipmentSpecific.getStock().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStock().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStock().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStock().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStock().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                stockService.save(equipmentSpecific.getStock());

                //4.2库存详情
                equipmentSpecific.getStockDetail().setCompanyName(reginParams.getCompany().getCompanyName());
                equipmentSpecific.getStockDetail().setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.getStockDetail().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                equipmentSpecific.getStockDetail().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                equipmentSpecific.getStockDetail().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                equipmentSpecific.getStockDetail().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                equipmentSpecific.getStockDetail().setStockId(equipmentSpecific.getStock().getId());
                equipmentSpecific.getStockDetail().setStatus(StockBillTypeEnum.DBRK.getValue());
                equipmentSpecific.getStockDetail().setUpdateDate(new Date());
                equipmentSpecific.getStockDetail().setWarehouseId(equipmentSpecific.getStock().getWarehouseId());
                equipmentSpecific.getStockDetail().setEquipmentSpecificId(equipmentSpecific.getId());
                equipmentSpecific.getStockDetail().setQrCode(qrCode);
                equipmentSpecific.getStockDetail().setBatchNum(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                equipmentSpecific.getStockDetail().setDescription(equipmentDetail.getArea());
                stockDetailService.save(equipmentSpecific.getStockDetail());

                //4.3生成入库单
                StockBill stockBill = buildStockBills(equipmentSpecific, reginParams, agencyUserModel);
                stockBillService.save(stockBill);
                //4.3生成入库单详情
                StockBillDetail stockBillDetail = new StockBillDetail();
                stockBillDetail.setAmount(equipmentSpecific.getStockDetail().getAmount());
                stockBillDetail.setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                stockBillDetail.setStockDetailId(equipmentSpecific.getStockDetail().getId());
                buildStockBatchNo(agencyUserModel, equipmentSpecific, stockBill, stockBillDetail);
            }

            //装备实例对应的性能指标保存
            equipmentSpecificIndexSave(equipmentData, equipmentSpecific);
        } else {
            //TODO 单件管理逻辑
            List<EquipmentSpecific> equipmentSpecifics = new ArrayList<>();
            //如果多个二维码说明单项管理，批量录入
            if (equipmentSpecific.getNum() > 1) {
                //TODO 1.去掉模板概念了，把EquipmentDetail当成EquipmentSpecific一对一子表,有多少二维码生成就有多少个EquipmentDetail
                List<EquipmentDetail> equipmentDetails = this.saveEquipmentDetailBatch(equipmentData.getEquipmentDetail(), (int) equipmentSpecific.getNum().floatValue());
                //2.生成二维码数据
                List<String> list = genQrCode(equipmentDetails);
                //3.插入设备实例基本表
                for (int i = 0; i < list.size(); i++) {
                    EquipmentSpecific equipmentSpecificBatch = new EquipmentSpecific();
                    BeanUtils.copyProperties(equipmentSpecific, equipmentSpecificBatch);
                    equipmentSpecificBatch.setQrCode(list.get(i));
                    equipmentSpecificBatch.setOrgCode(reginParams.getCompany().getOrgCode());
                    equipmentSpecificBatch.setEquipmentDetailId(equipmentDetails.get(i).getId());
                    if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                        equipmentSpecificBatch.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
                    }
                    equipmentSpecifics.add(equipmentSpecificBatch);
                    fireFightSysIdsBuffer.append(equipmentSpecificBatch.getSystemId() + ",");
                }
                this.saveBatch(equipmentSpecifics);


                //4.初始化统计表
                initEquipmentSystemSourceStatistics(equipmentSpecifics);
                //没传仓库的情况下，默认单个仓库
                if (equipmentSpecific.getStock().getWarehouseId() == null) {
                    List<Warehouse> warehouseslist = warehouseService.list();
                    if (warehouseslist.size() > 0) {
                        equipmentSpecific.getStock().setWarehouseId(warehouseslist.get(0).getId());
                    } else {
                        equipmentSpecific.getStock().setWarehouseId(0L);
                    }
                }
                //5.如果位置不为空,入库
                if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                    //5.1批量插入库存信息
                    List<Stock> stocks = new ArrayList<>();
                    equipmentSpecifics.forEach(y -> {
                        Stock stock = new Stock();
                        BeanUtils.copyProperties(y.getStock(), stock);
                        stock.setAmount(1d);
                        stock.setCompanyName(reginParams.getCompany().getCompanyName());
                        stock.setOrgCode(reginParams.getCompany().getOrgCode());
                        stock.setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                        stock.setDepartmentName(reginParams.getDepartment().getDepartmentName());
                        stock.setEquipmentDetailId(y.getEquipmentDetailId());
                        stocks.add(stock);
                    });
                    stockService.saveBatch(stocks);

                    //5.2批量插入库存详情
                    List<StockDetail> stockDetails = new ArrayList<>();
                    for (int i = 0; i < stocks.size(); i++) {
                        StockDetail stockDetail = new StockDetail();
                        BeanUtils.copyProperties(equipmentSpecifics.get(i).getStockDetail(), stockDetail);
                        stockDetail.setCompanyName(reginParams.getCompany().getCompanyName());
                        stockDetail.setOrgCode(reginParams.getCompany().getOrgCode());
                        stockDetail.setDepartmentName(reginParams.getDepartment().getDepartmentName());
                        stockDetail.setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                        stockDetail.setEquipmentDetailId(stocks.get(i).getEquipmentDetailId());
                        stockDetail.setStockId(stocks.get(i).getId());
                        stockDetail.setStatus(StockBillTypeEnum.DBRK.getValue());
                        stockDetail.setAmount(1d);
                        stockDetail.setWarehouseId(stocks.get(i).getWarehouseId());
                        stockDetail.setUpdateDate(new Date());
                        stockDetail.setQrCode(list.get(i));
                        stockDetail.setEquipmentSpecificId(equipmentSpecifics.get(i).getId());
                        stockDetail.setDescription(equipmentDetail.getArea());
                        stockDetails.add(stockDetail);
                        stockDetail.setBatchNum(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                    }
                    stockDetailService.saveBatch(stockDetails);
                    //5.3生成入库单
                    List<StockBill> stockBills = new ArrayList<>();
                    for (int i = 0; i < stockDetails.size(); i++) {
                        stockBills.add(buildStockBills(equipmentSpecific, reginParams, agencyUserModel));
                    }
                    stockBillService.saveBatch(stockBills);
                    //5.4生成入库单详情
                    List<StockBillDetail> stockBillDetails = new ArrayList<>();
                    for (int i = 0; i < stockBills.size(); i++) {
                        StockBillDetail stockBillDetail = new StockBillDetail();
                        stockBillDetail.setAmount(1d);
                        //TODO 顺序一致，所以按照下标取
                        stockBillDetail.setEquipmentDetailId(stockDetails.get(i).getEquipmentDetailId());
                        stockBillDetail.setStockDetailId(stockDetails.get(i).getId());
                        try {
                            stockBillDetail.setBatchNum(DateUtils.dateFormat(new Date(), DateUtils.DATE_PATTERN));
                        } catch (ParseException e) {
                            log.error(e.getMessage(), e);
                            throw new BaseException("格式化失败");
                        }
                        stockBillDetail.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
                        stockBillDetail.setSingleEquipCode(stockDetails.get(i).getQrCode());
                        stockBillDetail.setStockBillId(stockBills.get(i).getId());
                        stockBillDetail.setWarehouseStructureId(stockDetails.get(i).getWarehouseStructureId());
                        stockBillDetails.add(stockBillDetail);
                    }
                    stockBillDetailService.saveBatch(stockBillDetails);
                }
                //6.装备实例对应的性能指标保存
                List<EquipmentSpecificIndex> equipmentSpecificIndices = new ArrayList<>();
                List<EquProperty> equProperties = equipmentData.getEquipmentDetail().getEquPropertyList();
                for (EquipmentSpecific specific : equipmentSpecifics) {
                    buildEquipmentSpecificIndices(equipmentSpecificIndices, equProperties, specific, equipmentData.getEquipmentDetail().getName());
                }
                equipmentSpecificIndexSerivce.saveBatch(equipmentSpecificIndices);

                //页面参数返回数据处理
                EquipmentSpecific resultEquipSpec = equipmentSpecifics.get(0);
                resultEquipSpec.setNum(1F);
                equipmentData.setEquipmentDetail(equipmentDetails.get(0));
                equipmentData.setEquipmentSpecific(resultEquipSpec);
            } else {
                //单项管理,逐个录入
                equipmentDetail = equipmentDetailService.saveOne(equipmentDetail);
                String qrCode = QRCodeUtil.generateQRCode();
                equipmentSpecific.setQrCode(qrCode);
                equipmentSpecific.setOrgCode(reginParams.getCompany().getOrgCode());
                equipmentSpecific.setEquipmentDetailId(equipmentDetail.getId());
                equipmentSpecific.setCreateDate(new Date());
                if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                    equipmentSpecific.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
                }
                //插入设备数据
                int insert = this.baseMapper.insert(equipmentSpecific);
                if (insert > 0) {
                    fireFightSysIdsBuffer.append(equipmentSpecific.getSystemId() + ",");
                }
                equipmentSpecifics.add(equipmentSpecific);
                initEquipmentSystemSourceStatistics(equipmentSpecifics);
                //没传仓库的情况下，默认单个仓库
                if (equipmentSpecific.getStock().getWarehouseId() == null) {
                    List<Warehouse> warehouseslist = warehouseService.list();
                    if (warehouseslist.size() > 0) {
                        equipmentSpecific.getStock().setWarehouseId(warehouseslist.get(0).getId());
                    } else {
                        equipmentSpecific.getStock().setWarehouseId(0L);
                    }
                }
                //如果位置不为空,入库
                if (equipmentSpecific.getStockDetail() != null && equipmentSpecific.getStockDetail().getWarehouseStructureId() != null) {
                    //插入库存
                    equipmentSpecific.getStock().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                    equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getCompanyName());
                    equipmentSpecific.getStock().setCompanyName(reginParams.getCompany().getOrgCode());
                    equipmentSpecific.getStock().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                    equipmentSpecific.getStock().setCompanyName(reginParams.getDepartment().getDepartmentName());
                    equipmentSpecific.getStock().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                    stockService.save(equipmentSpecific.getStock());

                    //插入库存详情
                    equipmentSpecific.getStockDetail().setCompanyName(reginParams.getCompany().getCompanyName());
                    equipmentSpecific.getStockDetail().setOrgCode(reginParams.getCompany().getOrgCode());
                    equipmentSpecific.getStockDetail().setAmount(Double.valueOf(equipmentSpecific.getNum()));
                    equipmentSpecific.getStockDetail().setDepartmentName(reginParams.getDepartment().getDepartmentName());
                    equipmentSpecific.getStockDetail().setDepartmentOrgcode(reginParams.getDepartment().getOrgCode());
                    equipmentSpecific.getStockDetail().setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                    equipmentSpecific.getStockDetail().setStockId(equipmentSpecific.getStock().getId());
                    equipmentSpecific.getStockDetail().setStatus(StockBillTypeEnum.DBRK.getValue());
                    equipmentSpecific.getStockDetail().setUpdateDate(new Date());
                    equipmentSpecific.getStockDetail().setQrCode(qrCode);
                    equipmentSpecific.getStockDetail().setWarehouseId(equipmentSpecific.getStock().getWarehouseId());
                    equipmentSpecific.getStockDetail().setEquipmentSpecificId(equipmentSpecific.getId());
                    equipmentSpecific.getStockDetail().setBatchNum(new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
                    equipmentSpecific.getStockDetail().setDescription(equipmentDetail.getArea());
                    stockDetailService.save(equipmentSpecific.getStockDetail());
                    //生成入库单
                    StockBill stockBill = buildStockBills(equipmentSpecific, reginParams, agencyUserModel);
                    stockBillService.save(stockBill);
                    StockBillDetail stockBillDetail = new StockBillDetail();
                    stockBillDetail.setAmount(equipmentSpecific.getStockDetail().getAmount());
                    stockBillDetail.setEquipmentDetailId(equipmentSpecific.getEquipmentDetailId());
                    stockBillDetail.setStockDetailId(equipmentSpecific.getStockDetail().getId());
                    buildStockBatchNo(agencyUserModel, equipmentSpecific, stockBill, stockBillDetail);
                }
                //装备实例对应的性能指标保存
                equipmentSpecificIndexSave(equipmentData, equipmentSpecific);
            }
        }
        relationRedisUtil.delSysRedisKey(fireFightSysIdsBuffer.toString());
        return equipmentData;
    }

    @Override
    public FireEquipment getEquipSpecificDetail(EquipmentSpecific equipmentSpecific) {
        FireEquipment fireEquipment = equipmentSpecificMapper.getEquipSpecificDetail(equipmentSpecific.getId());
        String fullName = fireEquipment.getFullName();
        if (StringUtils.isNotBlank(fullName) && fullName.indexOf("-") != -1) {
            fireEquipment.setBuildName(fullName.split("-")[0]);
        }
        return fireEquipment;
    }

    @Override
    public FireEquipmentVO getInstanceIdAndOrgCode(Long sourceId) {
        FireEquipmentVO finalVo = new FireEquipmentVO();
        WarehouseStructure warehouseStructure = warehouseStructureMapper.selectById(sourceId);
        if (0 == warehouseStructure.getParentId()) {
            finalVo.setInstanceId(String.valueOf(warehouseStructure.getSourceId()));
            finalVo.setBizOrgCode(warehouseStructure.getBizOrgCode());
        } else {
            warehouseStructure = getWarehouseStructure(warehouseStructureMapper.selectById(warehouseStructure.getParentId()));
            finalVo.setInstanceId(String.valueOf(warehouseStructure.getSourceId()));
            finalVo.setBizOrgCode(warehouseStructure.getBizOrgCode());
        }
        QueryWrapper<FormInstance> qw = new QueryWrapper<>();
        qw.lambda().eq(FormInstance::getInstanceId, sourceId)
                .eq(FormInstance::getFieldName, "bizOrgCode");
        FormInstance formInstance = formInstanceMapper.selectOne(qw);
        finalVo.setBizOrgCode(formInstance.getFieldValue());
        return finalVo;
    }

    public WarehouseStructure getWarehouseStructure(WarehouseStructure warehouseStructure) {
        if (0 == warehouseStructure.getParentId()) {
            return warehouseStructure;
        } else {
            warehouseStructure = warehouseStructureMapper.selectById(warehouseStructure.getParentId());
            return getWarehouseStructure(warehouseStructure);
        }
    }

    @Override
    public String getEquipSpeTypeByQrcode(String qrCode) {
        List<EquipmentCategory> list = this.baseMapper.getEquipSpeTypeByQrcode(qrCode);
        if (list != null && list.size() > 0) {
            EquipmentCategory equipmentCategory = list.get(0);
            String pre = equipmentCategory.getCode().substring(0, 1);
            if ("4".equals(pre)) {
                return "agent";
            } else {
                return "equipment";
            }
        } else {
            throw new RuntimeException("请输入正确编码！");
        }
    }

    private List<String> genQrCode(List<EquipmentDetail> equipmentDetails) {
        List<String> all = new ArrayList<>();
        equipmentDetails.forEach(e -> {
            all.add(QRCodeUtil.generateQRCode());
        });
        return all;
    }

    private void buildEquipmentSpecificIndices(List<EquipmentSpecificIndex> equipmentSpecificIndices,
                                               List<EquProperty> equProperties, EquipmentSpecific specific, String equipName) {
        equProperties.forEach(x -> {
            EquipmentSpecificIndex equipmentSpecificIndex = new EquipmentSpecificIndex();
            equipmentSpecificIndex.setId(null);
            equipmentSpecificIndex.setValue(x.getValue());
            equipmentSpecificIndex.setEquipmentIndexId(x.getEquipmentIndexId());
            equipmentSpecificIndex.setEquipmentSpecificId(specific.getId());
            EquipmentIndex index = iEquipmentIndexService.getById(x.getEquipmentIndexId());
            equipmentSpecificIndex.setEquipmentSpecificName(equipName);
            equipmentSpecificIndex.setEquipmentIndexName(index.getPerfQuotaName());
            equipmentSpecificIndex.setEquipmentIndexKey(index.getPerfQuotaDefinitionId());
            equipmentSpecificIndex.setEmergencyLevelColor(index.getEmergencyLevelColor());
            equipmentSpecificIndex.setIsAlarm(index.getIsAlarm());
            equipmentSpecificIndex.setEmergencyLevel(index.getEmergencyLevel());
            equipmentSpecificIndex.setEmergencyLevelDescribe(index.getEmergencyLevelDescribe());
            equipmentSpecificIndex.setUnit(index.getUnit());
            equipmentSpecificIndex.setValueEnum(index.getValueEnum());
            equipmentSpecificIndex.setTypeCode(index.getTypeCode());
            equipmentSpecificIndex.setIsTrend(index.getIsTrend());
            equipmentSpecificIndex.setAlamReason(index.getAlarmRule());
            equipmentSpecificIndices.add(equipmentSpecificIndex);
        });
    }

    private void buildStockBatchNo(AgencyUserModel agencyUserModel, EquipmentSpecific equipmentSpecific, StockBill stockBill, StockBillDetail stockBillDetail) {
        try {
            stockBillDetail.setBatchNum(DateUtils.dateFormat(new Date(), DateUtils.DATE_PATTERN));
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            throw new BaseException("格式化失败");
        }
        stockBillDetail.setCreatorId(Long.valueOf(agencyUserModel.getUserId()));
        stockBillDetail.setSingleEquipCode(equipmentSpecific.getStockDetail().getQrCode());
        stockBillDetail.setStockBillId(stockBill.getId());
        stockBillDetail.setWarehouseStructureId(equipmentSpecific.getStockDetail().getWarehouseStructureId());
        stockBillDetailService.save(stockBillDetail);
    }

    public void equipmentSpecificIndexSave(EquipmentDate equipmentData, EquipmentSpecific equipmentSpecific) {
        List<EquipmentSpecificIndex> equipmentSpecificIndices = new ArrayList<>();
        List<EquProperty> equProperties = equipmentData.getEquipmentDetail().getEquPropertyList();
        buildEquipmentSpecificIndices(equipmentSpecificIndices, equProperties, equipmentSpecific, equipmentData.getEquipmentDetail().getName());
        equipmentSpecificIndexSerivce.saveBatch(equipmentSpecificIndices);
    }

    @Async("equipAsyncExecutor")
    void initEquipmentSystemSourceStatistics(List<EquipmentSpecific> equipmentSpecifics) {
        List<EquipmentSystemSourceStatistics> list = new ArrayList<>();
        equipmentSpecifics.parallelStream().forEach(x -> {
            //插入统计区域设备关表，初始化数据
            EquipmentSystemSourceStatistics equipmentSystemSourceStatistics = new EquipmentSystemSourceStatistics();
            equipmentSystemSourceStatistics.setEquipmentSpecificId(x.getId());
            equipmentSystemSourceStatistics.setStatus(1);
            if (x.getStockDetail() != null && x.getStockDetail().getWarehouseStructureId() != null) {
                WarehouseStructure warehouseStructure = warehouseStructureService.getById(x.getStockDetail().getWarehouseStructureId());
                while (warehouseStructure.getParentId() != null && !warehouseStructure.getParentId().equals(warehouseStructure.getWarehouseId())) {
                    warehouseStructure = warehouseStructureService.getById(warehouseStructure.getParentId());
                }
                equipmentSystemSourceStatistics.setSourceId(warehouseStructure.getId());
            }
            list.add(equipmentSystemSourceStatistics);
        });
        equipmentSystemSourceStatisticsService.saveBatch(list);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delEquipmentBySpecificId(Long specificId) {
        EquipmentSpecific specific = equipmentSpecificMapper.selectById(specificId);
        Long equipDetailId = specific.getEquipmentDetailId();
//        // 1.删除相关主表数据
//        this.baseMapper.deleteEquipDataBySpecificId(specificId, equipDetailId);
        try {
            this.baseMapper.deleteEquipDetail(equipDetailId);
            this.baseMapper.deleteEquipAlarmLog(specificId);
            this.baseMapper.deleteEquipAlarm(specificId);
            this.baseMapper.deleteEquipReportDay(specificId);
            this.baseMapper.deleteEquipSpecIndex(specificId);
            this.baseMapper.deleteEquipSpecVideo(specificId);
            this.baseMapper.deleteEquipSpecRelation(specificId);
            this.baseMapper.deleteEquipSpec(specificId);
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 2.删除已入库相关数据
        QueryWrapper<StockDetail> stockDetailQueryWrapper = new QueryWrapper<>();
        stockDetailQueryWrapper.eq("equipment_specific_id", specificId);
        StockDetail stockDetail = stockDetailService.getOne(stockDetailQueryWrapper);
        if (!ObjectUtils.isEmpty(stockDetail)) {
            // 已入库
            this.baseMapper.deleteEquipDataByStockDetailId(stockDetail.getId(), specificId);
        }

        if (syncSwitch) {
            //数据同步
            delEquipmentSpecificSyncData(specificId);
        }

        return Boolean.TRUE;
    }

    /**
     * 刷新数字化大屏缓存数据及推送
     *
     * @param systemTypeCode
     */
    @Async("equipAsyncExecutor")
    @Override
    public void integrationPageSysDataRefresh(String systemTypeCode) {
        if (ObjectUtils.isEmpty(systemTypeCode)) {
            return;
        }
        String[] systemTypeCodes = systemTypeCode.split(",");
        for (String code : systemTypeCodes) {
            iFireFightingSystemService.integrationPageSysData(code, true);
        }
    }


    @Override
    public List<EquipmentSpecificVo> getEquipAndCarIotcodeByIotcode(String iotCode) {
        // TODO Auto-generated method stub
        List<EquipmentSpecificVo> data;
        if (redisUtils.hasKey("equipAndCarIotCodes")) {
            data = JSON.parseArray(redisUtils.get("equipAndCarIotCodes").toString(), EquipmentSpecificVo.class);
        } else {
            data = equipmentSpecificMapper.getEquipOrCarByIotCode(null);
            redisUtils.set("equipAndCarIotCodes", JSONObject.toJSONString(data));
        }
        if (ObjectUtils.isEmpty(data)) {
            return data;
        }
        List<EquipmentSpecificVo> resultData = data.stream().filter(a -> a.getIotCode().equals(iotCode)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(resultData)) {
            List<EquipmentSpecificVo> equipOrCarByIotCode = equipmentSpecificMapper.getEquipOrCarByIotCode(iotCode);
            if (!CollectionUtils.isEmpty(equipOrCarByIotCode)) {
                data.addAll(equipOrCarByIotCode);
                redisUtils.set("equipAndCarIotCodes", JSONObject.toJSONString(data));
                return equipOrCarByIotCode;
            }
        }
        return resultData;
    }

    @Override
    public void updateEquipmentSpecIndexRealtimeData(EquipmentSpecificIndex index) {
        // TODO Auto-generated method stub
        if (!ObjectUtils.isEmpty(index.getEquipmentSpecificId())) {
            EquipmentSpecific es = equipmentSpecificMapper.selectById(index.getEquipmentSpecificId());
            if (!ObjectUtils.isEmpty(es)) {
                es.setRealtimeIotEsIndexId(index.getId());
                es.setRealtimeIotIndexKey(index.getNameKey());
                es.setRealtimeIotIndexName(index.getEquipmentSpecificIndexName());
                es.setRealtimeIotIndexValue(index.getValue());
                es.setRealtimeIotIndexId(index.getEquipmentIndexId());
                es.setRealtimeIotIndexUpdateDate(index.getUpdateDate());
                es.setValueLabel(index.getValueLabel());
                es.setTypeCode(index.getTypeCode());
                equipmentSpecificMapper.updateById(es);
            }
        }
    }

    @Override
    public Map<String, List<Map<String, String>>> getFessIndexDetails() {
        Map<String, List<Map<String, String>>> map = new HashMap<>();
        List<Map<String, String>> rainRoomIndexDetails = equipmentSpecificMapper.getRainRoomIndexDetails();
        List<Map<String, String>> choiceRoomIndexDetails = equipmentSpecificMapper.getChoiceRoomIndexDetails();
        List<Map<String, String>> boxTropicsIndexDetails = equipmentSpecificMapper.getBoxTropicsIndexDetails();
        List<Map<String, String>> tropicsIndexDetails = equipmentSpecificMapper.getTropicsIndexDetails();
        map.put("rainRoom", rainRoomIndexDetails);
        map.put("choiceRoom", choiceRoomIndexDetails);
        map.put("boxTropics", boxTropicsIndexDetails);
        map.put("tropics", tropicsIndexDetails);
        return map;
    }

    @Override
    public void refreshStaData() {
        List<Map<String, Object>> result = this.baseMapper.queryCompanyStaData();
        result.forEach(m -> redisUtils.set((buildKey(m)), m.get("total"), 86400));

        carService.iotrefreshStaData();
    }

    private String buildKey(Map<String, Object> row) {
        return SourcesStatisticsImpl.PREFIX_CATEGORY_COUNT + row.get("bizOrgCode").toString() + "_" + SourceTypeEnum.EQUIPMENT.getCode() + "_" + row.get("categoryCode").toString();
    }

    @Override
    public Boolean videoOnEquipmentSpecific(VideoOnEquipmentSpecificVo videoOnEquipmentSpecificVo) {
        Long equipmentSpecificId = videoOnEquipmentSpecificVo.getEquipmentSpecificId();
        List<Long> videoIdList = videoOnEquipmentSpecificVo.getVideoIdList();
        if (equipmentSpecificId != null) {

            EquipmentSpecific equipmentSpecific = this.baseMapper.selectById(equipmentSpecificId);
            if (!ObjectUtils.isEmpty(equipmentSpecific)) {
                QueryWrapper<VideoEquipmentSpecific> queryWrapper = new QueryWrapper<>();
                queryWrapper.eq("equipment_specific_id", equipmentSpecificId);
                if (0 == videoIdList.size()) {
                    videoEquipmentSpecificService.remove(queryWrapper);
                    return Boolean.TRUE;
                }
                List<VideoEquipmentSpecific> list = videoEquipmentSpecificService.getBaseMapper().selectList(queryWrapper);
                if (0 < list.size()) {
                    boolean remove = videoEquipmentSpecificService.remove(queryWrapper);
                    if (remove) {
                        this.bingEquipmentRelationshipToVideo(videoIdList, equipmentSpecificId);
                    }
                } else {
                    this.bingEquipmentRelationshipToVideo(videoIdList, equipmentSpecificId);
                }
                return Boolean.FALSE;
            } else {
                throw new RuntimeException("未获取到此设备！");
            }

        } else {
            throw new RuntimeException("设备ID为空！");
        }

    }


    @Override
    public Boolean videoOnEquipmentSpecificbj(Map<String, List<String>> date) {
        List<String> equipmentSpecificIds = date.get("eqid");
        List<String> videoIdList = date.get("videoid");
        if (equipmentSpecificIds != null) {
            for (String equipmentSpecificId : equipmentSpecificIds) {
                EquipmentSpecific equipmentSpecific = this.baseMapper.selectById(equipmentSpecificId);
                if (!ObjectUtils.isEmpty(equipmentSpecific)) {
                    QueryWrapper<VideoEquipmentSpecific> queryWrapper = new QueryWrapper<>();
                    queryWrapper.eq("equipment_specific_id", equipmentSpecificId);
                    List<VideoEquipmentSpecific> list = videoEquipmentSpecificService.getBaseMapper().selectList(queryWrapper);
                    if (list != null && list.size() > 0) {
                        for (VideoEquipmentSpecific videoEquipmentSpecific : list) {
                            if (videoIdList.contains(String.valueOf(videoEquipmentSpecific.getVideoId()))) {
                                videoIdList.remove(String.valueOf(videoEquipmentSpecific.getVideoId()));
                            }
                        }
                    }

                    List<VideoEquipmentSpecific> videoSpecificList1 = new ArrayList<>();
                    videoIdList.parallelStream().forEach(x -> {
                        VideoEquipmentSpecific videoEquipmentSpecific = new VideoEquipmentSpecific();
                        videoEquipmentSpecific.setVideoId(Long.valueOf(x));
                        videoEquipmentSpecific.setEquipmentSpecificId(Long.valueOf(equipmentSpecificId));
                        videoSpecificList1.add(videoEquipmentSpecific);
                    });
                    videoEquipmentSpecificService.saveBatch(videoSpecificList1);

                } else {
                    throw new RuntimeException("未获取到此设备！");
                }
            }
            return Boolean.TRUE;
        } else {
            throw new RuntimeException("设备ID为空！");
        }
    }


    @Override
    public Boolean delVideoOnEquipmentSpecific(Long equipmentSpecificId, Long videoId) {
        QueryWrapper<VideoEquipmentSpecific> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("equipment_specific_id", equipmentSpecificId);
        queryWrapper.eq("video_id", videoId);
        videoEquipmentSpecificService.remove(queryWrapper);
        return true;
    }

    @Override
    public Boolean delVideoOnEquipmentjb(List<String> ids) {
        QueryWrapper<VideoEquipmentSpecific> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("equipment_specific_id", ids);
        videoEquipmentSpecificService.remove(queryWrapper);
        return true;
    }


    private Boolean bingEquipmentRelationshipToVideo(List<Long> videoIdList, Long equipmentSpecificId) {
        List<VideoEquipmentSpecific> videoSpecificList = new ArrayList<>();
        videoIdList.parallelStream().forEach(x -> {
            VideoEquipmentSpecific videoEquipmentSpecific = new VideoEquipmentSpecific();
            videoEquipmentSpecific.setVideoId(x);
            videoEquipmentSpecific.setEquipmentSpecificId(equipmentSpecificId);
            videoSpecificList.add(videoEquipmentSpecific);
        });
        videoEquipmentSpecificService.saveBatch(videoSpecificList);
        return Boolean.TRUE;
    }

    @Override
    public List<Map<String, Object>> getListByEquipmentCodeJ(String code, String bizOrgCode) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtil.isNotEmpty(code)) {
            String[] strings = code.split(",");
            list = equipmentSpecificMapper.getFirePumpInfo(strings, bizOrgCode);
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> getListByEquipmentCodeCSZZ(String code, String bizOrgCode) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtil.isNotEmpty(code)) {
            String[] strings = code.split(",");
            list = equipmentSpecificMapper.getFirePumpInfoCSZZ(strings, bizOrgCode);
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> getFirePumpInfoEQ(String code, String bizCode) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtil.isNotEmpty(code)) {
            String[] strings = code.split(",");
            list = equipmentSpecificMapper.getFirePumpInfoEQ(strings, bizCode);
        }
        return list;
    }

    @Override
    public List<Map<String, Object>> getListByEquipmentCode(String code, String bizOrgCode) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtil.isNotEmpty(code)) {
            String[] strings = code.split(",");
            list = equipmentSpecificMapper.getListByEquipmentCode(strings, bizOrgCode);
        }
        return list;
    }

    @Override
    public List<IotIndexInfoVo> getIndexInfoList(String iotCode, ResponseModel entity, Integer isTrend, String fieldKey) {
        List<IotIndexInfoVo> infoVoList = new ArrayList<>();
        String json = JSON.toJSONString(entity.getResult());
        List<Map<String, String>> listObject = (List<Map<String, String>>) JSONArray.parse(json);
        listObject.sort((t1, t2) -> t2.get("time").compareTo(t1.get("time")));
        List<EquipmentSpecificIndex> indexes = equipmentSpecificIndexMapper.getEquipmentSpeIndexByIotCodeTrend(iotCode, isTrend, fieldKey);
        if (!ObjectUtils.isEmpty(indexes)) {
            Map<String, EquipmentSpecificIndex> collect = indexes.stream().collect(Collectors.toMap(EquipmentSpecificIndex::getNameKey, equipmentSpecificIndex -> equipmentSpecificIndex));
            for (Map<String, String> mapList : listObject) {
                String dateStr = null;
                String deviceName = String.valueOf(mapList.get("deviceName"));
                try {
                    String value = String.valueOf(mapList.get("time"));
                    String strDate = value.substring(0, 19);
                    SimpleDateFormat sdf = new SimpleDateFormat(ISO8601_DATE_HOUR_MIN_SEC);
                    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                    Date date = sdf.parse(strDate);
                    dateStr = DateTimeUtil.format(date, DateTimeUtil.ISO_DATE_HOUR24_MIN_SEC);
                } catch (Exception e) {
                    log.error("日期转换失败");
                }
                for (Map.Entry entry : mapList.entrySet()) {
                    if (!ObjectUtils.isEmpty(entry.getValue()) && !"null".equals(entry.getValue())) {
                        EquipmentSpecificIndex equipmentSpecificIndex = collect.get(entry.getKey());
                        if (!ObjectUtils.isEmpty(equipmentSpecificIndex)) {
                            IotIndexInfoVo iotIndexInfoVo = new IotIndexInfoVo();

                            iotIndexInfoVo.setType(equipmentSpecificIndex.getTypeName() != null ? equipmentSpecificIndex.getTypeName() : equipmentSpecificIndex.getIndexName());

                            iotIndexInfoVo.setNumber(deviceName);
                            if (equipmentSpecificIndex.getIsTrend()) {
                                if (!ObjectUtils.isEmpty(entry.getValue())){
                                    boolean isNum = StringUtil.isNumeric(String.valueOf(entry.getValue()));
                                    if (isNum) {
                                        BigDecimal val = new BigDecimal(String.valueOf(entry.getValue()));
                                        iotIndexInfoVo.setContent(equipmentSpecificIndex.getIndexName() + (val.setScale(2, BigDecimal.ROUND_HALF_UP)) + equipmentSpecificIndex.getIndexUnitName());
                                    }
                                }
                            } else {
                                if (pressurePumpStart.equals(equipmentSpecificIndex.getNameKey())) {
                                    iotIndexInfoVo.setContent(TrueOrFalseEnum.real.value.equals(entry.getValue()) ? equipmentSpecificIndex.getEquipmentIndexName() : PressurePumpRelateEnum.STOP.getDesc());
                                } else {
                                    iotIndexInfoVo.setContent(equipmentSpecificIndex.getEquipmentIndexName());
                                }
                            }
                            iotIndexInfoVo.setSendTime(dateStr);
                            infoVoList.add(iotIndexInfoVo);
                        }
                    }
                }
            }
        }
        return infoVoList;
    }

    /**
     * 在设备报废前30日 每日9点执行 系统推送提醒。设备报废后停止消息推送提醒。。
     *
     * @throws Exception
     */
    @Scheduled(cron = "${equipment.scrap.cron}")
    @Transactional(rollbackFor = Exception.class)
    public void equipmentScrap() throws Exception {
        List<Map<String, Object>> equipSpecificScrap = equipmentSpecificIndexMapper.getEquipSpecificScrap();
        equipSpecificScrap.forEach(e -> {
            try {
                if (e.get("weExpiry") != null) {
                    int year = Integer.parseInt(e.get("weExpiry").toString());
                    Date productDate = DateUtils.dateParse(e.get("product").toString().substring(0,10), DateUtils.DATE_PATTERN);
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTime(productDate);
                    calendar.add(Calendar.YEAR, year);

                    Date now = new Date();
                    String scrapTime = new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN).format(calendar.getTime());
                    int day = DateUtils.dateBetween(now, calendar.getTime());
                    if (day < Integer.parseInt(equipmentScrapDay) && day > -1) {
                        syncSystemctlMsg(e, scrapTime, day);
                    } else if (day == -1) {
                        // 发送emq消息 给idx
                        Map<String, String> map = new HashMap<>();
                        map.put("id", e.get("id").toString());
                        map.put("code", e.get("code").toString());
                        map.put("bizOrgCode", e.get("bizOrgCode").toString());
                        map.put("bizOrgName", e.get("bizOrgName").toString());
//
                        try {
                            emqKeeper.getMqttClient().publish("equip/scrap/put", JSONObject.toJSONString(map).getBytes(), 2, false);
                        } catch (MqttException exp) {
                            log.info(String.format("发送eqm转kafka消息失败：%s", exp.getMessage()));
                        }
//                        idxFeign.handleEquipNotScrapWhenExpired(String.valueOf(e.get("id")), String.valueOf(e.get("bizOrgCode")), String.valueOf(e.get("bizOrgName")));

                        // 发送消息，message监听，转发给中心级
                        Map<String, Object> mapZxj = new HashMap<>();
                        mapZxj.put("topic", "equip/scrap/put");
                        mapZxj.put("data", map);
                        try {
                            emqKeeper.getMqttClient().publish("equip/scrap/put/zxj", JSON.toJSONString(mapZxj).getBytes(), 2, false);
                        } catch (MqttException exp) {
                            log.info(String.format("发送eqm消息，message根据该消息转发为kafka消息,失败信息：%s", exp.getMessage()));
                        }
                    }
                }

            } catch (ParseException parseException) {
                parseException.printStackTrace();
            }
        });

    }


    /**
     * 每日计算当天巡检任务数量，任务是否至少有一次执行。。
     *
     * @throws Exception
     */
    @Scheduled(cron = "${equip.patrol.cron:0 0 23 * * ?}")
    @Transactional(rollbackFor = Exception.class)
    public void patrolTaskStatic() throws Exception {
        log.info("开始每天巡检定时任务===========");
        List<Map<String, Object>> mapPatrol = equipmentSpecificIndexMapper.patrolTaskStatic();
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (Map<String, Object> m : mapPatrol
             ) {
            if(m.get("isFinishOnce").toString().equals("1")) {
                Map<String, Object> map = new HashMap<>();
                map.put("planName", m.getOrDefault("planName", ""));
                map.put("bizOrgCode", m.get("bizOrgCode"));
                map.put("bizOrgName", m.get("bizOrgName"));
                mapList.add(map);
            }
            // 判断是否一次巡查都没有
//            if(m.get("isFinishOnce").toString().equals("0")) {
//                if(m.get("planNum").toString().equals("1")) {
//                    Map<String, Object> map = new HashMap<>();
//                    map.put("planName", m.getOrDefault("planName", ""));
//                    map.put("bizOrgCode", m.get("bizOrgCode"));
//                    map.put("bizOrgName", m.get("bizOrgName"));
//                    mapList.add(map);
//                } else if(Integer.parseInt(m.get("planNum").toString()) > 1){
//                    List<Map<String, Object>> mapPatrolTask = equipmentSpecificIndexMapper.patrolTaskQuery(m.get("bizOrgCode").toString());
//                    for (Map<String, Object> m1:mapPatrolTask
//                         ) {
//                        Map<String, Object> map = new HashMap<>();
//                        map.put("planName", m1.get("planName").toString());
//                        map.put("bizOrgCode", m1.get("bizOrgCode").toString());
//                        map.put("bizOrgName", m1.get("bizOrgName").toString());
//                        mapList.add(map);
//                    }
//                }
//            }
        }
        if(mapList.size() > 0) {
            try {
                emqKeeper.getMqttClient().publish("equip/patrol/put", JSONObject.toJSONString(mapList).getBytes(), 1, false);
            } catch (MqttException exp) {
                log.info(String.format("发送eqm转kafka消息失败：%s", exp.getMessage()));
            }
        }
        if(mapList.size() == 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("bizOrgCode", "");
            mapList.add(map);
            try {
                emqKeeper.getMqttClient().publish("equip/patrol/put", JSONObject.toJSONString(mapList).getBytes(), 2, false);
            } catch (MqttException exp) {
                log.info(String.format("发送eqm转kafka消息失败：%s", exp.getMessage()));
            }
        }

        List<Map<String, Object>> collect = mapPatrol.stream().filter(t -> !"0".equals(t.get("isFinishOnce").toString())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(collect)) {
            try {
                emqKeeper.getMqttClient().publish("assess/patrol/record", JSON.toJSONString(collect).getBytes(), 2, false);
            } catch (MqttException exp) {
                log.info(String.format("发送eqm转kafka消息失败：%s", exp.getMessage()));
            }
        }
    }

    void syncSystemctlMsg(Map<String, Object> map, String scrapTime, int i) {
        try {
            MessageModel model = new MessageModel();
            model.setTitle("报废到期提醒");

            String equipName = map.get("name").toString();
            String location = map.getOrDefault("position", "").toString() + map.getOrDefault("area", "").toString();

            String body = String.format("%s-%s于%s报废，请提前更换处理", equipName, location, scrapTime);
            String join = i != 0 ? String.format("设备还剩%s天报废，请提前更换", i) : "设备今日到期，请立即更换";
            model.setBody(body);
            model.setMsgType("scrapWarning");
            model.setSendTime(new Date());
            model.setIsSendApp(false);
            model.setTerminal("WEB");
            model.setIsSendWeb(true);
            model.setRelationId(map.get("id").toString());
            model.setCategory(1);
            List<String> receive = new ArrayList<>();
            receive.add("system");
            Map<String, String> ext = new HashMap<>();
            ext.put("content", join);
            ext.put("type", "报废到期");
            ext.put("name", map.get("name").toString());
            ext.put("time", new SimpleDateFormat(DateUtils.DATE_TIME_PATTERN).format(new Date()));
            model.setExtras(ext);
            model.setRecivers(receive);
            // Systemctl.messageClient.create(model);
            Token token = remoteSecurityService.getServerToken();
            systemctlFeign.create(token.getAppKey(), token.getProduct(), token.getToke(), model);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Map<String, Object>> normalIndexInfoList(String startDate, String endDate) {
        List<Map<String, Object>> list = equipmentSpecificMapper.normalIndexInfoList(startDate, endDate);
        List<Map<String, Object>> results = new ArrayList<>();
        if (0 < list.size()) {
            int i = 0;
            for (Map<String, Object> map : list) {
                Map<String, Object> map1 = new HashMap<>();
                map1.put("key", i + 1);
                map1.put("sb", map.get("equipName"));
                map1.put("cs", map.get("equipmentIndexName"));
                map1.put("zz", map.get("value"));
                map1.put("yz", map.get("standardValue"));
                map1.put("sj", map.get("time"));
                map1.put("zrr", map.get("chargePersonName"));
                map1.put("szqy", map.get("areaName"));
                map1.put("ssxt", map.get("fightSysName"));
                results.add(map1);
            }
        }
        return results;
    }

    @Override
    public Page<Map<String, Object>> normalIndexInfoListByPage(Page<Map<String, Object>> page, String startDate, String endDate, String systemCode, String name) {
        return equipmentSpecificMapper.normalIndexInfoListByPage(page, startDate, endDate, systemCode, name);
    }

    @Override
    public Map<String, Object> getFireAutoSysInfo(String startDate, String endDate) {
        return equipmentSpecificMapper.getFireAutoSysInfo();
    }

    @Override
    public Map<String, Object> getPaomoSysInfo(String startDate, String endDate) {
        return equipmentSpecificMapper.getPaomoSysInfo();
    }

    @Override
    public Map<String, Object> getWaterSysInfo(String startDate, String endDate) {
        return equipmentSpecificMapper.getWaterSysInfo();
    }

    @Override
    public List<Map<String, Object>> getEquipmentStatisticsInfo(String bizOrgCode) {
        String json = null;
        try {
            json = IOUtils.toString(equipmentCode.getInputStream(), java.lang.String.valueOf(StandardCharsets.UTF_8));
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<Map> mapList = JSONObject.parseArray(json, Map.class);
        Map<String, Object> map = new HashMap<>();
        mapList.forEach(x -> map.put(String.valueOf(x.get("nameKey")), x.get("code")));
        map.put("bizOrgCode", bizOrgCode);
        Map<String, Object> result = equipmentSpecificMapper.getEquipmentStatisticsInfo(map);
        List<Map<String, Object>> list = new ArrayList<>();
        mapList.forEach(y -> {
            Map<String, Object> tempMap = new HashMap<>();
            tempMap.put("name", y.get("name"));
            tempMap.put("code", y.get("nameKey"));
            tempMap.put("total", result.get(y.get("nameKey")));
            list.add(tempMap);
        });
        return list;
    }

    @Override
    public Page<FireFightingSystemDto> fireSysIotEquipCount(Page<Map<String, Object>> page, String bizOrgCode) {
        return equipmentSpecificMapper.fireSysIotEquipCount(page, bizOrgCode);
    }

    @Override
    public List<FireFightingSystemDto> fireSysIotEquipAlarmCount(Date date, String bizOrgCode) {
        return equipmentSpecificMapper.fireSysIotEquipAlarmCount(date, bizOrgCode);
    }

    @Override
    public List<Map> getWater(Long id) {
        return equipmentSpecificMapper.getWater(id);
    }

    @Override
    public Map<String, Object> getStationCode(Long id) {
        return equipmentSpecificMapper.getStationCode(id);
    }

    @Override
    public void updateEquipSpecificStatus(String status, String id) {
        // 权限处理
        PermissionInterceptorContext.setDataAuthRule(authKey);
        Integer num = equipmentSpecificMapper.updateEquipSpecificStatus(status, id);

        if (0 < num) {
            EquipmentSpecific equipmentSpecific = equipmentSpecificMapper.selectById(id);
            if (StringUtil.isNotEmpty(equipmentSpecific.getSystemId())) {
                List<String> ids = new ArrayList<>();
                ids = Arrays.asList(equipmentSpecific.getSystemId().split(","));
                // 权限处理
                PermissionInterceptorContext.setDataAuthRule(authKey);
                ids.forEach(x -> {
                    // 系统赋码
                    String equipStatus = equipmentSpecificMapper.getEquipStatusList(x);
                    fireFightingSystemMapper.updateStatusById(x, equipStatus);
                });
            }

            // 水源赋码
            QueryWrapper<Equipment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("code", equipmentSpecific.getEquipmentCode());
            Equipment equipment = equipmentService.getOne(queryWrapper);
            List<Long> ids = equipmentSpecificMapper.countEquipStatusListByEquipId(equipment.getId());
            if (0 < ids.size()) {
                String equipStatus = equipmentSpecificMapper.getSpecificStatusByEquipmentCode(equipment.getCode());
                equipmentSpecificMapper.updateWaterResourceStatus(equipment.getId(), equipStatus);
            }
        }
    }


    @Override
    public void updateCarStatus(String status, String carId) {
        equipmentSpecificMapper.updateCarStatus(carId, status);
    }

    @Override
    public String updateEquipSpecificStatusByCheckInput(String id) {
        return equipmentSpecificMapper.updateEquipSpecificStatusByCheckInput(id);
    }

    @Override
    public IPage<EquipTypeImgAmountVO> getMonitoringUnitList(EquipTypeAmountPageDTO equipTypeAmountPage, String useSource) {
        IPage<EquipTypeImgAmountVO> record = equipmentSpecificMapper.getMonitoringUnitList(equipTypeAmountPage.getPage(), equipTypeAmountPage, useSource);
        record.getRecords().forEach(e -> {
            e.setEquip(equipmentSpecificMapper.getMonitoringEquip(String.valueOf(e.getId())).get("num").toString());
            e.setOther(equipmentSpecificMapper.getMonitoringOther(String.valueOf(e.getId())).get("num").toString());
        });
        return record;
    }

    @Override
    public List<Map<String, Object>> getMonitoringCount(String bizOrgCode) {
        return equipmentSpecificMapper.getMonitoringCount(bizOrgCode);
    }

    @Override
    public void updateEquipQrCode(List<Map<String, String>> mapList, String status) {
        log.info("收到规则回调后调用装备消码方法》》》》》》》》》》》》》》,{}", mapList);
        if (!CollectionUtils.isEmpty(mapList)) {
            List<String> ids = mapList.stream().map(m -> m.get("sourceId")).filter(Objects::nonNull).collect(Collectors.toList());
            equipmentSpecificMapper.updateEquipQrCode(ids, status);

            Map<String, String> map = mapList.get(0);
            String equipId = map.get("sourceId");
            String specificIndexId = map.get("specificIndexId");
            idxFeign.cleanQrcode(specificIndexId, equipId, "equip");
        }
    }

    @Override
    public String getEquipRealtimeSignal(long id) {
        return equipmentSpecificMapper.selectEquipRealtimeSignal(id);
    }

    @Override
    public EquipmentSpecific getEquipSpecificEntityByCode(String code) {
        return equipmentSpecificMapper.getEquipSpecificEntityByCode(code);
    }

    @Override
    public void updateCarQrCode(List<Map<String, String>> carIds, String status) {
        carService.updateCarQrCode(carIds, status);
    }


    @Override
    public List<Map<String, Object>> getZJPatrolStatics(String bizOrgCode) {
        return equipmentSpecificMapper.getPatrolInfo(bizOrgCode);
    }

    @Override
    public List<Map<String, Object>> getZJScrapStatics(String bizOrgCode) {
        return equipmentSpecificMapper.getZJScrapStatics(bizOrgCode);
    }

    @Override
    public Page<Map<String, Object>> getFireEquipListByDefineCode(String code, String equipStatus, String bizOrgCode, Page<Map<String, Object>> pageBean) {
        List<Map<String, Object>> list = equipmentSpecificMapper.getFireEquipListByDefineCode(pageBean.offset(), pageBean.getSize(), bizOrgCode, code, equipStatus);
        int count = equipmentSpecificMapper.count(bizOrgCode, code, equipStatus);
        pageBean.setRecords(list);
        pageBean.setTotal(count);
        return pageBean;
    }

    @Override
    public EquipTrendResultVo operatingTrendIot(String startTime, String endTime, String bizOrgCode, String equipCode, String indexKey) {
        List<EquipTrendInfoVo> equipList = equipmentSpecificMapper.getEquipListByCode(equipCode, indexKey, bizOrgCode);
        List<String> allTimeList = new ArrayList<>();
        ResponseModel entity = null;

        //返回数据组装定义
        List<String> legends = new ArrayList<>();
        List<List<String>> threshold = new ArrayList<>();

        Map<String, Map<String, String>> dateValueMapInfo = new HashMap<>();

        EquipTrendResultVo equipTrendResultVo = new EquipTrendResultVo();
        for (EquipTrendInfoVo equipInfo : equipList) {
            //返回数据组装
            List<String> maxMinInfo = new ArrayList<>();
            maxMinInfo.add(equipInfo.getMinNum());
            maxMinInfo.add(equipInfo.getMaxNum());
            threshold.add(maxMinInfo);
            legends.add(equipInfo.getName());
            equipTrendResultVo.setyAxisName(equipInfo.getUnit());

            //iot数据查询组装
            String prefix = null;
            String suffix = null;
            String iotCode = equipInfo.getIotCode();
            if (StringUtil.isNotEmpty(iotCode) && iotCode.length() > 8) {
                prefix = iotCode.substring(0, 8);
                suffix = iotCode.substring(8);
            } else {
                throw new BadRequest("装备物联编码不存在或编码错误，请确认！");
            }
            try {
                entity = iotFeign.selectList(getAppKey(), getProduct(), getToken(), startTime, endTime, prefix, suffix, indexKey);
            } catch (Exception e) {
                throw new RuntimeException("调用AMOS-API-IOT服务失败，请检查服务是否正常！");
            }
            if (200 == entity.getStatus() && !ObjectUtils.isEmpty(entity.getResult())) {
                String json = JSON.toJSONString(entity.getResult());
                List<Map<String, String>> listObject = (List<Map<String, String>>) JSONArray.parse(json);
                // 使用Stream API进行排序
                List<Map<String, String>> sortedList = listObject.stream()
                        .sorted(Comparator.comparing(t -> t.get("time")))
                        .collect(Collectors.toList());
                Map<String, String> timeAndValue = new HashMap<>();
                for (Map<String, String> mapList : sortedList) {
                    if (mapList.containsKey(indexKey)) {
                        boolean isNum = StringUtil.isNumeric(mapList.get(indexKey));
                        if (isNum) {
                            try {
                                timeAndValue.put(change(mapList.get("time")), mapList.get(indexKey));
                                allTimeList.add(change(mapList.get("time")));
                            } catch (ParseException e) {
                                throw new RuntimeException(e);
                            }
                        }
                    }
                }
                dateValueMapInfo.put(equipInfo.getId(), timeAndValue);
            }
        }
        allTimeList = allTimeList.stream().distinct().collect(Collectors.toList());

        equipTrendResultVo.setLegends(legends);
        equipTrendResultVo.setThreshold(threshold);

        List<List<Object>> yaxisList = new ArrayList<>();
        for (EquipTrendInfoVo info : equipList) {
            //key：时间   value：数值
            Map<String, String> dateValueDataMap = dateValueMapInfo.get(info.getId());
            List<Object> values = new ArrayList<>();
            String lastValue = "0";
            List<String> allTimeListNew = new ArrayList<>();
            for (int i = 0; i < allTimeList.size(); i++) {
                if (!ObjectUtils.isEmpty(dateValueDataMap) && dateValueDataMap.containsKey(allTimeList.get(i))) {
                    lastValue = dateValueDataMap.get(allTimeList.get(i));
                }
                values.add(lastValue);

                allTimeListNew.add(allTimeList.get(i));

            }
            yaxisList.add(values);
            Collections.sort(allTimeListNew);
            equipTrendResultVo.setxAxisData(allTimeListNew);
        }
        equipTrendResultVo.setyAxisData(yaxisList);
        return equipTrendResultVo;
    }

    @Override
    public EquipTrendResultVo operatingTrendPressurePump(String startTime, String endTime, String bizOrgCode, String equipCode, String indexKey) throws ParseException {
        // 定义一个DateTimeFormatter来匹配时间字符串的格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 使用parse方法将字符串解析为LocalDateTime对象
        LocalDateTime startTimeLocal = LocalDateTime.parse(startTime, formatter);
        LocalDateTime endTimeLocal = LocalDateTime.parse(endTime, formatter);
        //横坐标数据
        List<String> allTimeList = getHourlyTimes(startTimeLocal, endTimeLocal);
        List<EquipTrendInfoVo> equipList = equipmentSpecificMapper.getEquipListByCode(equipCode, indexKey, bizOrgCode);
        ResponseModel entity = null;

        //返回数据组装定义
        List<String> legends = new ArrayList<>();
        List<List<String>> threshold = new ArrayList<>();

        List<List<Object>> yaxisList = new ArrayList<>();
        EquipTrendResultVo equipTrendResultVo = new EquipTrendResultVo();
        //横坐标数据
        List<String> allTimeListNew = new ArrayList<>();
        for (EquipTrendInfoVo equipInfo : equipList) {
            //返回数据组装
            List<String> maxMinInfo = new ArrayList<>();
            maxMinInfo.add(equipInfo.getMinNum());
            maxMinInfo.add(equipInfo.getMaxNum());
            threshold.add(maxMinInfo);
            legends.add(equipInfo.getName());
            equipTrendResultVo.setyAxisName(equipInfo.getUnit());

            //iot数据查询组装
            String prefix = null;
            String suffix = null;
            String iotCode = equipInfo.getIotCode();
            if (StringUtil.isNotEmpty(iotCode) && iotCode.length() > 8) {
                prefix = iotCode.substring(0, 8);
                suffix = iotCode.substring(8);
            } else {
                throw new BadRequest("装备物联编码不存在或编码错误，请确认！");
            }
            try {
                entity = iotFeign.selectList(getAppKey(), getProduct(), getToken(), startTime, endTime, prefix, suffix, indexKey);
            } catch (Exception e) {
                throw new RuntimeException("调用AMOS-API-IOT服务失败，请检查服务是否正常！");
            }

            HashMap<String, Integer> stringIntegerHashMap = new HashMap<>();
            if (200 == entity.getStatus() && !ObjectUtils.isEmpty(entity.getResult())) {
                String json = JSON.toJSONString(entity.getResult());
                List<Map<String, String>> listObject = (List<Map<String, String>>) JSONArray.parse(json);
                List<String> values = new ArrayList<>();
                for (Map<String, String> mapList : listObject) {
                    String time = change(mapList.get("time")).substring(0, 13);
                    if (mapList.containsKey(indexKey) && mapList.get(indexKey).equals("true")) {
                        if (stringIntegerHashMap.containsKey(time)) {
                            stringIntegerHashMap.put(time, stringIntegerHashMap.get(time) + 1);
                        } else {
                            stringIntegerHashMap.put(time, 1);
                        }
                    }
                }
            }

            List<Object> values = new ArrayList<>();
            for (int i = 0; i < allTimeList.size(); i++) {
                values.add(stringIntegerHashMap.getOrDefault(allTimeList.get(i), 0).toString());
            }
            yaxisList.add(values);
        }
        List<String> collect = allTimeList.stream().map(item -> item + ":00").collect(Collectors.toList());
        equipTrendResultVo.setxAxisData(collect);
        equipTrendResultVo.setLegends(legends);
        equipTrendResultVo.setThreshold(threshold);
        equipTrendResultVo.setyAxisData(yaxisList);
        return equipTrendResultVo;
    }

    @Override
    public EquipTrendResultVo operatingTrendWater(String startTime, String endTime, String bizOrgCode, String equipCode, String indexKey) throws ParseException {
        //横坐标数据
        List<String> allTimeList = getTimePoints(startTime, endTime);
        List<EquipTrendInfoVo> equipList = new ArrayList<>();

        // iot服务查到的数据，存储为map    key：iotCode   value: iot查询的液位数据
        HashMap<String, List<Map<String, String>>> iotDataInfoMap = new HashMap<>();
        Map<String, String> iotCodeIndexKeyMap = new HashMap<>();
        Set<String> strings = new HashSet<>();
        if (StrUtil.isEmpty(equipCode)) {
            equipList = equipmentSpecificMapper.getWaterList(bizOrgCode);

            equipList.forEach(item -> {
                String[] split = item.getIotCode().split(",");
                strings.addAll(Arrays.asList(split));
            });

            List<Map<String, String>> indexKeyByIotCode = equipmentSpecificMapper.getIndexKeyByIotCode(strings);
            iotCodeIndexKeyMap = indexKeyByIotCode.stream().collect(Collectors.toMap(t -> t.get("iotCode"), t -> t.get("indexKey")));
        } else {
            equipList = equipmentSpecificMapper.getEquipListByCode(equipCode, indexKey, bizOrgCode);
            equipList.forEach(item -> {
                String[] split = item.getIotCode().split(",");
                strings.addAll(Arrays.asList(split));
            });
            List<Map<String, String>> indexKeyByIotCode = equipmentSpecificMapper.getIndexKeyByIotCodeWaterTank(strings);
            iotCodeIndexKeyMap = indexKeyByIotCode.stream().collect(Collectors.toMap(t -> t.get("iotCode"), t -> t.get("indexKey")));

        }

        for (String iotCode : strings) {
            //iot数据查询组装
            String prefix = null;
            String suffix = null;
            if (StringUtil.isNotEmpty(iotCode) && iotCode.length() > 8) {
                prefix = iotCode.substring(0, 8);
                suffix = iotCode.substring(8);
            } else {
                throw new BadRequest("装备物联编码不存在或编码错误，请确认！");
            }
            ResponseModel entity = null;
            try {
                if (iotCodeIndexKeyMap.containsKey(iotCode) && StringUtil.isNotEmpty(iotCodeIndexKeyMap.get(iotCode))) {
                    String[] split = iotCodeIndexKeyMap.get(iotCode).split(",");
                    for (String indexKeyNew : split) {
                        entity = iotFeign.selectList(getAppKey(), getProduct(), getToken(), startTime, endTime, prefix, suffix, indexKeyNew);
                        if (200 == entity.getStatus() && !ObjectUtils.isEmpty(entity.getResult())) {
                            String json = JSON.toJSONString(entity.getResult());
                            List<Map<String, String>> listObject = (List<Map<String, String>>) JSONArray.parse(json);
                            if (!CollectionUtils.isEmpty(listObject)) {
                                if (iotDataInfoMap.containsKey(iotCode)) {
                                    iotDataInfoMap.get(iotCode).addAll(listObject);
                                } else {
                                    iotDataInfoMap.put(iotCode, listObject);
                                }
                            }
                        }
                    }
                }
            } catch (Exception e) {
                throw new RuntimeException("调用AMOS-API-IOT服务失败，请检查服务是否正常！");
            }
        }

        //返回数据组装定义
        List<String> legends = new ArrayList<>();
        List<List<String>> threshold = new ArrayList<>();

        List<List<Object>> yaxisList = new ArrayList<>();
        EquipTrendResultVo equipTrendResultVo = new EquipTrendResultVo();
        for (EquipTrendInfoVo equipInfo : equipList) {
            //返回数据组装
            List<String> maxMinInfo = new ArrayList<>();
            maxMinInfo.add(equipInfo.getMinNum());
            maxMinInfo.add(equipInfo.getMaxNum());
            threshold.add(maxMinInfo);
            legends.add(equipInfo.getName());
            equipTrendResultVo.setyAxisName(equipInfo.getUnit());

            HashMap<String, List<BigDecimal>> stringIntegerHashMap = new HashMap<>();
            String[] split = equipInfo.getIotCode().split(",");

            for (String iotCode : split) {
                HashMap<String, List<BigDecimal>> stringIntegerHashMapIn = new HashMap<>();
                String equipIndexKey = iotCodeIndexKeyMap.get(iotCode);
                String[] equipIndexKeyNew = equipIndexKey.split(",");
                if (!ObjectUtils.isEmpty(iotDataInfoMap) && iotDataInfoMap.containsKey(iotCode)) {
                    List<Map<String, String>> listObject = iotDataInfoMap.get(iotCode);
                    for (Map<String, String> mapList : listObject) {
                        String time = change(mapList.get("time"));
                        String dateX = roundToNextFiveMinutes(time);

                        for (String key : equipIndexKeyNew) {
                            if (mapList.containsKey(key) && !ObjectUtils.isEmpty(mapList.get(key))) {
                                if (stringIntegerHashMapIn.containsKey(dateX)) {
                                    boolean isNum = StringUtil.isNumeric(mapList.get(key));
                                    if (isNum) {
                                        stringIntegerHashMapIn.get(dateX).add(new BigDecimal(mapList.get(key)));
                                    }
                                } else {
                                    List<BigDecimal> bigDecimals = new ArrayList<>();
                                   if (!ObjectUtils.isEmpty(mapList.get(key))) {
                                       boolean isNum = StringUtil.isNumeric(mapList.get(key));
                                       if (isNum) {
                                           bigDecimals.add(new BigDecimal(mapList.get(key)));
                                           stringIntegerHashMapIn.put(dateX, bigDecimals);
                                       }
                                   }

                                }
                            }
                        }



                    }
                }

                for (Map.Entry<String, List<BigDecimal>> stringListEntry : stringIntegerHashMapIn.entrySet()) {
                    BigDecimal lastNum = BigDecimal.ZERO;
                    List<BigDecimal> orDefault = stringListEntry.getValue();
                    // 计算非空值的总和
                    BigDecimal sum = orDefault.stream()
                            .filter(Objects::nonNull)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);

                    // 计算非空值的数量
                    long count = orDefault.stream().filter(Objects::nonNull).count();

                    // 检查除数是否为0
                    BigDecimal divide;
                    if (count == 0) {
                        // 如果非空值数量为0，可以选择返回0或其他默认值
                        divide = lastNum;
                    } else {
                        // 否则，进行除法运算
                        divide = sum.divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
                    }

                    if (stringIntegerHashMap.containsKey(stringListEntry.getKey())) {
                        stringIntegerHashMap.get(stringListEntry.getKey()).add(divide);
                    } else {
                        List<BigDecimal> bigDecimals = new ArrayList<>();
                        bigDecimals.add(divide);
                        stringIntegerHashMap.put(stringListEntry.getKey(), bigDecimals);
                    }
                }
            }
            List<Object> values = new ArrayList<>();
            BigDecimal lastNum = BigDecimal.ZERO;
            for (int i = 0; i < allTimeList.size(); i++) {
                List<BigDecimal> orDefault = stringIntegerHashMap.getOrDefault(allTimeList.get(i), new ArrayList<>());
                // 计算非空值的总和
                BigDecimal sum = orDefault.stream()
                        .filter(Objects::nonNull)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                // 计算非空值的数量
                long count = orDefault.stream().filter(Objects::nonNull).count();

                // 检查除数是否为0
                BigDecimal divide;
                if (count == 0) {
                    // 如果非空值数量为0，可以选择返回0或其他默认值
                    divide = lastNum;
                } else {
                    // 否则，进行除法运算
                    divide = sum.divide(new BigDecimal(count), 2, RoundingMode.HALF_UP);
                }
                values.add(divide);
                lastNum = divide.compareTo(BigDecimal.ZERO) == 0 ? lastNum : divide;
            }
            yaxisList.add(values);
        }


        List<String> collect = allTimeList.stream().map(item -> item + ":00").collect(Collectors.toList());
        equipTrendResultVo.setxAxisData(collect);
        equipTrendResultVo.setLegends(legends);
        equipTrendResultVo.setThreshold(threshold);
        equipTrendResultVo.setyAxisData(yaxisList);
        return equipTrendResultVo;
    }

    private String change(String time) throws ParseException {
        Date date1 = null;
        try {
            String strDate = time.substring(0, 19);
            SimpleDateFormat sdf = new SimpleDateFormat(ISO8601_DATE_HOUR_MIN_SEC);
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
            date1 = sdf.parse(strDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return DateTimeUtil.format(date1, DateTimeUtil.ISO_DATE_HOUR24_MIN_SEC);
    }

    // 格式化器，用于输出时间
    private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH");

    /**
     * 获取给定时间段内每个整点的时间列表
     *
     * @param startTime 开始时间（包含）
     * @param endTime   结束时间（不包含其下一个整点）
     * @return 整点时间列表
     */
    public static List<String> getHourlyTimes(LocalDateTime startTime, LocalDateTime endTime) {
        List<String> hourlyTimes = new ArrayList<>();

        // 将开始时间调整为当前小时的起始点
        LocalDateTime currentTime = startTime.truncatedTo(java.time.temporal.ChronoUnit.HOURS);

        // 循环直到超过结束时间（不包含结束时间的下一个整点）
        while (!currentTime.isAfter(endTime)) {
            hourlyTimes.add(currentTime.format(formatter));
            currentTime = currentTime.plusHours(1);
        }
        return hourlyTimes;
    }


    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    /**
     * 根据开始时间和结束时间，每隔五分钟获取一个时间点
     *
     * @param startTimeStr 开始时间字符串，格式为"yyyy-MM-dd HH:mm:ss"
     * @param endTimeStr   结束时间字符串，格式为"yyyy-MM-dd HH:mm:ss"
     * @return 时间点列表，每个时间点格式为"yyyy-MM-dd HH:mm"
     */
    public static List<String> getTimePoints(String startTimeStr, String endTimeStr) {
        List<String> timePoints = new ArrayList<>();

        try {
            // 将字符串时间转换为Date对象
            // 注意：这里我们直接解析startTimeStr的完整格式，但只使用年和月日时分来计算下一个五分钟节点
            Date startTime = sdf.parse(startTimeStr);
            Date endTime = sdf.parse(endTimeStr);

            // 计算起始时间的下一个五分钟节点
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startTime);
            int minute = calendar.get(Calendar.MINUTE);
            int nextFiveMinute = (minute / 5 + 1) * 5; // 计算下一个五分钟节点的分钟数
            calendar.set(Calendar.MINUTE, nextFiveMinute);
            calendar.set(Calendar.SECOND, 0); // 重置秒为0
            calendar.set(Calendar.MILLISECOND, 0); // 重置毫秒为0

            // 初始时间点为起始时间的下一个五分钟节点
            Date currentTime = calendar.getTime();

            // 循环直到当前时间超过结束时间
            while (currentTime.before(endTime) || currentTime.equals(endTime)) {
                // 格式化当前时间并添加到列表中
                timePoints.add(sdf.format(currentTime));

                // 计算下一个时间点（五分钟后的时间）
                calendar.add(Calendar.MINUTE, 5);
                currentTime = calendar.getTime();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return timePoints;
    }

    // 定义一个DateTimeFormatter用于解析输入时间（包含秒）
    // 注意：虽然在这个方法中我们不会直接使用它，但保留它以备将来需要
    private static final DateTimeFormatter parserWithSeconds = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    // 定义一个DateTimeFormatter用于格式化输出时间（不包含秒）
    private static final DateTimeFormatter formatterFive = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");

    /**
     * 将给定的时间调整为下一个5分钟节点
     *
     * @param timeStr 输入的时间字符串，格式为"yyyy-MM-dd HH:mm:ss"
     * @return 转换后的时间字符串，格式为"yyyy-MM-dd HH:mm"
     */
    public static String roundToNextFiveMinutes(String timeStr) {
        // 直接解析包含秒的时间字符串（虽然在这个方法中我们不需要秒）
        LocalDateTime dateTime = LocalDateTime.parse(timeStr, parserWithSeconds);

        // 获取分钟数
        int minute = dateTime.getMinute();

        // 计算到下一个5分钟节点的分钟数
        int nextFiveMinutes = (minute / 5 + 1) * 5; // 总是向上调整到下一个5分钟倍数

        // 计算需要增加的分钟数
        int adjustment = nextFiveMinutes - minute;

        // 加上差值以调整到下一个5分钟节点，并保留小时和日期部分，但重置秒为0
        LocalDateTime roundedDateTime = dateTime.plusMinutes(adjustment).withSecond(0);

        // 格式化并返回结果
        return roundedDateTime.format(formatterFive);
    }

}
