package com.yeejoin.amos.boot.module.jg.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelReader;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.metadata.ReadSheet;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
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.conditions.update.UpdateWrapper;
import com.google.common.collect.Sets;
import com.yeejoin.amos.boot.biz.common.bo.CompanyBo;
import com.yeejoin.amos.boot.biz.common.bo.ReginParams;
import com.yeejoin.amos.boot.biz.common.utils.*;
import com.yeejoin.amos.boot.module.common.api.dao.ESEquipmentCategory;
import com.yeejoin.amos.boot.module.common.api.dao.ExcelImportErrorLogDao;
import com.yeejoin.amos.boot.module.common.api.dto.ESEquipmentCategoryDto;
import com.yeejoin.amos.boot.module.common.api.dto.ExcelImportErrorLogDto;
import com.yeejoin.amos.boot.module.jg.api.common.DataDockTemplateVersionUtils;
import com.yeejoin.amos.boot.module.jg.api.converter.DictParamsConverter;
import com.yeejoin.amos.boot.module.jg.api.converter.EquCategoryConverter;
import com.yeejoin.amos.boot.module.jg.api.converter.EquDefineConverter;
import com.yeejoin.amos.boot.module.jg.api.converter.EquListConverter;
import com.yeejoin.amos.boot.module.jg.api.dto.*;
import com.yeejoin.amos.boot.module.jg.api.entity.*;
import com.yeejoin.amos.boot.module.jg.api.enums.BusinessTypeEnum;
import com.yeejoin.amos.boot.module.jg.api.enums.CertificateStatusEnum;
import com.yeejoin.amos.boot.module.jg.api.mapper.*;
import com.yeejoin.amos.boot.module.jg.biz.config.LocalBadRequest;
import com.yeejoin.amos.boot.module.jg.biz.context.EquipUsedCheckStrategyContext;
import com.yeejoin.amos.boot.module.jg.biz.context.FlowingEquipRedisContext;
import com.yeejoin.amos.boot.module.jg.biz.event.publisher.EventPublisher;
import com.yeejoin.amos.boot.module.jg.biz.feign.TzsServiceFeignClient;
import com.yeejoin.amos.boot.module.jg.biz.reminder.core.event.EquipCreateOrEditEvent;
import com.yeejoin.amos.boot.module.jg.biz.service.*;
import com.yeejoin.amos.boot.module.jg.biz.utils.CodeUtil;
import com.yeejoin.amos.boot.module.jg.biz.utils.JsonUtils;
import com.yeejoin.amos.boot.module.ymt.api.entity.*;
import com.yeejoin.amos.boot.module.ymt.api.enums.ApplicationFormTypeEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquimentEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.EquipmentClassifityEnum;
import com.yeejoin.amos.boot.module.ymt.api.enums.FlowStatusEnum;
import com.yeejoin.amos.boot.module.ymt.api.mapper.*;
import com.yeejoin.amos.feign.privilege.Privilege;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.feign.privilege.model.CompanyModel;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.typroject.tyboot.core.foundation.context.RequestContext;
import org.typroject.tyboot.core.foundation.utils.ValidationUtil;
import org.typroject.tyboot.core.restful.exception.instance.BadRequest;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.alibaba.fastjson.JSON.toJSONString;
import static com.yeejoin.amos.boot.module.jg.biz.service.impl.IdxBizJgRegisterInfoServiceImpl.toCamelCase;

@Slf4j
@Service
@RequiredArgsConstructor
public class DataDockServiceImpl {
    private final SnowflakeIdUtil sequence;
    private final ESEquipmentCategory esEquipmentCategory;
    private final CategoryOtherInfoMapper categoryOtherInfoMapper;
    private final IIdxBizJgUseInfoService idxBizJgUseInfoService;
    private final IIdxBizJgProjectContraptionService idxBizJgProjectContraptionService;
    private final IdxBizJgDesignInfoServiceImpl idxBizJgDesignInfoService;
    private final IdxBizJgFactoryInfoServiceImpl idxBizJgFactoryInfoService;
    private final IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoServiceImpl;
    private final IdxBizJgSupervisionInfoServiceImpl idxBizJgSupervisionInfoService;
    private final IdxBizJgOtherInfoServiceImpl idxBizJgOtherInfoService;
    private final IIdxBizJgTechParamsVehicleService iIdxBizJgTechParamsVehicleService;
    private final IIdxBizJgTechParamsLiftingService iIdxBizJgTechParamsLiftingService;
    private final IIdxBizJgTechParamsBoilerService iIdxBizJgTechParamsBoilerService;
    private final IIdxBizJgTechParamsVesselService iIdxBizJgTechParamsVesselService;
    private final IIdxBizJgTechParamsPipelineService iIdxBizJgTechParamsPipelineService;
    private final IdxBizJgInspectionDetectionInfoServiceImpl idxBizJgInspectionDetectionInfoService;
    private final IIdxBizJgTechParamsRidesService iIdxBizJgTechParamsRidesService;
    private final IIdxBizJgTechParamsRopewayService iIdxBizJgTechParamsRopewayService;
    private final IIdxBizJgTechParamsElevatorService iIdxBizJgTechParamsElevatorService;
    private final IdxBizJgProjectContraptionServiceImplService idxBizJgProjectContraptionServiceImpl;
    private final IdxBizJgConstructionInfoServiceImpl idxBizJgConstructionInfoService;
    private final JgInstallationNoticeServiceImpl installationNoticeService;
    private final JgUseRegistrationManageServiceImpl jgUseRegistrationManageService;
    private final RedisUtils redisUtils;
    private final JgUseRegistrationServiceImpl jgUseRegistrationServiceImpl;
    private final JgUseRegistrationEqServiceImpl jgUseRegistrationEqServiceImpl;
    private final TzsServiceFeignClient tzsServiceFeignClient;
    private final CommonServiceImpl commonService;
    private final JgRegistrationHistoryServiceImpl jgRegistrationHistoryService;
    private final JgCertificateChangeRecordServiceImpl certificateChangeRecordService;
    private final JgCertificateChangeRecordEqServiceImpl certificateChangeRecordEqService;
    private final InspectionDetectionInfoMapper inspectionDetectionInfoMapper;
    private final IdxBizJgRegisterInfoServiceImpl idxBizJgRegisterInfoService;
    private final JgUseRegistrationEqMapper jgRelationEquipMapper;
    private final IdxBizJgOtherInfoMapper otherInfoMapper;
    private final ProduceInfoMapper produceInfoMapper;
    private final CodeUtil codeUtil;
    private final CommonMapper commonMapper;
    private final JgResumeInfoServiceImpl jgResumeInfoService;
    private final IdxBizJgMaintenanceRecordInfoServiceImpl idxBizJgMaintenanceRecordInfoService;
    private final Map<String, Object> resultError = new HashMap<>();
    List<String> useInnerCodeList = new ArrayList<>();// 单位内部编号集合
    List<String> equCodeList = new ArrayList<>();// 设备代码集合
    List<String> factoryNumList = new ArrayList<>();// 出厂编码集合
    List<String> useOrgCodeList = new ArrayList<>();// 使用登记证集合
    Map<String, List<String>> projectContraptionMap = new HashMap<>();// 工程装置名称集合
    private static final String DEFINITION_KEY = "useRegistration";
    @Value("classpath:/json/urlInfo.json")
    private Resource urlInfo;
    private final JgVehicleInformationMapper jgVehicleInformationMapper;
    private final IdxBizJgRegisterInfoMapper idxBizJgRegisterInfoMapper;
    private final ExcelImportErrorLogDao excelImportErrorLogDao;
    // 设备分类表单id
    public static final String EQUIP_CLASS_FORM_ID = "equipClass";
    // 设备基本信息表单id
    public static final String EQUIP_INFO_FORM_ID = "equipInfo";
    // 设备技术参数表单id
    private static final String ATTACHMENT_UPLOAD = "attachmentUpload";
    // 模版上传集合
    public static final String EQU_LISTS = "equLists";
    private final EventPublisher eventPublisher;
    private final JgUseRegistrationManageMapper jgUseRegistrationManageMapper;
    private final IdxBizJgTechParamsPipelineMapper idxBizJgTechParamsPipelineMapper;
    private final IdxBizJgUseInfoMapper idxBizJgUseInfoMapper;
    private final IdxBizJgFactoryInfoMapper idxBizJgFactoryInfoMapper;
    private final IdxBizJgDesignInfoMapper idxBizJgDesignInfoMapper;
    private final IdxBizJgSupervisionInfoMapper idxBizJgSupervisionInfoMapper;
    private final IdxBizJgConstructionInfoMapper idxBizJgConstructionInfoMapper;
    private final IdxBizJgOtherInfoMapper idxBizJgOtherInfoMapper;
    private final IdxBizJgInspectionDetectionInfoMapper idxBizJgInspectionDetectionInfoMapper;

    @Value("${equip.detail.path:/mixuap?appId=1742358052905971713&id=1734100233714954241&formType=detail&record=%s&DATA_SOURCE=%s}")
    private String equipRoutePath;

    @Value("${pipeline.detail.path:/mixuap?appId=1742358052905971713&id=1867406434120003586&formType=detail&sequenceNbr=%s}")
    private String pipelineRoutePath;

    /**
     * 西安数据对接-保存设备信息
     *
     * @param equLists 数据集
     * @return 保存结果
     */
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public boolean xiAnSaveEquipmentData(List<Map<String, Object>> equLists) {
        RequestContextWrapper contextWrapper = RequestContextWrapper.capture();
        Set<String> recordSet = new HashSet<>();
        CompletableFuture.allOf(
                equLists.parallelStream().map(equ -> CompletableFuture.runAsync(() -> {
                    contextWrapper.apply();
                    String record = saveEquipmentDataInTransaction(equ, "jg_his_xa", null);
                    recordSet.add(record);
                })).toArray(CompletableFuture[]::new)
        ).join();
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                eventPublisher.publish(new EquipCreateOrEditEvent(this, BusinessTypeEnum.JG_NEW_EQUIP.name(), recordSet, EquipCreateOrEditEvent.EquipType.equip));
            }
        });
        return Boolean.TRUE;
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    public String saveEquipmentDataInTransaction(Map<String, Object> equ, String dataSource, String remark) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        CompanyBo company = reginParams.getCompany();
        String record = UUID.randomUUID().toString();
        try {
            // transactionTemplate.execute(status -> {
            String equList = String.valueOf(equ.get("equList"));
            String isCompleteXa = String.valueOf(equ.get("isCompleteXa"));
            // 压力管道保存 工程装置表信息  必须在saveUseInfo之前进行，需要提前生成工程装置id
            //saveProjectContraption(equ, equList, company, dataSource);
            // 保存到设备表
            saveUseInfo(equ, record, dataSource, remark, company);
            saveDesignInfo(equ, record);
            saveFactoryInfo(equ, record);
            saveRegisterInfo(equ, record, equList);
            saveSupervisionInfo(equ, record);
            saveOtherInfo(equ, record, equList);
            saveInspectInfo(equ, record);
            if ("安装改造维修单位".equals(company.getCompanyType())){
                saveConstructionInfo(equ, record, company);
            }
            // 保存技术参数
            saveTechParams(equ, record, equList);
            // 保存到ES
            saveEquInfoToEs(record, isCompleteXa);
            return record;
            // });
        } catch (Exception e) {
            esEquipmentCategory.deleteById(record);
            e.printStackTrace();
            log.error("{}数据：保存时出现异常，对应数据：{}", dataSource, JSONObject.toJSONString(equ));
            log.error("异常信息：{}", e.getMessage());
            throw new RuntimeException(e);
        }
    }

    /**
     * 保存施工信息表
     *
     * @param equ
     * @param record
     */
    private void saveConstructionInfo(Map<String, Object> equ, String record,CompanyBo company) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgConstructionInfo constructionInfo  = JSON.parseObject(toJSONString(equ), IdxBizJgConstructionInfo.class);
        if (!ValidationUtil.isEmpty(constructionInfo)) {
            constructionInfo.setRecord(record);
            constructionInfo.setRecDate(new Date());
            constructionInfo.setUscUnitCreditCode(company.getCompanyCode());
            constructionInfo.setUscUnitName(company.getCompanyName());
            idxBizJgConstructionInfoService.save(constructionInfo);
        }
    }

    public Integer writeOrgBranchCode2YanChang(String remark) {
        List<String> records = idxBizJgUseInfoService.lambdaQuery().select(IdxBizJgUseInfo::getRecord).eq(IdxBizJgUseInfo::getRemark, remark).list().stream().map(IdxBizJgUseInfo::getRecord).collect(Collectors.toList());

        idxBizJgSupervisionInfoService.lambdaUpdate().set(IdxBizJgSupervisionInfo::getOrgBranchCode, "50*74*160*12478").set(IdxBizJgSupervisionInfo::getOrgBranchName, "交口河镇市场监管所").in(IdxBizJgSupervisionInfo::getRecord, records).update();
        records.forEach(record -> {
            esEquipmentCategory.deleteById(record);
            this.saveEquInfoToEs(record, "1");
        });
        return records.size();
    }

    /**
     * 根据name获取市区县Code
     *
     * @param name
     * @return code
     */
    private String getRegionCode(String name, String key) {
        return Optional.ofNullable((List<LinkedHashMap>) redisUtils.get(key))
                .flatMap(list -> list.stream()
                        .filter(item -> String.valueOf(item.get("regionName"))
                                .equals(name))
                        .map(item -> String.valueOf(item.get("regionCode")))
                        .findFirst())
                .orElse("");
    }

    /**
     * 保存工程装置表信息
     */
    private Long saveProjectContraption(Map<String, Object> equ, String equList,CompanyBo company,String dataSource) {
        Long sequenceNbr = null;
        if (EquipmentClassifityEnum.YLGD.getCode().equals(equList)) {
            IdxBizJgProjectContraption projectContraption = JSON.parseObject(toJSONString(equ), IdxBizJgProjectContraption.class);
            if (!ValidationUtil.isEmpty(projectContraption)) {
                String useUnitCode = Objects.toString(equ.get("useUnitCode"),company.getCompanyCode());// 使用单位Code
                String useUnit = Objects.toString(equ.get("useUnit"), company.getCompanyName());// 使用单位名称
                String proConName = String.valueOf(equ.get("projectContraption")).trim();// 工程装置名称
                // 查询该企业下是否已经有该工程装置名称 有-》追加 update   无-》新增 save
                IdxBizJgProjectContraption oldContraption = null;
                if ("使用单位".equals(company.getCompanyType())) {
                     oldContraption = idxBizJgProjectContraptionService.lambdaQuery()
                            .eq(IdxBizJgProjectContraption::getUseUnitCreditCode, useUnitCode)
                            .eq(IdxBizJgProjectContraption::getUseUnitName, useUnit)
                            .eq(IdxBizJgProjectContraption::getProjectContraption, proConName)
                            .list().stream().findFirst().orElse(null);
                }else{
                     oldContraption = idxBizJgProjectContraptionService.lambdaQuery()
                            .eq(IdxBizJgProjectContraption::getUscUnitCreditCode, company.getCompanyCode())
                            .eq(IdxBizJgProjectContraption::getUscUnitName, company.getCompanyName())
                            .eq(IdxBizJgProjectContraption::getProjectContraption, proConName)
                            .list().stream().findFirst().orElse(null);
                }
                projectContraption.setRecDate(new Date());
                projectContraption.setDataQualityScore("3");
                if (ObjectUtils.isEmpty(oldContraption) ) { // save
                    sequenceNbr = sequence.nextId();
                    projectContraption.setSequenceNbr(sequenceNbr);
                    if ("使用单位".equals(company.getCompanyType())) {
                        projectContraption.setUseUnitCreditCode(useUnitCode);
                        projectContraption.setUseUnitName(useUnit);
                    } else if ("安装改造维修单位".equals(company.getCompanyType())){
                        projectContraption.setUscUnitCreditCode(company.getCompanyCode());
                        projectContraption.setUscUnitName(company.getCompanyName());
                    }else{
                        projectContraption.setUseUnitCreditCode(MapUtil.getStr(equ,"useUnitCode"));
                        projectContraption.setUseUnitName(MapUtil.getStr(equ, "useUnit"));
                    }
                    projectContraption.setEquList(equList);
                    projectContraption.setEquListName(EquipmentClassifityEnum.getNameByCode(equList));
                    projectContraption.setEquCategory((String) equ.get("equCategory"));
                    projectContraption.setEquCategoryName(EquCategoryConverter.getKeyByValue((String) equ.get("equCategory")));
                    projectContraption.setEquDefine((String) equ.get("equDefine"));
                    projectContraption.setEquDefineName(EquDefineConverter.getKeyByValue((String) equ.get("equDefine")));
                    projectContraption.setPipelineLength(new BigDecimal(Objects.toString(equ.get("totalPipeLength"), "0")).doubleValue());
                    projectContraption.setUseRegistrationCode((String) equ.get("useOrgCode"));
                    projectContraption.setIsIntoManagement(Boolean.FALSE);
                    projectContraption.setDataSource(dataSource);
                    idxBizJgProjectContraptionService.save(projectContraption);
                } else { // update
                    sequenceNbr = oldContraption.getSequenceNbr();
                    Double oldPipelineLength = oldContraption.getPipelineLength();
                    UpdateWrapper<IdxBizJgProjectContraption> updateWrapper = new UpdateWrapper<>();
                    updateWrapper.eq("sequence_nbr", oldContraption.getSequenceNbr()) // 根据主键更新
                            .set("pipeline_length", Double.sum(oldPipelineLength, Double.parseDouble((String) equ.get("pipeLength"))));
                    idxBizJgProjectContraptionService.update(updateWrapper);
                }
            }
        }
        return sequenceNbr;
    }

    /**
     * 保存使用信息表
     *
     * @param equ
     * @param record
     */
    private void saveUseInfo(Map<String, Object> equ, String record, String dataSource, String remark,CompanyBo company) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgUseInfo useInfo = JSON.parseObject(toJSONString(equ), IdxBizJgUseInfo.class);
        if (!ValidationUtil.isEmpty(useInfo)) {
            String provinceName = Objects.toString(equ.get("provinceName"),"");
            String provinceCode = "610000";
            String cityName = Objects.toString(equ.get("cityName"),"");
            String cityCode = "";
            if (!ValidationUtil.isEmpty(cityName)) {
                cityCode = getRegionCode(cityName, "CITY");
            }
            String districtName = Objects.toString(equ.get("countyName"),"");
            String districtCode = "";
            if (!ValidationUtil.isEmpty(districtName)) {
                districtCode = getRegionCode(districtName, "REGION");
            }
            String streetName = Objects.toString(equ.get("factoryUseSiteStreet"),"");
            String streetCode = "";
            if (!ValidationUtil.isEmpty(streetName)) {
                streetCode = getRegionCode(streetName, "STREET");
            }
            useInfo.setProvince(provinceCode);
            useInfo.setProvinceName(provinceName);
            useInfo.setCity(cityCode);
            useInfo.setCityName(cityName);
            useInfo.setCounty(districtCode);
            useInfo.setCountyName(districtName);
            useInfo.setStreetName(streetName);
            useInfo.setFactoryUseSiteStreet(streetCode);
            if (company != null && "使用单位".equals(company.getCompanyType())) {
                useInfo.setUseUnitCreditCode(company.getCompanyCode());
                useInfo.setUseUnitName(company.getCompanyName());
            } else if (company != null && "安装改造维修单位".equals(company.getCompanyType())){
                useInfo.setUSC_UNIT_CREDIT_CODE(company.getCompanyCode());
                useInfo.setUSC_UNIT_NAME(company.getCompanyName());
            }else{
                useInfo.setUseUnitCreditCode(MapUtil.getStr(equ,"useUnitCode"));
                useInfo.setUseUnitName(MapUtil.getStr(equ, "useUnit"));
            }
            equ.put("province",useInfo.getProvince());
            equ.put("city",useInfo.getCity());
            equ.put("county",useInfo.getCounty());
            equ.put("factoryUseSiteStreet", streetCode);
            equ.put("isXixian", "0");
            if (!ValidationUtil.isEmpty(Objects.toString(equ.get("longitudeLatitude")))) {
                String[] parts = Objects.toString(equ.get("longitudeLatitude"), "").split(",", -1);
                String latitude = parts.length > 0 ? parts[0].trim() : "";
                String longitude = parts.length > 1 ? parts[1].trim() : "";
                useInfo.setLongitudeLatitude(String.format("{\"latitude\":\"%s\",\"longitude\":\"%s\"}", latitude, longitude));
            }
            useInfo.setRecDate(new Date());
            useInfo.setCreateDate(new Date());
            useInfo.setRecord(record);
            useInfo.setDataSource(dataSource);
            useInfo.setIsNotEs("1");
            useInfo.setIsIntoManagement(Boolean.FALSE);
            useInfo.setRemark(remark);
            if (Arrays.asList("jg_his","jg_his_xa","jg_his_pl").contains(dataSource)){
                String equState = Optional.ofNullable(equ.get("EQU_STATE"))
                        .map(Object::toString)
                        .orElse(String.valueOf(EquimentEnum.ZAIYONG.getCode()));
                useInfo.setEquState(equState);
            }
            useInfo.setProjectContraptionId(Objects.toString(equ.get("projectContraptionId"), ""));
            useInfo.setIsNotXiXian("0");
            idxBizJgUseInfoService.save(useInfo);
            equ.put("longitudeLatitude", useInfo.getLongitudeLatitude());
            equ.put("useUnitCreditCode", useInfo.getUseUnitCreditCode());
            equ.put("useUnitName", useInfo.getUseUnitName());
            equ.put("isNotXiXian", "0");
            equ.put("DATA_SOURCE", useInfo.getDataSource());
        }
    }

    /**
     * 保存设计信息表
     *
     * @param equ
     * @param record
     */
    private void saveDesignInfo(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgDesignInfo designInfo = JSON.parseObject(toJSONString(equ), IdxBizJgDesignInfo.class);
        if (!ValidationUtil.isEmpty(designInfo)) {
            designInfo.setRecord(record);
            designInfo.setRecDate(new Date());
            designInfo.setDesignIsComplete("2");
            idxBizJgDesignInfoService.save(designInfo);
        }
    }

    /**
     * 保存制造信息
     *
     * @param equ
     * @param record
     */
    private void saveFactoryInfo(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgFactoryInfo factoryInfo = JSON.parseObject(toJSONString(equ), IdxBizJgFactoryInfo.class);
        if (!ValidationUtil.isEmpty(factoryInfo)) {
            factoryInfo.setRecord(record);
            factoryInfo.setRecDate(new Date());
            factoryInfo.setFactoryIsComplete("2");
            idxBizJgFactoryInfoService.save(factoryInfo);
        }
    }

    /**
     * 保存注册登记信息表
     *
     * @param equ
     * @param record
     */
    private void saveRegisterInfo(Map<String, Object> equ, String record, String equList) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgRegisterInfo registerInfo = JSON.parseObject(toJSONString(equ), IdxBizJgRegisterInfo.class);
        if (!ValidationUtil.isEmpty(registerInfo)) {
            registerInfo.setRecord(record);
            registerInfo.setRecDate(new Date());
            registerInfo.setRegisterState("6045");
            registerInfo.setIsCompleteXa("1");
            registerInfo.setInInspectionPeriod("1");
            idxBizJgRegisterInfoServiceImpl.save(registerInfo);
        }
    }

    /**
     * 保存监督管理信息表
     *
     * @param equ
     * @param record
     */
    private void saveSupervisionInfo(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgSupervisionInfo supervisionInfo = JSON.parseObject(toJSONString(equ), IdxBizJgSupervisionInfo.class);
        log.error("数据===hou>{}", toJSONString(supervisionInfo));
//        if (ObjectUtils.isEmpty(supervisionInfo)) return;
        supervisionInfo.setRecord(record);
        supervisionInfo.setRecDate(new Date());
        if (!ValidationUtil.isEmpty(equ.get("orgBranchCode"))){
            supervisionInfo.setOrgBranchCode(String.valueOf(equ.get("orgBranchCode")));
            supervisionInfo.setOrgBranchName(String.valueOf(equ.get("orgBranchName")));
        } else {
            // 获取符合条件的公司 Map
            Map<String, Map<String, String>> countyMap;
            try {
                countyMap = Optional.ofNullable(Privilege.companyClient.queryAgencyList("county").getResult())
                        .orElse(Collections.emptyList())
                        .stream()
                        .filter(v -> "1442687786065854466".equals(String.valueOf(v.getParentId())))
                        .collect(Collectors.toMap(
                                CompanyModel::getCompanyCode,
                                v -> Stream.of(new AbstractMap.SimpleEntry<>("companyName", v.getCompanyName()),
                                                new AbstractMap.SimpleEntry<>("orgCode", v.getOrgCode()))
                                        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)),
                                (a, b) -> a
                        ));
            } catch (Exception e) {
                countyMap = Collections.emptyMap();
            }
            String companyCode = "1".equals(equ.get("equCodeType"))
                    ? String.valueOf(equ.get("equCode"))
                    : String.valueOf(equ.get("originalEquCode"));

            companyCode = companyCode.trim();
            if (companyCode.length() > 9) {
                companyCode = companyCode.substring(4, 10);
            }
            Map<String, String> companyInfo = countyMap.get(companyCode);
            if (companyInfo != null) {
                String companyName = companyInfo.get("companyName");
                String orgCode = companyInfo.get("orgCode");
                if (companyName != null && !companyName.trim().isEmpty()) {
                    supervisionInfo.setOrgBranchCode(orgCode);
                    supervisionInfo.setOrgBranchName(companyName);
                }
            } else {
                // 通过 useUnitCode 查询属地监管部门
                String useUnitCode = String.valueOf(equ.get("useUnitCode")).trim();
                CompanyModel companyModel = Privilege.companyClient.queryByCompanyCode(useUnitCode).getResult();

                if (companyModel != null) {
                    String orgCode = companyModel.getOrgCode();
                    if (orgCode != null && orgCode.contains("*")) {
                        String superOrgCode = orgCode.substring(0, orgCode.lastIndexOf("*"));
                        supervisionInfo.setOrgBranchCode(superOrgCode);
                        Optional.ofNullable(Privilege.companyClient.queryByOrgcode(superOrgCode).getResult())
                                .map(result -> JSON.parseObject(toJSONString(result)).getString("compnay"))
                                .map(json -> JSON.parseObject(json, CompanyModel.class))
                                .map(CompanyModel::getCompanyName)
                                .ifPresent(supervisionInfo::setOrgBranchName);
                    }
                } else {
                    supervisionInfo.setOrgBranchCode("50*52");
                    supervisionInfo.setOrgBranchName("西安市市场监督管理局");
                }
            }
        }
        idxBizJgSupervisionInfoService.save(supervisionInfo);
        equ.put("orgBranchCode", supervisionInfo.getOrgBranchCode() + "_" + supervisionInfo.getOrgBranchName());
    }

    /**
     * 保存其他信息表
     *
     * @param equ
     * @param record
     */
    private void saveOtherInfo(Map<String, Object> equ, String record, String equList) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgOtherInfo otherInfo = JSON.parseObject(toJSONString(equ), IdxBizJgOtherInfo.class);
        if (!ValidationUtil.isEmpty(otherInfo)) {
            otherInfo.setRecord(record);
            otherInfo.setClaimStatus("已认领");
            otherInfo.setRecDate(new Date());
            if (EquipmentClassifityEnum.DT.getCode().equals(equList)) {
                otherInfo.setCode96333Type(ValidationUtil.isEmpty(equ.get("code96333")) ? "2" : "1");
            }
            idxBizJgOtherInfoService.save(otherInfo);
        }
    }

    /**
     * 保存技术参数
     *
     * @param equ
     * @param record
     * @param equList
     */
    private void saveTechParams(Map<String, Object> equ, String record, String equList) {
        if (EquipmentClassifityEnum.QZJX.getCode().equals(equList)) {
            saveLiftingParams(equ, record);
        } else if (EquipmentClassifityEnum.CC.getCode().equals(equList)) {
            saveVehicleParams(equ, record);
        } else if (EquipmentClassifityEnum.GL.getCode().equals(equList)) {
            saveBoilerParams(equ, record);
        } else if (EquipmentClassifityEnum.YLRQ.getCode().equals(equList)) {
            saveVesselParams(equ, record);
        } else if (EquipmentClassifityEnum.YLGD.getCode().equals(equList)) {
            savePipelineParams(equ, record);
        } else if (EquipmentClassifityEnum.YLSS.getCode().equals(equList)) {
            saveRidesParams(equ, record);
        } else if (EquipmentClassifityEnum.KYSD.getCode().equals(equList)) {
            saveRopewayParams(equ, record);
        } else if (EquipmentClassifityEnum.DT.getCode().equals(equList)) {
            saveElevatorParams(equ, record);
        }
    }

    /**
     * 保存起重机械技术参数
     *
     * @param equ
     * @param record
     */
    private void saveLiftingParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsLifting equipTechParamLifting = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsLifting.class);
        if (!ValidationUtil.isEmpty(equipTechParamLifting)) {
            equipTechParamLifting.setRecord(record);
            equipTechParamLifting.setRecDate(new Date());
            iIdxBizJgTechParamsLiftingService.saveOrUpdateData(equipTechParamLifting);
        }
    }

    /**
     * 保存场内机动车辆技术参数
     *
     * @param equ
     * @param record
     */
    private void saveVehicleParams(Map<String, Object> equ, String record) {
        log.info("数据===>{}", toJSONString(equ));
        Stream.of("seatNumber", "carsNumber", "tractorSeatNumber")
                .forEach(key -> {

                });
        IdxBizJgTechParamsVehicle equipTechParamVehicle = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsVehicle.class);
        if (!ValidationUtil.isEmpty(equipTechParamVehicle)) {
            equipTechParamVehicle.setRecord(record);
            equipTechParamVehicle.setRecDate(new Date());
            iIdxBizJgTechParamsVehicleService.saveOrUpdateData(equipTechParamVehicle);
        }
    }

    /**
     * 保存锅炉技术参数
     *
     * @param equ
     * @param record
     */
    private void saveBoilerParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsBoiler equipTechParamBoiler = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsBoiler.class);
        if (!ValidationUtil.isEmpty(equipTechParamBoiler)) {
            equipTechParamBoiler.setRecord(record);
            equipTechParamBoiler.setRecDate(new Date());
            iIdxBizJgTechParamsBoilerService.saveOrUpdateData(equipTechParamBoiler);
        }
    }

    /**
     * 保存压力容器技术参数
     *
     * @param equ
     * @param record
     */
    private void saveVesselParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsVessel equipTechParamVessel = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsVessel.class);
        if (!ValidationUtil.isEmpty(equipTechParamVessel)) {
            equipTechParamVessel.setRecord(record);
            equipTechParamVessel.setRecDate(new Date());
            iIdxBizJgTechParamsVesselService.saveOrUpdateData(equipTechParamVessel);
        }
    }

    /**
     * 保存压力管道技术参数
     *
     * @param equ
     * @param record
     */
    private void savePipelineParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsPipeline equipTechParamPipeline = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsPipeline.class);
        if (!ValidationUtil.isEmpty(equipTechParamPipeline)) {
            equipTechParamPipeline.setWallThickness(String.valueOf(equ.get("wallThickness_YLGD")));
            equipTechParamPipeline.setMedium(String.valueOf(equ.get("medium_YLGD")));
            equipTechParamPipeline.setTemperature(String.valueOf(equ.get("temperature_YLGD")));
            equipTechParamPipeline.setDeviceLevel(String.valueOf(equ.get("deviceLevel_YLGD")));
            equipTechParamPipeline.setWorkTemperature(String.valueOf(equ.get("workTemperature_YLGD")));
            equipTechParamPipeline.setRecord(record);
            equipTechParamPipeline.setRecDate(new Date());
            iIdxBizJgTechParamsPipelineService.saveOrUpdateData(equipTechParamPipeline);
        }
    }

    /**
     * 保存大型游乐设施技术参数
     *
     * @param equ
     * @param record
     */
    private void saveRidesParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsRides equipTechParamRides = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsRides.class);
        if (!ValidationUtil.isEmpty(equipTechParamRides)) {
            equipTechParamRides.setRecord(record);
            equipTechParamRides.setRecDate(new Date());
            equipTechParamRides.setRunningSpeed(String.valueOf(equ.get("runningSpeed_DXYLSS")));
            equipTechParamRides.setSlideLength(String.valueOf(equ.get("slideLength_DXYLSS")));
            equipTechParamRides.setOperatingHeight(String.valueOf(equ.get("operatingHeight_DXYLSS")));
            iIdxBizJgTechParamsRidesService.saveOrUpdateData(equipTechParamRides);
        }
    }

    /**
     * 保存客运索道技术参数
     *
     * @param equ
     * @param record
     */
    private void saveRopewayParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsRopeway equipTechParamRopeway = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsRopeway.class);
        if (!ValidationUtil.isEmpty(equipTechParamRopeway)) {
            equipTechParamRopeway.setRecord(record);
            equipTechParamRopeway.setRecDate(new Date());
            iIdxBizJgTechParamsRopewayService.saveOrUpdateData(equipTechParamRopeway);
        }
    }

    /**
     * 保存电梯技术参数
     *
     * @param equ
     * @param record
     */
    private void saveElevatorParams(Map<String, Object> equ, String record) {
        log.error("数据===>{}", toJSONString(equ));
        IdxBizJgTechParamsElevator equipTechParamElevator = JSON.parseObject(toJSONString(equ), IdxBizJgTechParamsElevator.class);
        if (!ValidationUtil.isEmpty(equipTechParamElevator)) {
            equipTechParamElevator.setRecord(record);
            equipTechParamElevator.setRecDate(new Date());
            iIdxBizJgTechParamsElevatorService.saveOrUpdateData(equipTechParamElevator);
        }
    }


    /**
     * 保存设备数据至es
     *
     * @param record 设备唯一编码
     */
    private void saveEquInfoToEs(String record, String isCompleteXa) {
        Map<String, Object> map = categoryOtherInfoMapper.selectDataById(record);
        ESEquipmentCategoryDto equipmentCategoryDto = JSON.parseObject(toJSONString(map), ESEquipmentCategoryDto.class);
        if (!ObjectUtils.isEmpty(equipmentCategoryDto)) {
            long time = Timestamp.valueOf(map.get("REC_DATE").toString().substring(0, 19)).getTime();
            equipmentCategoryDto.setCREATE_DATE(time);
            equipmentCategoryDto.setREC_DATE(time);
            equipmentCategoryDto.setSTATUS("已认领");
            equipmentCategoryDto.setIS_DO_BUSINESS(Boolean.TRUE);
            equipmentCategoryDto.setIS_COMPLETE_XA(Objects.equals("0", isCompleteXa));
            esEquipmentCategory.save(equipmentCategoryDto);
        }
    }

    /**
     * 八大类历史设备导入
     *
     * @param file
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Object dataCheckAndImportEquipmentData(String remark, MultipartFile file) {

        List<EquipInfoExcelDto> equipInfoExcelDtos;
        try {
            // 1, 数据读取 + 格式、类型异常检查
            equipInfoExcelDtos = this.checkData(file, remark);
        } catch (Exception e) {
            throw new BadRequest(String.format("参数校验失败，详细请看返回信息：%s", e.getMessage()));
        }

        // 2, 保存设备数据
        this.batchSaveEquipmentData(remark, equipInfoExcelDtos);
        return Boolean.TRUE;
    }

    public Object checkSetEquipImportData(String remark, MultipartFile file) {
        List<EquipInfoExcelDto> equipInfoExcelDtos;
        try {
            // 1, 数据读取 + 格式、类型异常检查
            equipInfoExcelDtos = this.checkData(file, remark);
        } catch (Exception e) {
            throw new BadRequest(String.format("参数校验失败，详细请看返回信息：%s", e.getMessage()));
        }
        return equipInfoExcelDtos;
    }

    /**
     * excel 文件读取，字段校验
     *
     * @param file excel 文件
     * @return 设备数据
     * @throws Exception 异常信息
     */
    public List<EquipInfoExcelDto> checkData(MultipartFile file, String remark) {
        List<EquipInfoExcelDto> dataList = new ArrayList<>();
        resultError.clear();
        useInnerCodeList.clear();
        equCodeList.clear();
        factoryNumList.clear();
        useOrgCodeList.clear();
        projectContraptionMap.clear();

        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader excelReader = EasyExcel.read(inputStream).build();
            List<ReadSheet> sheetList = excelReader.excelExecutor().sheetList(); // 获取所有 sheet
            // 判断模板版本号
            String templateVersionError = DataDockTemplateVersionUtils.checkTemplateVersion(file, sheetList);
            if (!ValidationUtil.isEmpty(templateVersionError)) {
                throw new BadRequest(templateVersionError);
            }

            for (ReadSheet readSheet : sheetList) {
                String sheetName = readSheet.getSheetName();
                int sheetNo = readSheet.getSheetNo();

                // 忽略填充设备种类类别品种的三级联动sheet页
                if (sheetName.contains("忽略")) {
                    continue;
                }
                Map<String, Object> sheetError = new HashMap<>();
                EasyExcel.read(file.getInputStream(), EquipInfoExcelDto.class, new AnalysisEventListener<EquipInfoExcelDto>() {
                    // 每读一行都会执行
                    @Override
                    public void invoke(EquipInfoExcelDto data, AnalysisContext context) {
                        // 数据检查
                        checkExcelData(sheetName, data, context, sheetError, remark);
                        // if (!ValidationUtil.isEmpty(data.getUseInnerCode())) {
                        //     useInnerCodeList.add(data.getUseInnerCode());
                        // }
                        equCodeList.add(data.getEquCode());
                        useOrgCodeList.add(data.getUseOrgCode());
                        dataList.add(data);
                    }

                    // 每个sheet页读完都会执行
                    @Override
                    public void doAfterAllAnalysed(AnalysisContext context) {
                        // 记录每一个sheet页的错误集
                        if (!ValidationUtil.isEmpty(sheetError)) {
                            resultError.put(String.format("%s sheet页", sheetName), sheetError);
                        }
                    }
                }).headRowNumber(4).sheet(sheetNo, sheetName).doRead();
            }

            excelReader.finish(); // 关闭 reader，释放资源

            if (CollectionUtils.isEmpty(dataList)) {
                resultError.put("allSheet", "你上传了一个空数据的Excel文档!");
                throw new BadRequest("你上传了一个空数据的Excel文档!");
            }

            // 检查 resultError中的每一项，若存在内容，则有错误信息，直接抛异常
            if (!ValidationUtil.isEmpty(resultError)) {
                throw new BadRequest(toJSONString(resultError));
            }

            return dataList;
        } catch (Exception e) {
            throw new BadRequest(e.getMessage());
        }
    }

    /**
     * excel数据字段校验
     *
     * @param sheetName sheet页名称
     * @param data      excel数据
     * @param context
     */
    public void checkExcelData(String sheetName, EquipInfoExcelDto data, AnalysisContext context, Map<String, Object> sheetError, String remark) {
        ReadRowHolder readRowHolder = context.readRowHolder();
        int rowIndex = readRowHolder.getRowIndex() + 1;
        StringBuffer rowError = new StringBuffer();
        log.info("开始解析数据，第{}条数据", rowIndex);
        // 是否起重机械
        boolean isQZJX = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.QZJX.getCode().equals(data.getEquList());
        // 是否场内机动车辆
        boolean isCNJDXL = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.CC.getCode().equals(data.getEquList());
        // 是否锅炉
        boolean isGL = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.GL.getCode().equals(data.getEquList());
        // 是否压力容器
        boolean isYLRQ = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.YLRQ.getCode().equals(data.getEquList());
        // 是否压力管道
        boolean isYLGD = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.YLGD.getCode().equals(data.getEquList());
        // 是否大型游乐设施
        boolean isDXYNSS = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.YLSS.getCode().equals(data.getEquList());
        // 是否客运索道
        boolean isKYSD = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.KYSD.getCode().equals(data.getEquList());
        // 是否电梯
        boolean isDT = !ValidationUtil.isEmpty(data.getEquList()) && EquipmentClassifityEnum.DT.getCode().equals(data.getEquList());

        try {
            log.info("解析第{}行数据：{}", rowIndex, toJSONString(data));

            // 通用字段检查 每一个sheet页都有的基本信息，设计信息，制造信息和使用信息
            this.commonFieldCheck(data, rowError, remark);

            // 起重机械----技术参数 检查
            if (isQZJX) {
                this.QZJXTechnicalParamsCheck(data, rowError);
            }
            // 场内机动车辆----技术参数 检查
            if (isCNJDXL) {
                this.CNJDCLTechnicalParamsCheck(data, rowError);
            }
            // 锅炉----技术参数 检查
            if (isGL) {
                this.GLTechnicalParamsCheck(data, rowError);
            }
            // 压力容器----技术参数 检查
            if (isYLRQ) {
                this.YLRQTechnicalParamsCheck(data, rowError);
            }
            // 压力管道----技术参数 检查
            if (isYLGD) {
                this.YLGDTechnicalParamsCheck(data, rowError);
            }
            // 大型游乐设施----技术参数 检查
            if (isDXYNSS) {
                this.DXYLSSTechnicalParamsCheck(data, rowError);
            }
            // 客运索道----技术参数 检查
            if (isKYSD) {
                this.KYSDTechnicalParamsCheck(data, rowError);
            }
            // 电梯----技术参数 检查
            if (isDT) {
                this.DTTechnicalParamsCheck(data, rowError);
            }

            if (!StringUtils.isBlank(rowError)) {
                String excelErrorStr = "Excel 第[%s]行";
                sheetError.put(String.format(excelErrorStr, rowIndex), rowError);
            }

        } catch (Exception e) {
            log.error(String.format("sheet页：[%s] -> 对应行索引数: [%s] -> 失败的 Excel 数据: [%s]", sheetName, rowIndex, toJSONString(data)), e);
            throw e;
        }
    }

    /**
     * 通用字段检查 每一个sheet页都有的基本信息，设计信息，制造信息和使用信息
     *
     * @param data     源数据
     * @param rowError 错误集合
     */
    private void commonFieldCheck(EquipInfoExcelDto data, StringBuffer rowError, String remark) {
        boolean isYLRQ = !ObjectUtils.isEmpty(data.getEquList()) && EquipmentClassifityEnum.YLRQ.getCode().equals(data.getEquList());// 是否压力容器
        boolean isYLGD = !ObjectUtils.isEmpty(data.getEquList()) && EquipmentClassifityEnum.YLGD.getCode().equals(data.getEquList());// 是否压力管道
        boolean isDT = !ObjectUtils.isEmpty(data.getEquList()) && EquipmentClassifityEnum.DT.getCode().equals(data.getEquList());// 是否电梯
        boolean isCC = !ObjectUtils.isEmpty(data.getEquList()) && EquipmentClassifityEnum.CC.getCode().equals(data.getEquList());// 是否场车
        boolean isQZJX = !ObjectUtils.isEmpty(data.getEquList()) && EquipmentClassifityEnum.QZJX.getCode().equals(data.getEquList());// 是否起重机械

        // 基本信息
        checkNotBlank(data.getEquList(), "设备种类不能为空；", rowError);
        checkNotBlank(data.getEquCategory(), "设备类别不能为空；", rowError);
        data.setEquListName(EquListConverter.reverseEquipmentMap.get(data.getEquList()));
        data.setEquCategoryName(EquCategoryConverter.reverseEquipmentMap.get(data.getEquCategory()));
        data.setEquDefineName(Optional.ofNullable(data.getEquDefine()).map(EquDefineConverter.reverseEquipmentMap::get).orElse(""));
        data.setDeviceLevel_GD(Optional.ofNullable(data.getDeviceLevel_YLGD()).map(DictParamsConverter.reverseEquipmentMap::get).orElse(""));
        // checkNotBlank(data.getUseInnerCode(), "单位内编号不能为空；", rowError);
        // if (useInnerCodeList.contains(data.getUseInnerCode())) {
        //     rowError.append("单位内编号不能重复；");
        // }
        // checkNotBlank(data.getEquType(), "设备型号不能为空；", rowError);
        if (!isYLGD) {
            checkNotBlank(data.getProductName(), "产品名称不能为空；", rowError);
            checkNotBlank(data.getEquCodeType(), "有无设备代码不能为空；", rowError);
            if ("1".equals(data.getEquCodeType())) {
                checkNotBlank(data.getEquCode(), "设备代码不能为空；", rowError);
                String equCode = data.getEquCode();
                if (!StringUtils.isEmpty(equCode)) {
                    if (equCode.matches("[a-zA-Z0-9]+")) {
                         if (equCode.length() < 17) {
                             rowError.append("设备代码不能小于17位；");
                         }
                         if (equCode.length() > 21) {
                             rowError.append("设备代码不能大于21位；");
                         }
                    } else {
                        rowError.append("设备代码不能包含特殊字符；");
                    }
                }
                if (equCodeList.contains(data.getEquCode())) {
                    rowError.append("设备代码不能重复,").append(data.getEquCode());
                }
                this.checkEquCodeUniqueness(data.getEquCode(), rowError);
            } else {
                data.setEquCode("");
            }
        }
        if (isYLGD) {// 校验压力管道特有的参数
            checkNotBlank(data.getPipeName(), "管道名称不能为空；", rowError);
            checkNotBlank(data.getProjectContraption(), "工程（装置）名称不能为空；", rowError);
            checkNotBlank(data.getProjectContraptionNo(), "工程（装置）编号不能为空；", rowError);
            if (remark.equals("his")){
                // 使用登记证编号校验
                List<IdxBizJgRegisterInfo> idxBizJgRegisterInfos = idxBizJgRegisterInfoServiceImpl.getBaseMapper().selectList(new LambdaQueryWrapper<IdxBizJgRegisterInfo>().eq(IdxBizJgRegisterInfo::getUseOrgCode, data.getUseOrgCode()).notLike(IdxBizJgRegisterInfo::getUseOrgCode, "管"));
                if (!idxBizJgRegisterInfos.isEmpty()) {
                    rowError.append("使用登记证编号已存在系统中；");
                }
                List<IdxBizJgProjectContraption> projectContraptions = idxBizJgProjectContraptionService.lambdaQuery().eq(IdxBizJgProjectContraption::getEquList, EquipmentClassifityEnum.YLGD.getCode()).eq(IdxBizJgProjectContraption::getUseRegistrationCode, data.getUseOrgCode()).eq(IdxBizJgProjectContraption::getProjectContraption, data.getProjectContraption()).eq(IdxBizJgProjectContraption::getProjectContraptionNo, data.getProjectContraptionNo()).list();
                if (!projectContraptions.isEmpty()) {
                    rowError.append("使用登记证编号已存在系统中；");
                }
            }
            // 同一工程装置下管道编号不能重复
            if (!ValidationUtil.isEmpty(data.getProjectContraption())) {

                String useUnitCode = String.valueOf(data.getUseUnitCode()).trim();// 使用单位Code
                String useUnit = String.valueOf(data.getUseUnit()).trim();// 使用单位名称
                String proConName = data.getProjectContraption().trim();// 工程装置名称

                // 查询该企业下工程装置名称
                IdxBizJgProjectContraption oldContraption = idxBizJgProjectContraptionService.lambdaQuery()
                        .eq(IdxBizJgProjectContraption::getUseUnitCreditCode, useUnitCode)
                        .eq(IdxBizJgProjectContraption::getUseUnitName, useUnit)
                        .eq(IdxBizJgProjectContraption::getProjectContraption, proConName)
                        .list().stream().findFirst().orElse(null);
                Optional.ofNullable(oldContraption).ifPresent(old -> {
                    List<String> pipelineNumberList = idxBizJgProjectContraptionServiceImpl.getBaseMapper()
                            .selectEquipList(String.valueOf(old.getSequenceNbr()))
                            .stream()
                            .map(item -> (String) item.get("pipelineNumber"))
                            .collect(Collectors.toList());
//                    if (pipelineNumberList.contains(data.getPipelineNumber())) {
//                        rowError.append(String.format("系统中工程装置（%s）下已经存在管道编号（%s）；", data.getProjectContraption(), data.getPipelineNumber()));
//                    }
                });

                List<String> list = projectContraptionMap.get(data.getProjectContraption());
                if (null != list) {
                    // 判断该装置下是否已经存在该管道编号
//                    if (list.contains(data.getPipelineNumber())) {
//                        rowError.append(String.format("同一工程装置（%s）下管道编号不能重复；", data.getProjectContraption()));
//                    }
                    list.add(data.getPipelineNumber());
                } else {
                    list = new ArrayList<>();
                }
                projectContraptionMap.put(data.getProjectContraption(), list);
            }
        } else {
            data.setProjectContraption("");
        }
        if (isYLRQ) {// 校验压力容器特有的参数
            boolean isGasCylinder = !org.apache.commons.lang3.ObjectUtils.isEmpty(data.getEquCategory()) && "2300".equals(data.getEquCategory());// 是否气瓶
            boolean isFixedGasCylinder = !org.apache.commons.lang3.ObjectUtils.isEmpty(data.getEquCategory()) && "2100".equals(data.getEquCategory());// 是否固定式压力容器
            boolean isOxygenChamber = !org.apache.commons.lang3.ObjectUtils.isEmpty(data.getEquCategory()) && "2400".equals(data.getEquCategory());// 是否氧舱
            boolean isMobilePressureVessel = !org.apache.commons.lang3.ObjectUtils.isEmpty(data.getEquCategory()) && "2200".equals(data.getEquCategory());// 是否移动式压力容器
            boolean isSpecialGasCylinder = isGasCylinder && !org.apache.commons.lang3.ObjectUtils.isEmpty(data.getEquDefine()) && "23T0".equals(data.getEquDefine());// 是否特种气瓶
            boolean isCarGasCylinder = isSpecialGasCylinder && (!org.apache.commons.lang3.ObjectUtils.isEmpty(data.getWhetherVehicleCylinder()) && "1".equals(data.getWhetherVehicleCylinder()));// 是否车用气瓶
            if (isGasCylinder) { // 是气瓶
                if (!isSpecialGasCylinder) { // 不是特种气瓶
                    data.setWhetherVehicleCylinder("");
                    //checkNotBlank(data.getInformationSituation(), "信息化管理情况不能为空；", rowError);
                    if (!org.apache.commons.lang3.ObjectUtils.isEmpty(data.getInformationSituation())) {
                        //checkNotBlank(data.getInformationManageCode(), "二维码或者电子标签编号不能为空；", rowError);
                    }
                }
                if (isSpecialGasCylinder) { // 是特种气瓶
                    checkNotBlank(data.getWhetherVehicleCylinder(), "是否车用气瓶不能为空；", rowError);
                    if (!isCarGasCylinder) {// 不是车用气瓶
                        //checkNotBlank(data.getInformationSituation(), "信息化管理情况不能为空；", rowError);
                        if (!org.apache.commons.lang3.ObjectUtils.isEmpty(data.getInformationSituation())) {
                            //checkNotBlank(data.getInformationManageCode(), "二维码或者电子标签编号不能为空；", rowError);
                        }
                    }
                    if (isCarGasCylinder) { // 是车用气瓶
                        data.setInformationSituation("");
                        data.setInformationManageCode("");
                        checkFactoryNumUniqueness(data, rowError);// 校验出厂编号/产品编码唯一性
                    }
                }
                data.setWhetherSphericalTank("");
                data.setWhetherSkidMountedPressureVessel("");
            }
            if (isFixedGasCylinder) { // 是固定式压力容器
                checkNotBlank(data.getWhetherSphericalTank(), "是否球罐不能为空；", rowError);
                checkNotBlank(data.getWhetherSkidMountedPressureVessel(), "是否撬装式压力容器不能为空；", rowError);
                data.setInformationSituation("");
                data.setInformationManageCode("");
            }
            if (isMobilePressureVessel) {// 是移动式压力容器
                data.setWhetherSkidMountedPressureVessel("");
                data.setWhetherVehicleCylinder("");
                data.setWhetherSphericalTank("");
                data.setInformationSituation("");
                data.setInformationManageCode("");
            }
            if (isOxygenChamber) {// 是氧舱
                data.setWhetherSkidMountedPressureVessel("");
                data.setWhetherVehicleCylinder("");
                data.setWhetherSphericalTank("");
                data.setInformationSituation("");
                data.setInformationManageCode("");
            }
        }
        if (remark.equals("his")){
            checkNotBlank(data.getUseOrgCode(), "使用登记证编号不能为空；", rowError);
            if (!StringUtils.isEmpty(data.getUseOrgCode())) {
//                if (!this.useOrgCodeRegularMatching(data)) {
//                    rowError.append("使用登记证编号格式不正确；");
//                }
                if (!isYLGD && useOrgCodeList.contains(data.getUseOrgCode())) {
                    rowError.append("使用登记证编号不能重复；");
                }
                try {
                    idxBizJgRegisterInfoServiceImpl.checkUseRegistrationCode(data.getUseOrgCode(), "set");
                } catch (Exception e) {
                    rowError.append(e.getMessage());
                }
                if (!isYLGD && commonService.useRegistrationCertificateAccountUnique(data.getUseOrgCode(), null)) {
                    rowError.append("使用登记证编号已存在系统中；");
                }
            }
        }
        // 使用信息
//        checkNotBlank(data.getUseUnitCode(), "使用单位统一社会信用代码不能为空；", rowError);
//        Optional.ofNullable(data.getUseUnitCode()).ifPresent(v -> checkCreditCode(v, "使用单位统一社会信用代码格式不正确；", rowError));
//        checkNotBlank(data.getUseUnit(), "使用单位名称不能为空；", rowError);
        // 设计信息  电梯、场车、起重机械无"设计信息"
        if (!isDT && !isCC && !isQZJX) {

            // checkNotBlank(data.getDesignUnitCreditCode(), "设计单位统一社会信用代码不能为空；", rowError);
            //Optional.ofNullable(data.getDesignUnitCreditCode()).ifPresent(v -> checkCreditCode(v, "设计单位统一社会信用代码格式不正确；", rowError));
            // checkNotBlank(data.getDesignUnitName(), "设计单位名称不能为空；", rowError);
            // checkNotBlank(data.getDesignUseDate(), "设计使用年限不能为空；", rowError);
            // Optional.ofNullable(data.getDesignUseDate()).ifPresent(v -> checkDateFormatNumber(v, "设计使用年限不能为数字以外的其他类型；", rowError));
            if (!ValidationUtil.isEmpty(data.getDesignUseDate())) {
                data.setDesignUseDate(data.getDesignUseDate().replace("年", "").replace("/", ""));
            }
            // checkNotBlank(data.getDesignDate(), "设计日期不能为空；", rowError);
            if (!ValidationUtil.isEmpty(data.getDesignDate())) {
                if ("—".equals(data.getDesignDate().trim()) || "/".equals(data.getDesignDate().trim())) {
                    data.setDesignDate(null);
                    return;
                }
                data.setDesignDate(data.getDesignDate().trim().replace("—", ""));
                String formattedDate = checkDateFormatCorrect(data.getDesignDate().trim(), "设计日期格式不正确；", rowError);
                if (formattedDate != null) {
                    data.setDesignDate(formattedDate);
                }
            }

            if (!ValidationUtil.isEmpty(data.getAppraisalDate())) {
                data.setAppraisalDate(data.getAppraisalDate().trim().replace("—", ""));
                String formattedDate = checkDateFormatCorrect(data.getAppraisalDate().trim(), "设计文件鉴定日期格式不正确；", rowError);
                if (formattedDate != null) {
                    data.setAppraisalDate(formattedDate);
                }
            }

            if (ValidationUtil.isEmpty(data.getDesignUnitCreditCode()) || ValidationUtil.isEmpty(data.getDesignUnitName()) || ValidationUtil.isEmpty(data.getDesignUseDate()) || ValidationUtil.isEmpty(data.getDesignDate())) {
                data.setDesignIsComplete("2");
            } else {
                data.setDesignIsComplete("1");
            }
        }
        // 制造信息
        if (!isYLGD) {
            // checkNotBlank(data.getProduceUnitCreditCode(), "制造单位统一社会信用代码不能为空；", rowError);
            Optional.ofNullable(data.getProduceUnitCreditCode()).ifPresent(v -> checkCreditCode(v, "制造单位统一社会信用代码格式不正确；", rowError));
            // checkNotBlank(data.getProduceUnitName(), "制造单位名称不能为空；", rowError);
            // checkNotBlank(data.getProduceLicenseNum(), "制造许可编号不能为空；", rowError);
            // checkNotBlank(data.getFactoryNum(), "出厂编号/产品编码不能为空；", rowError);
            // checkNotBlank(data.getProduceDate(), "制造日期不能为空；", rowError);

            if (!ValidationUtil.isEmpty(data.getProduceDate())) {
                data.setProduceDate(data.getProduceDate().trim().replace("—", ""));
                String formattedDate = checkDateFormatCorrect(data.getProduceDate().trim(), "制造日期格式不正确；", rowError);
                if (formattedDate != null) {
                    data.setProduceDate(formattedDate);
                }
            }

            if (ValidationUtil.isEmpty(data.getProduceUnitCreditCode()) || ValidationUtil.isEmpty(data.getProduceUnitName()) || ValidationUtil.isEmpty(data.getProduceLicenseNum()) || ValidationUtil.isEmpty(data.getFactoryNum()) || ValidationUtil.isEmpty(data.getProduceDate())) {
                data.setFactoryIsComplete("2");
            } else {
                data.setFactoryIsComplete("1");
            }
        }
        data.setDataSourceDesc("his".equals(remark) ? "历史设备" : "new".equals(remark) ? "新设备" : "历史无证设备");
    }

    /**
     * 检查并格式化上传Excel中的日期格式
     *
     * @param date         待检查数据
     * @param errorMessage 错误内容
     * @param rowError     错误集
     * @return 格式化后的日期字符串，如果格式不正确则返回null
     */
    private String checkDateFormatCorrect(String date, String errorMessage, StringBuffer rowError) {
        String res = date.trim().replace("/", "-").replace(".", "-")
                .replace("年", "-").replace("月", "-").replace("日", "");

        // 处理不同格式的日期
        // 2017-12
        if (res.matches("\\d{4}\\-\\d{2}")) {
            res = res + "-01";
        }
        // 2017-1
        if (res.matches("\\d{4}\\-\\d{1}")) {
            res = res.substring(0, res.length() - 1) + "0" + res.substring(res.length() - 1) + "-01";
        }
        // 2023-5-5
        if (res.matches("\\d{4}\\-\\d{1}\\-\\d{1}")) {
            res = res.substring(0, res.length() - 3) + "0" + res.substring(res.length() - 3, res.length() - 1) + "0" + res.substring(res.length() - 1);
        }
        // 2023-5-15
        if (res.matches("\\d{4}\\-\\d{1}\\-\\d{2}")) {
            res = res.substring(0, res.length() - 4) + "0" + res.substring(res.length() - 4);
        }

        if (!res.matches("\\d{4}-\\d{2}-\\d{2}") && !res.matches("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}")) {
            rowError.append(errorMessage);
            return null;
        }
        return res;
    }

    /**
     * 检查上传Excel中的统一信用代码格式
     *
     * @param code         待检查数据
     * @param errorMessage 错误内容
     * @param rowError     错误集
     */
    private void checkCreditCode(String code, String errorMessage, StringBuffer rowError) {
        String regex = "^[A-Z0-9]{15}(?:[A-Z0-9]{3})?$";
        if (!code.matches(regex)) {
            rowError.append(errorMessage);
        }
    }

    /**
     * 检查上传Excel中的数字格式是否正确
     *
     * @param date         待检查数据
     * @param errorMessage 错误内容
     * @param rowError     错误集
     */
    private void checkDateFormatNumber(String date, String errorMessage, StringBuffer rowError) {
        if (!NumberUtils.isCreatable(date)) {
            rowError.append(errorMessage);
        }
    }

    /**
     * 车用气瓶业务里面的 出厂编号/产品编码 校验唯一性（产品编号在车用气瓶范围内全局唯一）
     *
     * @param data
     */
    private void checkFactoryNumUniqueness(EquipInfoExcelDto data, StringBuffer rowError) {
        Integer count = commonService.checkFactoryNumUniquenessForVehicleCylinder(data.getFactoryNum(), null);
        if (count > 0) {
            rowError.append("出厂编号/产品编码系统中已存在！");
        }
    }

    /**
     * 根据设备代码检查唯一性
     *
     * @param equCode
     * @param rowError
     */
    private void checkEquCodeUniqueness(String equCode, StringBuffer rowError) {
        Boolean bool = commonService.checkEquCodeUniqueness(equCode);
        if (bool) {
            rowError.append("设备代码系统中已存在；");
        }
    }

    /**
     * 起重机械----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void QZJXTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
    }

    /**
     * 场内机动车辆----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void CNJDCLTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
    }

    /**
     * 锅炉----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void GLTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
    }

    /**
     * 压力容器----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void YLRQTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
        // checkNotBlank(data.getSingleBottleVolume(), "单瓶容积不能为空；", rowError);
        // checkNotBlank(data.getChargingMedium(), "充装介质不能为空；", rowError);
        // checkNotBlank(data.getNominalWorkingPressure(), "公称工作压力不能为空；", rowError);
    }

    /**
     * 压力管道----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void YLGDTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
        checkNotBlank(data.getWallThickness_YLGD(), "公称壁厚不能为空；", rowError);
        checkNotBlank(data.getNominalDiameter(), "公称直径不能为空；", rowError);
        checkNotBlank(data.getPipeLength(), "管道长度不能为空；", rowError);
        checkNotBlank(data.getPressure(), "设计-压力不能为空；", rowError);
        checkNotBlank(data.getMedium_YLGD(), "设计-介质不能为空；", rowError);
        checkNotBlank(data.getTemperature_YLGD(), "设计-温度不能为空；", rowError);
        checkNotBlank(data.getPipelineNumber(), "管道编号不能为空；", rowError);
        checkNotBlank(data.getDeviceLevel_YLGD(), "管道级别不能为空；", rowError);
        Optional.ofNullable(data.getStartePosition()).ifPresent(v -> {
            if (v.split("-").length <= 1) {
                rowError.append("起/始位置 （经纬度）格式不正确");
            }
        });
        if (!ObjectUtils.isEmpty(data.getStartePosition()) && data.getStartePosition().split("-").length == 2) {
            String[] split = data.getStartePosition().split("-");
            data.setStartePosition(String.format("{\"latitude\":%s,\"longitude\":%s}", split[0], split[1]));
        }
    }

    /**
     * 检查字段是否为空，如果为空则追加错误信息到result
     *
     * @param value        待检查字段
     * @param errorMessage 错误信息
     * @param rowError     结果集
     */
    private void checkNotBlank(String value, String errorMessage, StringBuffer rowError) {
        if (StringUtils.isBlank(value)) {
            rowError.append(errorMessage);
        }
    }

    /**
     * 大型游乐设施----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void DXYLSSTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
    }

    /**
     * 客运索道----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void KYSDTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
    }

    /**
     * 使用等级证编号格式匹配
     *
     * @param data
     * @return 匹配通过true，反之false
     */
    private Boolean useOrgCodeRegularMatching(EquipInfoExcelDto data) {
        String useOrgCode = data.getUseOrgCode().replace("（", "(").replace("）", ")");
        data.setUseOrgCode(useOrgCode);
        // 梯00陕A00000(24) 起11陕K0127(15)
        String rule01 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}陕[A-Z0-9]{4,}\\(\\d{2}\\)$";
        boolean flage01 = Pattern.matches(rule01, useOrgCode);

        // 起17泾河0104(21) 锅10沣西 00004(20)
        String rule02 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}[\\u4e00-\\u9fa5]{2}[A-Z0-9]{4,5}\\(\\d{2}\\)$";
        boolean flage02 = Pattern.matches(rule02, useOrgCode);

        // CNG-A-01-A-116729
        String rule03 = "^[a-zA-Z]{3}-[a-zA-Z]-[0-9]{2}-[a-zA-Z]-\\d{6,8}$";
        boolean flage03 = Pattern.matches(rule03, useOrgCode);

        // 3010-610322-201212-3723
        String rule04 = "^\\d{4}-\\d{6}-\\d{4}(0[1-9]|1[0-2])-\\d{4}$";
        boolean flage04 = Pattern.matches(rule04, useOrgCode);

        // 容1LS陕G0053 起11陕K0127 容2LE陕DM6043
        String rule05 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2,3}[\\u4e00-\\u9fa5][A-Z0-9]{5,6}$";
        boolean flage05 = Pattern.matches(rule05, useOrgCode);

        // CC20160091
        String rule06 = "^[A-Z]{2}[0-9]{8}$";
        boolean flage06 = Pattern.matches(rule06, useOrgCode);

        // 容15陕C00176(19)B10
        String rule07 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}陕[A-Z0-9]{5,}\\(\\d{2}\\)[A-Z0-9]{3}$";
        boolean flage07 = Pattern.matches(rule07, useOrgCode);

        // 锅10秦汉0006(6020)(20)
        String rule08 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}[\\u4e00-\\u9fa5]{2}[A-Z0-9]{4}\\(\\d{4}\\)\\(\\d{2}\\)$";
        boolean flage08 = Pattern.matches(rule08, useOrgCode);

        // 锅陕KB0415 游20陕DP00002 锅陕FF587
        String rule09 = "^[\\u4e00-\\u9fa5]{1}[0-9]{0,2}[\\u4e00-\\u9fa5]{1}[A-Z]{1,2}[0-9]{3,6}$";
        boolean flage09 = Pattern.matches(rule09, useOrgCode);

        // 陕TK20142429
        String rule10 = "^[\\u4e00-\\u9fa5]{1}[A-Z]{1,2}[0-9]{8}$";
        boolean flage10 = Pattern.matches(rule10, useOrgCode);

        // 4010610300200106-1105
        String rule11 = "^[0-9]{16}\\-[0-9]{4}$";
        boolean flage11 = Pattern.matches(rule11, useOrgCode);

        // 容IIIMC陕G-1202
        String rule12 = "^[\\u4e00-\\u9fa5]{1}[A-Z]{5}[\\u4e00-\\u9fa5]{1}[A-Z]{1}-[0-9]{4}$";
        boolean flage12 = Pattern.matches(rule12, useOrgCode);

        // AT2011-076
        String rule13 = "^[A-Z]{2,3}[0-9]{2,4}-[0-9]{3,5}$";
        boolean flage13 = Pattern.matches(rule13, useOrgCode);

        // 610302--0561
        String rule14 = "^[0-9]{6}--[0-9]{4}$";
        boolean flage14 = Pattern.matches(rule14, useOrgCode);

        // XTS泰3546(F8N9G787)
        String rule15 = "^[A-Z]{3}[\\u4e00-\\u9fa5][0-9]{4}\\([A-Z0-9]{4,9}\\)$";
        boolean flage15 = Pattern.matches(rule15, useOrgCode);

        // 梯12秦汉1611(SJE2021103783)(23)
        String rule16 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}[\\u4e00-\\u9fa5]{1,2}[0-9]{4}\\([A-Z0-9]{4,15}\\)\\(\\d{2}\\)$";
        boolean flage16 = Pattern.matches(rule16, useOrgCode);

        // 锅20空港051(16)(1510574)
        String rule17 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}[\\u4e00-\\u9fa5]{1,2}[0-9]{3,8}\\(\\d{2}\\)\\([A-Z0-9]{4,15}\\)$";
        boolean flage17 = Pattern.matches(rule17, useOrgCode);

        // 容IIMR陕EH0515
        String rule18 = "^[\\u4e00-\\u9fa5]{1}[A-Z]{2,5}[\\u4e00-\\u9fa5]{1}[A-Z0-9]{4,9}$";
        boolean flage18 = Pattern.matches(rule18, useOrgCode);

        // 锅陕B10006(24)     车0036(21)
        String rule19 = "^[\\u4e00-\\u9fa5]{1,2}[A-Z]{0,1}[0-9]{4,6}\\(\\d{2}\\)$";
        boolean flage19 = Pattern.matches(rule19, useOrgCode);

        // 容1LE陕D三0384
        String rule20 = "^[\\u4e00-\\u9fa5]{1}[A-Z0-9]{3}[\\u4e00-\\u9fa5]{1}[A-Z]{1}[\\u4e00-\\u9fa5]{1}[0-9]{4,6}$";
        boolean flage20 = Pattern.matches(rule20, useOrgCode);

        // 384
        String rule21 = "^[0-9]{3,4}$";
        boolean flage21 = Pattern.matches(rule21, useOrgCode);

        // 梯12空港0063(20H2G20-590-6)(22)   梯12秦汉0509(2013-11-443)(16)
        String rule22 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}[\\u4e00-\\u9fa5]{1,2}[0-9]{4}\\([A-Z0-9]{4,7}-[A-Z0-9]{2,3}-[A-Z0-9]{1,3}\\)\\(\\d{2}\\)$";
        boolean flage22 = Pattern.matches(rule22, useOrgCode);

        // 游A10陕CA00116(23)
        String rule23 = "^[\\u4e00-\\u9fa5][0-9A-Z]{3}陕[A-Z0-9]{5,7}\\(\\d{2}\\)$";
        boolean flage23 = Pattern.matches(rule23, useOrgCode);

        // 容IIIMC陕D三0384(2K13B3-03)
        String rule24 = "^[\\u4e00-\\u9fa5]{1}[A-Z0-9]{5}[\\u4e00-\\u9fa5]{1}[A-Z]{1}[\\u4e00-\\u9fa5]{1}[0-9]{4,6}\\([A-Z0-9]{6}-[0-9]{2}\\)$";
        boolean flage24 = Pattern.matches(rule24, useOrgCode);

        // 陕YN0:004
        String rule25 = "^[\\u4e00-\\u9fa5][A-Z]{2}[0-9]{1}:[0-9]{3}$";
        boolean flage25 = Pattern.matches(rule25, useOrgCode);

        // 起1100001(21)
        String rule26 = "^[\\u4e00-\\u9fa5][A-Z0-9]{7}\\(\\d{2}\\)$";
        boolean flage26 = Pattern.matches(rule26, useOrgCode);

        // 梯12秦汉0750(SLT03159-2020)(21)
        String rule27 = "^[\\u4e00-\\u9fa5][0-9A-Z]{2}[\\u4e00-\\u9fa5]{1,2}[0-9]{4}\\([A-Z0-9]{4,8}-[A-Z0-9]{4}\\)\\(\\d{2}\\)$";
        boolean flage27 = Pattern.matches(rule27, useOrgCode);

        // G-01-T-003548
        String rule28 = "^[a-zA-Z]{1}-[0-9]{2}-[A-Z]-\\d{6}$";
        boolean flage28 = Pattern.matches(rule28, useOrgCode);

        // 客1LS0013
        String rule29 = "^[\\u4e00-\\u9fa5]{1}[0-9]{1}[A-Z]{1,2}[0-9]{4}$";
        boolean flage29 = Pattern.matches(rule29, useOrgCode);

        // T20090311
        String rule30 = "^[A-Za-z]\\d{4}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])$";
        boolean flage30 = Pattern.matches(rule30, useOrgCode);

        // 容2MS陕JI0487
        String rule31 = "^容\\d[A-Z]{2}陕[A-Z]{2}\\d{4}$";
        boolean flage31 = Pattern.matches(rule31, useOrgCode);

        // 3MR陕J0032
        String rule32 = "^\\d[A-Z]{2}陕[A-Z]\\d{4}$";
        boolean flage32 = Pattern.matches(rule32, useOrgCode);


        return flage01 || flage02 || flage03 || flage04 || flage05 || flage06 || flage07 || flage08 || flage09 || flage10 || flage11 || flage12 || flage13 || flage14 || flage15 || flage16 || flage17 || flage18 || flage19 || flage20 || flage21 || flage22 || flage23 || flage24 || flage25 || flage26 || flage27 || flage28 || flage29 || flage30 || flage31 || flage32;
    }


    /**
     * 电梯----技术参数 检查
     *
     * @param data
     * @param rowError
     */
    private void DTTechnicalParamsCheck(EquipInfoExcelDto data, StringBuffer rowError) {
    }

    @Transactional(rollbackFor = Exception.class)
    public void batchSaveHisEquipmentData(String remark, List<EquipInfoExcelDto> equipInfoExcelDtos, LinkedHashMap equipmentInfoForm) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        CompanyBo company = reginParams.getCompany();
        String[] keys = {
                "PRODUCT_PHOTO", "OTHER_ACCESSORIES_REG", "DESIGN_DOC", "DESIGN_STANDARD",
                "OTHER_ACCESSORIES_DES", "PRODUCT_QUALITY_YIELD_PROVE", "FACTORY_STANDARD",
                "INS_USE_MAINTAIN_EXPLAIN", "OTHER_ACCESSORIES_FACT",
                "BOILER_ENERGY_EFFICIENCY_CERTIFICATE", "FACT_SUPERVISION_INSPECTION_REPORT","INSPECT_REPORT"
        };

        String[] parts = Optional.ofNullable(equipmentInfoForm.get("orgBranchCode"))
                .map(String::valueOf)
                .map(s -> s.split("_", 2))
                .orElse(new String[0]);
        String orgBranchCode = parts.length > 0 ? parts[0] : "";
        String orgBranchName = parts.length > 1 ? parts[1] : "";

        String equList = String.valueOf(equipmentInfoForm.get("EQU_LIST"));
        String equCategory = String.valueOf(equipmentInfoForm.get("EQU_CATEGORY"));

        String dataSource = "new".equals(equipmentInfoForm.get("DATA_SOURCE"))
                ? "jg_pl"
                : "his".equals(equipmentInfoForm.get("DATA_SOURCE"))
                ? "jg_his_pl"
                : "jg_his_black_pl";

        for (EquipInfoExcelDto equ : equipInfoExcelDtos) {
            if (!equList.equals(equ.getEquList()) || !equCategory.equals(equ.getEquCategory())) {
                log.error("设备不一致：模板[{}, {}]，当前[{}, {}]",
                        equList, equCategory, equ.getEquList(), equ.getEquCategory());
                throw new BadRequest("设备种类或设备类型与模板上传不一致，请核对后进行上传!");
            }
        }
        Set<String> recordSet = new HashSet<>();
        Set<String> projectContraptionSet = new HashSet<>();
        Map<String, Long> projectContraptionMap = new HashMap<>();
        Map<String, BigDecimal> pipeLengthMap = equipInfoExcelDtos.stream()
                .collect(Collectors.groupingBy(
                        e -> Objects.toString(e.getProjectContraptionNo(), "").trim(),
                        Collectors.mapping(
                                e -> new BigDecimal(Objects.toString(e.getPipeLength(), "0")),
                                Collectors.reducing(BigDecimal.ZERO, BigDecimal::add)
                        )
                ));
        Set<String> projectContraptionIdSet = new HashSet<>();
        for (EquipInfoExcelDto equ : equipInfoExcelDtos) {
            List<Map<String, Object>> fileDataList = (List<Map<String, Object>>) equ.getFileData();
            Map<String, Object> equMap = (Map<String, Object>) JSON.parseObject(toJSONString(equ), Map.class);
            for (String key : keys) {
                String camelKey = toCamelCase(key.toLowerCase());
                equMap.put(camelKey, getUrlByKey(fileDataList, key));
            }
            equMap.put("orgBranchName", orgBranchName);
            equMap.put("orgBranchCode", orgBranchCode);
            equMap.put("EQU_STATE", equipmentInfoForm.get("EQU_STATE"));

            String projectContraptionNo = Objects.toString(equMap.get("projectContraptionNo"), "").trim();
            Long projectContraptionId;
            if (!projectContraptionSet.contains(projectContraptionNo)) {
                BigDecimal totalPipeLength = pipeLengthMap.getOrDefault(projectContraptionNo, BigDecimal.ZERO);
                equMap.put("totalPipeLength",totalPipeLength);
                projectContraptionId = this.saveProjectContraption(equMap, equList, company, dataSource);
                projectContraptionSet.add(projectContraptionNo);
                projectContraptionMap.put(projectContraptionNo, projectContraptionId);
            } else {
                projectContraptionId = projectContraptionMap.get(projectContraptionNo);
            }
            if (projectContraptionId != null) {
                projectContraptionIdSet.add(String.valueOf(projectContraptionId));
                equMap.put("projectContraptionId", projectContraptionId);
            }
            String record = this.saveEquipmentDataInTransaction(equMap, dataSource, remark);
            recordSet.add(record);
        }
        if (EquipmentClassifityEnum.YLGD.getCode().equals(equList)) {
            this.createResumePipelineBatch(projectContraptionIdSet, String.format(pipelineRoutePath, projectContraptionIdSet), company);
            eventPublisher.publish(new EquipCreateOrEditEvent(this, BusinessTypeEnum.JG_NEW_PROJECT.name(), projectContraptionIdSet, EquipCreateOrEditEvent.EquipType.project));
        }else{
            this.createResumeBatch(recordSet,dataSource, equipRoutePath, company);
            eventPublisher.publish(new EquipCreateOrEditEvent(this,BusinessTypeEnum.JG_NEW_EQUIP.name(),recordSet, EquipCreateOrEditEvent.EquipType.equip));
        }
    }

    private void createResumeBatch(Set<String> records, String dataSource, String routePath, CompanyBo company) {
        jgResumeInfoService.saveBatchResume(records.stream().map(record->JgResumeInfoDto.builder()
                .businessType(BusinessTypeEnum.JG_NEW_EQUIP.getName())
                .businessId(record)
                .equId(record)
                .status("正常")
                .approvalUnitCode(company.getCompanyCode())
                .approvalUnit(company.getCompanyName())
                .changeContent(BusinessTypeEnum.JG_NEW_EQUIP.getName() + "业务办理")
                .routePath(String.format(routePath, record, dataSource))
                .build()).collect(Collectors.toList())
        );
    }

    private void createResumePipelineBatch(Set<String> projectContraptionIdSet, String routePath, CompanyBo company) {
        jgResumeInfoService.saveBatchResume(projectContraptionIdSet.stream().map(projectContraptionId ->JgResumeInfoDto.builder()
                .businessType(BusinessTypeEnum.JG_NEW_PROJECT.getName())
                .businessId(projectContraptionId)
                .equId(projectContraptionId)
                .status("正常")
                .approvalUnitCode(company.getCompanyCode())
                .approvalUnit(company.getCompanyName())
                .changeContent(BusinessTypeEnum.JG_NEW_PROJECT.getName() + "业务办理")
                .routePath(routePath)
                .build()).collect(Collectors.toList())
        );
    }

    /**
     * 批量异步保存设备数据
     *
     * @param equipInfoExcelDtos
     */
    public void batchSaveEquipmentData(String remark, List<EquipInfoExcelDto> equipInfoExcelDtos) {
        String[] keys = {
                "PRODUCT_PHOTO", "OTHER_ACCESSORIES_REG", "DESIGN_DOC", "DESIGN_STANDARD",
                "OTHER_ACCESSORIES_DES", "PRODUCT_QUALITY_YIELD_PROVE", "FACTORY_STANDARD",
                "INS_USE_MAINTAIN_EXPLAIN", "OTHER_ACCESSORIES_FACT",
                "BOILER_ENERGY_EFFICIENCY_CERTIFICATE", "FACT_SUPERVISION_INSPECTION_REPORT","INSPECT_REPORT"
        };
        Arrays.stream(equipInfoExcelDtos.toArray(new EquipInfoExcelDto[0])).forEach(equ -> {
            List<Map<String, Object>> fileDataList = (List<Map<String, Object>>) equ.getFileData();
            Map<String, Object> equMap = (Map<String, Object>) JSON.parseObject(toJSONString(equ), Map.class);
            for (String key : keys) {
                String camelKey = toCamelCase(key.toLowerCase());
                equMap.put(camelKey, getUrlByKey(fileDataList, key));
            }
            this.saveEquipmentDataInTransaction(equMap, "jg_his", remark);
        });
    }

    private String getUrlByKey(List<Map<String, Object>> dataList, String key) {
        if (dataList == null || dataList.isEmpty()) {
            return null;
        }
        for (Map<String, Object> item : dataList) {
            if (key.equals(item.get("key"))) {
                return toJSONString(item.get("value"));
            }
        }
        return null;
    }

    /**
     * 检查管道的excel数据格式
     *
     * @param multipartFile 文件
     * @param isGYGD        是否工业管道
     * @return 结果集合
     * @throws Exception 检测不通过，异常情况描述
     */
    public Object checkGDData(MultipartFile multipartFile, Boolean isGYGD) throws Exception {
        List<PipingExcelDto> dataList = new ArrayList<>();
        List<String> resultGDError = new ArrayList<>();
        List<String> pipelineNumList = new ArrayList<>();
        try {
            // 判断模板版本号
            String templateVersionError = DataDockTemplateVersionUtils.checkTemplateVersion(multipartFile);
            if (!ValidationUtil.isEmpty(templateVersionError)) {
                resultGDError.add(templateVersionError);
                throw new BadRequest(templateVersionError);
            }
            EasyExcel.read(multipartFile.getInputStream(), PipingExcelDto.class, new AnalysisEventListener<PipingExcelDto>() {
                @Override
                public void invoke(PipingExcelDto data, AnalysisContext context) {
                    resultGDError.add(checkGDExcelData(data, context, isGYGD, pipelineNumList).toString());
                    dataList.add(data);
                }

                @Override
                public void doAfterAllAnalysed(AnalysisContext context) {
                    if (CollectionUtils.isEmpty(dataList)) {
                        log.info("你上传了一个空数据的Excel文档!");
                        resultGDError.add("你上传了一个空数据的Excel文档!");
                        throw new BadRequest("你上传了一个空数据的Excel文档!");
                    }
                }
            }).headRowNumber(4).sheet().doRead();
            if (resultGDError.stream().anyMatch(input -> !input.isEmpty())) {
                throw new BadRequest("上传失败！");
            }
            return dataList;
        } catch (Exception e) {
            throw new Exception(resultGDError.stream()
                    .filter(s -> !s.isEmpty())
                    .collect(Collectors.joining("<br/>")));
        }
    }

    public StringBuffer checkGDExcelData(PipingExcelDto data, AnalysisContext context, Boolean isGYGD, List<String> pipelineNumList) {

        StringBuffer rowError = new StringBuffer();
        ReadRowHolder readRowHolder = context.readRowHolder();
        int rowIndex = readRowHolder.getRowIndex() + 1;
        try {
            log.info("解析第{}行数据：{}", rowIndex, toJSONString(data));
            checkNotBlank(data.getPipeName(), "管道名称不能为空；", rowError);
            //checkNotBlank(data.getDesignUnitCreditCode(), "设计单位统一社会信用代码不能为空；", rowError);
            //checkNotBlank(data.getDesignUnitName(), "设计单位名称不能为空；", rowError);
            //checkNotBlank(data.getInspectOrgCode(), "检验机构\检测机构统一社会信用代码不能为空；", rowError);
            //checkNotBlank(data.getInspectOrgName(), "检验机构\检测机构名称不能为空；", rowError);
            //checkNotBlank(data.getInspectConclusion(), "检验结论不能为空；", rowError);
            //checkNotBlank(data.getInspectType(), "检验类型不能为空；", rowError);
            //checkNotBlank(data.getInspectDate(), "检验日期不能为空；", rowError);
            //Optional.ofNullable(data.getInspectDate()).ifPresent(v -> checkDateFormatCorrect(v, "检验日期格式不正确；", rowError));
            //checkNotBlank(data.getInspectStaff(), "检验人员名称不能为空；", rowError);
            //checkNotBlank(data.getNextInspectDate(), "下次检验日期不能为空；", rowError);
            //Optional.ofNullable(data.getNextInspectDate()).ifPresent(v -> checkDateFormatCorrect(v, "下次检验日期格式不正确；", rowError));
            //checkNotBlank(data.getInspectReportNo(), "检验报告编号不能为空；", rowError);
            //checkNotBlank(data.getUscUnitCreditCode(), "安装单位统一社会信用代码不能为空；", rowError);
            //checkNotBlank(data.getUscUnitName(), "安装单位名称不能为空；", rowError);
            //checkNotBlank(data.getUscDate(), "安装年月不能为空", rowError);
            // 技术参数
            //checkNotBlank(data.getWallThickness(), "公称壁厚不能为空；", rowError);
            //Optional.ofNullable(data.getWallThickness()).ifPresent(item -> checkPipeSpecifications(item, "公称壁厚请输入数字或者/分割的范围，如2/6；", rowError));
            //checkNotBlank(data.getNominalDiameter(), "公称直径不能为空；", rowError);
            //Optional.ofNullable(data.getNominalDiameter()).ifPresent(item -> checkPipeSpecifications(item, "公称直径请输入数字或者/分割的范围，如2/6；", rowError));
            checkNotBlank(data.getPipeLength(), "管道长度不能为空；", rowError);
            Optional.ofNullable(data.getPipeLength()).ifPresent(item -> checkDateFormatNumber(item, "管道长度必须为数字", rowError));
            //checkNotBlank(data.getPressure(), "设计-压力不能为空；", rowError);
            //checkNotBlank(data.getMedium(), "设计-介质不能为空；", rowError);
            //checkNotBlank(data.getTemperature(), "设计-温度不能为空；", rowError);
            //checkNotBlank(data.getPipelineNumber(), "管道编号不能为空；", rowError);
//            Optional.ofNullable(data.getPipelineNumber()).ifPresent(v -> {
//                if (pipelineNumList.contains(v)) {
//                    rowError.append("管道编号不能重复");
//                } else {
//                    pipelineNumList.add(v);
//                }
//            });
            //checkNotBlank(data.getDeviceLevel(), "管道级别不能为空；", rowError);


            // 工业管道校验使用信息
            if (isGYGD) {
                // todo
            }

            // 如果存在错误信息，则抛出 BadRequest 异常
            if (rowError.length() > 0) {
                rowError.insert(0, "Excel第[" + rowIndex + "]行 -> ");
            }

        } catch (Exception e) {
            log.error("行索引数: [{}] -> 失败的 Excel 数据: [{}]", rowIndex, toJSONString(data), e);
            throw e;
        }
        return rowError;
    }

    /**
     * 管道规格格式校验
     *
     * @param item
     * @param errorMessage
     * @param rowError
     */
    public void checkPipeSpecifications(String item, String errorMessage, StringBuffer rowError) {
        String regex = "^(?:0|[1-9]\\d*(?:[.]\\d*)?)((?:[-/](?:0[.]\\d+|[1-9]\\d*(?:[.]\\d*)?))?)+$";
        if (!item.matches(regex)) {
            rowError.append(errorMessage);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Object saveEquipImportData(Map<String, Object> paramMap) {
        if (paramMap == null) {
            throw new IllegalArgumentException("参数Map不能为空");
        }
        LinkedHashMap equipmentInfoForm = (LinkedHashMap) checkAndCast(paramMap.get(EQUIP_INFO_FORM_ID));
        LinkedHashMap attachmentUpload = (LinkedHashMap) checkAndCast(paramMap.get(ATTACHMENT_UPLOAD));
        List<EquipInfoExcelDto> equipInfoExcelDtos = JSON.parseArray(toJSONString(attachmentUpload.get(EQU_LISTS)), EquipInfoExcelDto.class);

        // 2, 保存设备数据
        this.batchSaveHisEquipmentData("", equipInfoExcelDtos,equipmentInfoForm);
        return Boolean.TRUE;
    }

    private Object checkAndCast(Object obj) {
        if (obj instanceof LinkedHashMap) {
            return obj;
        } else {
            throw new ClassCastException("对象类型不匹配");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public Object savePipingData(Map<String, Object> paramMap, CompanyBo company) {
        // 获取数据
        JSONObject equipInfo = JSON.parseObject(toJSONString(paramMap.get("equipInfo")), JSONObject.class);
        JSONObject attachmentUpload = JSON.parseObject(toJSONString(paramMap.get("attachmentUpload")), JSONObject.class);
        JSONArray equListsJSONArr = JSONArray.parseArray(toJSONString(attachmentUpload.get("equLists")));
        List<PipingExcelDto> equLists = equListsJSONArr.toJavaList(PipingExcelDto.class);
        for (int i = 0; i < equLists.size(); i++) {
            PipingExcelDto equ = equLists.get(i);
            JSONObject equJson = JSON.parseObject(toJSONString(equListsJSONArr.get(i)));
            JSONArray fileDataArray = equJson.getJSONArray("fileData");

            if (fileDataArray == null || fileDataArray.isEmpty()) {
                continue;
            }

            for (Object arr : fileDataArray) {
                JSONObject fileData = JSON.parseObject(toJSONString(arr));
                if (ValidationUtil.isEmpty(fileData) || !"inspectReport".equals(fileData.getString("key"))) {
                    continue;
                }
                JSONArray value = fileData.getJSONArray("value");
                if (value != null) {
                    equ.setInspectReport(value.toJSONString());
                }
            }
        }
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        // 监管——历史——管道——批量
        String dataSource = "jg_his_gd_pl";
        // 公共参数提取
        EquipRequestParamsDto paramsDto = this.extractCommonData(dataSource, reginParams, equipInfo, equLists);
        // 是否工业管道
        boolean isGYGD = "8300".equals(paramsDto.getEquCategoryCode());
        boolean haveUseRegistration = false;
        // 确保使用登记证和工程装置在该单位下都是不存在的，方可导入数据
        if (isGYGD) {
            haveUseRegistration = this.checkTheUnitRegManageAlreadyExists(paramsDto, haveUseRegistration);
        }
        idxBizJgProjectContraptionServiceImpl.checkTheUnitProConMatching(paramsDto);
        this.checkTheUnitProConAlreadyExists(paramsDto);
        // 生成工程装置表信息
        IdxBizJgProjectContraption proCon = this.saveProjectContraption(paramsDto);
        // 保存管道对应的idx表数据
        List<String> records = this.savePipInfoToIdxTables(equLists, paramsDto, proCon);
        if (isGYGD) {
            // 生成使用登记表信息 + 设备关系表 + 历史表
            JgUseRegistration useReg = this.saveUseRegAndEq(paramsDto, records, proCon);
            // 生成使用登记证表数据
            if (!haveUseRegistration) {
                JgUseRegistrationManage regManage = this.saveUseRegManage(paramsDto, useReg);
                // 流水表
                this.saveCertChangeRecord(useReg, regManage, records, paramsDto);
            } else {
                // 1.更新使用登记证信息
                JgUseRegistrationManage jgUseRegistrationManage = jgUseRegistrationManageService.lambdaQuery()
                        .eq(JgUseRegistrationManage::getUseRegistrationCode, paramsDto.getUseOrgCode())
                        .eq(JgUseRegistrationManage::getIsDelete, 0)
                        .one();
                if (jgUseRegistrationManage != null) {
                    jgUseRegistrationManage.setSuperviseOrgCode(paramsDto.getOrgBranchCode());
                    jgUseRegistrationManage.setSuperviseOrgName(paramsDto.getOrgBranchName());
                    jgUseRegistrationManage.setRecDate(new Date());
                    jgUseRegistrationManageService.updateById(jgUseRegistrationManage);
                }
            }
        }
        this.createResumePipeline(proCon.getSequenceNbr(), String.format(pipelineRoutePath, proCon.getSequenceNbr() + ""), company);
        eventPublisher.publish(new EquipCreateOrEditEvent(this, BusinessTypeEnum.JG_NEW_PROJECT.name(), Sets.newHashSet(proCon.getSequenceNbr() + ""), EquipCreateOrEditEvent.EquipType.project));
        return Boolean.TRUE;
    }

    private void createResumePipeline(Long sequenceNbr, String routePath, CompanyBo company) {
        jgResumeInfoService.saveBatchResume(Collections.singletonList(JgResumeInfoDto.builder()
                .businessType(BusinessTypeEnum.JG_NEW_PROJECT.getName())
                .businessId(sequenceNbr + "")
                .equId(sequenceNbr + "")
                .status("正常")
                .approvalUnitCode(company.getCompanyCode())
                .approvalUnit(company.getCompanyName())
                .changeContent(BusinessTypeEnum.JG_NEW_PROJECT.getName() + "业务办理")
                .routePath(routePath)
                .build())
        );
    }

    public void saveCertChangeRecord(JgUseRegistration useReg, JgUseRegistrationManage regManage, List<String> records, EquipRequestParamsDto paramsDto) {
        Long changeRecordId = sequence.nextId();
        JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord()
                .setApplyNo(useReg.getApplyNo())
                .setReceiveOrgName(useReg.getReceiveOrgName())
                .setAuditPassDate(new Date())
                .setRegType(BusinessTypeEnum.JG_USAGE_REGISTRATION.getName())
                .setRegDate(useReg.getCreateDate())
                .setChangeContent(this.buildRecordContent(useReg, paramsDto))
                .setUseRegistrationCode(useReg.getUseRegistrationCode())
                .setReceiveCompanyCode(useReg.getReceiveCompanyOrgCode())
                .setCertificateNo(regManage.getCertificateNo())
                .setUseUnitCreditCode(useReg.getUseUnitCreditCode())
                .setUseUnitName(useReg.getUseUnitName())
                .setEquCategory(paramsDto.getEquCategoryCode())
                .setCreateDate(new Date());
        certificateChangeRecordService.save(changeRecord);
        records.forEach(record -> {
            JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
            changeRecordEq.setChangeRecordId(String.valueOf(changeRecordId));
            changeRecordEq.setEquId(record);
            certificateChangeRecordEqService.save(changeRecordEq);
        });
    }

    public String buildRecordContent(JgUseRegistration useReg, EquipRequestParamsDto paramsDto) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        return paramsDto.getCompanyName() + "的" + paramsDto.getExecUserName() + "办理了【" + "历史设备登记" + "】，" +
                "单号【" + useReg.getApplyNo() + "】，办理日期" + simpleDateFormat.format(new Date());
    }

    private String buildRecordContent(JgUseRegistration useReg) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日");
        return useReg.getUseUnitName() + "的管理员" + "办理了【" + "历史设备登记" + "】，" +
                "单号【" + useReg.getApplyNo() + "】，办理日期" + simpleDateFormat.format(new Date());
    }

    /**
     * 检查本单位是否存在使用登记证编号 + 不能是系统未生成的
     *
     * @param paramsDto 设备请求参数
     */
    public boolean checkTheUnitRegManageAlreadyExists(EquipRequestParamsDto paramsDto, boolean haveUseRegistration) {
        // 1. 判断是否使用未来系统生成编号
        idxBizJgRegisterInfoServiceImpl.checkUseRegistrationCode(paramsDto.getUseOrgCode(), "unit");
        // 2. 获取使用登记管理列表
//        List<JgUseRegistration> useRegistrationList = jgUseRegistrationMapper.selectList(
//                new LambdaQueryWrapper<JgUseRegistration>()
//                        .eq(JgUseRegistration::getUseRegistrationCode, paramsDto.getUseOrgCode())
//                        .eq(JgUseRegistration::getIsDelete, 0)
//                        .eq(JgUseRegistration::getStatus, "已完成")
//                        .orderByDesc(JgUseRegistration::getRecDate)
//                        .last("limit 1"));
        List<JgUseRegistrationManage> useRegistrationManageList = jgUseRegistrationManageMapper.selectList(
                new LambdaQueryWrapper<JgUseRegistrationManage>()
                        .eq(JgUseRegistrationManage::getUseRegistrationCode, paramsDto.getUseOrgCode())
                        .eq(JgUseRegistrationManage::getIsDelete, 0)
                        .eq(JgUseRegistrationManage::getCertificateStatus, "已登记")
                        .orderByDesc(JgUseRegistrationManage::getRecDate));

        if (!useRegistrationManageList.isEmpty()) {
//            if (useRegistrationList.stream().filter(map -> !"1".equals(map.getRegType())).count() > 1) {
//                throw new BadRequest("该使用登记证编号已由系统自动生成，不能导入，请确认使用登记证编号是否正确！");
//            }
            if (useRegistrationManageList.stream().anyMatch(map -> !paramsDto.getCompanyCode().equals(map.getUseUnitCreditCode()))) {
                throw new BadRequest("该使用登记证编号在其他企业使用，不能导入，请确认使用登记证编号是否正确！");
            }
            haveUseRegistration = true;
        }
        return haveUseRegistration;
    }

    /**
     * 公共参数提取
     *
     * @param equipInfo
     * @param equLists
     * @return
     */
    public EquipRequestParamsDto extractCommonData(String dataSource, ReginParams reginParams, JSONObject equipInfo, List<PipingExcelDto> equLists) {
        AgencyUserModel userModel = reginParams.getUserModel();
        CompanyBo company = reginParams.getCompany();
        String orgBranchCode = equipInfo.getString("orgBranchCode");
        String equListCode = Objects.toString(equipInfo.get("EQU_LIST"), null);
        String equCategoryCode = Objects.toString(equipInfo.get("EQU_CATEGORY"), null);
        String equDefineCode = Objects.toString(equipInfo.get("EQU_DEFINE"), null);
        String receiveOrgCode = Optional.ofNullable(equipInfo.get("RECEIVE_ORG_CODE")).map(String::valueOf).orElse(null);
        String inspectUnitCreditCode = Optional.ofNullable(equLists.get(0).getInspectOrgCode()).orElse(null);
        String inspectUnitName = Optional.ofNullable(equLists.get(0).getInspectOrgName()).orElse(null);
        String useOrgCode = Optional.ofNullable(equipInfo.get("USE_ORG_CODE")).map(String::valueOf).orElse(null);
        String province = Objects.toString(equipInfo.get("province"), null);
        String city = Objects.toString(equipInfo.get("city"), null);
        String county = Objects.toString(equipInfo.get("county"), null);
        String street = Objects.toString(equipInfo.get("street"), null);
        String address = Objects.toString(equipInfo.get("address"), null);
        String usePlace = Objects.toString(equipInfo.get("usePlace"), null);
        String useDate = Objects.toString(equipInfo.get("useDate"), null);
        String equState = Objects.toString(equipInfo.get("EQU_STATE"), null);
        return new EquipRequestParamsDto().setCompanyCode(company.getCompanyCode().split("_")[0])
                .setProvince(province)
                .setProvinceName("陕西省")
                .setCity(city)
                .setCityName(this.getRegionName("CITY", "CITY".toLowerCase(), equipInfo))
                .setCounty(county)
                .setCountyName(this.getRegionName("REGION", "COUNTY".toLowerCase(), equipInfo))
                .setStreet(street)
                .setStreetName(this.getRegionName("STREET", "STREET".toLowerCase(), equipInfo))
                .setAddress(address)
                .setUsePlace(usePlace)
                .setCompanyName(company.getCompanyName())
                .setCompanyAddress(company.getAddress())
                .setExecUserId(userModel.getUserId())
                .setExecUserName(userModel.getUserName())
                .setEquListCode(equListCode)
                .setEquListName(EquipmentClassifityEnum.getNameByCode(equListCode))
                .setEquCategoryCode(equCategoryCode)
                .setEquCategoryName(EquCategoryConverter.getKeyByValue(equCategoryCode))
                .setEquDefineCode(equDefineCode).setEquDefineName(EquDefineConverter.getKeyByValue(equDefineCode))
                .setDataSource(dataSource)
                .setUseDate(useDate)
                .setOrgBranchCode(orgBranchCode.split("_").length > 1 ? orgBranchCode.split("_")[0] : "")
                .setOrgBranchName(orgBranchCode.split("_").length > 1 ? orgBranchCode.split("_")[1] : "")
                .setUseOrgCode(useOrgCode)
                .setVehicleApanage(Objects.toString(equipInfo.get("VEHICLE_APANAGE"),""))
                .setReceiveOrgCode(Optional.ofNullable(receiveOrgCode)
                        .map(code -> code.split("_"))
                        .filter(parts -> parts.length > 0)
                        .map(parts -> parts[0])
                        .orElse(null))
                .setReceiveOrgName(Optional.ofNullable(receiveOrgCode)
                        .map(code -> code.split("_"))
                        .filter(parts -> parts.length > 1)
                        .map(parts -> parts[1])
                        .orElse(null))
                .setProjectContraption(Objects.toString(equipInfo.get("PROJECT_CONTRAPTION"),null))
                .setProjectContraptionNo(Objects.toString(equipInfo.get("PROJECT_CONTRAPTION_NO"),null))
                .setProductPhoto(toJSONString(equipInfo.get("PRODUCT_PHOTO")))
                .setProductQualificationCertificate(toJSONString(equipInfo.get("PRODUCT_QUALIFICATION_CERTIFICATE")))
                .setOtherAccessories(ValidationUtil.isEmpty(equipInfo.get("OTHER_ACCESSORIES")) ? null : toJSONString(equipInfo.get("OTHER_ACCESSORIES")))
                .setPipelineLength(
                        Optional.ofNullable(equLists)
                                .orElse(Collections.emptyList())
                                .stream()
                                .filter(Objects::nonNull)
                                .map(PipingExcelDto::getPipeLength)
                                .filter(Objects::nonNull)
                                .map(String::trim)
                                .filter(s -> !s.isEmpty())
                                .mapToDouble(Double::parseDouble)
                                .sum()
                )
                .setInspectUnitCreditCode(inspectUnitCreditCode)
                .setInspectUnitName(inspectUnitName)
                .setStartLatitudeLongitude(toJSONString(equipInfo.get("startLatitudeLongitude")))
                .setEndLatitudeLongitude(toJSONString(equipInfo.get("endLatitudeLongitude")))
                .setEquState(equState)
                .setEquCode(installationNoticeService.generateEquCode(equListCode, equCategoryCode, equDefineCode, new Date(), receiveOrgCode));
    }

    /**
     * 根据code获取市区县名字
     *
     * @param key     key
     * @param codeKey codeKey
     * @param mapData 表单信息
     * @return name
     */
    private String getRegionName(String key, String codeKey, JSONObject mapData) {
        return Optional.ofNullable((List<LinkedHashMap>) redisUtils.get(key))
                .flatMap(list -> list.stream()
                        .filter(item -> String.valueOf(item.get("regionCode"))
                                .equals(String.valueOf(mapData.get(codeKey))))
                        .map(item -> (String) item.get("regionName"))
                        .findFirst())
                .orElse("");
    }

    /**
     * 检查本单位是否已存在该工程装置
     * 存在则抛出异常
     *
     * @param paramsDto
     */
    public void checkTheUnitProConAlreadyExists(EquipRequestParamsDto paramsDto) {
        Integer count = idxBizJgProjectContraptionService.lambdaQuery().select(IdxBizJgProjectContraption::getPipelineLength).eq(IdxBizJgProjectContraption::getUseUnitCreditCode, paramsDto.getCompanyCode()).eq(IdxBizJgProjectContraption::getUseUnitName, paramsDto.getCompanyName())
                // 限制到设备类别
                .eq(IdxBizJgProjectContraption::getEquCategory, paramsDto.getEquCategoryCode()).eq(IdxBizJgProjectContraption::getIsIntoManagement, Boolean.TRUE).eq(IdxBizJgProjectContraption::getIsDelete, Boolean.FALSE).eq(IdxBizJgProjectContraption::getProjectContraption, paramsDto.getProjectContraption()).eq(IdxBizJgProjectContraption::getProjectContraptionNo, paramsDto.getProjectContraptionNo()).count();
        // 存在数据 名称和编号能一一对应，限制不让导入
        if (count > 0) {
            throw new BadRequest("系统已存在该工程装置！");
        }
    }

    /**
     * 保存管道对应的idx表数据
     *
     * @param equLists
     * @param paramsDto
     */
    public List<String> savePipInfoToIdxTables(List<PipingExcelDto> equLists, EquipRequestParamsDto paramsDto, IdxBizJgProjectContraption proCon) {
        List<String> recordList = new ArrayList<>();
        List<IdxBizJgUseInfo> useInfoList = new ArrayList<>();
        List<IdxBizJgDesignInfo> designInfoList = new ArrayList<>();
        List<IdxBizJgFactoryInfo> factoryInfoList = new ArrayList<>();
        List<IdxBizJgConstructionInfo> constructionInfoList = new ArrayList<>();
        List<IdxBizJgRegisterInfo> registerInfoList = new ArrayList<>();
        List<IdxBizJgSupervisionInfo> supervisionInfoList = new ArrayList<>();
        List<IdxBizJgOtherInfo> otherInfoList = new ArrayList<>();
        List<IdxBizJgTechParamsPipeline> paramsPipelineList = new ArrayList<>();
        List<ESEquipmentCategoryDto> esEquipmentCategoryList = new ArrayList<>();
        List<IdxBizJgInspectionDetectionInfo> inspectionDetectionInfoList = new ArrayList<>();

        for (PipingExcelDto pipeline : equLists) {
            String record = UUID.randomUUID().toString();
            recordList.add(record);
            // 使用信息
            IdxBizJgUseInfo useInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgUseInfo.class);
            useInfo.setRecord(record);
            useInfo.setSequenceNbr(null);
            useInfo.setRecDate(new Date());
            useInfo.setCreateDate(new Date());
            useInfo.setDataSource(paramsDto.getDataSource());
            useInfo.setIsIntoManagement(Boolean.TRUE);
            useInfo.setProvince(paramsDto.getProvince());
            useInfo.setCity(paramsDto.getCity());
            useInfo.setCounty(paramsDto.getCounty());
            useInfo.setFactoryUseSiteStreet(paramsDto.getStreet());
            useInfo.setProvinceName(paramsDto.getProvinceName());
            useInfo.setCityName(paramsDto.getCityName());
            useInfo.setCountyName(paramsDto.getCountyName());
            useInfo.setStreetName(paramsDto.getStreetName());
            useInfo.setAddress(paramsDto.getAddress());
            useInfo.setEquState(Optional.ofNullable(paramsDto.getEquState()).orElse(String.valueOf(EquimentEnum.ZAIYONG.getCode())));
            useInfo.setUseUnitCreditCode(paramsDto.getCompanyCode());
            useInfo.setUseUnitName(paramsDto.getCompanyName());
            useInfo.setProjectContraption(paramsDto.getProjectContraption());
            useInfo.setUseDate(paramsDto.getUseDate());
            useInfo.setProjectContraptionId(paramsDto.getProjectContraptionSeq());
            useInfo.setDataQualityScore(StringUtils.isEmpty(paramsDto.getUseOrgCode()) ? 3 : 1);
            useInfoList.add(useInfo);

            // 检验检测信息
            IdxBizJgInspectionDetectionInfo inspectionDetectionInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgInspectionDetectionInfo.class);
            if (!ValidationUtil.isEmpty(inspectionDetectionInfo)) {
                inspectionDetectionInfo.setRecord(record);
                inspectionDetectionInfo.setRecDate(new Date());
                inspectionDetectionInfo.setSequenceNbr(null);
                if (inspectionDetectionInfo.getNextInspectDate() != null) {
                    inspectionDetectionInfo.setNextInspectDate(DateUtil.parse(DateUtil.format(inspectionDetectionInfo.getNextInspectDate(), DatePattern.NORM_DATE_PATTERN)));
                }
                // dictName -> dictCode
                inspectionDetectionInfo.setInspectType(InspectTypeConverter.dictMap.get(inspectionDetectionInfo.getInspectType()));
                inspectionDetectionInfo.setInspectConclusion(InspectConclusionConverter.dictMap.get(inspectionDetectionInfo.getInspectConclusion()));
                inspectionDetectionInfoList.add(inspectionDetectionInfo);
            }

            // 设计信息
            IdxBizJgDesignInfo designInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgDesignInfo.class);
            designInfo.setRecord(record);
            designInfo.setRecDate(new Date());
            designInfo.setSequenceNbr(null);
            designInfoList.add(designInfo);

            // 制造信息
            IdxBizJgFactoryInfo factoryInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgFactoryInfo.class);
            factoryInfo.setRecord(record);
            factoryInfo.setRecDate(new Date());
            factoryInfo.setSequenceNbr(null);
            factoryInfo.setFactoryIsComplete("2");
            factoryInfoList.add(factoryInfo);

            // 施工信息
            IdxBizJgConstructionInfo constructionInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgConstructionInfo.class);
            constructionInfo.setRecord(record);
            constructionInfo.setRecDate(new Date());
            constructionInfo.setSequenceNbr(null);
            constructionInfoList.add(constructionInfo);

            // 注册登记信息
            IdxBizJgRegisterInfo registerInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgRegisterInfo.class);
            registerInfo.setRecord(record);
            registerInfo.setUseOrgCode(paramsDto.getUseOrgCode());
            registerInfo.setRegisterState("6045");
            registerInfo.setEquCode(paramsDto.getEquCode());
            registerInfo.setEquList(paramsDto.getEquListCode());
            registerInfo.setEquCategory(paramsDto.getEquCategoryCode());
            registerInfo.setEquDefine(paramsDto.getEquDefineCode());
            registerInfo.setRecDate(new Date());
            registerInfo.setSequenceNbr(null);
            registerInfo.setEquCodeType("2");
            registerInfo.setRegisterState(idxBizJgRegisterInfoServiceImpl.getRegCode());
            registerInfo.setEquCode(paramsDto.getEquCode());

            // 监督管理
            IdxBizJgSupervisionInfo supervisionInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgSupervisionInfo.class);
            supervisionInfo.setRecord(record);
            supervisionInfo.setOrgBranchCode(paramsDto.getOrgBranchCode());
            supervisionInfo.setOrgBranchName(paramsDto.getOrgBranchName());
            HashMap<String, Object> parentMessage = (HashMap<String, Object>) Privilege.companyClient.queryByOrgcode(paramsDto.getOrgBranchCode()).getResult();
            // 目前平台返回key为compnay(存在拼写错误)
            CompanyModel parentModel = JSON.parseObject(toJSONString(parentMessage.get("compnay")), CompanyModel.class);
            supervisionInfo.setCompanyOrgBranchCode(parentModel.getCompanyCode());
            supervisionInfo.setRecDate(new Date());
            supervisionInfo.setSequenceNbr(null);
            supervisionInfoList.add(supervisionInfo);

            // 其他信息
            IdxBizJgOtherInfo otherInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgOtherInfo.class);
            otherInfo.setRecord(record);
            otherInfo.setSequenceNbr(null);
            otherInfo.setSupervisoryCode(proCon.getSupervisoryCode());
            otherInfo.setClaimStatus("已认领");
            otherInfo.setRecDate(new Date());
            otherInfoList.add(otherInfo);

            // 管道技术参数
            IdxBizJgTechParamsPipeline pipelineInfo = JSON.parseObject(toJSONString(pipeline), IdxBizJgTechParamsPipeline.class);
            if (!ValidationUtil.isEmpty(pipelineInfo)) {
                pipelineInfo.setRecord(record);
                pipelineInfo.setRecDate(new Date());
                pipelineInfo.setSequenceNbr(null);
                // 字典name -》 字典code
                pipelineInfo.setDeviceLevel(DictParamsConverter.dictMap.get(pipelineInfo.getDeviceLevel()));
                paramsPipelineList.add(pipelineInfo);
            }
            registerInfo.setProductName(pipelineInfo.getPipeName());
            registerInfoList.add(registerInfo);

            // es
            ESEquipmentCategoryDto esEquipmentDto = JSON.parseObject(toJSONString(pipeline), ESEquipmentCategoryDto.class);
            esEquipmentDto.setDATA_SOURCE(paramsDto.getDataSource());
            esEquipmentDto.setREC_DATE(System.currentTimeMillis());
            esEquipmentDto.setCREATE_DATE(System.currentTimeMillis());
            esEquipmentDto.setSEQUENCE_NBR(record);
            esEquipmentDto.setIS_INTO_MANAGEMENT(Boolean.TRUE);
            esEquipmentDto.setEQU_CATEGORY_CODE(paramsDto.getEquCategoryCode());
            esEquipmentDto.setEQU_CATEGORY(paramsDto.getEquCategoryName());
            esEquipmentDto.setEQU_LIST_CODE(paramsDto.getEquListCode());
            esEquipmentDto.setEQU_LIST(paramsDto.getEquListName());
            esEquipmentDto.setEQU_DEFINE_CODE(paramsDto.getEquDefineCode());
            esEquipmentDto.setEQU_DEFINE(paramsDto.getEquDefineName());
            esEquipmentDto.setSTATUS("已认领");
            esEquipmentDto.setEQU_STATE(Optional.ofNullable(paramsDto.getEquState())
                            .map(Integer::valueOf).orElse(EquimentEnum.ZAIYONG.getCode()));
            esEquipmentDto.setUSC_UNIT_CREDIT_CODE(pipeline.getUscUnitCreditCode());
            esEquipmentDto.setUSC_UNIT_NAME(pipeline.getUscUnitName());
            esEquipmentDto.setPROJECT_CONTRAPTION(paramsDto.getProjectContraption());
            esEquipmentDto.setPRODUCT_NAME(pipelineInfo.getPipeName());
            esEquipmentDto.setProjectContraptionId(paramsDto.getProjectContraptionSeq());
            esEquipmentDto.setUSE_ORG_CODE(paramsDto.getUseOrgCode());
            esEquipmentDto.setSUPERVISORY_CODE(proCon.getSupervisoryCode());
            esEquipmentDto.setUSE_UNIT_CREDIT_CODE(paramsDto.getCompanyCode());
            esEquipmentDto.setUSE_UNIT_NAME(paramsDto.getCompanyName());
            esEquipmentDto.setADDRESS(paramsDto.getAddress());
            esEquipmentDto.setUSE_PLACE(paramsDto.getProvinceName() + "/" + paramsDto.getCityName() + "/" + paramsDto.getCountyName() + "/" + paramsDto.getStreetName());
            esEquipmentDto.setUSE_PLACE_CODE(paramsDto.getProvince() + "#" + paramsDto.getCity() + "#" + paramsDto.getCounty() + "#" + paramsDto.getStreet());
            esEquipmentDto.setUSE_SITE_CODE(paramsDto.getUsePlace());
            esEquipmentDto.setOrgBranchCode(paramsDto.getOrgBranchCode());
            esEquipmentDto.setORG_BRANCH_NAME(paramsDto.getOrgBranchName());
            esEquipmentDto.setEQU_STATE(1);
            esEquipmentDto.setEQU_CODE(paramsDto.getEquCode());
            if (inspectionDetectionInfo.getNextInspectDate() != null) {
                esEquipmentDto.setNEXT_INSPECT_DATE(inspectionDetectionInfo.getNextInspectDate().getTime());
            }
            esEquipmentCategoryList.add(esEquipmentDto);
        }


        CompletableFuture<Void> useInfoFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgUseInfoMapper, useInfoList, "使用信息"));
        CompletableFuture<Void> designInfoFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgDesignInfoMapper, designInfoList, "设计信息"));
        CompletableFuture<Void> constructionFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgConstructionInfoMapper, constructionInfoList, "施工信息"));
        CompletableFuture<Void> factoryFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgFactoryInfoMapper, factoryInfoList, "制造信息"));
        CompletableFuture<Void> registerFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgRegisterInfoMapper, registerInfoList, "登记信息"));
        CompletableFuture<Void> otherFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgOtherInfoMapper, otherInfoList, "其他信息"));
        CompletableFuture<Void> supervisionFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgSupervisionInfoMapper, supervisionInfoList, "监管信息"));
        CompletableFuture<Void> paramsPipelineFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgTechParamsPipelineMapper, paramsPipelineList, "管道参数信息"));
        CompletableFuture<Void> inspectionFuture = CompletableFuture.runAsync(
                () -> idxBizJgRegisterInfoServiceImpl.batchInsert(idxBizJgInspectionDetectionInfoMapper, inspectionDetectionInfoList, "检验检测信息"));
        CompletableFuture<Void> esFuture = CompletableFuture.runAsync(() -> {
            if (!esEquipmentCategoryList.isEmpty()) {
                esEquipmentCategory.saveAll(esEquipmentCategoryList);
                log.info("ES批量保存完成，数量：{}", esEquipmentCategoryList.size());
            }
        });
        CompletableFuture.allOf(
                useInfoFuture, designInfoFuture, constructionFuture, factoryFuture,
                registerFuture, otherFuture, supervisionFuture, paramsPipelineFuture,
                inspectionFuture, esFuture
        ).join();
        log.info("所有批量操作完成");
        return recordList;
    }

    /**
     * 生成使用登记表信息 + 设备关系表 + 历史表
     *
     * @param paramsDto
     */
    public JgUseRegistration saveUseRegAndEq(EquipRequestParamsDto paramsDto, List<String> records, IdxBizJgProjectContraption proCon) {
        ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.SYDJ.getCode(), 1);
        String applyNo = listResponseModel.getResult().get(0);
        Long useRegseq = sequence.nextId();
        JgUseRegistration useReg = new JgUseRegistration()
                .setSupervisoryCode(proCon.getSupervisoryCode())
                .setUseUnitCreditCode(paramsDto.getCompanyCode())
                .setUseUnitName(paramsDto.getCompanyName())
                .setApplyNo(applyNo)
                .setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName())
                .setStatus(FlowStatusEnum.TO_BE_FINISHED.getName())
                .setReceiveOrgName(paramsDto.getReceiveOrgName())
                .setInspectUnitCreditCode(paramsDto.getInspectUnitCreditCode())
                .setInspectUnitName(paramsDto.getInspectUnitName())
                .setAuditPassDate(new Date()).setRegType("1").setRegDate(new Date())
                .setUseRegistrationCode(paramsDto.getUseOrgCode())
                .setReceiveOrgCode(paramsDto.getReceiveOrgCode())
                .setReceiveCompanyCode(paramsDto.getReceiveOrgCode())
                //.setReceiveCompanyOrgCode()
                //.setReceiveOrgName(paramsDto.getReceiveOrgName())
                .setUseAddress("")
                .setManageType("unit")
                .setCreateDate(new Date())
                .setCreateUserId(paramsDto.getExecUserId())
                .setCreateUserName(paramsDto.getExecUserName())
                .setProjectContraptionId(String.valueOf(proCon.getSequenceNbr()))
                .setProjectContraption(paramsDto.getProjectContraption())
                .setSupervisionOrgCode(paramsDto.getOrgBranchCode())
                .setRegDate(new Date());
        useReg.setSequenceNbr(useRegseq);
        jgUseRegistrationServiceImpl.save(useReg);

        records.forEach(record -> {
            JgUseRegistrationEq useRegEq = new JgUseRegistrationEq();
            useRegEq.setEquipTransferId(String.valueOf(useReg.getSequenceNbr()));
            useRegEq.setRecDate(new Date());
            useRegEq.setEquId(record);
            useRegEq.setRecUserId(paramsDto.getExecUserId());
            useRegEq.setRecUserName(paramsDto.getExecUserName());
            jgUseRegistrationEqServiceImpl.save(useRegEq);
        });
        JSONObject changeData = getJgUseRegistrationChangeData(paramsDto, records, applyNo);
        JgRegistrationHistory registrationHistory = JgRegistrationHistory.builder()
                .registrationClass("使用登记")
                .changeData(toJSONString(changeData))
                .status("history")
                .currentDocumentId(String.valueOf(useRegseq))
                .build();
        registrationHistory.setRecDate(new Date());
        registrationHistory.setCreateDate(new Date());
        registrationHistory.setRecUserId(paramsDto.getExecUserId());
        registrationHistory.setCreateUserId(paramsDto.getExecUserId());
        registrationHistory.setRecUserName(paramsDto.getExecUserName());
        jgRegistrationHistoryService.save(registrationHistory);
        String routePath = this.buildTaskModel(useReg, paramsDto);
        jgResumeInfoService.createWithModel(JgResumeInfoDto.builder()
                .applyNo(useReg.getApplyNo())
                .businessType(BusinessTypeEnum.JG_HISTORY_USAGE_REGISTRATION.getName())
                .businessId(useReg.getSequenceNbr() + "")
                .equId(useReg.getProjectContraptionId())
                .approvalUnit(useReg.getReceiveOrgName())
                .approvalUnitCode(useReg.getReceiveOrgCode())
                .status("正常")
                .routePath(routePath)
                .changeContent(BusinessTypeEnum.JG_HISTORY_USAGE_REGISTRATION.getName() + "业务办理")
                .build());
        return useReg;
    }

    public String buildTaskModel(JgUseRegistration jgUseRegistration, EquipRequestParamsDto paramsDto) {
        TaskModelDto modelDto = new TaskModelDto();
        modelDto.setNextExecuteUser(jgUseRegistration.getNextExecuteUserIds());
        modelDto.setPageType("look");
        modelDto.setStartUserId(RequestContext.getExeUserId());
        modelDto.setStartDate(new Date());

        TaskMessageDto taskMessageDto = new TaskMessageDto();
        BeanUtil.copyProperties(jgUseRegistration, taskMessageDto);
        taskMessageDto.setRegType("历史登记");
        taskMessageDto.setEQU_LIST_CODE(paramsDto.getEquCategoryCode());
        taskMessageDto.setAuditStatus(null);
        taskMessageDto.setEquipId((jgUseRegistration.getProjectContraptionId()));
        modelDto.setModel(taskMessageDto);

        // 获取URL配置并匹配对应业务类型和pageType
        List<Map> urlList = JsonUtils.getResourceList(urlInfo);
        if (CollectionUtils.isEmpty(urlList)) {
            throw new IllegalStateException("URL配置未初始化");
        }

        final String targetType = BusinessTypeEnum.JG_USAGE_REGISTRATION.getCode();
        final String targetPageType = modelDto.getPageType();

        for (Map urlMap : urlList) {
            Object type = urlMap.get("type");
            Object pageType = urlMap.get("pageType");
            if (Objects.equals(type, targetType) && Objects.equals(pageType, targetPageType)) {
                String baseUrl = String.valueOf(urlMap.get("url"));
                try {
                    String queryParams = commonService.toQueryParams(modelDto.getModel());
                    String roleIds = Optional.ofNullable(modelDto.getNextExecuteUser()).orElse("");
                    return baseUrl.replace("{roleIds}", roleIds)
                            .replace("{userId}", taskMessageDto.getCreateUserId())
                            + "&" + queryParams
                            + "&nextExecuteUserIds=" + Optional.ofNullable(modelDto.getExecuteUserIds()).orElse("");
                } catch (UnsupportedEncodingException e) {
                    // 建议记录日志，便于排查问题
                    log.error("URL参数编码失败", e);
                    throw new IllegalStateException("构建任务模型URL失败", e);
                }
            }
        }

        throw new IllegalStateException("未找到匹配的URL配置项，type=" + targetType + ", pageType=" + targetPageType);
    }

    private JSONObject getJgUseRegistrationChangeData(EquipRequestParamsDto paramsDto, List<String> records, String spplyNo) {
        String record = Optional.ofNullable(records.get(0)).orElse("");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("receiveOrgCode", paramsDto.getReceiveOrgCode() + "_" + paramsDto.getReceiveOrgName());
        jsonObject.put("status", FlowStatusEnum.TO_BE_FINISHED.getName());
        jsonObject.put("applyNo", spplyNo);
        jsonObject.remove("submit");
        jsonObject.remove("instanceId");
        if (!ObjectUtils.isEmpty(jsonObject.get("factoryUseSiteStreet"))) {
            jsonObject.put("factoryUseSiteStreet", String.valueOf(Long.valueOf(jsonObject.get("factoryUseSiteStreet").toString())));
        }
        IdxBizJgProjectContraption projectContraption = idxBizJgProjectContraptionService.getById(paramsDto.getProjectContraptionSeq());
        jsonObject.put("pipelineLength", projectContraption.getPipelineLength());
        jsonObject.put("useUnitCreditCode", paramsDto.getCompanyCode());
        jsonObject.put("useUnitName", paramsDto.getCompanyName());
        IdxBizJgConstructionInfo constructionInfo = idxBizJgConstructionInfoService.lambdaQuery().eq(IdxBizJgConstructionInfo::getRecord, record).orderByDesc(IdxBizJgConstructionInfo::getRecDate).one();
        jsonObject.put("uscUnitCreditCode", constructionInfo.getUscUnitCreditCode());
        jsonObject.put("uscUnitName", constructionInfo.getUscUnitName());
        IdxBizJgInspectionDetectionInfo inspectionDetectionInfo = idxBizJgInspectionDetectionInfoService.lambdaQuery().eq(IdxBizJgInspectionDetectionInfo::getRecord, record).orderByDesc(IdxBizJgInspectionDetectionInfo::getRecDate).one();
        JSONObject inspectionDetectionInfoJO = (JSONObject) JSON.toJSON(inspectionDetectionInfo);
        jsonObject.putAll(inspectionDetectionInfoJO);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        jsonObject.put("inspectDate", Optional.ofNullable(inspectionDetectionInfo.getInspectDate())
                .map(sdf::format)
                .orElse(null));
        jsonObject.put("nextInspectDate", Optional.ofNullable(inspectionDetectionInfo.getNextInspectDate())
                .map(sdf::format)
                .orElse(null));
        jsonObject.put("orgBranchCode", paramsDto.getOrgBranchCode() + "_" + paramsDto.getOrgBranchName());
        jsonObject.put("projectContraption", projectContraption.getProjectContraption());
        jsonObject.put("projectContraptionNo", projectContraption.getProjectContraptionNo());
        jsonObject.put("equipmentLists", jgUseRegistrationServiceImpl.getBaseMapper().queryForUnitPipelineEquipment(records));
        jsonObject.put("useRegistrationCode", paramsDto.getUseOrgCode());
        // 转化 附件 字段
        this.convertStringToJsonObject(jsonObject, JgUseRegistrationServiceImpl.jsonFields);
        return jsonObject;
    }

    /**
     * 生成使用登记证管理表信息
     *
     * @param paramsDto
     */
    public JgUseRegistrationManage saveUseRegManage(EquipRequestParamsDto paramsDto, JgUseRegistration useReg) {
        Map<String, String> equType = new HashMap<>();
        equType.put("equListCode", paramsDto.getEquCategoryCode());
        equType.put("equCategoryCode", paramsDto.getEquDefineCode());
        JgUseRegistrationManage registrationManage = JgUseRegistrationManage.builder()
                .equListCode(paramsDto.getEquListCode())
                .equList(paramsDto.getEquListName())
                .equCategoryCode(paramsDto.getEquCategoryCode())
                .equCategory(paramsDto.getEquCategoryName())
                .equDefineCode(paramsDto.getEquDefineCode())
                .equDefine(paramsDto.getEquDefineName())
                .useUnitName(paramsDto.getCompanyName())
                .useUnitCreditCode(paramsDto.getCompanyCode())
                .applyNo(useReg.getApplyNo())
                .receiveCompanyCode(paramsDto.getReceiveOrgCode())
                .receiveOrgName(paramsDto.getReceiveOrgName())
                .auditPassDate(new Date())
                .useRegistrationCode(paramsDto.getUseOrgCode())
                .certificateNo(commonService.generateCertificateNo(equType, new Date(), paramsDto.getReceiveOrgCode()))
                .regType(BusinessTypeEnum.JG_HISTORY_USAGE_REGISTRATION.getName())
                .certificateStatus("已登记")
                .regDate(new Date())
                // .equUseAddress()
                .createDate(new Date())
                .createUserId(paramsDto.getExecUserId())
                .useUnitAddress(paramsDto.getCompanyAddress())
                .manageType("unit")
                .isScrap("0")
                .version(1)
                .superviseOrgCode(paramsDto.getOrgBranchCode())
                .superviseOrgName(paramsDto.getOrgBranchName())
                .build();
        jgUseRegistrationManageService.save(registrationManage);
        return registrationManage;
    }

    /**
     * 生成工程装置表信息
     *
     * @param paramsDto
     */
    public IdxBizJgProjectContraption saveProjectContraption(EquipRequestParamsDto paramsDto) {
        Long seq = sequence.nextId();
        IdxBizJgProjectContraption contraption = IdxBizJgProjectContraption.builder()
                .projectContraption(paramsDto.getProjectContraption())
                .projectContraptionNo(paramsDto.getProjectContraptionNo())
                .useUnitCreditCode(paramsDto.getCompanyCode())
                .useUnitName(paramsDto.getCompanyName())
                // .uscUnitCreditCode().uscUnitName()
                .equList(paramsDto.getEquListCode())
                .equListName(paramsDto.getEquListName())
                .equCategory(paramsDto.getEquCategoryCode())
                .equCategoryName(paramsDto.getEquCategoryName())
                .equDefine(paramsDto.getEquDefineCode())
                .equDefineName(paramsDto.getEquDefineName())
                .pipelineLength(paramsDto.getPipelineLength())
                .productPhoto(paramsDto.getProductPhoto())
                .useRegistrationCode(paramsDto.getUseOrgCode())
                .otherAccessories(paramsDto.getOtherAccessories())
                .orgCode(paramsDto.getOrgBranchCode())
                .orgName(paramsDto.getOrgBranchName())
                .useDate(paramsDto.getUseDate())
                .productQualificationCertificate(paramsDto.getProductQualificationCertificate())
                .province(paramsDto.getProvince()).provinceName(paramsDto.getProvinceName()).city(paramsDto.getCity()).cityName(paramsDto.getCityName())
                .county(paramsDto.getCounty()).countyName(paramsDto.getCountyName()).street(paramsDto.getStreet()).streetName(paramsDto.getStreetName())
                .address(paramsDto.getAddress())
                .startLatitudeLongitude(paramsDto.getStartLatitudeLongitude())
                .endLatitudeLongitude(paramsDto.getEndLatitudeLongitude())
                .supervisoryCode(idxBizJgRegisterInfoServiceImpl.getSupervisoryCode(paramsDto.getVehicleApanage(), paramsDto.getEquCategoryCode())).isIntoManagement(Boolean.TRUE).dataSource(paramsDto.getDataSource()).equCode(paramsDto.getEquCode()).isFirstMerge(Boolean.FALSE).build();
        contraption.setSequenceNbr(seq);
        contraption.setCreateDate(new Date());
        contraption.setDataQualityScore(StringUtils.isEmpty(paramsDto.getUseOrgCode()) ? "3" : "1");
        paramsDto.setProjectContraptionSeq(String.valueOf(seq));
        idxBizJgProjectContraptionService.save(contraption);
        return contraption;
    }

    public void convertStringToJsonObject(Object obj, String[] jsonFields) {
        if (obj instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) obj;
            for (String field : jsonFields) {
                if (jsonObject.get(field) != null && jsonObject.get(field) instanceof String) {
                    jsonObject.put(field, JSON.parse(toJSONString(jsonObject.get(field))));
                }
            }
        } else if (obj instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) obj;
            for (String field : jsonFields) {
                if (map.containsKey(field) && map.get(field) instanceof String) {
                    map.put(field, JSON.parse(toJSONString(map.get(field))));
                }
            }
        } else {
            // 处理其他类型
            System.out.println("Unsupported Object Type");
        }
    }

    /**
     * 西安电梯历史设备以及业务数据批量导入
     *
     * @param equLists 数据集
     * @return 保存结果
     */
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public boolean saveElevatorData(List<Map<String, Object>> equLists) {
        String appKey = RequestContext.getAppKey();
        String product = RequestContext.getProduct();
        String token = RequestContext.getToken();
        String exeUserId = RequestContext.getExeUserId();
        Set<String> recordSet = new HashSet<>();
        CompletableFuture.allOf(
                equLists.parallelStream().map(equ -> CompletableFuture.runAsync(() -> {
                    RequestContext.setAppKey(appKey);
                    RequestContext.setProduct(product);
                    RequestContext.setToken(token);
                    RequestContext.setExeUserId(exeUserId);
                    String record = saveElevatorDataInTransaction(equ, "jg_his_xa", null);
                    recordSet.add(record);
                })).toArray(CompletableFuture[]::new)
        ).join();
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                eventPublisher.publish(new EquipCreateOrEditEvent(this, BusinessTypeEnum.JG_NEW_EQUIP.name(), recordSet, EquipCreateOrEditEvent.EquipType.equip));
            }
        });
        return Boolean.TRUE;
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    public String saveElevatorDataInTransaction(Map<String, Object> equ, String dataSource, String remark) {
        String record = Optional.ofNullable(equ.get("record")).map(String::valueOf).orElse(UUID.randomUUID().toString());
        String equList = Optional.ofNullable(equ.get("equList")).map(String::valueOf).orElse("");
        String businessId = Optional.ofNullable(equ.get("businessId")).map(String::valueOf).orElse("");
        String isCompleteXa = Optional.ofNullable(equ.get("isCompleteXa")).map(String::valueOf).orElse("");
        String useRegistrationCode = Optional.ofNullable(equ.get("useOrgCode")).map(String::valueOf).orElse("").trim();
        try {
            if (!equList.isEmpty()) {
                saveUseInfo(equ, record, dataSource, remark, null);
                saveDesignInfo(equ, record);
                saveFactoryInfo(equ, record);
                saveRegisterInfo(equ, record, equList);
                saveSupervisionInfo(equ, record);
                saveOtherInfo(equ, record, equList);
                saveInspectInfo(equ, record);
                saveTechParams(equ, record, equList);
                saveEquInfoToEs(record, isCompleteXa);
                this.saveInstallInfo(equ);//安装信息
                this.historyEquUpdateMaintenanceInfo(equ);//维保信息
                if (!useRegistrationCode.isEmpty()){
                    this.handleHistoryEquip(equ);//历史登记
                }
            } else if (!businessId.isEmpty()){
                this.saveResumeInfo(equ);
                equ.put("record", equ.get("resumeSeq"));
                equ.put("xaSerial", equ.get("resumeSeq"));
            }else{
                String orgBranchName = (String) Optional.ofNullable(equ.get("supervisionOffice"))
                        .orElseGet(() -> equ.get("supervisionDepartment"));
                String orgBranchCode = (String) Optional.ofNullable(equ.get("supervisionOfficeCode"))
                        .orElseGet(() -> equ.get("supervisionDepartmentCode"));
                this.updateOrgBranchInfo(record, orgBranchName, orgBranchCode);
            }
            return record;
        } catch (Exception e) {
//            esEquipmentCategory.deleteById(record);
//            superviseInfoMapper.deleteDataAll(Collections.singletonList(record));
            ExcelImportErrorLogDto errorLogDto = JSON.parseObject(toJSONString(equ), ExcelImportErrorLogDto.class);
            errorLogDto.setErrorInfo(e.getMessage());
            excelImportErrorLogDao.save(errorLogDto);
            log.error("{}数据：保存时出现异常，对应数据：{}", dataSource, toJSONString(equ), e);
            log.error("==========================西安电梯数据：保存时出现异常，对应数据：{}==========================",record);
            throw new RuntimeException("保存电梯数据失败", e);
        }
    }

    @GlobalTransactional(rollbackFor = Exception.class)
    public void updateOrgBranchInfo(String record, String orgBranchName, String orgBranchCode) {
        this.updateSupervisionInfo(record, orgBranchName, orgBranchCode);
        this.updateEsOrgBranch(record, orgBranchName, orgBranchCode);
        this.updateUseRegistrationInfo(record, orgBranchName, orgBranchCode);
    }

    private void updateUseRegistrationInfo(String record, String orgBranchName, String orgBranchCode) {
        Optional.ofNullable(
                        idxBizJgRegisterInfoMapper.selectOne(
                                new QueryWrapper<IdxBizJgRegisterInfo>()
                                        .lambda()
                                        .eq(IdxBizJgRegisterInfo::getRecord, record)
                        ))
                .map(IdxBizJgRegisterInfo::getUseOrgCode)
                .ifPresent(useOrgCode -> jgUseRegistrationManageService.update(
                        new LambdaUpdateWrapper<JgUseRegistrationManage>()
                                .set(JgUseRegistrationManage::getSuperviseOrgCode, orgBranchCode)
                                .set(JgUseRegistrationManage::getSuperviseOrgName, orgBranchName)
                                .eq(JgUseRegistrationManage::getUseRegistrationCode, useOrgCode)
                                .eq(JgUseRegistrationManage::getIsDoBusiness, 0)
                ));
        Optional.ofNullable(
                        jgRelationEquipMapper.selectOne(
                                new QueryWrapper<JgUseRegistrationEq>()
                                        .lambda()
                                        .eq(JgUseRegistrationEq::getEquId, record)
                                        .eq(JgUseRegistrationEq::getIsDelete, false)
                        ))
                .map(JgUseRegistrationEq::getEquipTransferId)
                .ifPresent(equipTransferId -> jgUseRegistrationServiceImpl.update(
                        new LambdaUpdateWrapper<JgUseRegistration>()
                                .set(JgUseRegistration::getSupervisionOrgCode, orgBranchCode)
                                .eq(JgUseRegistration::getSequenceNbr, equipTransferId)
                ));
    }

    private void updateSupervisionInfo(String record, String orgBranchName, String orgBranchCode) {
        idxBizJgSupervisionInfoService.update(
                new IdxBizJgSupervisionInfo()
                        .setOrgBranchName(orgBranchName)
                        .setOrgBranchCode(orgBranchCode),
                new QueryWrapper<IdxBizJgSupervisionInfo>()
                        .lambda()
                        .eq(IdxBizJgSupervisionInfo::getRecord, record)
        );
    }

    private void saveResumeInfo(Map<String, Object> equ) {
        JgResumeInfoDto resumeInfoDto = JSON.parseObject(toJSONString(equ), JgResumeInfoDto.class);
        resumeInfoDto.setEquId(Objects.toString(equ.get("resumeSeq"), ""));
        resumeInfoDto.setStatus("正常");
        resumeInfoDto.setDataSource("1");
        resumeInfoDto.setApplyNo(Objects.toString(equ.get("businessId"), ""));
        jgResumeInfoService.createWithModel(resumeInfoDto);
    }

    /**
     * 历史设备登记-》更新维保信息
     */
    private void historyEquUpdateMaintenanceInfo(Map<String, Object> map) {
        IdxBizJgMaintenanceRecordInfo info = JSON.parseObject(toJSONString(map), IdxBizJgMaintenanceRecordInfo.class);
        info.setRecDate(new Date());
        info.setRecUserId(RequestContext.getExeUserId());
        try {
            info.setInformStart(ValidationUtil.isEmpty(map.get("informStart")) ? null : DateUtil.parse(String.valueOf(map.get("informStart"))));
            info.setInformEnd(ValidationUtil.isEmpty(map.get("informEnd")) ? null : DateUtil.parse(String.valueOf(map.get("informEnd"))));
        } catch (Exception exception) {
            exception.printStackTrace();
            log.info("date转化失败");
        }
        info.setRepairInform(ValidationUtil.isEmpty(map.get("maintenanceContract")) ? null : toJSONString(map.get("maintenanceContract")));
        idxBizJgMaintenanceRecordInfoService.save(info);
    }

    /**
     * 按台套新增历史设备
     *
     * @param map
     * @return
     */
    public void handleHistoryEquip(Map<String, Object> map) {
        ReginParams reginParams = JSONObject.parseObject(redisUtils.get(RedisKey.buildReginKey(RequestContext.getExeUserId(), RequestContext.getToken())).toString(), ReginParams.class);
        try {
            String useRegistrationCode = String.valueOf(map.get("useOrgCode")).trim();
            String equipId = String.valueOf(map.get("record"));
            Boolean used = commonService.useRegistrationCertificateAccountUnique(useRegistrationCode, equipId);
            if (used) {
                throw new BadRequest("使用登记证编号已存在！");
            }
            //使用登记证编号判断是否使用未来系统生成编号
            idxBizJgRegisterInfoService.checkUseRegistrationCode(useRegistrationCode, "set");
            JgUseRegistration jgUseRegistration = new JgUseRegistration();
            jgUseRegistration.setRegDate(new Date());

            if (map.containsKey("orgBranchCode")) {
                // 监察处置机构代码
                String[] splitOrgBranchCode = String.valueOf(map.get("orgBranchCode")).split("_");
                jgUseRegistration.setSupervisionOrgCode(splitOrgBranchCode[0]);
            }
            // 安全管理员
            if (map.containsKey("safetyManager")) {
                map.put("safetyManagerName", map.get("safetyManager"));
            }
            // 使用单位提交
            jgUseRegistration.setUseUnitName((String) map.get("useUnit"));
            jgUseRegistration.setUseUnitCreditCode((String) map.get("useUnitCode"));
            jgUseRegistration.setCreateUserId(reginParams.getUserModel().getUserId());
            jgUseRegistration.setCreateUserName(reginParams.getUserModel().getUserName());
            if (!ObjectUtils.isEmpty(map.get("inspectOrgCode"))) {
                jgUseRegistration.setInspectUnitCreditCode(map.get("inspectOrgCode").toString());
            }
            if (!ObjectUtils.isEmpty(map.get("inspectOrgName"))) {
                jgUseRegistration.setInspectUnitName(map.get("inspectOrgName").toString());
            }
            jgUseRegistration.setUseAddress(
                    Stream.of("provinceName", "cityName", "countyName", "factoryUseSiteStreet", "address")
                            .map(key -> Objects.toString(map.get(key), ""))
                            .collect(Collectors.joining())
            );

            // 业务管理设备信息保存
            JgUseRegistrationEq jgRelationEquip = new JgUseRegistrationEq();
            jgRelationEquip.setEquId(map.get("record").toString());
            ResponseModel<List<String>> listResponseModel = tzsServiceFeignClient.applicationFormCode(ApplicationFormTypeEnum.SYDJ.getCode(), 1);
            if (!ObjectUtils.isEmpty(listResponseModel)) {
                jgUseRegistration.setApplyNo(listResponseModel.getResult().get(0));
            }
            jgUseRegistration.setAuditPassDate(new Date());
            jgUseRegistration.setCreateDate(new Date());
            jgUseRegistration.setManageType("set");
            jgUseRegistration.setIsXixian("0");
            jgUseRegistration.setAuditStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgUseRegistration.setStatus(FlowStatusEnum.TO_BE_FINISHED.getName());
            jgUseRegistration.setUseRegistrationCode(ValidationUtil.isEmpty(map.get("useOrgCode")) ? "" : String.valueOf(map.get("useOrgCode")));
            jgUseRegistration.setRegType("1");

            // 生成监管码 96333码
            LambdaQueryWrapper<IdxBizJgOtherInfo> otherLambda = new QueryWrapper<IdxBizJgOtherInfo>().lambda();
            otherLambda.eq(IdxBizJgOtherInfo::getRecord, map.get("record"));
            IdxBizJgOtherInfo otherInfo = otherInfoMapper.selectOne(otherLambda);
            this.createCode(map, jgUseRegistration, otherInfo);

            // 注册信息
            LambdaQueryWrapper<IdxBizJgRegisterInfo> lambdaReg = new QueryWrapper<IdxBizJgRegisterInfo>().lambda();
            lambdaReg.eq(IdxBizJgRegisterInfo::getRecord, equipId);
            IdxBizJgRegisterInfo registerInfo = idxBizJgRegisterInfoMapper.selectOne(lambdaReg);
            registerInfo.setUseOrgCode(jgUseRegistration.getUseRegistrationCode());
            registerInfo.setEquCodeType("2");
            String equCode = this.getEquCode(map);
            registerInfo.setEquCode(equCode);
            registerInfo.setInstallationIsComplete("2");
            idxBizJgRegisterInfoMapper.updateById(registerInfo);
            map.put("equCode", equCode);

            // 更新es
            this.updateEsData2(map, otherInfo);
            jgUseRegistrationServiceImpl.save(jgUseRegistration);
            jgRelationEquip.setEquipTransferId(jgUseRegistration.getSequenceNbr() + "");
            jgRelationEquipMapper.insert(jgRelationEquip);
            // 暂存历史表
            updateHistory(map, map.get("record").toString(), String.valueOf(jgUseRegistration.getSequenceNbr()), jgUseRegistration.getSupervisoryCode());
            // 历史设备
            this.historyEquGenManageRelated(map, jgUseRegistration);
        } catch (BadRequest | LocalBadRequest e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw e;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            this.rollBackForDelRedisData();
            throw new BadRequest(e.getMessage());
        } finally {
            FlowingEquipRedisContext.clean();
        }
    }

    private void historyEquGenManageRelated(Map<String, Object> map, JgUseRegistration jgUseRegistration) {
        // 生成证书管理表记录
        generateRegistrationManage(jgUseRegistration, map);
        // 使用登记证变更记录 -> 使用登记记录
        long jgUseRegSeq = sequence.nextId();
        generateCertificateChangeRecord(jgUseRegistration, map, jgUseRegSeq);
        // 使用登记证变更记录 -> 使用登记记录 ——> 生成tzs_jg_certificate_change_record_eq记录
        JgCertificateChangeRecordEq changeRecordEq = new JgCertificateChangeRecordEq();
        changeRecordEq.setChangeRecordId(String.valueOf(jgUseRegSeq));//登记证记录主键
        changeRecordEq.setEquId(String.valueOf(map.get("record")));//设备主键
        changeRecordEq.setProductCode(String.valueOf(map.get("factoryNum")));
        certificateChangeRecordEqService.save(changeRecordEq);
    }

    /**
     * 生成使用登记证变更记录
     *
     * @param jgUseRegistration
     * @param changeRecordId
     */
    private void generateCertificateChangeRecord(JgUseRegistration jgUseRegistration, Map<String, Object> map,
                                                 Long changeRecordId) {
        JgCertificateChangeRecord changeRecord = new JgCertificateChangeRecord();
        changeRecord.setApplyNo(jgUseRegistration.getApplyNo());
        changeRecord.setReceiveOrgName(jgUseRegistration.getReceiveOrgName());
        changeRecord.setAuditPassDate(new Date());
        changeRecord.setRegType(BusinessTypeEnum.JG_USAGE_REGISTRATION.getName());
        changeRecord.setRegDate(jgUseRegistration.getCreateDate());
        changeRecord.setChangeContent(this.buildRecordContent(jgUseRegistration));//变更内容
        changeRecord.setUseRegistrationCode(jgUseRegistration.getUseRegistrationCode());//使用登记编号
        changeRecord.setReceiveCompanyCode(jgUseRegistration.getReceiveCompanyOrgCode());//接收机构公司代码
        // 流水表不需要再次生成唯一编号，使用证管理表对应值
        if (!ObjectUtils.isEmpty(jgUseRegistration.getUseRegistrationCode())) {
            JgUseRegistrationManage manage = jgUseRegistrationManageService.lambdaQuery()
                    .eq(JgUseRegistrationManage::getUseRegistrationCode, jgUseRegistration.getUseRegistrationCode())
                    .eq(JgUseRegistrationManage::getIsDelete, 0)
                    .eq(JgUseRegistrationManage::getCertificateStatus, CertificateStatusEnum.YIDENGJI.getName()).one();
            changeRecord.setCertificateNo(manage.getCertificateNo());//登记证书唯一码
        }
        changeRecord.setUseUnitCreditCode(jgUseRegistration.getUseUnitCreditCode());//使用单位统一信用代码
        changeRecord.setUseUnitName(jgUseRegistration.getUseUnitName());//使用单位名称
        changeRecord.setEquCategory(Objects.toString(map.get("equCategory")));//设备类别编码
        changeRecord.setCreateDate(new Date());
        changeRecord.setRoutePath("");
        changeRecord.setSequenceNbr(changeRecordId);
        certificateChangeRecordService.save(changeRecord);
    }

        /**
         * 生成登记证数据
         *
         * @param jgUseRegistration 使用登记单
         */
    private void generateRegistrationManage(JgUseRegistration jgUseRegistration, Map<String, Object> map) {
        Map<String, String> equType = Stream.of(
                new AbstractMap.SimpleEntry<>("equList", "equListName"),
                new AbstractMap.SimpleEntry<>("equCategory", "equCategoryName"),
                new AbstractMap.SimpleEntry<>("equDefine", "equDefineName")
        ).collect(Collectors.toMap(
                Map.Entry::getValue,
                entry -> jgVehicleInformationMapper.getEquCategoryNameByCode(Objects.toString(map.get(entry.getKey())))
        ));
        JgUseRegistrationManage manage = new JgUseRegistrationManage();
        // 设置基本信息
        manage.setUseUnitName(jgUseRegistration.getUseUnitName());
        manage.setApplyNo(jgUseRegistration.getApplyNo());
        manage.setCertificateStatus(CertificateStatusEnum.YIDENGJI.getName());
        manage.setReceiveOrgName(jgUseRegistration.getReceiveOrgName());
        manage.setAuditPassDate(jgUseRegistration.getAuditPassDate());
        manage.setRegType(BusinessTypeEnum.JG_USAGE_REGISTRATION.getName());
        manage.setRegDate(jgUseRegistration.getRegDate());
        manage.setEquList(equType.get("equListName"));
        manage.setEquListCode(Objects.toString(map.get("equList")));
        manage.setEquCategory(equType.get("equCategoryName"));
        manage.setEquCategoryCode(Objects.toString(map.get("equCategory")));
        manage.setEquDefine(equType.get("equDefineName"));
        manage.setEquDefineCode(Objects.toString(map.get("equDefine")));

        manage.setIsDelete(Boolean.FALSE);
        manage.setRecUserId(jgUseRegistration.getRecUserId());
        manage.setRecUserName(jgUseRegistration.getRecUserName());
        manage.setRecDate(jgUseRegistration.getRecDate());
        manage.setCreateUserId(jgUseRegistration.getCreateUserId());
        manage.setCreateDate(jgUseRegistration.getRecDate());
        manage.setEquUseAddress(jgUseRegistration.getUseAddress());
        manage.setUseUnitAddress(jgUseRegistration.getUseAddress());
        manage.setUseRegistrationCode(jgUseRegistration.getUseRegistrationCode());
        manage.setUseUnitCreditCode(jgUseRegistration.getUseUnitCreditCode());
        manage.setReceiveCompanyCode(jgUseRegistration.getReceiveCompanyCode());
        manage.setManageType(jgUseRegistration.getManageType());
        manage.setIsDoBusiness("0"); // 不可做业务
        // 生成证书编号
        equType.put("equDefineCode",Objects.toString(map.get("equDefine")));
        manage.setCertificateNo(commonService.generateCertificateNo(equType, new Date(), (String) map.get("county")));
        // 设置监管机构信息
        this.setSuperviseOrgInfo(manage, jgUseRegistration);
        jgUseRegistrationManageService.save(manage);
    }

    private void setSuperviseOrgInfo(JgUseRegistrationManage jgUseRegistrationManage, JgUseRegistration jgUseRegistration) {
        jgUseRegistrationManage.setSuperviseOrgCode(jgUseRegistration.getSupervisionOrgCode());
        jgUseRegistrationManage.setSuperviseOrgName(commonMapper.getCompanyNameByOrgCode(jgUseRegistration.getSupervisionOrgCode()));
    }

    public String getEquCode(Map<String, Object> dataMap) {
        ProduceInfo produceInfo = produceInfoMapper.selectOne(new LambdaQueryWrapper<ProduceInfo>().eq(AbstractEquipBaseEntity::getRecord, dataMap.get("record")));
        CodeGenerateDto codeGenerateDto = new CodeGenerateDto();
        codeGenerateDto.setEquList((String) dataMap.get("equList"));
        codeGenerateDto.setEquCategory((String) dataMap.get("equCategory"));
        codeGenerateDto.setEquDefine((String) dataMap.get("equDefine"));
        codeGenerateDto.setProduceDate(produceInfo.getProduceDate());
        codeGenerateDto.setReceiveCompanyCode((String) dataMap.get("county"));
        return codeUtil.generateEquipmentCode(codeGenerateDto);
    }

    public void updateEsData2(Map<String, Object> dataMap, IdxBizJgOtherInfo otherInfo) {
        HashMap<String, Map<String, Object>> objMap = new HashMap<>();
        HashMap<String, Object> param = new HashMap<>();
        param.put("SUPERVISORY_CODE", otherInfo.getSupervisoryCode());
        param.put("CODE96333", otherInfo.getCode96333());
        param.put("EQU_STATE", 1);
        param.put("IS_INTO_MANAGEMENT", true);
        param.put("EQU_CODE", dataMap.get("equCode"));
        objMap.put((String) dataMap.get("record"), param);
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

    public void updateEsOrgBranch(String record, String orgBranchName, String orgBranchCode) {
        HashMap<String, Map<String, Object>> objMap = new HashMap<>();
        HashMap<String, Object> param = new HashMap<>();
        param.put("ORG_BRANCH_CODE", orgBranchCode);
        param.put("ORG_BRANCH_NAME", orgBranchName);
        objMap.put(record, param);
        tzsServiceFeignClient.commonUpdateEsDataByIds(objMap);
    }

    private void rollBackForDelRedisData() {
        FlowingEquipRedisContext.getContext().forEach(e -> EquipUsedCheckStrategyContext.getUsedStrategy(DEFINITION_KEY).delDataForCheckWithKey(e.getData(), e.getRedisKey()));
    }

    /**
     * 生成监管码、96333码
     */
    public void createCode(Map<String, Object> dataMap, JgUseRegistration jgUseRegistration, IdxBizJgOtherInfo otherInfo) {
        // 生成监管码、96333码
        Map<String, Object> map = new HashMap<>();
        map.put("cityCode", dataMap.get("city"));
        map.put("countyCode", dataMap.get("county"));
        map.put("equCategory", dataMap.get("equCategory"));
        map.put("isXiXian", 0);
        //有96333码,不生成96333码，只生成监管码
        map.put("code96333", dataMap.get("code96333"));
        ResponseModel<Map<String, Object>> code = tzsServiceFeignClient.createCode(map);
        Map<String, Object> result = code.getResult();
        if (!ObjectUtils.isEmpty(result)) {
            otherInfo.setSupervisoryCode(String.valueOf(result.get("superviseCode")));
            // 历史登记时 96333如果自行输入则不再进行生成插入
            if (StringUtils.isEmpty(otherInfo.getCode96333())) {
                otherInfo.setCode96333(ObjectUtils.isEmpty(result.get("code96333")) ? null : String.valueOf(result.get("code96333")));
            }
            // 更新使用登记业务表
            jgUseRegistration.setSupervisoryCode(String.valueOf(result.get("superviseCode")));
        }
        otherInfo.setClaimStatus("已认领");
        otherInfoMapper.updateById(otherInfo);
    }

    public void updateHistory(Map<String, Object> map, String equipId, String currentDocumentId, String supervisoryCode) {
        JgRegistrationHistory jgRegistrationHistory = new JgRegistrationHistory();
        LambdaQueryWrapper<JgRegistrationHistory> lambda = new QueryWrapper<JgRegistrationHistory>().lambda();
        lambda.eq(JgRegistrationHistory::getCurrentDocumentId, currentDocumentId);
        lambda.eq(JgRegistrationHistory::getRegistrationClass, "使用登记");
        lambda.eq(JgRegistrationHistory::getIsDelete, false);
        Integer integer = jgRegistrationHistoryService.getBaseMapper().selectCount(lambda);
        if (integer > 0) {
            jgRegistrationHistory.setChangeData(toJSONString(map));
            jgRegistrationHistoryService.update(jgRegistrationHistory, lambda);
        } else {
            jgRegistrationHistory.setChangeData(toJSONString(map));
            jgRegistrationHistory.setStatus("new");
            jgRegistrationHistory.setRegistrationClass("使用登记");
            jgRegistrationHistory.setSupervisoryCode(supervisoryCode);
            jgRegistrationHistory.setEquId(equipId);
            jgRegistrationHistory.setCurrentDocumentId(currentDocumentId);
            jgRegistrationHistoryService.save(jgRegistrationHistory);
        }
    }

    private void saveInstallInfo(Map<String, Object> equ) {
        IdxBizJgConstructionInfo constructionInfo = JSON.parseObject(toJSONString(equ), IdxBizJgConstructionInfo.class);
        constructionInfo.setUscUnitName(ValidationUtil.isEmpty(equ.get("installUnitName")) ? null : String.valueOf(equ.get("installUnitName")));
        constructionInfo.setUscUnitCreditCode(ValidationUtil.isEmpty(equ.get("installUnitCreditCode")) ? null : String.valueOf(equ.get("installUnitCreditCode")));
        constructionInfo.setConstructionLeaderName(ValidationUtil.isEmpty(equ.get("installLeaderName")) ? null : String.valueOf(equ.get("installLeaderName")));
        constructionInfo.setConstructionLeaderPhone(ValidationUtil.isEmpty(equ.get("installLeaderPhone")) ? null : String.valueOf(equ.get("installLeaderPhone")));
        try {
            constructionInfo.setUscDate(ValidationUtil.isEmpty(equ.get("installStartDate")) ? null : DateUtils.dateParse((String) equ.get("installStartDate"), DateUtils.DATE_PATTERN));
        } catch (ParseException e) {
            log.error(e.getMessage(), e);
            throw new BadRequest("安装日期时间转化错误");
        }
     idxBizJgConstructionInfoService.getBaseMapper().insert(constructionInfo);
    }

    private void saveInspectInfo(Map<String, Object> equ, String record) {
        InspectionDetectionInfo inspectionDetectionInfo = new InspectionDetectionInfo();
        BeanUtil.copyProperties(equ, inspectionDetectionInfo);
        if (inspectionDetectionInfo.getInspectType() != null && inspectionDetectionInfo.getInspectConclusion() != null) {
            inspectionDetectionInfo.setRecord(record);
            inspectionDetectionInfo.setRecDate(new Date());
            inspectionDetectionInfo.setSequenceNbr(String.valueOf(sequence.nextId()));
            //inspectionDetectionInfo.setInspectType(InspectTypeConverter.dictMap.get(inspectionDetectionInfo.getInspectType()));
            //inspectionDetectionInfo.setInspectConclusion(InspectConclusionConverter.dictMap.get(inspectionDetectionInfo.getInspectConclusion()));
            inspectionDetectionInfoMapper.insert(inspectionDetectionInfo);
            equ.put("inspectType",inspectionDetectionInfo.getInspectType());
            equ.put("inspectConclusion",inspectionDetectionInfo.getInspectConclusion());
        }
    }

    public String updatePipingUseInfo() {
        LambdaQueryWrapper<IdxBizJgProjectContraption> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(IdxBizJgProjectContraption::getIsDelete, 0);
        queryWrapper.isNotNull(IdxBizJgProjectContraption::getProvince);
        List<IdxBizJgProjectContraption> idxBizJgProjectContraptions = idxBizJgProjectContraptionServiceImpl.getBaseMapper().selectList(queryWrapper);
        if (!ObjectUtils.isEmpty(idxBizJgProjectContraptions)) {
            List<Long> seqList = idxBizJgProjectContraptions.stream().map(e -> e.getSequenceNbr()).collect(Collectors.toList());
            LambdaQueryWrapper<IdxBizJgUseInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.in(IdxBizJgUseInfo::getProjectContraptionId, seqList);
            List<IdxBizJgUseInfo> useInfoList = idxBizJgUseInfoService.getBaseMapper().selectList(lambdaQueryWrapper);
            List<IdxBizJgUseInfo> newList = new ArrayList<>();
            if (!ObjectUtils.isEmpty(useInfoList)) {
                for (IdxBizJgUseInfo useInfo : useInfoList) {
                    List<IdxBizJgProjectContraption> collect = idxBizJgProjectContraptions.stream().filter(e -> useInfo.getProjectContraptionId().equals(e.getSequenceNbr().toString())).collect(Collectors.toList());
                    if (!ObjectUtils.isEmpty(collect)) {
                        IdxBizJgProjectContraption idxBizJgProjectContraption = collect.get(0);
                        useInfo.setProvince(idxBizJgProjectContraption.getProvince());
                        useInfo.setCity(idxBizJgProjectContraption.getCity());
                        useInfo.setCounty(idxBizJgProjectContraption.getCounty());
                        useInfo.setFactoryUseSiteStreet(idxBizJgProjectContraption.getStreet());
                        useInfo.setProvinceName(idxBizJgProjectContraption.getProvinceName());
                        useInfo.setCityName(idxBizJgProjectContraption.getCityName());
                        useInfo.setCountyName(idxBizJgProjectContraption.getCountyName());
                        useInfo.setStreetName(idxBizJgProjectContraption.getStreetName());
                        useInfo.setAddress(idxBizJgProjectContraption.getAddress());
                        newList.add(useInfo);
                    }
                }
            }
            idxBizJgUseInfoService.saveOrUpdateBatch(newList);
        }
        return "success";
    }
}
