Lius
2025-06-09 a79d1641ab162cf1e96d3af666d1e77abde68c1b
lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEfficiencyReportServiceImpl.java
@@ -1,27 +1,35 @@
package org.jeecg.modules.mdc.service.impl;
import com.alipay.api.domain.NewsfeedMediaGiftInfo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.commons.lang3.StringUtils;
import org.checkerframework.checker.units.qual.A;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.mdc.dto.*;
import org.jeecg.modules.mdc.entity.*;
import org.jeecg.modules.mdc.mapper.MdcEfficiencyReportMapper;
import org.jeecg.modules.mdc.service.*;
import org.jeecg.modules.mdc.util.CustomExcelView;
import org.jeecg.modules.mdc.util.DateUtils;
import org.jeecg.modules.mdc.vo.MdcUtilizationRateDto;
import org.jeecg.modules.mdc.vo.*;
import org.jeecg.modules.system.entity.MdcProduction;
import org.jeecg.modules.system.entity.SysDepart;
import org.jeecg.modules.system.service.IMdcProductionService;
import org.jeecg.modules.system.service.ISysDepartService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
@@ -56,6 +64,9 @@
    @Resource
    private IMdcEquipmentRunningSectionService mdcEquipmentRunningSectionService;
    @Resource
    private IMdcEquipmentStatisticalInfoService mdcEquipmentStatisticalInfoService;
    /**
     * 利用率报表
     *
@@ -67,172 +78,375 @@
    public MdcEfficiencyVo efficiencyList(String userId, MdcEfficiencyReportQueryVo vo) {
        MdcEfficiencyVo result = new MdcEfficiencyVo();
        List<MdcEfficiencyListDto> listDtos = new ArrayList<>();
        List<String> equipmentIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(vo.getParentId()) && StringUtils.isEmpty(vo.getEquipmentId())) {
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, vo.getParentId());
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, vo.getParentId());
            }
        } else if (StringUtils.isNotEmpty(vo.getEquipmentId())) {
            // 单台设备信息
            vo.setEquipmentIdList(Collections.singletonList(vo.getEquipmentId()));
        } else {
            // 查询用户拥有的所有设备信息
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, null);
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, null);
            }
        }
        // 获取设备 ID 列表
        List<String> equipmentIds = getEquipmentIds(userId, vo);
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            vo.setEquipmentIdList(equipmentIds);
        }
        // 获取日期列表
        List<String> dates = DateUtils.getDatesStringList2(DateUtils.getShortDate2(vo.getStartTime()), DateUtils.getShortDate2(vo.getEndTime()));
        result.setDates(dates);
        // 获取设备利用率列表
        List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("lyl");
        // 如果设备 ID 列表为空,直接返回
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            result.setMdcEfficiencyList(listDtos);
        } else {
            // 查询利用率数据
            List<MdcEfficiencyDto> efficiencyList = mdcEfficiencyReportMapper.efficiencyList(vo);
            // 利用率等级
            List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("lyl");
            // 封装结果
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
                // 查询所有部门信息
                List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>().ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString()));
                for (MdcEquDepDto mdcEquDepDto : equipmentList) {
                    MdcEfficiencyListDto mdcEfficiencyListDto = new MdcEfficiencyListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquDepDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquDepDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquDepDto.getEquipmentType());
                    switch (mdcEquDepDto.getOrgType()) {
                        case "1":
                            mdcEfficiencyListDto.setLevel1(mdcEquDepDto.getDepartName());
                            break;
                        case "2":
                            mdcEfficiencyListDto.setLevel2(mdcEquDepDto.getDepartName());
                            break;
                        case "3":
                            mdcEfficiencyListDto.setLevel3(mdcEquDepDto.getDepartName());
                            break;
                        default:
                    }
                    SysDepart sysDepart = departList.stream().filter(depart -> depart.getId().equals(mdcEquDepDto.getParentId())).findAny().orElse(null);
                    if (sysDepart != null) {
                        switch (sysDepart.getOrgType()) {
                            case "1":
                                mdcEfficiencyListDto.setLevel1(sysDepart.getDepartName());
                                break;
                            case "2":
                                mdcEfficiencyListDto.setLevel2(sysDepart.getDepartName());
                                break;
                            case "3":
                                mdcEfficiencyListDto.setLevel3(sysDepart.getDepartName());
                                break;
                            default:
                        }
                        if (StringUtils.isNotEmpty(sysDepart.getParentId())) {
                            departList.stream().filter(depart -> depart.getId().equals(sysDepart.getParentId())).findAny().ifPresent(depart1 -> {
                                switch (depart1.getOrgType()) {
                                    case "1":
                                        mdcEfficiencyListDto.setLevel1(depart1.getDepartName());
                                        break;
                                    case "2":
                                        mdcEfficiencyListDto.setLevel2(depart1.getDepartName());
                                        break;
                                    case "3":
                                        mdcEfficiencyListDto.setLevel3(depart1.getDepartName());
                                        break;
                                    default:
                                }
                            });
                        }
                    }
                    List<MdcEfficiencyResultDto> list = new ArrayList<>();
                    for (String date : dates) {
                        list.add(this.efficiencyRate(efficiencyList, date, mdcEquDepDto.getEquipmentId(), mdcUtilizationRateList));
                    }
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
            } else {
                // 产线层级
                List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
                // 查询所有产线信息
                List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>().ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString()));
                for (MdcEquProDto mdcEquProDto : equipmentList) {
                    MdcEfficiencyListDto mdcEfficiencyListDto = new MdcEfficiencyListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquProDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquProDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquProDto.getEquipmentType());
                    switch (mdcEquProDto.getOrgType()) {
                        case "1":
                            mdcEfficiencyListDto.setLevel1(mdcEquProDto.getProductionName());
                            break;
                        case "2":
                            mdcEfficiencyListDto.setLevel2(mdcEquProDto.getProductionName());
                            break;
                        case "3":
                            mdcEfficiencyListDto.setLevel3(mdcEquProDto.getProductionName());
                            break;
                        default:
                    }
                    MdcProduction mdcProduction = productionList.stream().filter(production -> production.getId().equals(mdcEquProDto.getParentId())).findAny().orElse(null);
                    if (mdcProduction != null) {
                        switch (mdcProduction.getOrgType()) {
                            case "1":
                                mdcEfficiencyListDto.setLevel1(mdcProduction.getProductionName());
                                break;
                            case "2":
                                mdcEfficiencyListDto.setLevel2(mdcProduction.getProductionName());
                                break;
                            case "3":
                                mdcEfficiencyListDto.setLevel3(mdcProduction.getProductionName());
                                break;
                            default:
                        }
                        if (StringUtils.isNotEmpty(mdcProduction.getParentId())) {
                            productionList.stream().filter(production -> production.getId().equals(mdcProduction.getParentId())).findAny().ifPresent(production1 -> {
                                switch (production1.getOrgType()) {
                                    case "1":
                                        mdcEfficiencyListDto.setLevel1(production1.getProductionName());
                                        break;
                                    case "2":
                                        mdcEfficiencyListDto.setLevel2(production1.getProductionName());
                                        break;
                                    case "3":
                                        mdcEfficiencyListDto.setLevel3(production1.getProductionName());
                                        break;
                                    default:
                                }
                            });
                        }
                    }
                    List<MdcEfficiencyResultDto> list = new ArrayList<>();
                    for (String date : dates) {
                        list.add(this.efficiencyRate(efficiencyList, date, mdcEquProDto.getEquipmentId(), mdcUtilizationRateList));
                    }
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
            }
            result.setMdcEfficiencyList(listDtos);
            return result;
        }
        // 获取设备 ID 列表
        List<String> equipmentIdList = mdcEquipmentService.listEquipmentId(vo);
        if (equipmentIdList == null || equipmentIdList.isEmpty()) {
            result.setMdcEfficiencyList(listDtos);
            return result;
        }
        vo.setEquipmentIdList(equipmentIdList);
        // 查询设备效率数据
        List<MdcEfficiencyDto> efficiencyList = mdcEfficiencyReportMapper.efficiencyList(vo);
        // 根据类型树处理不同的层级
        if ("2".equals(vo.getTypeTree())) {
            // 部门层级
            listDtos = processDepartmentLevel(vo, efficiencyList, dates, mdcUtilizationRateList);
        } else {
            // 产线层级
            listDtos = processProductionLevel(vo, efficiencyList, dates, mdcUtilizationRateList);
        }
        result.setMdcEfficiencyList(listDtos);
        // 添加合计值和平均值
        addSummaryAndAverage(result, listDtos, mdcUtilizationRateList);
        return result;
    }
    /**
     * 获取设备 ID 列表
     */
    private List<String> getEquipmentIds(String userId, MdcEfficiencyReportQueryVo vo) {
        if (StringUtils.isNotEmpty(vo.getParentId()) && StringUtils.isEmpty(vo.getEquipmentId())) {
            return "2".equals(vo.getTypeTree())
                    ? mdcEquipmentService.getEquipmentIdsByDepart(userId, vo.getParentId())
                    : mdcEquipmentService.getEquipmentIdsProduction(userId, vo.getParentId());
        } else if (StringUtils.isNotEmpty(vo.getEquipmentId())) {
            vo.setEquipmentIdList(Collections.singletonList(vo.getEquipmentId()));
            return Collections.emptyList();
        } else {
            return "2".equals(vo.getTypeTree())
                    ? mdcEquipmentService.getEquipmentIdsByDepart(userId, null)
                    : mdcEquipmentService.getEquipmentIdsProduction(userId, null);
        }
    }
    /**
     * 处理部门层级
     */
    private List<MdcEfficiencyListDto> processDepartmentLevel(MdcEfficiencyReportQueryVo vo, List<MdcEfficiencyDto> efficiencyList, List<String> dates, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
        List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>()
                .ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString())
                .orderByAsc(SysDepart::getDepartOrder));
        return equipmentList.stream().map(mdcEquDepDto -> {
            MdcEfficiencyListDto mdcEfficiencyListDto = createEfficiencyListDto(mdcEquDepDto);
            setDepartmentLevels(mdcEfficiencyListDto, mdcEquDepDto, departList);
            mdcEfficiencyListDto.setDataList(processEfficiencyData(efficiencyList, dates, mdcEquDepDto.getEquipmentId(), mdcUtilizationRateList));
            return mdcEfficiencyListDto;
        }).collect(Collectors.toList());
    }
    /**
     * 处理产线层级
     */
    private List<MdcEfficiencyListDto> processProductionLevel(MdcEfficiencyReportQueryVo vo, List<MdcEfficiencyDto> efficiencyList, List<String> dates, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
        List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>()
                .ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString())
                .orderByAsc(MdcProduction::getProductionOrder));
        return equipmentList.stream().map(mdcEquProDto -> {
            MdcEfficiencyListDto mdcEfficiencyListDto = createEfficiencyListDto(mdcEquProDto);
            setProductionLevels(mdcEfficiencyListDto, mdcEquProDto, productionList);
            mdcEfficiencyListDto.setDataList(processEfficiencyData(efficiencyList, dates, mdcEquProDto.getEquipmentId(), mdcUtilizationRateList));
            return mdcEfficiencyListDto;
        }).collect(Collectors.toList());
    }
    /**
     * 创建 MdcEfficiencyListDto 对象
     */
    private MdcEfficiencyListDto createEfficiencyListDto(MdcEquDepDto mdcEquDepDto) {
        MdcEfficiencyListDto dto = new MdcEfficiencyListDto();
        dto.setEquipmentId(mdcEquDepDto.getEquipmentId());
        dto.setEquipmentName(mdcEquDepDto.getEquipmentName());
        dto.setEquipmentType(mdcEquDepDto.getEquipmentType());
        dto.setEquipmentModel(mdcEquDepDto.getEquipmentModel());
        return dto;
    }
    private MdcEfficiencyListDto createEfficiencyListDto(MdcEquProDto mdcEquProDto) {
        MdcEfficiencyListDto dto = new MdcEfficiencyListDto();
        dto.setEquipmentId(mdcEquProDto.getEquipmentId());
        dto.setEquipmentName(mdcEquProDto.getEquipmentName());
        dto.setEquipmentType(mdcEquProDto.getEquipmentType());
        dto.setEquipmentModel(mdcEquProDto.getEquipmentModel());
        return dto;
    }
    /**
     * 设置部门层级信息
     */
    private void setDepartmentLevels(MdcEfficiencyListDto dto, MdcEquDepDto mdcEquDepDto, List<SysDepart> departList) {
        switch (mdcEquDepDto.getOrgType()) {
            case "1":
                dto.setLevel1(mdcEquDepDto.getDepartName());
                break;
            case "2":
                dto.setLevel2(mdcEquDepDto.getDepartName());
                break;
            case "3":
                dto.setLevel3(mdcEquDepDto.getDepartName());
                break;
        }
        Optional<SysDepart> sysDepart = departList.stream().filter(depart -> depart.getId().equals(mdcEquDepDto.getParentId())).findAny();
        sysDepart.ifPresent(depart -> {
            switch (depart.getOrgType()) {
                case "1":
                    dto.setLevel1(depart.getDepartName());
                    break;
                case "2":
                    dto.setLevel2(depart.getDepartName());
                    break;
                case "3":
                    dto.setLevel3(depart.getDepartName());
                    break;
            }
            if (StringUtils.isNotEmpty(depart.getParentId())) {
                departList.stream().filter(d -> d.getId().equals(depart.getParentId())).findAny().ifPresent(parent -> {
                    switch (parent.getOrgType()) {
                        case "1":
                            dto.setLevel1(parent.getDepartName());
                            break;
                        case "2":
                            dto.setLevel2(parent.getDepartName());
                            break;
                        case "3":
                            dto.setLevel3(parent.getDepartName());
                            break;
                    }
                });
            }
        });
    }
    /**
     * 设置部门层级信息
     */
    private void setProductionLevels(MdcEfficiencyListDto dto, MdcEquProDto mdcEquProDto, List<MdcProduction> productionList) {
        switch (mdcEquProDto.getOrgType()) {
            case "1":
                dto.setLevel1(mdcEquProDto.getProductionName());
                break;
            case "2":
                dto.setLevel2(mdcEquProDto.getProductionName());
                break;
            case "3":
                dto.setLevel3(mdcEquProDto.getProductionName());
                break;
        }
        Optional<MdcProduction> mdcProduction = productionList.stream().filter(production -> production.getId().equals(mdcEquProDto.getParentId())).findAny();
        mdcProduction.ifPresent(production -> {
            switch (production.getOrgType()) {
                case "1":
                    dto.setLevel1(production.getProductionName());
                    break;
                case "2":
                    dto.setLevel2(production.getProductionName());
                    break;
                case "3":
                    dto.setLevel3(production.getProductionName());
                    break;
            }
            if (StringUtils.isNotEmpty(production.getParentId())) {
                productionList.stream().filter(p -> p.getId().equals(production.getParentId())).findAny().ifPresent(parent -> {
                    switch (parent.getOrgType()) {
                        case "1":
                            dto.setLevel1(parent.getProductionName());
                            break;
                        case "2":
                            dto.setLevel2(parent.getProductionName());
                            break;
                        case "3":
                            dto.setLevel3(parent.getProductionName());
                            break;
                    }
                });
            }
        });
    }
    /**
     * 处理设备效率数据
     */
    private List<MdcEfficiencyResultDto> processEfficiencyData(List<MdcEfficiencyDto> efficiencyList, List<String> dates, String equipmentId, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyResultDto> list = new ArrayList<>();
        MdcEfficiencyResultDto avgDto = new MdcEfficiencyResultDto();
        avgDto.setTheDate("平均值");
        MdcEfficiencyResultDto sumDto = new MdcEfficiencyResultDto();
        sumDto.setTheDate("合计");
        for (String date : dates) {
            MdcEfficiencyResultDto dto = efficiencyRate(efficiencyList, date, equipmentId, mdcUtilizationRateList, avgDto);
            list.add(dto);
        }
        sumDto.setProcessLong(avgDto.getProcessLong());
        avgDto.setProcessLong(avgDto.getProcessLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
        avgDto.setUtilizationRate(avgDto.getUtilizationRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
        sumDto.setUtilizationRate(avgDto.getUtilizationRate());
        avgDto.setStartRate(avgDto.getStartRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
        sumDto.setStartRate(avgDto.getStartRate());
        avgDto.setOpenRate(avgDto.getOpenRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
        sumDto.setOpenRate(avgDto.getOpenRate());
        sumDto.setOpenLong(avgDto.getOpenLong());
        avgDto.setOpenLong(avgDto.getOpenLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
        sumDto.setWaitLong(avgDto.getWaitLong());
        avgDto.setWaitLong(avgDto.getWaitLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
        sumDto.setCloseLong(avgDto.getCloseLong());
        avgDto.setCloseLong(avgDto.getCloseLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
        long rate = avgDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
        for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
            if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                avgDto.setColor(mdcUtilizationRate.getRateParameterColor());
                sumDto.setColor(mdcUtilizationRate.getRateParameterColor());
            }
        }
        list.add(sumDto);
        list.add(avgDto);
        return list;
    }
    /**
     * 添加合计值和平均值
     */
    private void addSummaryAndAverage(MdcEfficiencyVo result, List<MdcEfficiencyListDto> listDtos, List<MdcUtilizationRate> mdcUtilizationRateList) {
        result.getDates().add("合计");
        result.getDates().add("平均值");
        MdcEfficiencyListDto sum = new MdcEfficiencyListDto();
        sum.setLevel1("合计");
        sum.setLevel2("合计");
        sum.setLevel3("合计");
        sum.setEquipmentId("合计");
        sum.setEquipmentName("合计");
        sum.setEquipmentType("合计");
        sum.setDataList(calculateTotal(listDtos, mdcUtilizationRateList));
        MdcEfficiencyListDto avg = new MdcEfficiencyListDto();
        avg.setLevel1("平均值");
        avg.setLevel2("平均值");
        avg.setLevel3("平均值");
        avg.setEquipmentId("平均值");
        avg.setEquipmentName("平均值");
        avg.setEquipmentType("平均值");
        avg.setDataList(calculateAverage(listDtos, mdcUtilizationRateList));
        result.getMdcEfficiencyList().add(sum);
        result.getMdcEfficiencyList().add(avg);
    }
    /**
     * 计算平均值
     *
     * @param mdcEfficiencyList
     * @param mdcUtilizationRateList
     * @return
     */
    private List<MdcEfficiencyResultDto> calculateAverage(List<MdcEfficiencyListDto> mdcEfficiencyList, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyResultDto> result = new ArrayList<>();
        List<MdcEfficiencyResultDto> dataList = new ArrayList<>();
        for (MdcEfficiencyListDto mdcEfficiencyListDto : mdcEfficiencyList) {
            dataList.addAll(mdcEfficiencyListDto.getDataList());
        }
        dataList.parallelStream().collect(Collectors.groupingBy(MdcEfficiencyResultDto::getTheDate, Collectors.toList()))
                .forEach((theDate, mert) -> {
                    mert.stream().reduce((a, b) -> new MdcEfficiencyResultDto(
                            a.getTheDate(),
                            a.getProcessLong().add(b.getProcessLong()),
                            a.getUtilizationRate().add(b.getUtilizationRate()),
                            a.getStartRate().add(b.getStartRate()),
                            a.getOpenRate().add(b.getOpenRate()),
                            a.getOpenLong().add(b.getOpenLong()),
                            a.getWaitLong().add(b.getWaitLong()),
                            a.getCloseLong().add(b.getCloseLong()))).ifPresent(result::add);
                });
        for (MdcEfficiencyResultDto mdcEfficiencyResultDto : result) {
            mdcEfficiencyResultDto.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setOpenRate(mdcEfficiencyResultDto.getOpenRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setStartRate(mdcEfficiencyResultDto.getStartRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setCloseLong(mdcEfficiencyResultDto.getCloseLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setWaitLong(mdcEfficiencyResultDto.getWaitLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setOpenLong(mdcEfficiencyResultDto.getOpenLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setProcessLong(mdcEfficiencyResultDto.getProcessLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            long rate = mdcEfficiencyResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        result.sort(Comparator.comparing(MdcEfficiencyResultDto::getTheDate));
        return result;
    }
    /**
     * 计算合计值
     *
     * @param mdcEfficiencyList
     * @return
     */
    private List<MdcEfficiencyResultDto> calculateTotal(List<MdcEfficiencyListDto> mdcEfficiencyList, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyResultDto> result = new ArrayList<>();
        List<MdcEfficiencyResultDto> dataList = new ArrayList<>();
        for (MdcEfficiencyListDto mdcEfficiencyListDto : mdcEfficiencyList) {
            dataList.addAll(mdcEfficiencyListDto.getDataList());
        }
        dataList.parallelStream().collect(Collectors.groupingBy(MdcEfficiencyResultDto::getTheDate, Collectors.toList()))
                .forEach((theDate, mert) -> {
                    mert.stream().reduce((a, b) -> new MdcEfficiencyResultDto(
                            a.getTheDate(),
                            a.getProcessLong().add(b.getProcessLong()),
                            a.getUtilizationRate().add(b.getUtilizationRate()),
                            a.getStartRate().add(b.getStartRate()),
                            a.getOpenRate().add(b.getOpenRate()),
                            a.getOpenLong().add(b.getOpenLong()),
                            a.getWaitLong().add(b.getWaitLong()),
                            a.getCloseLong().add(b.getCloseLong()))).ifPresent(result::add);
                });
        for (MdcEfficiencyResultDto mdcEfficiencyResultDto : result) {
            mdcEfficiencyResultDto.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setOpenRate(mdcEfficiencyResultDto.getOpenRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setStartRate(mdcEfficiencyResultDto.getStartRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            long rate = mdcEfficiencyResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        result.sort(Comparator.comparing(MdcEfficiencyResultDto::getTheDate));
        return result;
    }
@@ -276,26 +490,36 @@
        List<String> dates = DateUtils.getDatesStringList2(DateUtils.getShortDate2(vo.getStartTime()), DateUtils.getShortDate2(vo.getEndTime()));
        result.setDates(dates);
        // 利用率等级
        List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("kdl");
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            result.setMdcEfficiencyList(listDtos);
        } else {
            List<String> equipmentIdList = mdcEquipmentService.listEquipmentId(vo);
            if (equipmentIdList != null && !equipmentIdList.isEmpty()) {
                vo.setEquipmentIdList(equipmentIdList);
            } else {
                result.setMdcEfficiencyList(listDtos);
                return result;
            }
            // 查询利用率数据
            List<MdcEfficiencyDto> efficiencyList = mdcEfficiencyReportMapper.efficiencyPOList(vo);
            // 利用率等级
            List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("kdl");
            // 封装结果
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
                // 查询所有部门信息
                List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>().ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString()));
                List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>().ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString()).orderByAsc(SysDepart::getDepartOrder));
                for (MdcEquDepDto mdcEquDepDto : equipmentList) {
                    MdcEfficiencyListDto mdcEfficiencyListDto = new MdcEfficiencyListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquDepDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquDepDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquDepDto.getEquipmentType());
                    mdcEfficiencyListDto.setEquipmentModel(mdcEquDepDto.getEquipmentModel());
                    switch (mdcEquDepDto.getOrgType()) {
                        case "1":
                            mdcEfficiencyListDto.setLevel1(mdcEquDepDto.getDepartName());
@@ -341,9 +565,36 @@
                        }
                    }
                    List<MdcEfficiencyResultDto> list = new ArrayList<>();
                    MdcEfficiencyResultDto mdcEfficiencyResultDto = new MdcEfficiencyResultDto();
                    MdcEfficiencyResultDto mdcEfficiencyResultDto1 = new MdcEfficiencyResultDto();
                    mdcEfficiencyResultDto1.setTheDate("合计");
                    mdcEfficiencyResultDto.setTheDate("平均值");
                    for (String date : dates) {
                        list.add(this.efficiencyRate(efficiencyList, date, mdcEquDepDto.getEquipmentId(), mdcUtilizationRateList));
                        list.add(this.efficiencyRate(efficiencyList, date, mdcEquDepDto.getEquipmentId(), mdcUtilizationRateList, mdcEfficiencyResultDto));
                    }
                    mdcEfficiencyResultDto1.setProcessLong(mdcEfficiencyResultDto.getProcessLong());
                    mdcEfficiencyResultDto.setProcessLong(mdcEfficiencyResultDto.getProcessLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate());
                    mdcEfficiencyResultDto.setStartRate(mdcEfficiencyResultDto.getStartRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setStartRate(mdcEfficiencyResultDto.getStartRate());
                    mdcEfficiencyResultDto.setOpenRate(mdcEfficiencyResultDto.getOpenRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setOpenRate(mdcEfficiencyResultDto.getOpenRate());
                    mdcEfficiencyResultDto1.setOpenLong(mdcEfficiencyResultDto.getOpenLong());
                    mdcEfficiencyResultDto.setOpenLong(mdcEfficiencyResultDto.getOpenLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setWaitLong(mdcEfficiencyResultDto.getWaitLong());
                    mdcEfficiencyResultDto.setWaitLong(mdcEfficiencyResultDto.getWaitLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setCloseLong(mdcEfficiencyResultDto.getCloseLong());
                    mdcEfficiencyResultDto.setCloseLong(mdcEfficiencyResultDto.getCloseLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    long rate = mdcEfficiencyResultDto.getStartRate().multiply(new BigDecimal("100")).longValue();
                    for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                        if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                            mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                            mdcEfficiencyResultDto1.setColor(mdcUtilizationRate.getRateParameterColor());
                        }
                    }
                    list.add(mdcEfficiencyResultDto1);
                    list.add(mdcEfficiencyResultDto);
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
@@ -351,13 +602,14 @@
                // 产线层级
                List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
                // 查询所有产线信息
                List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>().ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString()));
                List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>().ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString()).orderByAsc(MdcProduction::getProductionOrder));
                for (MdcEquProDto mdcEquProDto : equipmentList) {
                    MdcEfficiencyListDto mdcEfficiencyListDto = new MdcEfficiencyListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquProDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquProDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquProDto.getEquipmentType());
                    mdcEfficiencyListDto.setEquipmentModel(mdcEquProDto.getEquipmentModel());
                    switch (mdcEquProDto.getOrgType()) {
                        case "1":
                            mdcEfficiencyListDto.setLevel1(mdcEquProDto.getProductionName());
@@ -402,17 +654,149 @@
                        }
                    }
                    List<MdcEfficiencyResultDto> list = new ArrayList<>();
                    MdcEfficiencyResultDto mdcEfficiencyResultDto = new MdcEfficiencyResultDto();
                    MdcEfficiencyResultDto mdcEfficiencyResultDto1 = new MdcEfficiencyResultDto();
                    mdcEfficiencyResultDto1.setTheDate("合计");
                    mdcEfficiencyResultDto.setTheDate("平均值");
                    for (String date : dates) {
                        list.add(this.efficiencyRate(efficiencyList, date, mdcEquProDto.getEquipmentId(), mdcUtilizationRateList));
                        list.add(this.efficiencyRate(efficiencyList, date, mdcEquProDto.getEquipmentId(), mdcUtilizationRateList, mdcEfficiencyResultDto));
                    }
                    mdcEfficiencyResultDto1.setProcessLong(mdcEfficiencyResultDto.getProcessLong());
                    mdcEfficiencyResultDto.setProcessLong(mdcEfficiencyResultDto.getProcessLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate());
                    mdcEfficiencyResultDto.setStartRate(mdcEfficiencyResultDto.getStartRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setStartRate(mdcEfficiencyResultDto.getStartRate());
                    mdcEfficiencyResultDto.setOpenRate(mdcEfficiencyResultDto.getOpenRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setOpenRate(mdcEfficiencyResultDto.getOpenRate());
                    mdcEfficiencyResultDto1.setOpenLong(mdcEfficiencyResultDto.getOpenLong());
                    mdcEfficiencyResultDto.setOpenLong(mdcEfficiencyResultDto.getOpenLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setWaitLong(mdcEfficiencyResultDto.getWaitLong());
                    mdcEfficiencyResultDto.setWaitLong(mdcEfficiencyResultDto.getWaitLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyResultDto1.setCloseLong(mdcEfficiencyResultDto.getCloseLong());
                    mdcEfficiencyResultDto.setCloseLong(mdcEfficiencyResultDto.getCloseLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    long rate = mdcEfficiencyResultDto.getStartRate().multiply(new BigDecimal("100")).longValue();
                    for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                        if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                            mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                            mdcEfficiencyResultDto1.setColor(mdcUtilizationRate.getRateParameterColor());
                        }
                    }
                    list.add(mdcEfficiencyResultDto1);
                    list.add(mdcEfficiencyResultDto);
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
            }
            result.setMdcEfficiencyList(listDtos);
        }
        result.getDates().add("合计");
        result.getDates().add("平均值");
        MdcEfficiencyListDto sum = new MdcEfficiencyListDto();
        sum.setLevel1("合计");
        sum.setLevel2("合计");
        sum.setLevel3("合计");
        sum.setEquipmentId("合计");
        sum.setEquipmentName("合计");
        sum.setEquipmentType("合计");
        //计算合计值
        sum.setDataList(this.calculateOpenTotal(result.getMdcEfficiencyList(), mdcUtilizationRateList));
        MdcEfficiencyListDto avg = new MdcEfficiencyListDto();
        avg.setLevel1("平均值");
        avg.setLevel2("平均值");
        avg.setLevel3("平均值");
        avg.setEquipmentId("平均值");
        avg.setEquipmentName("平均值");
        avg.setEquipmentType("平均值");
        //计算平均值
        avg.setDataList(this.calculateOpenAverage(result.getMdcEfficiencyList(), mdcUtilizationRateList));
        result.getMdcEfficiencyList().add(sum);
        result.getMdcEfficiencyList().add(avg);
        return result;
    }
    /**
     * 计算平均值
     *
     * @param mdcEfficiencyList
     * @param mdcUtilizationRateList
     * @return
     */
    private List<MdcEfficiencyResultDto> calculateOpenAverage(List<MdcEfficiencyListDto> mdcEfficiencyList, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyResultDto> result = new ArrayList<>();
        List<MdcEfficiencyResultDto> dataList = new ArrayList<>();
        for (MdcEfficiencyListDto mdcEfficiencyListDto : mdcEfficiencyList) {
            dataList.addAll(mdcEfficiencyListDto.getDataList());
        }
        dataList.parallelStream().collect(Collectors.groupingBy(MdcEfficiencyResultDto::getTheDate, Collectors.toList()))
                .forEach((theDate, mert) -> {
                    mert.stream().reduce((a, b) -> new MdcEfficiencyResultDto(
                            a.getTheDate(),
                            a.getProcessLong().add(b.getProcessLong()),
                            a.getUtilizationRate().add(b.getUtilizationRate()),
                            a.getStartRate().add(b.getStartRate()),
                            a.getOpenRate().add(b.getOpenRate()),
                            a.getOpenLong().add(b.getOpenLong()),
                            a.getWaitLong().add(b.getWaitLong()),
                            a.getCloseLong().add(b.getCloseLong()))).ifPresent(result::add);
                });
        for (MdcEfficiencyResultDto mdcEfficiencyResultDto : result) {
            mdcEfficiencyResultDto.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setOpenRate(mdcEfficiencyResultDto.getOpenRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setStartRate(mdcEfficiencyResultDto.getStartRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setCloseLong(mdcEfficiencyResultDto.getCloseLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setWaitLong(mdcEfficiencyResultDto.getWaitLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setOpenLong(mdcEfficiencyResultDto.getOpenLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setProcessLong(mdcEfficiencyResultDto.getProcessLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            long rate = mdcEfficiencyResultDto.getStartRate().multiply(new BigDecimal("100")).longValue();
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        result.sort(Comparator.comparing(MdcEfficiencyResultDto::getTheDate));
        return result;
    }
    /**
     * 计算合计值
     *
     * @param mdcEfficiencyList
     * @param mdcUtilizationRateList
     * @return
     */
    private List<MdcEfficiencyResultDto> calculateOpenTotal(List<MdcEfficiencyListDto> mdcEfficiencyList, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyResultDto> result = new ArrayList<>();
        List<MdcEfficiencyResultDto> dataList = new ArrayList<>();
        for (MdcEfficiencyListDto mdcEfficiencyListDto : mdcEfficiencyList) {
            dataList.addAll(mdcEfficiencyListDto.getDataList());
        }
        dataList.parallelStream().collect(Collectors.groupingBy(MdcEfficiencyResultDto::getTheDate, Collectors.toList()))
                .forEach((theDate, mert) -> {
                    mert.stream().reduce((a, b) -> new MdcEfficiencyResultDto(
                            a.getTheDate(),
                            a.getProcessLong().add(b.getProcessLong()),
                            a.getUtilizationRate().add(b.getUtilizationRate()),
                            a.getStartRate().add(b.getStartRate()),
                            a.getOpenRate().add(b.getOpenRate()),
                            a.getOpenLong().add(b.getOpenLong()),
                            a.getWaitLong().add(b.getWaitLong()),
                            a.getCloseLong().add(b.getCloseLong()))).ifPresent(result::add);
                });
        for (MdcEfficiencyResultDto mdcEfficiencyResultDto : result) {
            mdcEfficiencyResultDto.setUtilizationRate(mdcEfficiencyResultDto.getUtilizationRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setOpenRate(mdcEfficiencyResultDto.getOpenRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyResultDto.setStartRate(mdcEfficiencyResultDto.getStartRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            long rate = mdcEfficiencyResultDto.getStartRate().multiply(new BigDecimal("100")).longValue();
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        result.sort(Comparator.comparing(MdcEfficiencyResultDto::getTheDate));
        return result;
    }
@@ -453,14 +837,25 @@
            vo.setEquipmentIdList(equipmentIds);
        }
        // 班次利用率等级
        List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("bclyl");
        List<String> dates = DateUtils.getDatesStringList2(DateUtils.getShortDate2(vo.getStartTime()), DateUtils.getShortDate2(vo.getEndTime()));
        result.setDates(dates);
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            result.setMdcEfficiencyList(listDtos);
        } else {
            // 班次利用率等级
            List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("bclyl");
            List<String> equipmentIdList = mdcEquipmentService.listEquipmentIdShift(vo);
            if (equipmentIdList != null && !equipmentIdList.isEmpty()) {
                vo.setEquipmentIdList(equipmentIdList);
            } else {
                result.setMdcEfficiencyList(listDtos);
                return result;
            }
            // 班次利用率数据
            List<MdcEquipmentStatisticalShiftInfo> mdcEquipmentStatisticalShiftInfoList = mdcEfficiencyReportMapper.efficiencyShiftSumList(vo);
@@ -469,7 +864,7 @@
                // 部门层级
                List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
                // 查询所有部门信息
                List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>().ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString()));
                List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>().ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString()).orderByAsc(SysDepart::getDepartOrder));
                // 班次名称显示处理
                String shiftSubName = "";
                if (StringUtils.isBlank(vo.getShiftId())) {
@@ -496,6 +891,7 @@
                    mdcEfficiencyShiftListDto.setEquipmentId(mdcEquDepDto.getEquipmentId());
                    mdcEfficiencyShiftListDto.setEquipmentName(mdcEquDepDto.getEquipmentName());
                    mdcEfficiencyShiftListDto.setEquipmentType(mdcEquDepDto.getEquipmentType());
                    mdcEfficiencyShiftListDto.setEquipmentModel(mdcEquDepDto.getEquipmentModel());
                    mdcEfficiencyShiftListDto.setShiftSubName(shiftSubName);
                    switch (mdcEquDepDto.getOrgType()) {
                        case "1":
@@ -542,9 +938,36 @@
                        }
                    }
                    List<MdcEfficiencyShiftResultDto> list = new ArrayList<>();
                    MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto = new MdcEfficiencyShiftResultDto();
                    MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto1 = new MdcEfficiencyShiftResultDto();
                    mdcEfficiencyShiftResultDto.setTheDate("平均值");
                    mdcEfficiencyShiftResultDto1.setTheDate("合计");
                    for (String date : dates) {
                        list.add(this.efficiencyShiftRate(mdcEquipmentStatisticalShiftInfoList, date, mdcEquDepDto.getEquipmentId(), mdcUtilizationRateList));
                        list.add(this.efficiencyShiftRate(mdcEquipmentStatisticalShiftInfoList, date, mdcEquDepDto.getEquipmentId(), mdcUtilizationRateList, mdcEfficiencyShiftResultDto));
                    }
                    mdcEfficiencyShiftResultDto1.setProcessLong(mdcEfficiencyShiftResultDto.getProcessLong());
                    mdcEfficiencyShiftResultDto.setProcessLong(mdcEfficiencyShiftResultDto.getProcessLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto.setUtilizationRate(mdcEfficiencyShiftResultDto.getUtilizationRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setUtilizationRate(mdcEfficiencyShiftResultDto.getUtilizationRate());
                    mdcEfficiencyShiftResultDto.setStartRate(mdcEfficiencyShiftResultDto.getStartRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setStartRate(mdcEfficiencyShiftResultDto.getStartRate());
                    mdcEfficiencyShiftResultDto.setOpenRate(mdcEfficiencyShiftResultDto.getOpenRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setOpenRate(mdcEfficiencyShiftResultDto.getOpenRate());
                    mdcEfficiencyShiftResultDto1.setOpenLong(mdcEfficiencyShiftResultDto.getOpenLong());
                    mdcEfficiencyShiftResultDto.setOpenLong(mdcEfficiencyShiftResultDto.getOpenLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setWaitLong(mdcEfficiencyShiftResultDto.getWaitLong());
                    mdcEfficiencyShiftResultDto.setWaitLong(mdcEfficiencyShiftResultDto.getWaitLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setCloseLong(mdcEfficiencyShiftResultDto.getCloseLong());
                    mdcEfficiencyShiftResultDto.setCloseLong(mdcEfficiencyShiftResultDto.getCloseLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    long rate = mdcEfficiencyShiftResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
                    for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                        if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                            mdcEfficiencyShiftResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                            mdcEfficiencyShiftResultDto1.setColor(mdcUtilizationRate.getRateParameterColor());
                        }
                    }
                    list.add(mdcEfficiencyShiftResultDto1);
                    list.add(mdcEfficiencyShiftResultDto);
                    mdcEfficiencyShiftListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyShiftListDto);
                }
@@ -552,7 +975,7 @@
                // 产线层级
                List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
                // 查询所有产线信息
                List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>().ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString()));
                List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>().ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString()).orderByAsc(MdcProduction::getProductionOrder));
                // 班次名称显示处理
                String shiftSubName = "";
@@ -580,6 +1003,7 @@
                    mdcEfficiencyShiftListDto.setEquipmentId(mdcEquProDto.getEquipmentId());
                    mdcEfficiencyShiftListDto.setEquipmentName(mdcEquProDto.getEquipmentName());
                    mdcEfficiencyShiftListDto.setEquipmentType(mdcEquProDto.getEquipmentType());
                    mdcEfficiencyShiftListDto.setEquipmentModel(mdcEquProDto.getEquipmentModel());
                    mdcEfficiencyShiftListDto.setShiftSubName(shiftSubName);
                    switch (mdcEquProDto.getOrgType()) {
                        case "1":
@@ -625,31 +1049,173 @@
                        }
                    }
                    List<MdcEfficiencyShiftResultDto> list = new ArrayList<>();
                    MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto = new MdcEfficiencyShiftResultDto();
                    MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto1 = new MdcEfficiencyShiftResultDto();
                    mdcEfficiencyShiftResultDto.setTheDate("平均值");
                    mdcEfficiencyShiftResultDto1.setTheDate("合计");
                    for (String date : dates) {
                        list.add(this.efficiencyShiftRate(mdcEquipmentStatisticalShiftInfoList, date, mdcEquProDto.getEquipmentId(), mdcUtilizationRateList));
                        list.add(this.efficiencyShiftRate(mdcEquipmentStatisticalShiftInfoList, date, mdcEquProDto.getEquipmentId(), mdcUtilizationRateList, mdcEfficiencyShiftResultDto));
                    }
                    mdcEfficiencyShiftResultDto1.setProcessLong(mdcEfficiencyShiftResultDto.getProcessLong());
                    mdcEfficiencyShiftResultDto.setProcessLong(mdcEfficiencyShiftResultDto.getProcessLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto.setUtilizationRate(mdcEfficiencyShiftResultDto.getUtilizationRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setUtilizationRate(mdcEfficiencyShiftResultDto.getUtilizationRate());
                    mdcEfficiencyShiftResultDto.setStartRate(mdcEfficiencyShiftResultDto.getStartRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setStartRate(mdcEfficiencyShiftResultDto.getStartRate());
                    mdcEfficiencyShiftResultDto.setOpenRate(mdcEfficiencyShiftResultDto.getOpenRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setOpenRate(mdcEfficiencyShiftResultDto.getOpenRate());
                    mdcEfficiencyShiftResultDto1.setOpenLong(mdcEfficiencyShiftResultDto.getOpenLong());
                    mdcEfficiencyShiftResultDto.setOpenLong(mdcEfficiencyShiftResultDto.getOpenLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setWaitLong(mdcEfficiencyShiftResultDto.getWaitLong());
                    mdcEfficiencyShiftResultDto.setWaitLong(mdcEfficiencyShiftResultDto.getWaitLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    mdcEfficiencyShiftResultDto1.setCloseLong(mdcEfficiencyShiftResultDto.getCloseLong());
                    mdcEfficiencyShiftResultDto.setCloseLong(mdcEfficiencyShiftResultDto.getCloseLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
                    long rate = mdcEfficiencyShiftResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
                    for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                        if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                            mdcEfficiencyShiftResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                            mdcEfficiencyShiftResultDto1.setColor(mdcUtilizationRate.getRateParameterColor());
                        }
                    }
                    list.add(mdcEfficiencyShiftResultDto1);
                    list.add(mdcEfficiencyShiftResultDto);
                    mdcEfficiencyShiftListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyShiftListDto);
                }
            }
//            listDtos.sort(((o1, o2) -> Collator.getInstance(Locale.TRADITIONAL_CHINESE).compare(o1.getLevel3(), o2.getLevel3())));
            result.setMdcEfficiencyList(listDtos);
        }
        result.getDates().add("合计");
        result.getDates().add("平均值");
        MdcEfficiencyShiftListDto sum = new MdcEfficiencyShiftListDto();
        sum.setLevel1("合计");
        sum.setLevel2("合计");
        sum.setLevel3("合计");
        sum.setEquipmentId("合计");
        sum.setEquipmentName("合计");
        sum.setEquipmentType("合计");
        sum.setShiftSubName("合计");
        sum.setDataList(this.calculateShiftTotal(result.getMdcEfficiencyList(), mdcUtilizationRateList));
        MdcEfficiencyShiftListDto avg = new MdcEfficiencyShiftListDto();
        avg.setLevel1("平均值");
        avg.setLevel2("平均值");
        avg.setLevel3("平均值");
        avg.setEquipmentId("平均值");
        avg.setEquipmentName("平均值");
        avg.setEquipmentType("平均值");
        avg.setShiftSubName("平均值");
        avg.setDataList(this.calculateShiftAverage(result.getMdcEfficiencyList(), mdcUtilizationRateList));
        result.getMdcEfficiencyList().add(sum);
        result.getMdcEfficiencyList().add(avg);
        return result;
    }
    /**
     * 计算平均值
     *
     * @param mdcEfficiencyList
     * @param mdcUtilizationRateList
     * @return
     */
    private List<MdcEfficiencyShiftResultDto> calculateShiftAverage(List<MdcEfficiencyShiftListDto> mdcEfficiencyList, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyShiftResultDto> result = new ArrayList<>();
        List<MdcEfficiencyShiftResultDto> dataList = new ArrayList<>();
        for (MdcEfficiencyShiftListDto mdcEfficiencyShiftListDto : mdcEfficiencyList) {
            dataList.addAll(mdcEfficiencyShiftListDto.getDataList());
        }
        dataList.parallelStream().collect(Collectors.groupingBy(MdcEfficiencyShiftResultDto::getTheDate, Collectors.toList()))
                .forEach((theDate, mert) -> {
                    mert.stream().reduce((a, b) -> new MdcEfficiencyShiftResultDto(
                            a.getTheDate(),
                            a.getProcessLong().add(b.getProcessLong()),
                            a.getUtilizationRate().add(b.getUtilizationRate()),
                            a.getStartRate().add(b.getStartRate()),
                            a.getOpenRate().add(b.getOpenRate()),
                            a.getOpenLong().add(b.getOpenLong()),
                            a.getWaitLong().add(b.getWaitLong()),
                            a.getCloseLong().add(b.getCloseLong()))).ifPresent(result::add);
                });
        for (MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto : result) {
            mdcEfficiencyShiftResultDto.setUtilizationRate(mdcEfficiencyShiftResultDto.getUtilizationRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setOpenRate(mdcEfficiencyShiftResultDto.getOpenRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setStartRate(mdcEfficiencyShiftResultDto.getStartRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setCloseLong(mdcEfficiencyShiftResultDto.getCloseLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setWaitLong(mdcEfficiencyShiftResultDto.getWaitLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setOpenLong(mdcEfficiencyShiftResultDto.getOpenLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setProcessLong(mdcEfficiencyShiftResultDto.getProcessLong().divide(new BigDecimal(mdcEfficiencyList.size()), 0, RoundingMode.HALF_UP));
            long rate = mdcEfficiencyShiftResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyShiftResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        result.sort(Comparator.comparing(MdcEfficiencyShiftResultDto::getTheDate));
        return result;
    }
    /**
     * 计算合计值
     *
     * @param mdcEfficiencyList
     * @param mdcUtilizationRateList
     * @return
     */
    private List<MdcEfficiencyShiftResultDto> calculateShiftTotal(List<MdcEfficiencyShiftListDto> mdcEfficiencyList, List<MdcUtilizationRate> mdcUtilizationRateList) {
        List<MdcEfficiencyShiftResultDto> result = new ArrayList<>();
        List<MdcEfficiencyShiftResultDto> dataList = new ArrayList<>();
        for (MdcEfficiencyShiftListDto mdcEfficiencyShiftListDto : mdcEfficiencyList) {
            dataList.addAll(mdcEfficiencyShiftListDto.getDataList());
        }
        dataList.parallelStream().collect(Collectors.groupingBy(MdcEfficiencyShiftResultDto::getTheDate, Collectors.toList()))
                .forEach((theDate, mert) -> {
                    mert.stream().reduce((a, b) -> new MdcEfficiencyShiftResultDto(
                            a.getTheDate(),
                            a.getProcessLong().add(b.getProcessLong()),
                            a.getUtilizationRate().add(b.getUtilizationRate()),
                            a.getStartRate().add(b.getStartRate()),
                            a.getOpenRate().add(b.getOpenRate()),
                            a.getOpenLong().add(b.getOpenLong()),
                            a.getWaitLong().add(b.getWaitLong()),
                            a.getCloseLong().add(b.getCloseLong()))).ifPresent(result::add);
                });
        for (MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto : result) {
            mdcEfficiencyShiftResultDto.setUtilizationRate(mdcEfficiencyShiftResultDto.getUtilizationRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setOpenRate(mdcEfficiencyShiftResultDto.getOpenRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            mdcEfficiencyShiftResultDto.setStartRate(mdcEfficiencyShiftResultDto.getStartRate().divide(new BigDecimal(mdcEfficiencyList.size()), 4, RoundingMode.HALF_UP));
            long rate = mdcEfficiencyShiftResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyShiftResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        result.sort(Comparator.comparing(MdcEfficiencyShiftResultDto::getTheDate));
        return result;
    }
    private MdcEfficiencyShiftResultDto efficiencyShiftRate(List<MdcEquipmentStatisticalShiftInfo> mdcEquipmentStatisticalShiftInfoList, String date, String equipmentId, List<MdcUtilizationRate> mdcUtilizationRateList) {
    private MdcEfficiencyShiftResultDto efficiencyShiftRate(List<MdcEquipmentStatisticalShiftInfo> mdcEquipmentStatisticalShiftInfoList, String date, String equipmentId, List<MdcUtilizationRate> mdcUtilizationRateList, MdcEfficiencyShiftResultDto efficiencyShiftResultDto) {
        MdcEfficiencyShiftResultDto mdcEfficiencyShiftResultDto = new MdcEfficiencyShiftResultDto();
        if (mdcEquipmentStatisticalShiftInfoList != null && !mdcEquipmentStatisticalShiftInfoList.isEmpty()) {
            for (MdcEquipmentStatisticalShiftInfo equipmentStatisticalShiftInfo : mdcEquipmentStatisticalShiftInfoList) {
                if (date.equals(equipmentStatisticalShiftInfo.getTheDate()) && equipmentStatisticalShiftInfo.getEquipmentId().equals(equipmentId)) {
                    mdcEfficiencyShiftResultDto.setTheDate(equipmentStatisticalShiftInfo.getTheDate());
                    mdcEfficiencyShiftResultDto.setProcessLong(equipmentStatisticalShiftInfo.getProcessLong());
                    mdcEfficiencyShiftResultDto.setUtilizationRate(equipmentStatisticalShiftInfo.getProcessLong().divide(equipmentStatisticalShiftInfo.getTotalLong(), 6, BigDecimal.ROUND_HALF_UP));
                    if (equipmentStatisticalShiftInfo.getTotalLong().compareTo(BigDecimal.ZERO) == 0) {
                        mdcEfficiencyShiftResultDto.setUtilizationRate(BigDecimal.ZERO);
                    } else {
                        mdcEfficiencyShiftResultDto.setUtilizationRate(equipmentStatisticalShiftInfo.getProcessLong().divide(equipmentStatisticalShiftInfo.getTotalLong(), 6, RoundingMode.HALF_UP));
                    }
                    mdcEfficiencyShiftResultDto.setCloseLong(equipmentStatisticalShiftInfo.getCloseLong());
                    mdcEfficiencyShiftResultDto.setOpenLong(equipmentStatisticalShiftInfo.getOpenLong());
                    mdcEfficiencyShiftResultDto.setWaitLong(equipmentStatisticalShiftInfo.getWaitLong());
                    mdcEfficiencyShiftResultDto.setOpenRate(equipmentStatisticalShiftInfo.getOpenLong().divide(equipmentStatisticalShiftInfo.getTotalLong(), 6, BigDecimal.ROUND_HALF_UP));
                    if (equipmentStatisticalShiftInfo.getTotalLong().compareTo(BigDecimal.ZERO) == 0) {
                        mdcEfficiencyShiftResultDto.setOpenRate(BigDecimal.ZERO);
                    } else {
                        mdcEfficiencyShiftResultDto.setOpenRate(equipmentStatisticalShiftInfo.getOpenLong().divide(equipmentStatisticalShiftInfo.getTotalLong(), 6, RoundingMode.HALF_UP));
                    }
                    long rate = mdcEfficiencyShiftResultDto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
                    for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                        if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
@@ -673,6 +1239,28 @@
                }
            }
        }
        if (StringUtils.isBlank(mdcEfficiencyShiftResultDto.getColor())) {
            mdcEfficiencyShiftResultDto.setTheDate(date);
            mdcEfficiencyShiftResultDto.setProcessLong(new BigDecimal("0"));
            mdcEfficiencyShiftResultDto.setUtilizationRate(new BigDecimal("0"));
            mdcEfficiencyShiftResultDto.setStartRate(new BigDecimal("0"));
            mdcEfficiencyShiftResultDto.setOpenRate(new BigDecimal("0"));
            mdcEfficiencyShiftResultDto.setOpenLong(new BigDecimal("0"));
            mdcEfficiencyShiftResultDto.setWaitLong(new BigDecimal("0"));
            mdcEfficiencyShiftResultDto.setCloseLong(new BigDecimal("0"));
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (0 >= mdcUtilizationRate.getMinimumRange() && 0 < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyShiftResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        efficiencyShiftResultDto.setProcessLong(efficiencyShiftResultDto.getProcessLong().add(mdcEfficiencyShiftResultDto.getProcessLong()));
        efficiencyShiftResultDto.setUtilizationRate(efficiencyShiftResultDto.getUtilizationRate().add(mdcEfficiencyShiftResultDto.getUtilizationRate()));
        efficiencyShiftResultDto.setStartRate(efficiencyShiftResultDto.getStartRate().add(mdcEfficiencyShiftResultDto.getStartRate()));
        efficiencyShiftResultDto.setOpenRate(efficiencyShiftResultDto.getOpenRate().add(mdcEfficiencyShiftResultDto.getOpenRate()));
        efficiencyShiftResultDto.setOpenLong(efficiencyShiftResultDto.getOpenLong().add(mdcEfficiencyShiftResultDto.getOpenLong()));
        efficiencyShiftResultDto.setWaitLong(efficiencyShiftResultDto.getWaitLong().add(mdcEfficiencyShiftResultDto.getWaitLong()));
        efficiencyShiftResultDto.setCloseLong(efficiencyShiftResultDto.getCloseLong().add(mdcEfficiencyShiftResultDto.getCloseLong()));
        return mdcEfficiencyShiftResultDto;
    }
@@ -753,10 +1341,10 @@
        }
        result = this.efficiencyStatisticalRate(efficiencyList);
        if (result.getOpenRate().compareTo(new BigDecimal("0")) > 0) {
            result.setOpenRate(result.getOpenRate().multiply(new BigDecimal("100")).divide(new BigDecimal(equipmentIds.size()), 2, BigDecimal.ROUND_HALF_UP));
            result.setOpenRate(result.getOpenRate().multiply(new BigDecimal("100")).divide(new BigDecimal(vo.getEquipmentIdList().size()), 2, BigDecimal.ROUND_HALF_UP));
        }
        if (result.getUtilizationRate().compareTo(new BigDecimal("0")) > 0) {
            result.setUtilizationRate(result.getUtilizationRate().multiply(new BigDecimal(100)).divide(new BigDecimal(equipmentIds.size()), 2, BigDecimal.ROUND_HALF_UP));
            result.setUtilizationRate(result.getUtilizationRate().multiply(new BigDecimal(100)).divide(new BigDecimal(vo.getEquipmentIdList().size()), 2, BigDecimal.ROUND_HALF_UP));
        }
        if (result.getOpenLong().compareTo(new BigDecimal(0)) > 0 && result.getProcessLong().compareTo(new BigDecimal(0)) > 0) {
            result.setUsedOpenRate(result.getProcessLong().divide(result.getOpenLong(), 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)));
@@ -781,7 +1369,7 @@
            }
        } else if (StringUtils.isNotEmpty(vo.getEquipmentId())) {
            // 单台设备信息
            vo.setEquipmentIdList(Collections.singletonList(vo.getEquipmentId()));
            vo.setEquipmentIdList(Arrays.asList(vo.getEquipmentId().split(",")));
        } else {
            // 查询用户拥有的所有设备信息
            if ("2".equals(vo.getTypeTree())) {
@@ -798,6 +1386,10 @@
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            return result;
        }
        vo.setDeviceCategoryList(Arrays.asList(vo.getDeviceCategory().split(",")));
        vo.setDeviceLevelList(Arrays.asList(vo.getDeviceLevel().split(",")));
        vo.setDriveTypeList(Arrays.asList(vo.getDriveType().split(",")));
        vo.setEquipmentTypeList(Arrays.asList(vo.getEquipmentType().split(",")));
        // 查询原始数据
        List<MdcComAnaDto> resultDtos = mdcEfficiencyReportMapper.comparativeAnalysis(vo);
@@ -806,7 +1398,7 @@
            List<GraphicsDto> graphicsDtos = new ArrayList<>();
            // 获取天数
            long days = ChronoUnit.DAYS.between(LocalDate.parse(vo.getStartTime(), DateTimeFormatter.ofPattern("yyyyMMdd")), LocalDate.parse(vo.getEndTime(), DateTimeFormatter.ofPattern("yyyyMMdd"))) + 1;
            BigDecimal time = new BigDecimal("24").multiply(new BigDecimal(days));
            BigDecimal time = new BigDecimal("24").multiply(new BigDecimal(days)).multiply(new BigDecimal("60")).multiply(new BigDecimal("60"));
            for (MdcComAnaDto mdcComAnaDto : resultDtos) {
                GraphicsDto graphicsDto = new GraphicsDto();
                graphicsDto.setEquipmentId(mdcComAnaDto.getEquipmentId());
@@ -887,7 +1479,9 @@
                vo.setEquipmentId(equipmentIds.get(0));
            }
        }
        result.setEquipmentId(vo.getEquipmentId());
        MdcEquipment mdcEquipment = mdcEquipmentService.getOne(new LambdaQueryWrapper<MdcEquipment>().eq(MdcEquipment::getEquipmentId, vo.getEquipmentId()));
        result.setEquipmentName(mdcEquipment.getEquipmentName());
        List<String> dateList = new ArrayList<>();
        for (int i = 1; i <= 24 / vo.getTimeType(); i++) {
            if (i * vo.getTimeType() < 10) {
@@ -897,8 +1491,6 @@
            }
        }
//        result.setDateList(dateList);
        dateList.add(0, "00:00");
        List<DayRateDto> dayRateDtoList = new ArrayList<>();
@@ -906,8 +1498,8 @@
            DayRateDto dayRateDto = new DayRateDto();
            dayRateDto.setDateTime(dateList.get(i + 1));
            String dateTime = DateUtils.dateConvertion(vo.getDateTime());
            Date startTime = DateUtils.toDate(dateTime + " " + dateList.get(i), DateUtils.STR_DATE_TIME_MIN);
            Date endTime = DateUtils.toDate(dateTime + " " + dateList.get(i + 1), DateUtils.STR_DATE_TIME_MIN);
            Date startTime = DateUtils.toDate(dateTime + " " + dateList.get(i) + ":00", DateUtils.STR_DATE_TIME_SMALL);
            Date endTime = DateUtils.toDate(dateTime + " " + dateList.get(i + 1) + ":00", DateUtils.STR_DATE_TIME_SMALL);
            List<MdcEquipmentRunningSection> runningSections = mdcEquipmentRunningSectionService.listEquipmentRunningSection(vo.getEquipmentId(), startTime.getTime(), endTime.getTime());
            if (runningSections != null && !runningSections.isEmpty()) {
                // 时间修正
@@ -940,6 +1532,753 @@
        return result;
    }
    /**
     * 设备日利用率对比分析
     *
     * @param userId
     * @param vo
     * @return
     */
    @Override
    public DayUtilizationRateDto dayUtilizationRateContrast(String userId, DayUtilizationRateContrastQueryVo vo) {
        DayUtilizationRateDto result = new DayUtilizationRateDto();
        if (StringUtils.isBlank(vo.getEquipmentId())) {
            List<String> equipmentIds;
            // 获取用户拥有设备权限
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, null);
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, null);
            }
            if (equipmentIds != null && !equipmentIds.isEmpty()) {
                vo.setEquipmentId(equipmentIds.get(0));
            }
        }
        result.setEquipmentId(vo.getEquipmentId());
        MdcEquipment mdcEquipment = mdcEquipmentService.getOne(new LambdaQueryWrapper<MdcEquipment>().eq(MdcEquipment::getEquipmentId, vo.getEquipmentId()));
        result.setEquipmentName(mdcEquipment.getEquipmentName());
        Date start = DateUtils.toDate(vo.getStartDate(), DateUtils.STRDATE);
        Date end = DateUtils.toDate(vo.getEndDate(), DateUtils.STRDATE);
        List<String> dateList = DateUtils.getDatesStringLists(start, end);
        result.setDateList(dateList);
        List<String> datesStringList = DateUtils.getDatesStringList(start, end);
        List<DayRateDto> dayRateDtoList = new ArrayList<>();
        for (String date : datesStringList) {
            DayRateDto dayRateDto = new DayRateDto();
            String format = DateUtils.format(DateUtils.toDate(date, DateUtils.STR_DATE), DateUtils.STR_MMDD);
            dayRateDto.setDateTime(format);
            Date startTime = DateUtils.toDate(date + " " + vo.getStartTime() + ":00", DateUtils.STR_DATE_TIME_SMALL);
            Date endTime = DateUtils.toDate(date + " " + vo.getEndTime() + ":00", DateUtils.STR_DATE_TIME_SMALL);
            List<MdcEquipmentRunningSection> runningSections = mdcEquipmentRunningSectionService.listEquipmentRunningSection(vo.getEquipmentId(), startTime.getTime(), endTime.getTime());
            if (runningSections != null && !runningSections.isEmpty()) {
                //时间修正
                runningSections.get(0).setStartTime(startTime);
                if (runningSections.size() > 1) {
                    runningSections.get(runningSections.size() - 1).setEndTime(endTime);
                } else {
                    runningSections.get(0).setEndTime(endTime);
                }
                // 利用率计算
                BigDecimal processLong = new BigDecimal("0");
                for (MdcEquipmentRunningSection runningSection : runningSections) {
                    if (runningSection.getStatus() == 3) {
                        long duration = DateUtils.differentSecond(runningSection.getStartTime(), runningSection.getEndTime());
                        processLong = processLong.add(new BigDecimal(duration));
                    }
                }
                BigDecimal totalLong = new BigDecimal(DateUtils.differentSecond(startTime, endTime));
                BigDecimal utilizationRate = processLong.divide(totalLong, 6, BigDecimal.ROUND_HALF_UP);
                dayRateDto.setUtilizationRate(utilizationRate);
            } else {
                dayRateDto.setUtilizationRate(new BigDecimal("0"));
            }
            dayRateDtoList.add(dayRateDto);
        }
        result.setDayRateDto(dayRateDtoList);
        return result;
    }
    /**
     * 设备利用率分段分析
     *
     * @param userId
     * @param vo
     * @return
     */
    @Override
    public MdcUtilizationRateDto utilizationRateSectionAnalyze(String userId, DayUtilizationRateContrastQueryVo vo) {
        MdcUtilizationRateDto result = new MdcUtilizationRateDto();
        List<MdcUtilizationRateListDto> listDtos = new ArrayList<>();
        List<String> equipmentIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(vo.getParentId()) && StringUtils.isEmpty(vo.getEquipmentId())) {
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, vo.getParentId());
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, vo.getParentId());
            }
        } else if (StringUtils.isNotEmpty(vo.getEquipmentId())) {
            // 单台设备信息
            vo.setEquipmentIdList(Collections.singletonList(vo.getEquipmentId()));
        } else {
            // 查询用户拥有的所有设备信息
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, null);
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, null);
            }
        }
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            vo.setEquipmentIdList(equipmentIds);
        }
        List<String> dates = DateUtils.getDatesStringList2(DateUtils.getShortDate2(vo.getStartDate()), DateUtils.getShortDate2(vo.getEndDate()));
        List<String> dateList = DateUtils.getDatesStringList(DateUtils.getShortDate2(vo.getStartDate()), DateUtils.getShortDate2(vo.getEndDate()));
        result.setDates(dates);
        String startString = vo.getStartTime();
        String endString = vo.getEndTime();
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            result.setMdcEfficiencyList(listDtos);
        } else {
            MdcEfficiencyReportQueryVo vo1 = new MdcEfficiencyReportQueryVo();
            BeanUtils.copyProperties(vo, vo1);
            List<String> equipmentIdList = mdcEquipmentService.listEquipmentId(vo1);
            if (equipmentIdList != null && !equipmentIdList.isEmpty()) {
                vo.setEquipmentIdList(equipmentIdList);
            } else {
                result.setMdcEfficiencyList(listDtos);
                return result;
            }
            // 利用率等级
            List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("lyl");
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
                for (MdcEquDepDto mdcEquDepDto : equipmentList) {
                    MdcUtilizationRateListDto mdcUtilizationRateListDto = new MdcUtilizationRateListDto();
                    mdcUtilizationRateListDto.setEquipmentId(mdcEquDepDto.getEquipmentId());
                    mdcUtilizationRateListDto.setEquipmentName(mdcEquDepDto.getEquipmentName());
                    mdcUtilizationRateListDto.setEquipmentType(mdcEquDepDto.getEquipmentType());
                    //
                    List<MdcUtilizationResultDto> list = new ArrayList<>();
                    for (String date : dateList) {
                        Date startTime = DateUtils.toDate(date + " " + startString + ":00", DateUtils.STR_DATE_TIME_SMALL);
                        Date endTime = DateUtils.toDate(date + " " + endString + ":00", DateUtils.STR_DATE_TIME_SMALL);
                        list.add(this.utilizationRate(mdcEquDepDto.getEquipmentId(), mdcEquDepDto.getEquipmentName(), mdcEquDepDto.getEquipmentType(), startTime, endTime, date, mdcUtilizationRateList));
                    }
                    mdcUtilizationRateListDto.setDataList(list);
                    listDtos.add(mdcUtilizationRateListDto);
                }
            } else {
                // 产线层级
                List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
                for (MdcEquProDto mdcEquProDto : equipmentList) {
                    MdcUtilizationRateListDto mdcEfficiencyListDto = new MdcUtilizationRateListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquProDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquProDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquProDto.getEquipmentType());
                    //
                    List<MdcUtilizationResultDto> list = new ArrayList<>();
                    for (String date : dateList) {
                        Date startTime = DateUtils.toDate(date + " " + startString + ":00", DateUtils.STR_DATE_TIME_SMALL);
                        Date endTime = DateUtils.toDate(date + " " + endString + ":00", DateUtils.STR_DATE_TIME_SMALL);
                        list.add(this.utilizationRate(mdcEquProDto.getEquipmentId(), mdcEquProDto.getEquipmentName(), mdcEquProDto.getEquipmentType(), startTime, endTime, date, mdcUtilizationRateList));
                    }
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
            }
            result.setMdcEfficiencyList(listDtos);
        }
        return result;
    }
    /**
     * 设备利用率走势分析
     *
     * @param userId
     * @param vo
     * @return
     */
    @Override
    public MdcUtilizationRateDto utilizationRateTrendAnalyze(String userId, DayUtilizationRateContrastQueryVo vo) {
        MdcUtilizationRateDto result = new MdcUtilizationRateDto();
        List<MdcUtilizationRateListDto> listDtos = new ArrayList<>();
        List<String> equipmentIds = new ArrayList<>();
        if (StringUtils.isNotEmpty(vo.getParentId()) && StringUtils.isEmpty(vo.getEquipmentId())) {
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, vo.getParentId());
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, vo.getParentId());
            }
        } else if (StringUtils.isNotEmpty(vo.getEquipmentId())) {
            // 单台设备信息
            vo.setEquipmentIdList(Collections.singletonList(vo.getEquipmentId()));
        } else {
            // 查询用户拥有的所有设备信息
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsByDepart(userId, null);
            } else {
                // 产线层级
                equipmentIds = mdcEquipmentService.getEquipmentIdsProduction(userId, null);
            }
        }
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            vo.setEquipmentIdList(equipmentIds);
        }
        List<String> dateList = DateUtils.getDatesStringList(DateUtils.getShortDate2(vo.getStartDate()), DateUtils.getShortDate2(vo.getEndDate()));
        result.setDates(dateList);
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            result.setMdcEfficiencyList(listDtos);
        } else {
            MdcEfficiencyReportQueryVo vo1 = new MdcEfficiencyReportQueryVo();
            BeanUtils.copyProperties(vo, vo1);
            List<String> equipmentIdList = mdcEquipmentService.listEquipmentId(vo1);
            if (equipmentIdList != null && !equipmentIdList.isEmpty()) {
                vo.setEquipmentIdList(equipmentIdList);
            } else {
                result.setMdcEfficiencyList(listDtos);
                return result;
            }
            // 利用率等级
            List<MdcUtilizationRate> mdcUtilizationRateList = mdcUtilizationRateService.listByType("lyl");
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
                for (MdcEquDepDto mdcEquDepDto : equipmentList) {
                    MdcUtilizationRateListDto mdcEfficiencyListDto = new MdcUtilizationRateListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquDepDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquDepDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquDepDto.getEquipmentType());
                    List<MdcUtilizationResultDto> list = new ArrayList<>();
                    for (String date : dateList) {
                        list.add(this.utilizationRateTrend(mdcEquDepDto.getEquipmentId(), mdcEquDepDto.getEquipmentName(), mdcEquDepDto.getEquipmentType(), date, mdcUtilizationRateList));
                    }
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
            } else {
                // 产线层级
                List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
                for (MdcEquProDto mdcEquProDto : equipmentList) {
                    MdcUtilizationRateListDto mdcEfficiencyListDto = new MdcUtilizationRateListDto();
                    mdcEfficiencyListDto.setEquipmentId(mdcEquProDto.getEquipmentId());
                    mdcEfficiencyListDto.setEquipmentName(mdcEquProDto.getEquipmentName());
                    mdcEfficiencyListDto.setEquipmentType(mdcEquProDto.getEquipmentType());
                    List<MdcUtilizationResultDto> list = new ArrayList<>();
                    for (String date : dateList) {
                        list.add(this.utilizationRateTrend(mdcEquProDto.getEquipmentId(), mdcEquProDto.getEquipmentName(), mdcEquProDto.getEquipmentType(), date, mdcUtilizationRateList));
                    }
                    mdcEfficiencyListDto.setDataList(list);
                    listDtos.add(mdcEfficiencyListDto);
                }
            }
            result.setMdcEfficiencyList(listDtos);
        }
        return result;
    }
    private MdcUtilizationResultDto utilizationRateTrend(String equipmentId, String equipmentName, String equipmentType, String date, List<MdcUtilizationRate> mdcUtilizationRateList) {
        MdcUtilizationResultDto dto = new MdcUtilizationResultDto();
        dto.setEquipmentId(equipmentId);
        dto.setEquipmentName(equipmentName);
        dto.setEquipmentType(equipmentType);
        dto.setTheDate(date);
        MdcEquipmentStatisticalInfo mdcEquipmentStatisticalInfo = mdcEquipmentStatisticalInfoService.findMdcEquipmentStatisticalInfo(equipmentId, date);
        if (mdcEquipmentStatisticalInfo != null) {
            dto.setUtilizationRate(mdcEquipmentStatisticalInfo.getProcessLong().divide(new BigDecimal("86400"), 6, RoundingMode.HALF_UP));
        } else {
            dto.setUtilizationRate(new BigDecimal("0"));
        }
        long rate = dto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
        for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
            if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                dto.setColor(mdcUtilizationRate.getRateParameterColor());
            }
        }
        if (StringUtils.isBlank(dto.getColor())) {
            dto.setColor(mdcUtilizationRateList.get(mdcUtilizationRateList.size() - 1).getRateParameterColor());
        }
        return dto;
    }
    @Override
    public List<BigDecimal> getEfficiencyRate(String equipmentId, String date) {
        return mdcEfficiencyReportMapper.getEfficiencyRate(equipmentId, date);
    }
    /**
     * 利用率列表导出
     *
     * @param vo
     * @return
     */
    @Override
    public ModelAndView exportEfficiencyXls(MdcEfficiencyReportQueryVo vo){
        LoginUser user = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 获取设备 ID 列表
        List<String> equipmentIds = getEquipmentIds(user.getId(), vo);
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            vo.setEquipmentIdList(equipmentIds);
        }
        // 如果设备 ID 列表为空,直接返回
        if (vo.getEquipmentIdList() == null || vo.getEquipmentIdList().isEmpty()) {
            throw new JeecgBootException("无数据");
        }
        // 获取设备 ID 列表
        List<String> equipmentIdList = mdcEquipmentService.listEquipmentId(vo);
        if (equipmentIdList == null || equipmentIdList.isEmpty()) {
            throw new JeecgBootException("无数据");
        }
        vo.setEquipmentIdList(equipmentIdList);
        // 3. 准备设备数据
        List<MdcEfficiencyListDto> exportData = new ArrayList<>();
        // 获取日期列表并按月分组
        List<String> dates = DateUtils.getDatesStringList2(DateUtils.getShortDate2(vo.getStartTime()), DateUtils.getShortDate2(vo.getEndTime()));
        Map<String, List<String>> groupedByMonth = dates.stream()
                .collect(Collectors.groupingBy(
                        date -> date.substring(0, 6) // 提取年月(如 "202405")
                ));
        // 2. 提取每月的首尾日期
        List<Map<String, Object>> monthRanges = groupedByMonth.entrySet().stream()
                .map(entry -> {
                    List<String> monthDates = entry.getValue();
                    Map<String, Object> map = new HashMap<>();
                    map.put("startTime", monthDates.get(0));
                    map.put("endTime", monthDates.get(monthDates.size() - 1));
                    map.put("dateList", monthDates);
                    return map;
                })
                .collect(Collectors.toList());
        for (Map<String, Object> monthRange : monthRanges) {
            List<MdcEfficiencyListDto> listDtos = new ArrayList<>();
            vo.setStartTime((String) monthRange.get("startTime"));
            vo.setEndTime((String) monthRange.get("endTime"));
            List<String> dateList = (List<String>) monthRange.get("dateList");
            // 查询设备效率数据
            List<MdcEfficiencyDto> efficiencyList = mdcEfficiencyReportMapper.efficiencyList(vo);
            // 处理数据
            // 根据类型树处理不同的层级
            if ("2".equals(vo.getTypeTree())) {
                // 部门层级
                listDtos = processDeLevel(vo, efficiencyList, dateList);
            } else {
                // 产线层级
                listDtos = processProLevel(vo, efficiencyList, dateList);
            }
            if (exportData.isEmpty()) {
                exportData.addAll(listDtos);
            } else {
                Map<String, MdcEfficiencyListDto> map = listDtos.stream().collect(Collectors.toMap(MdcEfficiencyListDto::getEquipmentId, a -> a, (k1, k2) -> k1));
                exportData.forEach(mdcEfficiencyListDto -> {
                    List<MdcEfficiencyResultDto> dataList = mdcEfficiencyListDto.getDataList();
                    if (map.containsKey(mdcEfficiencyListDto.getEquipmentId())) {
                        MdcEfficiencyListDto mdcEfficiencyListDto1 = map.get(mdcEfficiencyListDto.getEquipmentId());
                        List<MdcEfficiencyResultDto> dataList1 = mdcEfficiencyListDto1.getDataList();
                        dataList.addAll(dataList1);
                        mdcEfficiencyListDto.setDataList(dataList);
                    }
                });
            }
        }
        // 数据排序
        exportData = exportData.stream().sorted(Comparator.comparing(MdcEfficiencyListDto::getLevel2)).sorted(Comparator.comparing(MdcEfficiencyListDto::getLevel3)).collect(Collectors.toList());
        // 1. 创建工作簿和工作表
        XSSFWorkbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("利用率数据");
        // 3. 准备设备数据
        // 创建样式
        CellStyle centerStyle = createCenterStyle(workbook);
        CellStyle fixedHeaderStyle = createFixedHeaderStyle(workbook);
        CellStyle dateHeaderStyle = createDateHeaderStyle(workbook);
        CellStyle metricHeaderStyle = createMetricHeaderStyle(workbook);
//        dates.add("合计");
//        dates.add("平均");
        // 写入标题行
        writeHeaderRows(sheet, fixedHeaderStyle, dateHeaderStyle, metricHeaderStyle, dates);
        // 写入数据行
        writeDataRows(sheet, centerStyle, exportData, dates);
        // 添加自适应列宽(所有列,从0开始到最后一列)
//        autoSizeAllColumns(sheet, 0, sheet.getRow(0).getLastCellNum() - 1);
        // 7. 将工作簿转换为字节数组输出流
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            workbook.write(bos);
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 具体实现可能需要根据你的项目结构进行调整
        ModelAndView mv = new ModelAndView(new CustomExcelView(bos.toByteArray()));
        return mv;
    }
    /**
     * 自适应所有列宽(处理合并单元格)
     * @param sheet 工作表
     * @param startCol 起始列索引
     * @param endCol 结束列索引
     */
    private void autoSizeAllColumns(Sheet sheet, int startCol, int endCol) {
        // 先处理合并单元格对列宽的影响
        adjustMergedCells(sheet);
        // 自动调整列宽
        for (int i = startCol; i <= endCol; i++) {
            sheet.autoSizeColumn(i);
            // 解决POI自动列宽过窄问题,增加额外宽度(单位:1/256字符宽度,这里增加200相当于约3个字符)
            sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 1800);
        }
    }
    /**
     * 处理合并单元格,确保列宽计算正确
     * (POI的autoSizeColumn对合并单元格支持不佳,需要手动展开计算)
     */
    private void adjustMergedCells(Sheet sheet) {
        List<CellRangeAddress> mergedRegions = new ArrayList<>();
        for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
            mergedRegions.add(sheet.getMergedRegion(i));
        }
        for (CellRangeAddress region : mergedRegions) {
            int firstCol = region.getFirstColumn();
            int lastCol = region.getLastColumn();
            if (firstCol == lastCol) continue; // 单列合并无需处理
            // 计算合并区域的最大宽度
            int maxWidth = 0;
            for (int row = region.getFirstRow(); row <= region.getLastRow(); row++) {
                Row rowData = sheet.getRow(row);
                if (rowData == null) continue;
                Cell cell = rowData.getCell(firstCol);
                if (cell == null) continue;
                int width = getCellWidth(cell);
                if (width > maxWidth) {
                    maxWidth = width;
                }
            }
            // 应用到所有合并列(只设置首列宽度,POI会自动同步到合并列)
            sheet.setColumnWidth(firstCol, maxWidth);
        }
    }
    /**
     * 获取单元格内容宽度(考虑字体和内容)
     */
    private int getCellWidth(Cell cell) {
        // 通过Sheet获取Workbook,兼容性更好
        Workbook workbook = cell.getSheet().getWorkbook();
        CellStyle style = cell.getCellStyle();
        Font font = workbook.getFontAt(style.getFontIndex());
        String text = cell.getStringCellValue();
        // 计算文本宽度(粗略估计,可根据实际字体调整)
        int width = text.length() * 256;
        if (font.getBold()) width = (int) (width * 1.2); // 加粗字体增加20%宽度
        return width + 512; // 增加额外宽度
    }
    /**
     * 处理部门层级
     */
    private List<MdcEfficiencyListDto> processDeLevel(MdcEfficiencyReportQueryVo vo, List<MdcEfficiencyDto> efficiencyList, List<String> dates) {
        List<MdcEquDepDto> equipmentList = mdcEquipmentService.findEquDepList(vo.getEquipmentIdList());
        List<SysDepart> departList = sysDepartService.list(new LambdaQueryWrapper<SysDepart>()
                .ne(SysDepart::getDelFlag, CommonConstant.DEL_FLAG_1.toString())
                .orderByAsc(SysDepart::getDepartOrder));
        return equipmentList.stream().map(mdcEquDepDto -> {
            MdcEfficiencyListDto mdcEfficiencyListDto = createEfficiencyListDto(mdcEquDepDto);
            setDepartmentLevels(mdcEfficiencyListDto, mdcEquDepDto, departList);
            mdcEfficiencyListDto.setDataList(processEffData(efficiencyList, dates, mdcEquDepDto.getEquipmentId()));
            return mdcEfficiencyListDto;
        }).collect(Collectors.toList());
    }
    private List<MdcEfficiencyListDto> processProLevel(MdcEfficiencyReportQueryVo vo, List<MdcEfficiencyDto> efficiencyList, List<String> dates) {
        List<MdcEquProDto> equipmentList = mdcEquipmentService.findEquProList(vo.getEquipmentIdList());
        List<MdcProduction> productionList = mdcProductionService.list(new LambdaQueryWrapper<MdcProduction>()
                .ne(MdcProduction::getDelFlag, CommonConstant.DEL_FLAG_1.toString())
                .orderByAsc(MdcProduction::getProductionOrder));
        return equipmentList.stream().map(mdcEquProDto -> {
            MdcEfficiencyListDto mdcEfficiencyListDto = createEfficiencyListDto(mdcEquProDto);
            setProductionLevels(mdcEfficiencyListDto, mdcEquProDto, productionList);
            mdcEfficiencyListDto.setDataList(processEffData(efficiencyList, dates, mdcEquProDto.getEquipmentId()));
            return mdcEfficiencyListDto;
        }).collect(Collectors.toList());
    }
    private List<MdcEfficiencyResultDto> processEffData(List<MdcEfficiencyDto> efficiencyList, List<String> dates, String equipmentId) {
        List<MdcEfficiencyResultDto> list = new ArrayList<>();
//        MdcEfficiencyResultDto avgDto = new MdcEfficiencyResultDto();
//        avgDto.setTheDate("平均值");
//        MdcEfficiencyResultDto sumDto = new MdcEfficiencyResultDto();
//        sumDto.setTheDate("合计");
        for (String date : dates) {
            MdcEfficiencyResultDto dto = effRate(efficiencyList, date, equipmentId);
            list.add(dto);
        }
//        sumDto.setProcessLong(avgDto.getProcessLong());
//        avgDto.setProcessLong(avgDto.getProcessLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
//        avgDto.setUtilizationRate(avgDto.getUtilizationRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
//        sumDto.setUtilizationRate(avgDto.getUtilizationRate());
//        avgDto.setStartRate(avgDto.getStartRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
//        sumDto.setStartRate(avgDto.getStartRate());
//        avgDto.setOpenRate(avgDto.getOpenRate().divide(new BigDecimal(dates.size()), 4, RoundingMode.HALF_UP));
//        sumDto.setOpenRate(avgDto.getOpenRate());
//        sumDto.setOpenLong(avgDto.getOpenLong());
//        avgDto.setOpenLong(avgDto.getOpenLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
//        sumDto.setWaitLong(avgDto.getWaitLong());
//        avgDto.setWaitLong(avgDto.getWaitLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
//        sumDto.setCloseLong(avgDto.getCloseLong());
//        avgDto.setCloseLong(avgDto.getCloseLong().divide(new BigDecimal(dates.size()), 0, RoundingMode.HALF_UP));
//
//        list.add(sumDto);
//        list.add(avgDto);
        return list;
    }
    private MdcEfficiencyResultDto effRate(List<MdcEfficiencyDto> efficiencyList, String date, String equipmentId) {
        MdcEfficiencyResultDto mdcEfficiencyResultDto = new MdcEfficiencyResultDto();
        if (efficiencyList != null && !efficiencyList.isEmpty()) {
            Map<String, MdcEfficiencyDto> collect = new HashMap<>();
            efficiencyList.forEach(mdcEfficiencyDto -> {
                if (!collect.containsKey(mdcEfficiencyDto.getEquipmentId() + "_" + mdcEfficiencyDto.getTheDate())) {
                    collect.put(mdcEfficiencyDto.getEquipmentId() + "_" + mdcEfficiencyDto.getTheDate(), mdcEfficiencyDto);
                }
            });
            if (collect.containsKey(equipmentId + "_" + date)) {
                MdcEfficiencyDto efficiencyDto = collect.get(equipmentId + "_" + date);
                mdcEfficiencyResultDto.setTheDate(efficiencyDto.getTheDate());
                mdcEfficiencyResultDto.setProcessLong(efficiencyDto.getProcessLong().divide(new BigDecimal("3600"), 2, RoundingMode.HALF_UP));
                mdcEfficiencyResultDto.setUtilizationRate(efficiencyDto.getUtilizationRate().multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP));
                mdcEfficiencyResultDto.setStartRate(efficiencyDto.getStartRate().multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP));
                mdcEfficiencyResultDto.setOpenRate(efficiencyDto.getOpenRate().multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP));
                mdcEfficiencyResultDto.setOpenLong(efficiencyDto.getOpenLong().divide(new BigDecimal("3600"), 2, RoundingMode.HALF_UP));
                mdcEfficiencyResultDto.setWaitLong(efficiencyDto.getWaitLong().divide(new BigDecimal("3600"), 2, RoundingMode.HALF_UP));
                mdcEfficiencyResultDto.setCloseLong(efficiencyDto.getCloseLong().divide(new BigDecimal("3600"), 2, RoundingMode.HALF_UP));
            } else {
                mdcEfficiencyResultDto.setTheDate(date);
            }
        } else {
            mdcEfficiencyResultDto.setTheDate(date);
            mdcEfficiencyResultDto.setProcessLong(new BigDecimal("0"));
            mdcEfficiencyResultDto.setUtilizationRate(new BigDecimal("0"));
            mdcEfficiencyResultDto.setStartRate(new BigDecimal("0"));
            mdcEfficiencyResultDto.setOpenRate(new BigDecimal("0"));
            mdcEfficiencyResultDto.setOpenLong(new BigDecimal("0"));
            mdcEfficiencyResultDto.setWaitLong(new BigDecimal("0"));
            mdcEfficiencyResultDto.setCloseLong(new BigDecimal("0"));
        }
        return mdcEfficiencyResultDto;
    }
    private void writeHeaderRows(Sheet sheet, CellStyle fixedHeaderStyle, CellStyle dateHeaderStyle, CellStyle metricHeaderStyle, List<String> dateList) {
        Row titleRow1 = sheet.createRow(0);
        Row titleRow2 = sheet.createRow(1);
        int colIndex = 0;
        // 写入固定列标题(公司、车间等)
        String[] fixedHeaders = {"公司", "车间", "工段", "设备ID", "设备名称", "设备类型"};
        for (int i = 0; i < fixedHeaders.length; i++) {
            createCellWithStyle(titleRow1, colIndex, fixedHeaders[i], fixedHeaderStyle);
            createCellWithStyle(titleRow2, colIndex, "", fixedHeaderStyle);
            // 合并单元格(跨行不跨列)
            CellRangeAddress region = new CellRangeAddress(0, 1, colIndex, colIndex);
            sheet.addMergedRegion(region);
            colIndex++;
        }
        // 写入日期,跨6列合并
        for (String date : dateList) {
            CellRangeAddress dateRegion = new CellRangeAddress(0, 0, colIndex, colIndex + 5);
            sheet.addMergedRegion(dateRegion);
            createCellWithStyle(titleRow1, colIndex, date, dateHeaderStyle);
            colIndex += 6;
        }
        // 写入日期指标标题(每个日期对应6列)
        colIndex = 6;
        for (String date : dateList) {
            createCellWithStyle(titleRow2, colIndex++, "利用率(%)", metricHeaderStyle);
            createCellWithStyle(titleRow2, colIndex++, "开机率(%)", metricHeaderStyle);
            createCellWithStyle(titleRow2, colIndex++, "开机时长(小时)", metricHeaderStyle);
            createCellWithStyle(titleRow2, colIndex++, "加工时长(小时)", metricHeaderStyle);
            createCellWithStyle(titleRow2, colIndex++, "待机时长(小时)", metricHeaderStyle);
            createCellWithStyle(titleRow2, colIndex++, "关机时长(小时)", metricHeaderStyle);
        }
    }
    private CellStyle createCenterStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        // 添加完整边框
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }
    private CellStyle createFixedHeaderStyle(Workbook workbook) {
        CellStyle style = createCenterStyle(workbook);
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }
    private CellStyle createDateHeaderStyle(Workbook workbook) {
        CellStyle style = createCenterStyle(workbook);
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }
    private CellStyle createMetricHeaderStyle(Workbook workbook) {
        CellStyle style = createCenterStyle(workbook);
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        Font font = workbook.createFont();
        font.setBold(true);
        style.setFont(font);
        return style;
    }
    private void writeDataRows(Sheet sheet, CellStyle style, List<MdcEfficiencyListDto> exportData, List<String> dateList) {
        int rowIndex = 2;
        for (MdcEfficiencyListDto device : exportData) {
            Row dataRow = sheet.createRow(rowIndex++);
            int colIndex = 0;
            // 写入固定列数据(公司、车间等)
            createCellWithStyle(dataRow, colIndex++, device.getLevel1(), style);
            createCellWithStyle(dataRow, colIndex++, device.getLevel2(), style);
            createCellWithStyle(dataRow, colIndex++, device.getLevel3(), style);
            createCellWithStyle(dataRow, colIndex++, device.getEquipmentId(), style);
            createCellWithStyle(dataRow, colIndex++, device.getEquipmentName(), style);
            createCellWithStyle(dataRow, colIndex++, device.getEquipmentType(), style);
            // 写入日期指标数据(每个日期对应6列)
            for (String date : dateList) {
                // 确保dateStr对应的Map已初始化
                MdcEfficiencyResultDto dateData = device.getDataList().stream().filter(mdcEfficiencyResultDto -> date.equals(mdcEfficiencyResultDto.getTheDate())).collect(Collectors.toList()).get(0);
                createCellWithStyle(dataRow, colIndex++, dateData.getUtilizationRate().doubleValue(), style);
                createCellWithStyle(dataRow, colIndex++, dateData.getOpenRate().doubleValue(), style);
                createCellWithStyle(dataRow, colIndex++, dateData.getOpenLong().doubleValue(), style);
                createCellWithStyle(dataRow, colIndex++, dateData.getProcessLong().doubleValue(), style);
                createCellWithStyle(dataRow, colIndex++, dateData.getWaitLong().doubleValue(), style);
                createCellWithStyle(dataRow, colIndex++, dateData.getCloseLong().doubleValue(), style);
            }
        }
    }
    private void createCellWithStyle(Row row, int colIndex, Object value, CellStyle style) {
        Cell cell = row.createCell(colIndex);
        if (value instanceof String) {
            cell.setCellValue((String) value);
        } else if (value instanceof Double) {
            cell.setCellValue((Double) value);
        }
        cell.setCellStyle(style);
    }
    private MdcUtilizationResultDto utilizationRate(String equipmentId, String equipmentName, String equipmentType, Date startTime, Date endTime, String date, List<MdcUtilizationRate> mdcUtilizationRateList) {
        MdcUtilizationResultDto dto = new MdcUtilizationResultDto();
        dto.setEquipmentId(equipmentId);
        dto.setEquipmentName(equipmentName);
        dto.setEquipmentType(equipmentType);
        dto.setTheDate(date);
        List<MdcEquipmentRunningSection> runningSections = mdcEquipmentRunningSectionService.listEquipmentRunningSection(equipmentId, startTime.getTime(), endTime.getTime());
        if (runningSections != null && !runningSections.isEmpty()) {
            // 时间修正
            runningSections.get(0).setStartTime(startTime);
            if (runningSections.size() > 1) {
                runningSections.get(runningSections.size() - 1).setEndTime(endTime);
            } else {
                runningSections.get(0).setEndTime(endTime);
            }
            // 利用率计算
            BigDecimal processLong = new BigDecimal("0");
            for (MdcEquipmentRunningSection runningSection : runningSections) {
                if (runningSection.getStatus() == 3) {
                    long duration = DateUtils.differentSecond(runningSection.getStartTime(), runningSection.getEndTime());
                    processLong = processLong.add(new BigDecimal(duration));
                }
            }
            BigDecimal totalLong = new BigDecimal(DateUtils.differentSecond(startTime, endTime));
            BigDecimal utilizationRate = processLong.divide(totalLong, 6, BigDecimal.ROUND_HALF_UP);
            dto.setUtilizationRate(utilizationRate);
        } else {
            dto.setUtilizationRate(new BigDecimal("0"));
        }
        long rate = dto.getUtilizationRate().multiply(new BigDecimal("100")).longValue();
        for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
            if (rate >= mdcUtilizationRate.getMinimumRange() && rate < mdcUtilizationRate.getMaximumRange()) {
                dto.setColor(mdcUtilizationRate.getRateParameterColor());
            }
        }
        if (StringUtils.isBlank(dto.getColor())) {
            dto.setColor(mdcUtilizationRateList.get(mdcUtilizationRateList.size() - 1).getRateParameterColor());
        }
        return dto;
    }
    private StatisticalAnalysisVo efficiencyStatisticalRate(List<MdcEfficiencyDto> efficiencyList) {
        StatisticalAnalysisVo vo = new StatisticalAnalysisVo();
        for (MdcEfficiencyDto mdcEfficiencyDto : efficiencyList) {
@@ -953,7 +2292,7 @@
        return vo;
    }
    private MdcEfficiencyResultDto efficiencyRate(List<MdcEfficiencyDto> efficiencyList, String date, String equipmentId, List<MdcUtilizationRate> mdcUtilizationRateList) {
    private MdcEfficiencyResultDto efficiencyRate(List<MdcEfficiencyDto> efficiencyList, String date, String equipmentId, List<MdcUtilizationRate> mdcUtilizationRateList, MdcEfficiencyResultDto efficiencyResultDto) {
        MdcEfficiencyResultDto mdcEfficiencyResultDto = new MdcEfficiencyResultDto();
        if (efficiencyList != null && !efficiencyList.isEmpty()) {
            for (MdcEfficiencyDto efficiencyDto : efficiencyList) {
@@ -989,7 +2328,28 @@
                }
            }
        }
        if (StringUtils.isBlank(mdcEfficiencyResultDto.getColor())) {
            mdcEfficiencyResultDto.setTheDate(date);
            mdcEfficiencyResultDto.setProcessLong(new BigDecimal("0"));
            mdcEfficiencyResultDto.setUtilizationRate(new BigDecimal("0"));
            mdcEfficiencyResultDto.setStartRate(new BigDecimal("0"));
            mdcEfficiencyResultDto.setOpenRate(new BigDecimal("0"));
            mdcEfficiencyResultDto.setOpenLong(new BigDecimal("0"));
            mdcEfficiencyResultDto.setWaitLong(new BigDecimal("0"));
            mdcEfficiencyResultDto.setCloseLong(new BigDecimal("0"));
            for (MdcUtilizationRate mdcUtilizationRate : mdcUtilizationRateList) {
                if (0 >= mdcUtilizationRate.getMinimumRange() && 0 < mdcUtilizationRate.getMaximumRange()) {
                    mdcEfficiencyResultDto.setColor(mdcUtilizationRate.getRateParameterColor());
                }
            }
        }
        efficiencyResultDto.setProcessLong(efficiencyResultDto.getProcessLong().add(mdcEfficiencyResultDto.getProcessLong()));
        efficiencyResultDto.setUtilizationRate(efficiencyResultDto.getUtilizationRate().add(mdcEfficiencyResultDto.getUtilizationRate()));
        efficiencyResultDto.setStartRate(efficiencyResultDto.getStartRate().add(mdcEfficiencyResultDto.getStartRate()));
        efficiencyResultDto.setOpenRate(efficiencyResultDto.getOpenRate().add(mdcEfficiencyResultDto.getOpenRate()));
        efficiencyResultDto.setOpenLong(efficiencyResultDto.getOpenLong().add(mdcEfficiencyResultDto.getOpenLong()));
        efficiencyResultDto.setWaitLong(efficiencyResultDto.getWaitLong().add(mdcEfficiencyResultDto.getWaitLong()));
        efficiencyResultDto.setCloseLong(efficiencyResultDto.getCloseLong().add(mdcEfficiencyResultDto.getCloseLong()));
        return mdcEfficiencyResultDto;
    }