From 1a22f9f330ef0a51cd2a838932c1499346365dae Mon Sep 17 00:00:00 2001
From: Lius <Lius2225@163.com>
Date: 星期四, 29 五月 2025 09:30:48 +0800
Subject: [PATCH] 批量导出设备利用率

---
 lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/util/CustomExcelView.java                          |   32 +++
 lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEfficiencyReportServiceImpl.java   |  489 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEfficiencyReportController.java      |    8 
 lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml |    2 
 lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/MdcEfficiencyReportService.java            |    9 +
 5 files changed, 516 insertions(+), 24 deletions(-)

diff --git a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEfficiencyReportController.java b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEfficiencyReportController.java
index 96ef9b8..ffa2614 100644
--- a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEfficiencyReportController.java
+++ b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/controller/MdcEfficiencyReportController.java
@@ -14,8 +14,10 @@
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.servlet.ModelAndView;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
 
 /**
  * @author: LiuS
@@ -40,6 +42,12 @@
         return Result.OK(result);
     }
 
+    @ApiOperation(value = "璁惧鏁堢巼鎶ヨ〃-鍒╃敤鐜囧垪琛ㄥ鍑�", notes = "璁惧鏁堢巼鎶ヨ〃-鍒╃敤鐜囧垪琛ㄥ鍑�")
+    @RequestMapping(value = "/exportEfficiencyXls")
+    public ModelAndView exportEfficiencyXls(HttpServletRequest request, MdcEfficiencyReportQueryVo vo) {
+        return mdcEfficiencyReportService.exportEfficiencyXls(vo);
+    }
+
     @AutoLog(value = "璁惧鏁堢巼鎶ヨ〃-寮�鍔ㄧ巼鍒楄〃鏌ヨ")
     @ApiOperation(value = "璁惧鏁堢巼鎶ヨ〃-寮�鍔ㄧ巼鍒楄〃鏌ヨ", notes = "璁惧鏁堢巼鎶ヨ〃-寮�鍔ㄧ巼鍒楄〃鏌ヨ")
     @GetMapping("/efficiencyPOList")
diff --git a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/MdcEfficiencyReportService.java b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/MdcEfficiencyReportService.java
index d3dccf2..0a81a8b 100644
--- a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/MdcEfficiencyReportService.java
+++ b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/MdcEfficiencyReportService.java
@@ -3,6 +3,7 @@
 import org.jeecg.modules.mdc.dto.ComparativeAnalysisDto;
 import org.jeecg.modules.mdc.dto.DayUtilizationRateDto;
 import org.jeecg.modules.mdc.vo.*;
+import org.springframework.web.servlet.ModelAndView;
 
 import java.math.BigDecimal;
 import java.util.List;
@@ -102,4 +103,12 @@
      * @return
      */
     List<BigDecimal> getEfficiencyRate(String equipmentId, String date);
+
+    /**
+     * 鍒╃敤鐜囧垪琛ㄥ鍑�
+     *
+     * @param vo
+     * @return
+     */
+    ModelAndView exportEfficiencyXls(MdcEfficiencyReportQueryVo vo);
 }
diff --git a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEfficiencyReportServiceImpl.java b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEfficiencyReportServiceImpl.java
index c5899fb..4d4d140 100644
--- a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEfficiencyReportServiceImpl.java
+++ b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/service/impl/MdcEfficiencyReportServiceImpl.java
@@ -2,12 +2,18 @@
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.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.*;
@@ -17,8 +23,11 @@
 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.math.RoundingMode;
 import java.time.LocalDate;
@@ -196,24 +205,42 @@
      */
     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;
+            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;
+                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;
+                        case "1":
+                            dto.setLevel1(parent.getDepartName());
+                            break;
+                        case "2":
+                            dto.setLevel2(parent.getDepartName());
+                            break;
+                        case "3":
+                            dto.setLevel3(parent.getDepartName());
+                            break;
                     }
                 });
             }
@@ -225,24 +252,42 @@
      */
     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;
+            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;
+                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;
+                        case "1":
+                            dto.setLevel1(parent.getProductionName());
+                            break;
+                        case "2":
+                            dto.setLevel2(parent.getProductionName());
+                            break;
+                        case "3":
+                            dto.setLevel3(parent.getProductionName());
+                            break;
                     }
                 });
             }
@@ -451,7 +496,7 @@
         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);
@@ -1728,10 +1773,6 @@
 
                     List<MdcUtilizationResultDto> list = new ArrayList<>();
                     for (String date : dateList) {
-//                        Date startTime = DateUtils.toDate(date + " 00:00:00", DateUtils.STR_DATE_TIME_SMALL);
-//                        Date endTime = DateUtils.toDate(date + " 00:00:00", DateUtils.STR_DATE_TIME_SMALL);
-//                        endTime = DateUtils.addDays(endTime, 1);
-//                        list.add(this.utilizationRate(mdcEquDepDto.getEquipmentId(), mdcEquDepDto.getEquipmentName(), mdcEquDepDto.getEquipmentType(), startTime, endTime, date, mdcUtilizationRateList));
                         list.add(this.utilizationRateTrend(mdcEquDepDto.getEquipmentId(), mdcEquDepDto.getEquipmentName(), mdcEquDepDto.getEquipmentType(), date, mdcUtilizationRateList));
                     }
                     mdcEfficiencyListDto.setDataList(list);
@@ -1790,6 +1831,408 @@
         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);
+            // 瑙e喅POI鑷姩鍒楀杩囩獎闂锛屽鍔犻澶栧搴︼紙鍗曚綅锛�1/256瀛楃瀹藉害锛岃繖閲屽鍔�200鐩稿綋浜庣害3涓瓧绗︼級
+            sheet.setColumnWidth(i, sheet.getColumnWidth(i) + 1800);
+        }
+    }
+
+    /**
+     * 澶勭悊鍚堝苟鍗曞厓鏍硷紝纭繚鍒楀璁$畻姝g‘
+     * 锛圥OI鐨刟utoSizeColumn瀵瑰悎骞跺崟鍏冩牸鏀寔涓嶄匠锛岄渶瑕佹墜鍔ㄥ睍寮�璁$畻锛�
+     */
+    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;
+                }
+            }
+
+            // 搴旂敤鍒版墍鏈夊悎骞跺垪锛堝彧璁剧疆棣栧垪瀹藉害锛孭OI浼氳嚜鍔ㄥ悓姝ュ埌鍚堝苟鍒楋級
+            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 = efficiencyList.stream().collect(Collectors.toMap(dto -> dto.getEquipmentId() + "_" + dto.getTheDate(), dto -> dto));
+            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瀵瑰簲鐨凪ap宸插垵濮嬪寲
+                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);
diff --git a/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/util/CustomExcelView.java b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/util/CustomExcelView.java
new file mode 100644
index 0000000..63c1778
--- /dev/null
+++ b/lxzn-module-mdc/src/main/java/org/jeecg/modules/mdc/util/CustomExcelView.java
@@ -0,0 +1,32 @@
+package org.jeecg.modules.mdc.util;
+
+import org.springframework.web.servlet.view.AbstractView;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Map;
+
+/**
+ * @Author: Lius
+ * @CreateTime: 2025-05-28
+ * @Description:
+ */
+public class CustomExcelView extends AbstractView {
+    private byte[] excelData;
+
+    public CustomExcelView(byte[] excelData) {
+        this.excelData = excelData;
+        setContentType("application/vnd.openxmlformats - officedocument.spreadsheetml.sheet");
+    }
+
+    @Override
+    protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
+        response.setHeader("Content - Disposition", "attachment; filename=鍒╃敤鐜囨暟鎹�.xlsx");
+        response.setContentLength(excelData.length);
+        ServletOutputStream out = response.getOutputStream();
+        out.write(excelData);
+        out.flush();
+        out.close();
+    }
+}
diff --git a/lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml b/lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml
index b40648b..a1edd02 100644
--- a/lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml
+++ b/lxzn-module-system/lxzn-system-biz/src/main/java/org/jeecg/modules/system/mapper/xml/SysUserMapper.xml
@@ -215,7 +215,7 @@
 				LEFT JOIN sys_user_role t2 ON t1.id = t2.user_id
 				LEFT JOIN sys_role t3 ON t2.role_id = t3.id
 		WHERE
-			t3.role_code = #{roleCode} AND equipment_ids LIKE concat(concat('%',#{equipmentId}),'%')
+			t3.role_code = #{roleCode} AND t1.equipment_ids LIKE concat(concat('%',#{equipmentId}),'%')
 	</select>
     <select id="getUserByRoleCodeList" resultType="org.jeecg.modules.system.entity.SysUser">
 		SELECT

--
Gitblit v1.9.3