Jelajahi Sumber

增加生产日报数据导出接口,bug修复

wangb 6 hari lalu
induk
melakukan
ba650e0a42

+ 10 - 1
runeconomy-xk/src/main/java/com/gyee/runeconomy/controller/ProEconEquipmentInfoJsController.java

@@ -8,6 +8,7 @@ import com.gyee.runeconomy.service.ProEconEquipmentInfoJsService;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
@@ -42,7 +43,7 @@ public class ProEconEquipmentInfoJsController {
      * 查询单个记录
      */
     @PostMapping("/query")
-    public  List<ProEconEquipmentInfoJs> query(@RequestBody Map<String, List<String>> name) {
+    public List<ProEconEquipmentInfoJs> query(@RequestBody Map<String, List<String>> name) {
 
         return proEconEquipmentInfoJsService.query(name);
 
@@ -57,5 +58,13 @@ public class ProEconEquipmentInfoJsController {
     }
 
 
+    @GetMapping("/dailyReport/export")
+    public void dailyReportExport(@RequestParam("date") String date, HttpServletResponse response) throws Exception {
+
+        proEconEquipmentInfoJsService.dailyReportExport(date, response);
+
+    }
+
+
 }
 

+ 0 - 1
runeconomy-xk/src/main/java/com/gyee/runeconomy/controller/SingleAnalysisController.java

@@ -265,7 +265,6 @@ public class SingleAnalysisController {
 
             byzb.setWtcode(wtcode);
             SingleAnalysisVo singleAnalysisVo = singleAnalysisService.SingleAnalysisTurbineinfoday(wtId, year, month, byzb, "byzb");
-
             cal.add(Calendar.YEAR, -1);
             Date lastYear = DateUtils.truncate(cal.getTime());
             LocalDate localDate = lastYear.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

+ 3 - 0
runeconomy-xk/src/main/java/com/gyee/runeconomy/service/ProEconEquipmentInfoJsService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.gyee.runeconomy.model.vo.ProEconEquipmentInfoJsVo;
 import com.gyee.runeconomy.model.vo.ProductionDailyReportVo;
 
+import javax.servlet.http.HttpServletResponse;
 import java.util.List;
 import java.util.Map;
 
@@ -23,4 +24,6 @@ public interface ProEconEquipmentInfoJsService extends IService<ProEconEquipment
     boolean update(List<ProEconEquipmentInfoJsVo> jsls);
 
     ProductionDailyReportVo queryAll(String date) throws Exception;
+
+    void dailyReportExport(String date, HttpServletResponse response) throws Exception;
 }

+ 9 - 7
runeconomy-xk/src/main/java/com/gyee/runeconomy/service/agc/AgcDeviateService.java

@@ -171,7 +171,7 @@ public class AgcDeviateService {
         if (ap.getMultiplier() != 1) {
             for (TsDoubleTsData pd : lpds) {
                 long now = new Date().getTime();
-                if (pd.getTs()> now){
+                if (pd.getTs() > now) {
                     pd.setDoubleValue(0.0);
                 } else {
                     pd.setDoubleValue(pd.getDoubleValue() * ap.getMultiplier());
@@ -367,9 +367,9 @@ public class AgcDeviateService {
             List<ProBasicEquipmentPoint> speedPoint = proBasicEquipmentPoints.stream().filter(p -> p.getUniformCode().equals("AI066")).collect(Collectors.toList());
             List<PointData> historyspeedDatas = edosUtil.getHistoryDatasSnap(speedPoint.get(0).getNemCode(), startTs, endTs, interval);
             List<Double> speedDatas = historyspeedDatas.stream()
-                    .map(point->{
+                    .map(point -> {
                         double value = point.getPointValueInDouble();
-                        return  NumberUtil.round(value, 2).doubleValue();
+                        return NumberUtil.round(value, 2).doubleValue();
                     })
                     .collect(Collectors.toList());
             spa.setWindSpeed(speedDatas);
@@ -387,13 +387,15 @@ public class AgcDeviateService {
             ConcurrentHashMap<Double, Double> wtyc = JSON.parseObject(yc, new com.alibaba.fastjson.TypeReference<ConcurrentHashMap<Double, Double>>() {
             }.getType());
             fitcoef.put(firstKey.replaceFirst(powerCurveMonth, ""), wtyc);
-            List<Double> llgl = speedDatas.stream().map(a ->{
+            List<Double> llgl = speedDatas.stream().map(a -> {
                 double ll = 0.0;
-                if (a > 0) {
-                     ll = fitcoef.get(wtId).get(a);
+                if (a > 0 && a < 25) {
+                    ll = fitcoef.get(wtId).get(a);
+                } else if (a >= 25) {
+                    ll = 2000.0;
                 }
                 return ll;
-            } ).collect(Collectors.toList());
+            }).collect(Collectors.toList());
             spa.setTheoreticalPower(llgl);
             ls.add(spa);
             map.put(wtId, ls);

+ 16 - 17
runeconomy-xk/src/main/java/com/gyee/runeconomy/service/auto/impl/ProBasicOriginalCodeServiceImpl.java

@@ -141,29 +141,28 @@ public class ProBasicOriginalCodeServiceImpl extends ServiceImpl<ProBasicOrigina
 
     @Override
     public List<ProBasicOriginalCode> getData(String modelId, String query) {
-        List<ProBasicOriginalCode> oriLists = CacheContext.oriLists;
-
-        List<ProBasicOriginalCode> description = new ArrayList<>(oriLists.stream()
-                .collect(Collectors.toMap(
-                        ProBasicOriginalCode::getDescription,
-                        item -> item,
-                        (existing, replacement) -> existing,
-                        LinkedHashMap::new
-                ))
-                .values());
-
-        if (null != modelId && !modelId.trim().isEmpty() && !"".equals(modelId)) {
-            description = description.stream()
-                    .filter(ori -> ori.getModelId().equals(modelId))
-                    .collect(Collectors.toList());
+        List<ProBasicOriginalCode> oriLists = new ArrayList<>();
+        List<ProBasicOriginalCode> WT2000 = CacheContext.oriMap.get("1101");
+        List<ProBasicOriginalCode> UP2000 = CacheContext.oriMap.get("2301");
+
+        if ("WT2000D121H85".equals(modelId)) {
+            oriLists.addAll(WT2000);
+        } else if ("UP2000-130".equals(modelId)) {
+            oriLists.addAll(UP2000);
+        } else {
+            oriLists.addAll(WT2000);
+            oriLists.addAll(UP2000);
         }
 
         if (null != query && !query.trim().isEmpty() && !"".equals(query)) {
-            description = description.stream()
+            oriLists = oriLists.stream()
                     .filter(ori -> ori.getDescription().contains(query))
                     .collect(Collectors.toList());
         }
-        return description;
+
+        oriLists.sort(Comparator.comparing(ProBasicOriginalCode::getRank));
+
+        return oriLists;
 
     }
 

+ 32 - 17
runeconomy-xk/src/main/java/com/gyee/runeconomy/service/auto/impl/ProEconEquipmentInfoDayTopServiceImpl.java

@@ -2,6 +2,7 @@ package com.gyee.runeconomy.service.auto.impl;
 
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.NumberUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -270,24 +271,38 @@ public class ProEconEquipmentInfoDayTopServiceImpl extends ServiceImpl<ProEconEq
 
     public List<ProEconEquipmentInfoDayTop> getEquipmentInfoDayTopHistoryList_bf(String windturbineId, Integer types, String beginDate, String endDate) {
 
-        QueryWrapper<ProEconEquipmentInfoDayTop> qw = new QueryWrapper<>();
-
-        if (StringUtils.isNotEmpty(windturbineId)) {
-            qw.lambda().eq(ProEconEquipmentInfoDayTop::getWindturbineId, windturbineId);
-        }
-        if (null != types) {
-            qw.lambda().eq(ProEconEquipmentInfoDayTop::getTypes, types);
+//        QueryWrapper<ProEconEquipmentInfoDayTop> qw = new QueryWrapper<>();
+//
+//        if (StringUtils.isNotEmpty(windturbineId)) {
+//            qw.lambda().eq(ProEconEquipmentInfoDayTop::getWindturbineId, windturbineId);
+//        }
+//        if (null != types) {
+//            qw.lambda().eq(ProEconEquipmentInfoDayTop::getTypes, types);
+//        }
+//
+//        if (StringUtils.isNotEmpty(beginDate) && StringUtils.isNotEmpty(endDate))
+//            qw.lambda().ge(ProEconEquipmentInfoDayTop::getRecordDate, DateUtils.parseDate(beginDate)).
+//                    lt(ProEconEquipmentInfoDayTop::getRecordDate, DateUtils.parseDate(endDate));
+//
+//        qw.orderByAsc("record_date");
+//        List<ProEconEquipmentInfoDayTop> list = baseMapper.selectList(qw);
+//        list.stream().forEach(i -> {
+//            i.setNemCode(CacheContext.wtmap.get(i.getWindturbineId()).getAname());
+//        });
+        List<ProEconEquipmentInfoDayTop> list = new ArrayList<>();
+        long days = DateUtil.between(
+                DateUtil.parse(beginDate),
+                DateUtil.parse(endDate),
+                DateUnit.DAY
+        );
+        for (int i = 0; i < days; i++) {
+            ProEconEquipmentInfoDayTop ed = new ProEconEquipmentInfoDayTop();
+            ed.setRecordDate(DateUtil.offsetDay(DateUtil.parse(beginDate), i));
+            ed.setNemCode(CacheContext.wtmap.get(windturbineId).getAname());
+            ed.setWindpowerstationId("NX_FGS_HA_FDC_STA");
+            ed.setWindturbineId(windturbineId);
+            list.add(ed);
         }
-
-        if (StringUtils.isNotEmpty(beginDate) && StringUtils.isNotEmpty(endDate))
-            qw.lambda().ge(ProEconEquipmentInfoDayTop::getRecordDate, DateUtils.parseDate(beginDate)).
-                    lt(ProEconEquipmentInfoDayTop::getRecordDate, DateUtils.parseDate(endDate));
-
-        qw.orderByAsc("record_date");
-        List<ProEconEquipmentInfoDayTop> list = baseMapper.selectList(qw);
-        list.stream().forEach(i -> {
-            i.setNemCode(CacheContext.wtmap.get(i.getWindturbineId()).getAname());
-        });
         return list;
     }
 

+ 1518 - 0
runeconomy-xk/src/main/java/com/gyee/runeconomy/service/impl/ProEconEquipmentInfoJsServiceImpl.java

@@ -13,10 +13,17 @@ import com.gyee.runeconomy.model.vo.ProductionDailyReportVo;
 import com.gyee.runeconomy.service.ProEconEquipmentInfoJsService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.gyee.runeconomy.util.realtimesource.EdosUtil;
+import org.apache.poi.ss.usermodel.*;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.usermodel.XSSFCellStyle;
+import org.apache.poi.xssf.usermodel.XSSFColor;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URLEncoder;
 import java.time.LocalDate;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -38,6 +45,1517 @@ public class ProEconEquipmentInfoJsServiceImpl extends ServiceImpl<ProEconEquipm
     @Resource
     private EdosUtil edosUtil;
 
+
+    @Override
+    public void dailyReportExport(String date, HttpServletResponse response) throws Exception {
+
+        // 1. 获取数据
+        ProductionDailyReportVo vo = queryAll(date);
+
+        // 2. 创建Excel工作簿
+        Workbook workbook = new XSSFWorkbook();
+        Sheet sheet = workbook.createSheet("惠安风电场生产日报");
+
+        // 3. 设置列宽
+        sheet.setColumnWidth(0, 3 * 256);     // A列
+        sheet.setColumnWidth(1, 15 * 256);    // B列
+        sheet.setColumnWidth(2, 26 * 256);    // C列
+        sheet.setColumnWidth(3, 20 * 256);    // D列
+        sheet.setColumnWidth(4, 24 * 256);    // E列
+        sheet.setColumnWidth(5, 13 * 256);    // F列
+        sheet.setColumnWidth(6, 14 * 256);    // G列
+        sheet.setColumnWidth(7, 13 * 256);    // H列
+        sheet.setColumnWidth(8, 13 * 256);    // I列
+        sheet.setColumnWidth(9, 14 * 256);    // J列
+        sheet.setColumnWidth(10, 13 * 256);   // K列
+        sheet.setColumnWidth(11, 13 * 256);   // L列
+        sheet.setColumnWidth(12, 14 * 256);   // M列
+
+        // 4. 创建样式
+        int fontSize =14;
+        CellStyle titleStyle = createTitleStyle(workbook);
+        CellStyle headerGrayStyle = createHeaderGrayStyle(workbook,fontSize); // 灰色背景样式 E1DFDF
+        CellStyle headerBlueStyle = createHeaderBlueStyle(workbook); // 蓝色背景样式 3B95F4
+        CellStyle headerWhiteStyle = createHeaderWhiteStyle(workbook); // 白色背景表头样式
+        CellStyle dataStyle = createDataStyle(workbook);
+
+        // 6. 写入数据
+        int rowNum = 0;
+
+        // 第一行,隐藏
+        Row row1 = sheet.createRow(0);  // 创建第一行(索引为0)
+        row1.setZeroHeight(true);
+
+        // 第1-2行:空行
+        rowNum += 2;
+
+        // 第3行:标题行
+        Row row3 = sheet.createRow(rowNum++);
+        row3.setHeight((short) 1100);
+
+        // 先合并
+        sheet.addMergedRegion(new CellRangeAddress(2, 2, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = row3.createCell(col);
+            cell.setCellStyle(titleStyle);
+        }
+
+        // 设置值(只需要设置左上角单元格的值)
+        Cell cellB3 = row3.getCell(1);
+        cellB3.setCellValue("新能源分公司生产日报" + date);
+
+        // 第4行:"生产指标完成情况"
+        Row row4 = sheet.createRow(rowNum++);
+        row4.setHeight((short) 580);
+
+        // 先合并
+        sheet.addMergedRegion(new CellRangeAddress(3, 3, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = row4.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+
+        // 设置值
+        Cell cellB4 = row4.getCell(1);
+        cellB4.setCellValue("生产指标完成情况");
+
+        // 第5行:"主要指标"(合并B-D列,纵向合并第5-7行)和"风电合计"(合并E-M列)
+        Row row5 = sheet.createRow(rowNum++);
+        row5.setHeight((short) 580);
+
+        // B5:"主要指标"(合并B5:D7)- 灰色背景,纵向合并第5-7行
+        // 先创建合并区域
+        sheet.addMergedRegion(new CellRangeAddress(4, 6, 1, 3));
+
+        // 为B5:D7所有单元格设置样式
+        for (int rowIdx = 4; rowIdx <= 6; rowIdx++) {
+            Row row = sheet.getRow(rowIdx);
+            if (row == null) {
+                row = sheet.createRow(rowIdx);
+            }
+            for (int col = 1; col <= 3; col++) {
+                Cell cell = row.createCell(col);
+                cell.setCellStyle(createHeaderGrayStyle(workbook, 15));
+            }
+        }
+
+        // 设置值
+        Cell cellB5 = row5.getCell(1);
+        cellB5.setCellValue("主要指标");
+
+        // E5:"风电合计"(合并E5:M5)- 蓝色背景
+        // 先合并
+        sheet.addMergedRegion(new CellRangeAddress(4, 4, 4, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 4; col <= 12; col++) {
+            Cell cell = row5.createCell(col);
+            cell.setCellStyle(headerBlueStyle);
+        }
+
+        // 设置值
+        Cell cellE5 = row5.getCell(4);
+        cellE5.setCellValue("风电合计");
+
+        // 第6行:表头第二行 - "惠安全场"、"一期风机"、"二期风机"
+        Row row6 = sheet.createRow(rowNum++);
+        row6.setHeight((short) 580);
+
+        // E6:"惠安全场"(合并E6:G6)- 灰色背景
+        // 先合并
+        sheet.addMergedRegion(new CellRangeAddress(5, 5, 4, 6));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row6.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+
+        // 设置值
+        Cell cellE6 = row6.getCell(4);
+        cellE6.setCellValue("惠安全场");
+
+        // H6:"一期风机"(合并H6:J6)- 灰色背景
+        // 先合并
+        sheet.addMergedRegion(new CellRangeAddress(5, 5, 7, 9));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row6.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+
+        // 设置值
+        Cell cellH6 = row6.getCell(7);
+        cellH6.setCellValue("一期风机");
+
+        // K6:"二期风机"(合并K6:M6)- 灰色背景
+        // 先合并
+        sheet.addMergedRegion(new CellRangeAddress(5, 5, 10, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row6.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+
+        // 设置值
+        Cell cellK6 = row6.getCell(10);
+        cellK6.setCellValue("二期风机");
+
+        // 第7行:表头第三行(时间维度)- 白色背景
+        Row row7 = sheet.createRow(rowNum++);
+        row7.setHeight((short) 580);
+
+        // C7: 创建空单元格,为后面的子指标列做准备
+        Cell cellC7 = row7.createCell(2);
+        cellC7.setCellValue("");
+        cellC7.setCellStyle(headerWhiteStyle);
+
+        // D7: 创建空单元格
+        Cell cellD7 = row7.createCell(3);
+        cellD7.setCellValue("");
+        cellD7.setCellStyle(headerWhiteStyle);
+
+        // 时间维度表头 - 灰色背景
+        // 惠安全场区域:E7-G7
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row7.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+        row7.getCell(4).setCellValue("本期");
+        row7.getCell(5).setCellValue("月累/均");
+        row7.getCell(6).setCellValue("年累/均");
+
+        // 一期风机区域:H7-J7
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row7.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+        row7.getCell(7).setCellValue("本期");
+        row7.getCell(8).setCellValue("月累/均");
+        row7.getCell(9).setCellValue("年累/均");
+
+        // 二期风机区域:K7-M7
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row7.createCell(col);
+            cell.setCellStyle(headerGrayStyle);
+        }
+        row7.getCell(10).setCellValue("本期");
+        row7.getCell(11).setCellValue("月累/均");
+        row7.getCell(12).setCellValue("年累/均");
+
+        // 第8行:风机发电数量(台)
+        Row row8 = sheet.createRow(rowNum++);
+        row8.setHeight((short) 580);
+
+        // 合并B8:D8
+        sheet.addMergedRegion(new CellRangeAddress(7, 7, 1, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 3; col++) {
+            Cell cell = row8.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellB8 = row8.getCell(1);
+        cellB8.setCellValue("风机发电数量(台)");
+
+        // 全场数据 - 合并E8:G8
+        sheet.addMergedRegion(new CellRangeAddress(7, 7, 4, 6));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row8.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellE8 = row8.getCell(4);
+        cellE8.setCellValue(50);
+
+        // 一期数据 - 合并H8:J8
+        sheet.addMergedRegion(new CellRangeAddress(7, 7, 7, 9));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row8.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellH8 = row8.getCell(7);
+        cellH8.setCellValue(25);
+
+        // 二期数据 - 合并K8:M8
+        sheet.addMergedRegion(new CellRangeAddress(7, 7, 10, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row8.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellK8 = row8.getCell(10);
+        cellK8.setCellValue(25);
+
+        // 第9行:发电量计划
+        Row row9 = sheet.createRow(rowNum++);
+        row9.setHeight((short) 600);
+
+        // 合并B9:C10(纵向合并第9-10行,横向合并B-C列)
+        sheet.addMergedRegion(new CellRangeAddress(8, 9, 1, 2));
+
+        // 为合并区域所有单元格设置样式
+        for (int rowIdx = 8; rowIdx <= 9; rowIdx++) {
+            Row row = sheet.getRow(rowIdx);
+            if (row == null) {
+                row = sheet.createRow(rowIdx);
+            }
+            for (int col = 1; col <= 2; col++) {
+                Cell cell = row.createCell(col);
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 设置值
+        Cell cellB9 = row9.getCell(1);
+        cellB9.setCellValue("发电量\n(万kW.h)");
+        cellB9.getCellStyle().setWrapText(true);
+
+        // "计划"写在D列(注意:D列现在是第4列,索引为3)
+        Cell cellD9 = row9.createCell(3);
+        cellD9.setCellValue("计划");
+        cellD9.setCellStyle(dataStyle);
+
+        // 全场计划数据 - E9-G9
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row9.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        row9.getCell(4).setCellValue(vo.getFdl_plan().getAll_bq());    // E9
+        row9.getCell(5).setCellValue(vo.getFdl_plan().getAll_month()); // F9
+        row9.getCell(6).setCellValue(vo.getFdl_plan().getAll_year());  // G9
+
+        // 一期计划数据 - H9-J9
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row9.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        row9.getCell(7).setCellValue(vo.getFdl_plan().getProject1_bq());    // H9
+        row9.getCell(8).setCellValue(vo.getFdl_plan().getProject1_month()); // I9
+        row9.getCell(9).setCellValue(vo.getFdl_plan().getProject1_year());  // J9
+
+        // 二期计划数据 - K9-M9
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row9.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        row9.getCell(10).setCellValue(vo.getFdl_plan().getProject2_bq());    // K9
+        row9.getCell(11).setCellValue(vo.getFdl_plan().getProject2_month()); // L9
+        row9.getCell(12).setCellValue(vo.getFdl_plan().getProject2_year());  // M9
+
+        // 第10行:发电量实发
+        Row row10 = sheet.createRow(rowNum++);
+        row10.setHeight((short) 580);
+
+        // D10:写"实发"
+        Cell cellD10 = row10.createCell(3);
+        cellD10.setCellValue("实发");
+        cellD10.setCellStyle(dataStyle);
+
+        // 全场实发数据 - E10-G10
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row10.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        row10.getCell(4).setCellValue(vo.getFdl_actual().getAll_bq());    // E10
+        row10.getCell(5).setCellValue(vo.getFdl_actual().getAll_month()); // F10
+        row10.getCell(6).setCellValue(vo.getFdl_actual().getAll_year());  // G10
+
+        // 一期实发数据 - H10-J10
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row10.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        row10.getCell(7).setCellValue(vo.getFdl_actual().getProject1_bq());    // H10
+        row10.getCell(8).setCellValue(vo.getFdl_actual().getProject1_month()); // I10
+        row10.getCell(9).setCellValue(vo.getFdl_actual().getProject1_year());  // J10
+
+        // 二期实发数据 - K10-M10
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row10.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        row10.getCell(10).setCellValue(vo.getFdl_actual().getProject2_bq());    // K10
+        row10.getCell(11).setCellValue(vo.getFdl_actual().getProject2_month()); // L10
+        row10.getCell(12).setCellValue(vo.getFdl_actual().getProject2_year());  // M10
+
+        // 第11行:利用小时数
+        Row row11 = sheet.createRow(rowNum++);
+        row11.setHeight((short) 580);
+        writeDataRow(row11, "利用小时数(h)", vo.getLyxss(), dataStyle, sheet, rowNum - 1);
+
+        // 第12行:平均风速
+        Row row12 = sheet.createRow(rowNum++);
+        row12.setHeight((short) 580);
+        writeDataRow(row12, "平均风速(m/s)", vo.getPjfs(), dataStyle, sheet, rowNum - 1);
+
+        // 第13行:上网电量
+        Row row13 = sheet.createRow(rowNum++);
+        row13.setHeight((short) 580);
+        writeSingleDataRow(row13, "上网电量(万kWh)", vo.getSwdl(), dataStyle, sheet, rowNum - 1);
+
+        // 第14行:网购电量
+        Row row14 = sheet.createRow(rowNum++);
+        row14.setHeight((short) 580);
+        writeSingleDataRow(row14, "网购电量(万kWh)", vo.getWgdl(), dataStyle, sheet, rowNum - 1);
+
+        // 第15行:限电量
+        Row row15 = sheet.createRow(rowNum++);
+        row15.setHeight((short) 580);
+        writeDataRow(row15, "限电量Y(万kWh)", vo.getXdli(), dataStyle, sheet, rowNum - 1);
+
+        // 第16行:限电率
+        Row row16 = sheet.createRow(rowNum++);
+        row16.setHeight((short) 580);
+        writeDataRow(row16, "限电率Y(%)", vo.getXdlv(), dataStyle, sheet, rowNum - 1);
+
+        // 第17行:损失电量-故障损失
+        Row row17 = sheet.createRow(rowNum++);
+        row17.setHeight((short) 580);
+
+        // B17:"损失电量 (万 kWh)"
+        Cell cellB17 = row17.createCell(1);
+        cellB17.setCellValue("损失电量 (万 kWh)");
+        cellB17.setCellStyle(dataStyle);
+
+        // 合并C17:D17
+        sheet.addMergedRegion(new CellRangeAddress(16, 16, 2, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 2; col <= 3; col++) {
+            Cell cell = row17.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellC17 = row17.getCell(2);
+        cellC17.setCellValue("故障损失");
+
+        // 全场数据 - E17-G17
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row17.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getGzss().getAll_bq() != null) row17.getCell(4).setCellValue(vo.getGzss().getAll_bq());
+        if (vo.getGzss().getAll_month() != null) row17.getCell(5).setCellValue(vo.getGzss().getAll_month());
+        if (vo.getGzss().getAll_year() != null) row17.getCell(6).setCellValue(vo.getGzss().getAll_year());
+
+        // 一期数据 - H17-J17
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row17.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getGzss().getProject1_bq() != null) row17.getCell(7).setCellValue(vo.getGzss().getProject1_bq());
+        if (vo.getGzss().getProject1_month() != null)
+            row17.getCell(8).setCellValue(vo.getGzss().getProject1_month());
+        if (vo.getGzss().getProject1_year() != null) row17.getCell(9).setCellValue(vo.getGzss().getProject1_year());
+
+        // 二期数据 - K17-M17
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row17.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getGzss().getProject2_bq() != null) row17.getCell(10).setCellValue(vo.getGzss().getProject2_bq());
+        if (vo.getGzss().getProject2_month() != null)
+            row17.getCell(11).setCellValue(vo.getGzss().getProject2_month());
+        if (vo.getGzss().getProject2_year() != null) row17.getCell(12).setCellValue(vo.getGzss().getProject2_year());
+
+        // 第18行:定检维护
+        Row row18 = sheet.createRow(rowNum++);
+        row18.setHeight((short) 580);
+
+        // B18: 空单元格
+        Cell cellB18 = row18.createCell(1);
+        cellB18.setCellValue("");
+        cellB18.setCellStyle(dataStyle);
+
+        // 合并C18:D18
+        sheet.addMergedRegion(new CellRangeAddress(17, 17, 2, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 2; col <= 3; col++) {
+            Cell cell = row18.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellC18 = row18.getCell(2);
+        cellC18.setCellValue("定检维护");
+
+        // 全场数据 - E18-G18
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row18.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getDjss().getAll_bq() != null) row18.getCell(4).setCellValue(vo.getDjss().getAll_bq());
+        if (vo.getDjss().getAll_month() != null) row18.getCell(5).setCellValue(vo.getDjss().getAll_month());
+        if (vo.getDjss().getAll_year() != null) row18.getCell(6).setCellValue(vo.getDjss().getAll_year());
+
+        // 一期数据 - H18-J18
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row18.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getDjss().getProject1_bq() != null) row18.getCell(7).setCellValue(vo.getDjss().getProject1_bq());
+        if (vo.getDjss().getProject1_month() != null)
+            row18.getCell(8).setCellValue(vo.getDjss().getProject1_month());
+        if (vo.getDjss().getProject1_year() != null) row18.getCell(9).setCellValue(vo.getDjss().getProject1_year());
+
+        // 二期数据 - K18-M18
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row18.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getDjss().getProject2_bq() != null) row18.getCell(10).setCellValue(vo.getDjss().getProject2_bq());
+        if (vo.getDjss().getProject2_month() != null)
+            row18.getCell(11).setCellValue(vo.getDjss().getProject2_month());
+        if (vo.getDjss().getProject2_year() != null) row18.getCell(12).setCellValue(vo.getDjss().getProject2_year());
+
+        // 第19行:受累损失
+        Row row19 = sheet.createRow(rowNum++);
+        row19.setHeight((short) 580);
+
+        // B19: 空单元格
+        Cell cellB19 = row19.createCell(1);
+        cellB19.setCellValue("");
+        cellB19.setCellStyle(dataStyle);
+
+        // 合并C19:D19
+        sheet.addMergedRegion(new CellRangeAddress(18, 18, 2, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 2; col <= 3; col++) {
+            Cell cell = row19.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellC19 = row19.getCell(2);
+        cellC19.setCellValue("受累损失");
+
+        // 全场数据 - E19-G19
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row19.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getSlss().getAll_bq() != null) row19.getCell(4).setCellValue(vo.getSlss().getAll_bq());
+        if (vo.getSlss().getAll_month() != null) row19.getCell(5).setCellValue(vo.getSlss().getAll_month());
+        if (vo.getSlss().getAll_year() != null) row19.getCell(6).setCellValue(vo.getSlss().getAll_year());
+
+        // 一期数据 - H19-J19
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row19.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getSlss().getProject1_bq() != null) row19.getCell(7).setCellValue(vo.getSlss().getProject1_bq());
+        if (vo.getSlss().getProject1_month() != null)
+            row19.getCell(8).setCellValue(vo.getSlss().getProject1_month());
+        if (vo.getSlss().getProject1_year() != null) row19.getCell(9).setCellValue(vo.getSlss().getProject1_year());
+
+        // 二期数据 - K19-M19
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row19.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+        if (vo.getSlss().getProject2_bq() != null) row19.getCell(10).setCellValue(vo.getSlss().getProject2_bq());
+        if (vo.getSlss().getProject2_month() != null)
+            row19.getCell(11).setCellValue(vo.getSlss().getProject2_month());
+        if (vo.getSlss().getProject2_year() != null) row19.getCell(12).setCellValue(vo.getSlss().getProject2_year());
+
+        // 现在合并B17:B19
+        sheet.addMergedRegion(new CellRangeAddress(16, 18, 1, 1));
+
+        // 为合并区域所有单元格设置样式
+        for (int r = 16; r <= 18; r++) {
+            Row row = sheet.getRow(r);
+            for (int c = 1; c <= 1; c++) {
+                Cell cell = row.getCell(c);
+                if (cell == null) {
+                    cell = row.createCell(c);
+                }
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 为这三行的所有单元格应用样式
+        for (int r = 16; r <= 18; r++) {
+            Row row = sheet.getRow(r);
+            if (row != null) {
+                for (int c = 1; c <= 12; c++) {
+                    Cell cell = row.getCell(c);
+                    if (cell != null) {
+                        cell.setCellStyle(dataStyle);
+                    }
+                }
+            }
+        }
+
+        // 第20行:场用电量
+        Row row20 = sheet.createRow(rowNum++);
+        row20.setHeight((short) 580);
+        writeSingleDataRow(row20, "场用电量(万kWh)", vo.getCydli(), dataStyle, sheet, rowNum - 1);
+
+        // 第21行:场用电率
+        Row row21 = sheet.createRow(rowNum++);
+        row21.setHeight((short) 580);
+        writeSingleDataRow(row21, "场用电率(%)", vo.getCydlv(), dataStyle, sheet, rowNum - 1);
+
+        // 第22行:综合场用电量
+        Row row22 = sheet.createRow(rowNum++);
+        row22.setHeight((short) 580);
+        writeSingleDataRow(row22, "综合场用电量(万kWh)", vo.getZhcydli(), dataStyle, sheet, rowNum - 1);
+
+        // 第23行:综合场用电率
+        Row row23 = sheet.createRow(rowNum++);
+        row23.setHeight((short) 580);
+        writeSingleDataRow(row23, "综合场用电率(%)", vo.getZhcydlv(), dataStyle, sheet, rowNum - 1);
+
+        // 第24行:设备可利用率
+        Row row24 = sheet.createRow(rowNum++);
+        row24.setHeight((short) 580);
+        writeDataRow(row24, "设备可利用率(%)", vo.getSbklyl(), dataStyle, sheet, rowNum - 1);
+
+        // 为所有数据单元格应用样式
+        applyDataStyle(sheet, dataStyle, 7, 23, 1, 12);
+
+        // 7. 写入Excel后面的部分
+        writeRemainingParts(sheet, rowNum, headerGrayStyle, dataStyle);
+
+        // 8. 设置响应头
+        String fileName = "惠安风电场生产日报(" + date + ").xlsx";
+        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
+
+        // 9. 写入输出流
+        workbook.write(response.getOutputStream());
+        workbook.close();
+    }
+
+    // 写入主要数据行(有全场、一期、二期数据)
+    private void writeDataRow(Row row, String indicator, ProductionDailyReport data,
+                              CellStyle style, Sheet sheet, int rowIndex) {
+        // 合并B-D列
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 3; col++) {
+            Cell cell = row.createCell(col);
+            cell.setCellStyle(style);
+        }
+
+        // 设置值
+        Cell cellB = row.getCell(1);
+        cellB.setCellValue(indicator);
+
+        // 全场数据 - E列开始
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row.createCell(col);
+            cell.setCellStyle(style);
+        }
+        if (data.getAll_bq() != null) row.getCell(4).setCellValue(data.getAll_bq());
+        if (data.getAll_month() != null) row.getCell(5).setCellValue(data.getAll_month());
+        if (data.getAll_year() != null) row.getCell(6).setCellValue(data.getAll_year());
+
+        // 一期数据 - H列开始
+        for (int col = 7; col <= 9; col++) {
+            Cell cell = row.createCell(col);
+            cell.setCellStyle(style);
+        }
+        if (data.getProject1_bq() != null) row.getCell(7).setCellValue(data.getProject1_bq());
+        if (data.getProject1_month() != null) row.getCell(8).setCellValue(data.getProject1_month());
+        if (data.getProject1_year() != null) row.getCell(9).setCellValue(data.getProject1_year());
+
+        // 二期数据 - K列开始
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = row.createCell(col);
+            cell.setCellStyle(style);
+        }
+        if (data.getProject2_bq() != null) row.getCell(10).setCellValue(data.getProject2_bq());
+        if (data.getProject2_month() != null) row.getCell(11).setCellValue(data.getProject2_month());
+        if (data.getProject2_year() != null) row.getCell(12).setCellValue(data.getProject2_year());
+    }
+
+    // 写入只有全场数据的行
+    private void writeSingleDataRow(Row row, String indicator, ProductionDailyReport data,
+                                    CellStyle style, Sheet sheet, int rowIndex) {
+        // 合并B-D列
+        sheet.addMergedRegion(new CellRangeAddress(rowIndex, rowIndex, 1, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 3; col++) {
+            Cell cell = row.createCell(col);
+            cell.setCellStyle(style);
+        }
+
+        // 设置值
+        Cell cellB = row.getCell(1);
+        cellB.setCellValue(indicator);
+
+        // 全场数据 - E-G列
+        for (int col = 4; col <= 6; col++) {
+            Cell cell = row.createCell(col);
+            cell.setCellStyle(style);
+        }
+        if (data.getAll_bq() != null) row.getCell(4).setCellValue(data.getAll_bq());
+        if (data.getAll_month() != null) row.getCell(5).setCellValue(data.getAll_month());
+        if (data.getAll_year() != null) row.getCell(6).setCellValue(data.getAll_year());
+
+        // 一期二期留空 - H-M列
+        for (int i = 7; i <= 12; i++) {
+            Cell cell = row.createCell(i);
+            cell.setCellValue("");
+            cell.setCellStyle(style);
+        }
+    }
+
+    // 写入Excel后面的部分
+    private void writeRemainingParts(Sheet sheet, int startRow, CellStyle headerStyle, CellStyle dataStyle) {
+        int rowNum = startRow;
+
+        // 第1行(第25行):当前运行方式
+        Row currentOpRow = sheet.createRow(rowNum++);
+        currentOpRow.setHeight((short) 580);
+
+        // 合并B25:M25
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = currentOpRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellCurrentOp = currentOpRow.getCell(1);
+        cellCurrentOp.setCellValue("当前运行方式");
+
+        // 第2行(第26行):运行方式数据行1
+        Row opDataRow1 = sheet.createRow(rowNum++);
+        opDataRow1.setHeight((short) 580);
+
+        // 第26行的索引
+        int row26Index = rowNum - 1;
+
+        // B26:惠安风电
+        Cell cellB26 = opDataRow1.createCell(1);
+        cellB26.setCellValue("惠安风电");
+        cellB26.setCellStyle(dataStyle);
+
+        // C26:空
+        Cell cellC26 = opDataRow1.createCell(2);
+        cellC26.setCellValue("");
+        cellC26.setCellStyle(dataStyle);
+
+        // E列:#1主变
+        Cell cellE26 = opDataRow1.createCell(3);
+        cellE26.setCellValue("#1主变");
+        cellE26.setCellStyle(dataStyle);
+
+        // F列:宋四风场线
+        Cell cellF26 = opDataRow1.createCell(4);
+        cellF26.setCellValue("宋四风场线");
+        cellF26.setCellStyle(dataStyle);
+
+        // G列:35kV集电一线
+        Cell cellG26 = opDataRow1.createCell(5);
+        cellG26.setCellValue("35kV集电一线");
+        cellG26.setCellStyle(dataStyle);
+
+        // H列:35kV集电三线
+        Cell cellH26 = opDataRow1.createCell(6);
+        cellH26.setCellValue("35kV集电三线");
+        cellH26.setCellStyle(dataStyle);
+
+        // I列:#1接地变
+        Cell cellI26 = opDataRow1.createCell(7);
+        cellI26.setCellValue("#1接地变");
+        cellI26.setCellStyle(dataStyle);
+
+        // J列:#1SVG
+        Cell cellJ26 = opDataRow1.createCell(8);
+        cellJ26.setCellValue("#1SVG");
+        cellJ26.setCellStyle(dataStyle);
+
+        // K列:一期风机
+        Cell cellK26 = opDataRow1.createCell(9);
+        cellK26.setCellValue("一期风机");
+        cellK26.setCellStyle(dataStyle);
+
+        // 合并L26:M26
+        sheet.addMergedRegion(new CellRangeAddress(row26Index, row26Index, 10, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = opDataRow1.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellL26 = opDataRow1.getCell(10);
+        cellL26.setCellValue("运行25台,故障0台");
+
+        // 第3行(第27行):运行方式数据行2
+        Row opDataRow2 = sheet.createRow(rowNum++);
+        opDataRow2.setHeight((short) 580);
+
+        // 第27行的索引
+        int row27Index = rowNum - 1;
+
+        // B27:空
+        Cell cellB27 = opDataRow2.createCell(1);
+        cellB27.setCellValue("");
+        cellB27.setCellStyle(dataStyle);
+
+        // C27:空
+        Cell cellC27 = opDataRow2.createCell(2);
+        cellC27.setCellValue("");
+        cellC27.setCellStyle(dataStyle);
+
+        // E列:#2主变
+        Cell cellE27 = opDataRow2.createCell(3);
+        cellE27.setCellValue("#2主变");
+        cellE27.setCellStyle(dataStyle);
+
+        // F列:110kV母线
+        Cell cellF27 = opDataRow2.createCell(4);
+        cellF27.setCellValue("110kV母线");
+        cellF27.setCellStyle(dataStyle);
+
+        // G列:35kV集电二线
+        Cell cellG27 = opDataRow2.createCell(5);
+        cellG27.setCellValue("35kV集电二线");
+        cellG27.setCellStyle(dataStyle);
+
+        // H列:35kV集电四线
+        Cell cellH27 = opDataRow2.createCell(6);
+        cellH27.setCellValue("35kV集电四线");
+        cellH27.setCellStyle(dataStyle);
+
+        // I列:#2接地变
+        Cell cellI27 = opDataRow2.createCell(7);
+        cellI27.setCellValue("#2接地变");
+        cellI27.setCellStyle(dataStyle);
+
+        // J列:#2SVG
+        Cell cellJ27 = opDataRow2.createCell(8);
+        cellJ27.setCellValue("#2SVG");
+        cellJ27.setCellStyle(dataStyle);
+
+        // K列:二期风机
+        Cell cellK27 = opDataRow2.createCell(9);
+        cellK27.setCellValue("二期风机");
+        cellK27.setCellStyle(dataStyle);
+
+        // 合并L27:M27
+        sheet.addMergedRegion(new CellRangeAddress(row27Index, row27Index, 10, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 10; col <= 12; col++) {
+            Cell cell = opDataRow2.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellL27 = opDataRow2.getCell(10);
+        cellL27.setCellValue("运行25台,故障0台");
+
+        // 现在合并第26行和第27行的B-C列(B26:C27)
+        sheet.addMergedRegion(new CellRangeAddress(row26Index, row27Index, 1, 2));
+
+        // 为合并区域所有单元格设置样式
+        for (int r = row26Index; r <= row27Index; r++) {
+            Row row = sheet.getRow(r);
+            for (int c = 1; c <= 2; c++) {
+                Cell cell = row.getCell(c);
+                if (cell == null) {
+                    cell = row.createCell(c);
+                }
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 风功率预测 - 灰色背景
+        Row windPowerRow = sheet.createRow(rowNum++);
+        windPowerRow.setHeight((short) 580);
+
+        // 合并
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = windPowerRow.createCell(col);
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 设置值
+        Cell cellWindPower = windPowerRow.getCell(1);
+        cellWindPower.setCellValue("风功率预测");
+
+        // 风功率预测表头行
+        Row windPowerHeaderRow = sheet.createRow(rowNum++);
+        windPowerHeaderRow.setHeight((short) 580);
+
+        // B29:超短期功率预测准确率(%) - 合并B-E列
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 4));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 4; col++) {
+            Cell cell = windPowerHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellE29 = windPowerHeaderRow.getCell(1);
+        cellE29.setCellValue("超短期功率预测准确率(%)");
+
+        // F29:短期功率预测准确率(%) - 合并F-I列
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 5, 8));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 5; col <= 8; col++) {
+            Cell cell = windPowerHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellI29 = windPowerHeaderRow.getCell(5);
+        cellI29.setCellValue("短期功率预测准确率(%)");
+
+        // J29:可用电量日准确率(%) - 合并J-M列
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 9, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 9; col <= 12; col++) {
+            Cell cell = windPowerHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellM29 = windPowerHeaderRow.getCell(9);
+        cellM29.setCellValue("可用电量日准确率(%)");
+
+        // 风功率预测数据行
+        Row windPowerDataRow = sheet.createRow(rowNum++);
+        windPowerDataRow.setHeight((short) 580);
+
+        // 合并B30:E30
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 4));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 4; col++) {
+            Cell cell = windPowerDataRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+            cell.setCellValue("");
+        }
+
+        // 合并F30:I30
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 5, 8));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 5; col <= 8; col++) {
+            Cell cell = windPowerDataRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+            cell.setCellValue("");
+        }
+
+        // 合并J30:M30
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 9, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 9; col <= 12; col++) {
+            Cell cell = windPowerDataRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        windPowerDataRow.getCell(9).setCellValue("0");
+
+        // 两票统计 - 灰色背景
+        Row ticketRow = sheet.createRow(rowNum++);
+        ticketRow.setHeight((short) 580);
+
+        // 合并
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = ticketRow.createCell(col);
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 设置值
+        Cell cellTicket = ticketRow.getCell(1);
+        cellTicket.setCellValue("两票统计");
+
+        // 第32行:两票统计表头行
+        Row ticketHeaderRow32 = sheet.createRow(rowNum++);
+        ticketHeaderRow32.setHeight((short) 580);
+        int row32Index = rowNum - 1;
+
+        // C列
+        Cell cellC31 = ticketHeaderRow32.createCell(1);
+        cellC31.setCellValue("");
+        cellC31.setCellStyle(dataStyle);
+
+        // D列:操作票
+        Cell cellC32 = ticketHeaderRow32.createCell(2);
+        cellC32.setCellValue("操作票");
+        cellC32.setCellStyle(dataStyle);
+
+        // E列:月累
+        Cell cellD32 = ticketHeaderRow32.createCell(3);
+        cellD32.setCellValue("月累");
+        cellD32.setCellStyle(dataStyle);
+
+        // 合并E32:F32
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row32Index, 4, 5));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 4; col <= 5; col++) {
+            Cell cell = ticketHeaderRow32.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellE32 = ticketHeaderRow32.getCell(4);
+        cellE32.setCellValue("电气一种");
+
+        // 合并G32:H32
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row32Index, 6, 7));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 6; col <= 7; col++) {
+            Cell cell = ticketHeaderRow32.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellG32 = ticketHeaderRow32.getCell(6);
+        cellG32.setCellValue("电气二种");
+
+        // 合并I32:J32
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row32Index, 8, 9));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 8; col <= 9; col++) {
+            Cell cell = ticketHeaderRow32.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellI32 = ticketHeaderRow32.getCell(8);
+        cellI32.setCellValue("动火票");
+
+        // 合并K32:L32
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row32Index, 10, 11));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 10; col <= 11; col++) {
+            Cell cell = ticketHeaderRow32.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellK32 = ticketHeaderRow32.getCell(10);
+        cellK32.setCellValue("风机/线路票");
+
+        // M列:月累
+        ticketHeaderRow32.createCell(12).setCellValue("月累");
+        ticketHeaderRow32.getCell(12).setCellStyle(dataStyle);
+
+        // 第33行:两票统计表头第二行
+        Row ticketHeaderRow33 = sheet.createRow(rowNum++);
+        ticketHeaderRow33.setHeight((short) 580);
+        int row33Index = rowNum - 1;
+
+        // C列
+        ticketHeaderRow33.createCell(1).setCellValue("");
+        ticketHeaderRow33.getCell(1).setCellStyle(dataStyle);
+
+        // D列
+        ticketHeaderRow33.createCell(2).setCellValue("");
+        ticketHeaderRow33.getCell(2).setCellStyle(dataStyle);
+
+        // E列
+        ticketHeaderRow33.createCell(3).setCellValue("");
+        ticketHeaderRow33.getCell(3).setCellStyle(dataStyle);
+
+        // F列:许可
+        ticketHeaderRow33.createCell(4).setCellValue("许可");
+        ticketHeaderRow33.getCell(4).setCellStyle(dataStyle);
+
+        // G列:终结
+        ticketHeaderRow33.createCell(5).setCellValue("终结");
+        ticketHeaderRow33.getCell(5).setCellStyle(dataStyle);
+
+        // H列:许可
+        ticketHeaderRow33.createCell(6).setCellValue("许可");
+        ticketHeaderRow33.getCell(6).setCellStyle(dataStyle);
+
+        // I列:终结
+        ticketHeaderRow33.createCell(7).setCellValue("终结");
+        ticketHeaderRow33.getCell(7).setCellStyle(dataStyle);
+
+        // J列:许可
+        ticketHeaderRow33.createCell(8).setCellValue("许可");
+        ticketHeaderRow33.getCell(8).setCellStyle(dataStyle);
+
+        // K列:终结
+        ticketHeaderRow33.createCell(9).setCellValue("终结");
+        ticketHeaderRow33.getCell(9).setCellStyle(dataStyle);
+
+        // L列:许可
+        ticketHeaderRow33.createCell(10).setCellValue("许可");
+        ticketHeaderRow33.getCell(10).setCellStyle(dataStyle);
+
+        // M列:终结
+        ticketHeaderRow33.createCell(11).setCellValue("终结");
+        ticketHeaderRow33.getCell(11).setCellStyle(dataStyle);
+
+        // N列
+        ticketHeaderRow33.createCell(12).setCellValue("");
+        ticketHeaderRow33.getCell(12).setCellStyle(dataStyle);
+
+        // 合并第32-33行的B列
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row33Index, 1, 1));
+
+        // 为合并区域所有单元格设置样式
+        for (int r = row32Index; r <= row33Index; r++) {
+            Row row = sheet.getRow(r);
+            for (int c = 1; c <= 1; c++) {
+                Cell cell = row.getCell(c);
+                if (cell == null) {
+                    cell = row.createCell(c);
+                }
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 合并第32-33行的C列
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row33Index, 2, 2));
+
+        // 为合并区域所有单元格设置样式
+        for (int r = row32Index; r <= row33Index; r++) {
+            Row row = sheet.getRow(r);
+            for (int c = 2; c <= 2; c++) {
+                Cell cell = row.getCell(c);
+                if (cell == null) {
+                    cell = row.createCell(c);
+                }
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 合并第32-33行的D列
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row33Index, 3, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int r = row32Index; r <= row33Index; r++) {
+            Row row = sheet.getRow(r);
+            for (int c = 3; c <= 3; c++) {
+                Cell cell = row.getCell(c);
+                if (cell == null) {
+                    cell = row.createCell(c);
+                }
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 合并第32-33行的M列
+        sheet.addMergedRegion(new CellRangeAddress(row32Index, row33Index, 12, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int r = row32Index; r <= row33Index; r++) {
+            Row row = sheet.getRow(r);
+            for (int c = 12; c <= 12; c++) {
+                Cell cell = row.getCell(c);
+                if (cell == null) {
+                    cell = row.createCell(c);
+                }
+                cell.setCellStyle(dataStyle);
+            }
+        }
+
+        // 第34行:两票统计数据行
+        Row ticketDataRow = sheet.createRow(rowNum++);
+        ticketDataRow.setHeight((short) 580);
+
+        // 为所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = ticketDataRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+            cell.setCellValue("");
+        }
+
+        // 设置值
+        ticketDataRow.getCell(1).setCellValue("惠安风电");
+
+        // 缺陷情况 - 灰色背景
+        Row defectRow = sheet.createRow(rowNum++);
+        defectRow.setHeight((short) 580);
+
+        // 合并
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = defectRow.createCell(col);
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 设置值
+        Cell cellDefect = defectRow.getCell(1);
+        cellDefect.setCellValue("缺陷情况");
+
+        // 缺陷情况表头行
+        Row defectHeaderRow = sheet.createRow(rowNum++);
+        defectHeaderRow.setHeight((short) 580);
+
+        // B列空
+        defectHeaderRow.createCell(1).setCellValue("");
+        defectHeaderRow.getCell(1).setCellStyle(dataStyle);
+
+        // 合并C36:D36
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 2, 3));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 2; col <= 3; col++) {
+            Cell cell = defectHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellC36 = defectHeaderRow.getCell(2);
+        cellC36.setCellValue("当日新增");
+
+        // 合并E36:F36
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 4, 5));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 4; col <= 5; col++) {
+            Cell cell = defectHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellE36 = defectHeaderRow.getCell(4);
+        cellE36.setCellValue("当日消除");
+
+        // 合并G36:H36
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 6, 7));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 6; col <= 7; col++) {
+            Cell cell = defectHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellG36 = defectHeaderRow.getCell(6);
+        cellG36.setCellValue("累计未消除");
+
+        // 合并I36:J36
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 8, 9));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 8; col <= 9; col++) {
+            Cell cell = defectHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellI36 = defectHeaderRow.getCell(8);
+        cellI36.setCellValue("月发生");
+
+        // 合并K36:L36
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 10, 11));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 10; col <= 11; col++) {
+            Cell cell = defectHeaderRow.createCell(col);
+            cell.setCellStyle(dataStyle);
+        }
+
+        // 设置值
+        Cell cellK36 = defectHeaderRow.getCell(10);
+        cellK36.setCellValue("年发生");
+
+        // M列:空
+        defectHeaderRow.createCell(12).setCellValue("");
+        defectHeaderRow.getCell(12).setCellStyle(dataStyle);
+
+        // 缺陷情况数据行
+        Row defectDataRow = sheet.createRow(rowNum++);
+        defectDataRow.setHeight((short) 580);
+
+        // B37:惠安风电
+        Cell cellB37 = defectDataRow.createCell(1);
+        cellB37.setCellValue("惠安风电");
+        cellB37.setCellStyle(dataStyle);
+
+        // 合并C37:M37
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 2, 12));
+
+        // 为合并区域所有单元格设置白色背景样式
+        for (int i = 2; i <= 12; i++) {
+            Cell cell = defectDataRow.createCell(i);
+            cell.setCellValue("");
+            CellStyle whiteBgStyle = sheet.getWorkbook().createCellStyle();
+            whiteBgStyle.setAlignment(HorizontalAlignment.LEFT);
+            whiteBgStyle.setVerticalAlignment(VerticalAlignment.TOP);
+            whiteBgStyle.setWrapText(true);
+            whiteBgStyle.setBorderBottom(BorderStyle.NONE);
+            whiteBgStyle.setBorderTop(BorderStyle.NONE);
+            whiteBgStyle.setBorderLeft(BorderStyle.NONE);
+            whiteBgStyle.setBorderRight(BorderStyle.NONE);
+            whiteBgStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+            whiteBgStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            cell.setCellStyle(whiteBgStyle);
+        }
+
+        // 重要缺陷处理进度 - 灰色背景
+        Row importantDefectRow = sheet.createRow(rowNum++);
+        importantDefectRow.setHeight((short) 580);
+
+        // 合并
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = importantDefectRow.createCell(col);
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 设置值
+        Cell cellImpDefect = importantDefectRow.getCell(1);
+        cellImpDefect.setCellValue("重要缺陷处理进度");
+
+        // 重要缺陷处理进度数据行
+        Row impDefectDataRow = sheet.createRow(rowNum++);
+        impDefectDataRow.setHeight((short) 2800);
+
+        // B39:惠安风电
+        Cell cellB39 = impDefectDataRow.createCell(1);
+        cellB39.setCellValue("惠安风电");
+        cellB39.setCellStyle(dataStyle);
+
+        // 合并C39:M39
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 2, 12));
+
+        // 为合并区域所有单元格设置白色背景样式
+        for (int i = 2; i <= 12; i++) {
+            Cell cell = impDefectDataRow.createCell(i);
+            cell.setCellValue("");
+            CellStyle whiteBgStyle = sheet.getWorkbook().createCellStyle();
+            whiteBgStyle.setAlignment(HorizontalAlignment.LEFT);
+            whiteBgStyle.setVerticalAlignment(VerticalAlignment.TOP);
+            whiteBgStyle.setWrapText(true);
+            whiteBgStyle.setBorderBottom(BorderStyle.NONE);
+            whiteBgStyle.setBorderTop(BorderStyle.NONE);
+            whiteBgStyle.setBorderLeft(BorderStyle.NONE);
+            whiteBgStyle.setBorderRight(BorderStyle.NONE);
+            whiteBgStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+            whiteBgStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            cell.setCellStyle(whiteBgStyle);
+        }
+
+        // 主要工作 - 灰色背景
+        Row mainWorkRow = sheet.createRow(rowNum++);
+        mainWorkRow.setHeight((short) 580);
+
+        // 合并
+        sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 1, 12));
+
+        // 为合并区域所有单元格设置样式
+        for (int col = 1; col <= 12; col++) {
+            Cell cell = mainWorkRow.createCell(col);
+            cell.setCellStyle(headerStyle);
+        }
+
+        // 设置值
+        Cell cellMainWork = mainWorkRow.getCell(1);
+        cellMainWork.setCellValue("主要工作");
+
+        // 主要工作数据行
+        Row mainWorkDataRow = sheet.createRow(rowNum);
+        mainWorkDataRow.setHeight((short) 4800);
+
+        // B41:惠安风电
+        Cell cellB41 = mainWorkDataRow.createCell(1);
+        cellB41.setCellValue("惠安风电");
+        cellB41.setCellStyle(dataStyle);
+
+        // 合并C41:M41
+        sheet.addMergedRegion(new CellRangeAddress(rowNum, rowNum, 2, 12));
+
+        // 为合并区域所有单元格设置白色背景样式
+        for (int i = 2; i <= 12; i++) {
+            Cell cell = mainWorkDataRow.createCell(i);
+            cell.setCellValue("");
+            CellStyle whiteBgStyle = sheet.getWorkbook().createCellStyle();
+            whiteBgStyle.setAlignment(HorizontalAlignment.LEFT);
+            whiteBgStyle.setVerticalAlignment(VerticalAlignment.TOP);
+            whiteBgStyle.setWrapText(true);
+            whiteBgStyle.setBorderBottom(BorderStyle.NONE);
+            whiteBgStyle.setBorderTop(BorderStyle.NONE);
+            whiteBgStyle.setBorderLeft(BorderStyle.NONE);
+            whiteBgStyle.setBorderRight(BorderStyle.NONE);
+            whiteBgStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+            whiteBgStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+            cell.setCellStyle(whiteBgStyle);
+        }
+    }
+
+    // 创建样式方法
+    private CellStyle createTitleStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+        font.setBold(true);
+        font.setFontHeightInPoints((short) 16);
+        style.setFont(font);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        return createGrayBorderStyle(style);
+    }
+
+    /**
+     * 设置灰色边框方法
+     */
+    private CellStyle createGrayBorderStyle(CellStyle style) {
+        short colorIndex = IndexedColors.GREY_25_PERCENT.getIndex();
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBottomBorderColor(colorIndex);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setTopBorderColor(colorIndex);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setLeftBorderColor(colorIndex);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setRightBorderColor(colorIndex);
+
+        return style;
+    }
+
+    private CellStyle createHeaderGrayStyle(Workbook workbook,int fontSize) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+        font.setBold(false);  // 修改为不加粗
+        font.setFontHeightInPoints((short) fontSize);
+        style.setFont(font);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+
+        // 使用XSSFColor设置精确灰色E1DFDF
+        if (workbook instanceof XSSFWorkbook) {
+            XSSFColor greyColor = new XSSFColor(new java.awt.Color(0xE1, 0xDF, 0xDF), null);
+            ((XSSFCellStyle) style).setFillForegroundColor(greyColor);
+        } else {
+            style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+        }
+        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+
+        return createGrayBorderStyle(style);
+    }
+
+    private CellStyle createHeaderBlueStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+        font.setBold(true);
+        style.setFont(font);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+
+        // 使用XSSFColor设置精确蓝色3B95F4
+        if (workbook instanceof XSSFWorkbook) {
+            XSSFColor blueColor = new XSSFColor(new java.awt.Color(0x3B, 0x95, 0xF4), null);
+            ((XSSFCellStyle) style).setFillForegroundColor(blueColor);
+        } else {
+            style.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
+        }
+        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+
+        return createGrayBorderStyle(style);
+    }
+
+
+    private CellStyle createHeaderWhiteStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+        Font font = workbook.createFont();
+        font.setFontHeightInPoints((short) 12);  // 改为12号字体
+        style.setFont(font);
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        return createGrayBorderStyle(style);
+    }
+
+    private CellStyle createDataStyle(Workbook workbook) {
+        CellStyle style = workbook.createCellStyle();
+
+        // 添加字体设置,12号字体
+        Font font = workbook.createFont();
+        font.setFontHeightInPoints((short) 14);
+        style.setFont(font);
+
+        style.setAlignment(HorizontalAlignment.CENTER);
+        style.setVerticalAlignment(VerticalAlignment.CENTER);
+        style.setBorderBottom(BorderStyle.THIN);
+        style.setBorderTop(BorderStyle.THIN);
+        style.setBorderLeft(BorderStyle.THIN);
+        style.setBorderRight(BorderStyle.THIN);
+        style.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+        style.setWrapText(true);
+        return createGrayBorderStyle(style);
+    }
+
+    // 为指定区域应用样式
+    private void applyDataStyle(Sheet sheet, CellStyle style, int startRow, int endRow, int startCol, int endCol) {
+        for (int rowNum = startRow; rowNum <= endRow; rowNum++) {
+            Row row = sheet.getRow(rowNum);
+            if (row != null) {
+                for (int colNum = startCol; colNum <= endCol; colNum++) {
+                    Cell cell = row.getCell(colNum);
+                    if (cell != null) {
+                        cell.setCellStyle(style);
+                    }
+                }
+            }
+        }
+    }
+
     @Override
     public ProductionDailyReportVo queryAll(String date) throws Exception {
         LocalDate recordDate = LocalDate.parse(date);

+ 266 - 188
runeconomy-xk/src/main/java/com/gyee/runeconomy/service/singleanalysis/SingleAnalysisService.java

@@ -1,5 +1,6 @@
 package com.gyee.runeconomy.service.singleanalysis;
 
+import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.NumberUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -1115,207 +1116,284 @@ public class SingleAnalysisService {
 
     public Map<String, List<SingleAnalysisVo>> SingleAnalysisListByWtIdDetiml(String wtId, Date beginDate, Date endDate) {
         Map<String, List<SingleAnalysisVo>> map = new HashMap<>();
+        if (!StringUtils.notEmp(wtId) || !StringUtils.notEmp(beginDate) || !StringUtils.notEmp(endDate)) {
+            map.put("ff", new ArrayList<>());
+            map.put("ws", new ArrayList<>());
+            map.put("jd", new ArrayList<>());
+            return map;
+        }
+
+        long days = DateUtil.between(beginDate, endDate, DateUnit.DAY);
+        if (days <= 0) {
+            map.put("ff", new ArrayList<>());
+            map.put("ws", new ArrayList<>());
+            map.put("jd", new ArrayList<>());
+            return map;
+        }
+
         List<SingleAnalysisVo> fdlfsls = new ArrayList<>();
         List<SingleAnalysisVo> wsls = new ArrayList<>();
         List<SingleAnalysisVo> jfpldjsjls = new ArrayList<>();
-        if (StringUtils.notEmp(wtId) && StringUtils.notEmp(beginDate) && StringUtils.notEmp(endDate)) {
-            LocalDate now = LocalDate.now();
-            int year = DateUtil.year(beginDate);
-            int month = DateUtil.month(beginDate);
-            if (year == now.getYear() && month + 1 == now.getMonthValue()) {
-                endDate = DateUtil.beginOfDay(Date.from(now.atStartOfDay(ZoneId.systemDefault()).toInstant()));
-            }
-
-            Map<String, Map<Long, ProEconEquipmentInfoDay1>> day1map = new HashMap<>();
-            Map<String, Map<Long, ProEconEquipmentInfoDay2>> day2map = new HashMap<>();
-
-            QueryWrapper<ProEconEquipmentInfoDay1> queryWrapper = new QueryWrapper<>();
-            queryWrapper.eq("windturbine_id", wtId).ge("record_date", beginDate)
-                    .lt("record_date", endDate)
-                    .orderByAsc("record_date");
-            List<ProEconEquipmentInfoDay1> wtday1ls = proEconEquipmentInfoDay1Service.list(queryWrapper);
-            if (!wtday1ls.isEmpty()) {
-                for (ProEconEquipmentInfoDay1 wtday1 : wtday1ls) {
-                    if (day1map.containsKey(wtday1.getWindturbineId())) {
-                        Map<Long, ProEconEquipmentInfoDay1> tempmap = day1map.get(wtday1.getWindturbineId());
-                        tempmap.put(wtday1.getRecordDate().getTime(), wtday1);
-                        day1map.put(wtId, tempmap);
-                    } else {
-                        Map<Long, ProEconEquipmentInfoDay1> tempmap = new HashMap<>();
-                        tempmap.put(wtday1.getRecordDate().getTime(), wtday1);
-                        day1map.put(wtId, tempmap);
-                    }
-                }
-            }
-            QueryWrapper<ProEconEquipmentInfoDay2> queryWrapper2 = new QueryWrapper<>();
-            queryWrapper2.eq("windturbine_id", wtId).ge("record_date", beginDate)
-                    .lt("record_date", endDate)
-                    .orderByAsc("record_date");
-            ;
-            List<ProEconEquipmentInfoDay2> wtday2ls = proEconEquipmentInfoDay2Service.list(queryWrapper2);
-            if (!wtday2ls.isEmpty()) {
-                for (ProEconEquipmentInfoDay2 wtday2 : wtday2ls) {
-                    if (day2map.containsKey(wtday2.getWindturbineId())) {
-                        Map<Long, ProEconEquipmentInfoDay2> tempmap = day2map.get(wtday2.getWindturbineId());
-                        tempmap.put(wtday2.getRecordDate().getTime(), wtday2);
-                        day2map.put(wtId, tempmap);
-                    } else {
-                        Map<Long, ProEconEquipmentInfoDay2> tempmap = new HashMap<>();
-                        tempmap.put(wtday2.getRecordDate().getTime(), wtday2);
-                        day2map.put(wtId, tempmap);
-                    }
-                }
-            }
-            QueryWrapper<ProEconEquipmentInfoDay4> queryWrapper4 = new QueryWrapper<>();
-            queryWrapper4.eq("windturbine_id", wtId).ge("record_date", beginDate)
-                    .lt("record_date", endDate)
-                    .orderByAsc("record_date");
-            List<ProEconEquipmentInfoDay4> wtday4ls = proEconEquipmentInfoDay4Service.list(queryWrapper4);
-            ProBasicEquipment wt = CacheContext.wtmap.get(wtId);
-            ProBasicPowerstation wp = CacheContext.wpmap.get(wt.getWindpowerstationId());
-
-            if (StringUtils.notEmp(wtday2ls) && !wtday2ls.isEmpty()) {
-
-                for (ProEconEquipmentInfoDay2 wtd : wtday2ls) {
-
-                    SingleAnalysisVo vo = new SingleAnalysisVo();
-
-                    Calendar c = Calendar.getInstance();
-
-                    c.setTime(wtd.getRecordDate());
-                    int dayTimes = 24;//风机日历小时合计
-
-
-                    if (day1map.containsKey(wtd.getWindturbineId())) {
-                        Map<Long, ProEconEquipmentInfoDay1> map1 = day1map.get(wtd.getWindturbineId());
-                        if (map1.containsKey(wtd.getRecordDate().getTime())) {
-                            ProEconEquipmentInfoDay1 daypo = map1.get(wtd.getRecordDate().getTime());
-                            double fdl = null != daypo.getRfdl() ? daypo.getRfdl() : 0.0;//风机发电量合计
-                            if (CacheContext.modelMap.containsKey(wt.getModelId())) {
-                                ProEconEquipmentmodel model = CacheContext.modelMap.get(wt.getModelId());
-                                double lyxs = new BigDecimal(fdl).divide(new BigDecimal(model.getPowerProduction()), 2, RoundingMode.HALF_UP).doubleValue();
-                                vo.setLyxs(lyxs);
-                            }
-
-                            fdl = new BigDecimal(fdl).divide(new BigDecimal(10000), 2, RoundingMode.HALF_UP).doubleValue();
-                            double fs = null != daypo.getRpjfs() ? daypo.getRpjfs() : 0.0;//风机平均风速
-                            vo.setFdl(StringUtils.round(fdl, 2));
-                            vo.setFs(StringUtils.round(fs, 2));
-                        }
-                    }
-
-                    double yxxs = null != wtd.getRyxxs() ? wtd.getRyxxs() : 0.0;//风机运行小时合计
-                    double gzxs = null != wtd.getRgztjxs() ? wtd.getRgztjxs() : 0.0;//风机故障小时合计
-                    double jxxs = null != wtd.getRjxtjxs() ? wtd.getRjxtjxs() : 0.0;//风机检修小时合计
-                    double tjxs = null != wtd.getRxdxs() ? wtd.getRxdxs() : 0.0;//风限电小时合计
-                    double zdxs = null != wtd.getRtxzdxs() ? wtd.getRtxzdxs() : 0.0;//风机中断小时合计
-
-                    vo.setWindPowerStationId(wt.getWindpowerstationId());
-                    vo.setWindPowerStationName(wp.getName());
-                    vo.setWindturbineName(wt.getName());
-                    vo.setWindturbineid(wt.getId());
-                    vo.setRecorddate(wtd.getRecordDate());
-
-
-                    vo.setYxxs(StringUtils.round(yxxs, 2));
-                    vo.setGzxs(StringUtils.round(gzxs, 2));
-                    vo.setJxxs(StringUtils.round(jxxs, 2));
-                    vo.setTjxs(StringUtils.round(tjxs, 2));
-                    vo.setZdxs(StringUtils.round(zdxs, 2));
-                    vo.setRlxs(StringUtils.round(dayTimes, 2));
-
-                    fdlfsls.add(vo);
-
-                }
-
-            }
-
-            if (StringUtils.notEmp(wtday1ls) && !wtday1ls.isEmpty()) {
-                for (ProEconEquipmentInfoDay1 wtd : wtday1ls) {
-                    SingleAnalysisVo vo = new SingleAnalysisVo();
-                    double gzss = null != wtd.getRgzssdl() ? wtd.getRgzssdl() : 0.0;//风机故障损失合计
-                    double jxss = null != wtd.getRjxssdl() ? wtd.getRjxssdl() : 0.0;//风机检修损失合计
-                    double xdss = null != wtd.getRxdtjssdl() ? wtd.getRxdtjssdl() : 0.0;//风机限电损失合计
-                    double xnss = null != wtd.getRxnssdl() ? wtd.getRxnssdl() : 0.0;//风机性能损失时合计
-                    double ycwsldwssdl = null != wtd.getRcwsldwssdl() ? wtd.getRcwsldwssdl() : 0.0;//场外受累电网损失电量
-                    double ycwsltqssdl = null != wtd.getRcwsltqssdl() ? wtd.getRcwsldwssdl() : 0.0;//场外受累天气损失电量
-                    double slss = StringUtils.round(ycwsldwssdl + ycwsltqssdl, 2);
-
-
-                    vo.setWindPowerStationId(wt.getWindpowerstationId());
-                    vo.setWindPowerStationName(wp.getName());
-                    vo.setWindturbineName(wt.getName());
-                    vo.setWindturbineid(wt.getId());
-                    vo.setRecorddate(wtd.getRecordDate());
-
-                    vo.setGzss(StringUtils.round(gzss, 2));
-                    vo.setJxss(StringUtils.round(jxss, 2));
-                    vo.setXdss(StringUtils.round(xdss, 2));
-                    vo.setXnss(StringUtils.round(xnss, 2));
-                    vo.setSlss(StringUtils.round(slss, 2));
-                    wsls.add(vo);
-                }
 
-            }
+        for (int i = 0; i < days; i++) {
+            Date currentDate = DateUtil.offsetDay(beginDate, i);
 
+            SingleAnalysisVo sa1 = new SingleAnalysisVo();
+            sa1.setRecorddate(currentDate);
+            sa1.setWindturbineid(wtId);
+            fdlfsls.add(sa1);
 
-            if (StringUtils.notEmp(wtday4ls) && !wtday4ls.isEmpty()) {
+            SingleAnalysisVo sa2 = new SingleAnalysisVo();
+            sa2.setRecorddate(currentDate);
+            sa2.setWindturbineid(wtId);
+            wsls.add(sa2);
 
-                for (ProEconEquipmentInfoDay4 wtd : wtday4ls) {
-
-                    SingleAnalysisVo vo = new SingleAnalysisVo();
-
-                    vo.setRecorddate(wtd.getRecordDate());
-
-                    double jfsc = null != wtd.getRjfsc() ? wtd.getRjfsc() : 0.0;//静风时长
-                    double jfpl = new BigDecimal(jfsc).divide(new BigDecimal(24), 2, RoundingMode.HALF_EVEN).multiply(new BigDecimal(100)).doubleValue();//静风频率
+            SingleAnalysisVo sa3 = new SingleAnalysisVo();
+            sa3.setRecorddate(currentDate);
+            sa3.setWindturbineid(wtId);
+            jfpldjsjls.add(sa3);
+        }
+//            LocalDate now = LocalDate.now();
+//            int year = DateUtil.year(beginDate);
+//            int month = DateUtil.month(beginDate);
+//            if (year == now.getYear() && month + 1 == now.getMonthValue()) {
+//                endDate = DateUtil.beginOfDay(Date.from(now.atStartOfDay(ZoneId.systemDefault()).toInstant()));
+//            }
+//
+//            Map<String, Map<Long, ProEconEquipmentInfoDay1>> day1map = new HashMap<>();
+//            Map<String, Map<Long, ProEconEquipmentInfoDay2>> day2map = new HashMap<>();
+//
+//            QueryWrapper<ProEconEquipmentInfoDay1> queryWrapper = new QueryWrapper<>();
+//            queryWrapper.eq("windturbine_id", wtId).ge("record_date", beginDate)
+//                    .lt("record_date", endDate)
+//                    .orderByAsc("record_date");
+//            List<ProEconEquipmentInfoDay1> wtday1ls = proEconEquipmentInfoDay1Service.list(queryWrapper);
+//            if (!wtday1ls.isEmpty()) {
+//                for (ProEconEquipmentInfoDay1 wtday1 : wtday1ls) {
+//                    if (day1map.containsKey(wtday1.getWindturbineId())) {
+//                        Map<Long, ProEconEquipmentInfoDay1> tempmap = day1map.get(wtday1.getWindturbineId());
+//                        tempmap.put(wtday1.getRecordDate().getTime(), wtday1);
+//                        day1map.put(wtId, tempmap);
+//                    } else {
+//                        Map<Long, ProEconEquipmentInfoDay1> tempmap = new HashMap<>();
+//                        tempmap.put(wtday1.getRecordDate().getTime(), wtday1);
+//                        day1map.put(wtId, tempmap);
+//                    }
+//                }
+//            }
+//            QueryWrapper<ProEconEquipmentInfoDay2> queryWrapper2 = new QueryWrapper<>();
+//            queryWrapper2.eq("windturbine_id", wtId).ge("record_date", beginDate)
+//                    .lt("record_date", endDate)
+//                    .orderByAsc("record_date");
+//            ;
+//            List<ProEconEquipmentInfoDay2> wtday2ls = proEconEquipmentInfoDay2Service.list(queryWrapper2);
+//            if (!wtday2ls.isEmpty()) {
+//                for (ProEconEquipmentInfoDay2 wtday2 : wtday2ls) {
+//                    if (day2map.containsKey(wtday2.getWindturbineId())) {
+//                        Map<Long, ProEconEquipmentInfoDay2> tempmap = day2map.get(wtday2.getWindturbineId());
+//                        tempmap.put(wtday2.getRecordDate().getTime(), wtday2);
+//                        day2map.put(wtId, tempmap);
+//                    } else {
+//                        Map<Long, ProEconEquipmentInfoDay2> tempmap = new HashMap<>();
+//                        tempmap.put(wtday2.getRecordDate().getTime(), wtday2);
+//                        day2map.put(wtId, tempmap);
+//                    }
+//                }
+//            }
+//            QueryWrapper<ProEconEquipmentInfoDay4> queryWrapper4 = new QueryWrapper<>();
+//            queryWrapper4.eq("windturbine_id", wtId).ge("record_date", beginDate)
+//                    .lt("record_date", endDate)
+//                    .orderByAsc("record_date");
+//            List<ProEconEquipmentInfoDay4> wtday4ls = proEconEquipmentInfoDay4Service.list(queryWrapper4);
+//            ProBasicEquipment wt = CacheContext.wtmap.get(wtId);
+//            ProBasicPowerstation wp = CacheContext.wpmap.get(wt.getWindpowerstationId());
+//
+//            if (StringUtils.notEmp(wtday2ls) && !wtday2ls.isEmpty()) {
+//
+//                for (ProEconEquipmentInfoDay2 wtd : wtday2ls) {
+//
+//                    SingleAnalysisVo vo = new SingleAnalysisVo();
+//
+//                    Calendar c = Calendar.getInstance();
+//
+//                    c.setTime(wtd.getRecordDate());
+//                    int dayTimes = 24;//风机日历小时合计
+//
+//
+//                    if (day1map.containsKey(wtd.getWindturbineId())) {
+//                        Map<Long, ProEconEquipmentInfoDay1> map1 = day1map.get(wtd.getWindturbineId());
+//                        if (map1.containsKey(wtd.getRecordDate().getTime())) {
+//                            ProEconEquipmentInfoDay1 daypo = map1.get(wtd.getRecordDate().getTime());
+//                            double fdl = null != daypo.getRfdl() ? daypo.getRfdl() : 0.0;//风机发电量合计
+//                            if (CacheContext.modelMap.containsKey(wt.getModelId())) {
+//                                ProEconEquipmentmodel model = CacheContext.modelMap.get(wt.getModelId());
+//                                double lyxs = new BigDecimal(fdl).divide(new BigDecimal(model.getPowerProduction()), 2, RoundingMode.HALF_UP).doubleValue();
+//                                vo.setLyxs(lyxs);
+//                            }
+//
+//                            fdl = new BigDecimal(fdl).divide(new BigDecimal(10000), 2, RoundingMode.HALF_UP).doubleValue();
+//                            double fs = null != daypo.getRpjfs() ? daypo.getRpjfs() : 0.0;//风机平均风速
+//                            vo.setFdl(StringUtils.round(fdl, 2));
+//                            vo.setFs(StringUtils.round(fs, 2));
+//                        }
+//                    }
+//
+//                    double yxxs = null != wtd.getRyxxs() ? wtd.getRyxxs() : 0.0;//风机运行小时合计
+//                    double gzxs = null != wtd.getRgztjxs() ? wtd.getRgztjxs() : 0.0;//风机故障小时合计
+//                    double jxxs = null != wtd.getRjxtjxs() ? wtd.getRjxtjxs() : 0.0;//风机检修小时合计
+//                    double tjxs = null != wtd.getRxdxs() ? wtd.getRxdxs() : 0.0;//风限电小时合计
+//                    double zdxs = null != wtd.getRtxzdxs() ? wtd.getRtxzdxs() : 0.0;//风机中断小时合计
+//
+//                    vo.setWindPowerStationId(wt.getWindpowerstationId());
+//                    vo.setWindPowerStationName(wp.getName());
+//                    vo.setWindturbineName(wt.getName());
+//                    vo.setWindturbineid(wt.getId());
+//                    vo.setRecorddate(wtd.getRecordDate());
+//
+//
+//                    vo.setYxxs(StringUtils.round(yxxs, 2));
+//                    vo.setGzxs(StringUtils.round(gzxs, 2));
+//                    vo.setJxxs(StringUtils.round(jxxs, 2));
+//                    vo.setTjxs(StringUtils.round(tjxs, 2));
+//                    vo.setZdxs(StringUtils.round(zdxs, 2));
+//                    vo.setRlxs(StringUtils.round(dayTimes, 2));
+//
+//                    fdlfsls.add(vo);
+//
+//                }
+//
+//            }
+//
+//            if (StringUtils.notEmp(wtday1ls) && !wtday1ls.isEmpty()) {
+//                for (ProEconEquipmentInfoDay1 wtd : wtday1ls) {
+//                    SingleAnalysisVo vo = new SingleAnalysisVo();
+//                    double gzss = null != wtd.getRgzssdl() ? wtd.getRgzssdl() : 0.0;//风机故障损失合计
+//                    double jxss = null != wtd.getRjxssdl() ? wtd.getRjxssdl() : 0.0;//风机检修损失合计
+//                    double xdss = null != wtd.getRxdtjssdl() ? wtd.getRxdtjssdl() : 0.0;//风机限电损失合计
+//                    double xnss = null != wtd.getRxnssdl() ? wtd.getRxnssdl() : 0.0;//风机性能损失时合计
+//                    double ycwsldwssdl = null != wtd.getRcwsldwssdl() ? wtd.getRcwsldwssdl() : 0.0;//场外受累电网损失电量
+//                    double ycwsltqssdl = null != wtd.getRcwsltqssdl() ? wtd.getRcwsldwssdl() : 0.0;//场外受累天气损失电量
+//                    double slss = StringUtils.round(ycwsldwssdl + ycwsltqssdl, 2);
+//
+//
+//                    vo.setWindPowerStationId(wt.getWindpowerstationId());
+//                    vo.setWindPowerStationName(wp.getName());
+//                    vo.setWindturbineName(wt.getName());
+//                    vo.setWindturbineid(wt.getId());
+//                    vo.setRecorddate(wtd.getRecordDate());
+//
+//                    vo.setGzss(StringUtils.round(gzss, 2));
+//                    vo.setJxss(StringUtils.round(jxss, 2));
+//                    vo.setXdss(StringUtils.round(xdss, 2));
+//                    vo.setXnss(StringUtils.round(xnss, 2));
+//                    vo.setSlss(StringUtils.round(slss, 2));
+//                    wsls.add(vo);
+//                }
+//
+//            }
+//
+//
+//            if (StringUtils.notEmp(wtday4ls) && !wtday4ls.isEmpty()) {
+//
+//                for (ProEconEquipmentInfoDay4 wtd : wtday4ls) {
+//
+//                    SingleAnalysisVo vo = new SingleAnalysisVo();
+//
+//                    vo.setRecorddate(wtd.getRecordDate());
+//
+//                    double jfsc = null != wtd.getRjfsc() ? wtd.getRjfsc() : 0.0;//静风时长
+//                    double jfpl = new BigDecimal(jfsc).divide(new BigDecimal(24), 2, RoundingMode.HALF_EVEN).multiply(new BigDecimal(100)).doubleValue();//静风频率
+//
+//                    vo.setJfpl(StringUtils.round(jfpl, 2));
+//                    if (day2map.containsKey(wtd.getWindturbineId())) {
+//                        Map<Long, ProEconEquipmentInfoDay2> map2 = day2map.get(wtd.getWindturbineId());
+//                        if (map2.containsKey(wtd.getRecordDate().getTime())) {
+//                            ProEconEquipmentInfoDay2 daypo = map2.get(wtd.getRecordDate().getTime());
+//                            vo.setTjxs(daypo.getRdjxsmx());
+//                        }
+//                    }
+//
+//                    vo.setWindPowerStationId(wt.getWindpowerstationId());
+//                    vo.setWindPowerStationName(wp.getName());
+//                    vo.setWindturbineName(wt.getName());
+//                    vo.setWindturbineid(wt.getId());
+//
+//
+//                    jfpldjsjls.add(vo);
+//                }
+//            }
+        map.put("ff", fdlfsls);//发电量和风速
+        map.put("ws", wsls);//五项损失,绑定五个
+        map.put("jd", jfpldjsjls);//静风频率和待机时间
 
-                    vo.setJfpl(StringUtils.round(jfpl, 2));
-                    if (day2map.containsKey(wtd.getWindturbineId())) {
-                        Map<Long, ProEconEquipmentInfoDay2> map2 = day2map.get(wtd.getWindturbineId());
-                        if (map2.containsKey(wtd.getRecordDate().getTime())) {
-                            ProEconEquipmentInfoDay2 daypo = map2.get(wtd.getRecordDate().getTime());
-                            vo.setTjxs(daypo.getRdjxsmx());
-                        }
-                    }
+        List<TurbineInfoDay> turbineSingle = turbineInfoDayService.getTurbineSingleList(wtId, beginDate, endDate);
+        if (turbineSingle == null || turbineSingle.isEmpty()) {
+            return map;
+        }
 
-                    vo.setWindPowerStationId(wt.getWindpowerstationId());
-                    vo.setWindPowerStationName(wp.getName());
-                    vo.setWindturbineName(wt.getName());
-                    vo.setWindturbineid(wt.getId());
+        TreeMap<Date, TurbineInfoDay> col = turbineSingle.stream()
+                .filter(Objects::nonNull)
+                .filter(t -> t.getRecordDate() != null)
+                .collect(Collectors.toMap(
+                        TurbineInfoDay::getRecordDate,
+                        Function.identity(),
+                        (v1, v2) -> v1,
+                        TreeMap::new
+                ));
+
+        if (!col.isEmpty()) {
+            Date lastDate = col.lastKey();
+            col.remove(lastDate);
+        }
 
+        List<SingleAnalysisVo> ffList = map.get("ff");
+        if (ffList != null && !ffList.isEmpty()) {
+            ffList.removeIf(f -> {
+                if (f == null || f.getRecorddate() == null) return true;
+                TurbineInfoDay tb = col.get(f.getRecorddate());
+                if (tb == null) return true;
+                Double rfdl = tb.getRfdl();
+                f.setFdl(NumberUtil.round(rfdl != null ? rfdl / 1000 : 0, 2).doubleValue());
+                Double pjfs = tb.getPjfs();
+                f.setFs(NumberUtil.round(pjfs != null ? pjfs : 0, 2).doubleValue());
+
+                return false;
+            });
+        }
 
-                    jfpldjsjls.add(vo);
-                }
-            }
-            map.put("ff", fdlfsls);//发电量和风速
-            map.put("ws", wsls);//五项损失,绑定五个
-            map.put("jd", jfpldjsjls);//静风频率和待机时间
+        List<SingleAnalysisVo> wsList = map.get("ws");
+        if (wsList != null && !wsList.isEmpty()) {
+            wsList.removeIf(w -> {
+                if (w == null || w.getRecorddate() == null) return true;
+                TurbineInfoDay tb = col.get(w.getRecorddate());
+                if (tb == null) return true;
+                Double slss = tb.getSlss();
+                w.setSlss(NumberUtil.round(slss != null ? slss / 1000 : 0, 2).doubleValue());
+                Double xnss = tb.getXnss();
+                w.setXnss(NumberUtil.round(xnss != null ? xnss / 1000 : 0, 2).doubleValue());
+                Double xdss = tb.getXdss();
+                w.setXdss(NumberUtil.round(xdss != null ? xdss / 1000 : 0, 2).doubleValue());
+                Double jhjxss = tb.getJhjxss();
+                w.setJxss(NumberUtil.round(jhjxss != null ? jhjxss / 1000 : 0, 2).doubleValue());
+                Double gzss = tb.getGzss();
+                w.setGzss(NumberUtil.round(gzss != null ? gzss / 1000 : 0, 2).doubleValue());
+                return false;
+            });
         }
 
-        List<TurbineInfoDay> turbineSingle = turbineInfoDayService.getTurbineSingleList(wtId, beginDate, endDate);
-        Map<Date, TurbineInfoDay> col = turbineSingle.stream().collect(Collectors.toMap(TurbineInfoDay::getRecordDate, Function.identity()));
-        List<SingleAnalysisVo> ff = map.get("ff").stream().collect(Collectors.toList());
-        List<SingleAnalysisVo> ws = map.get("ws").stream().collect(Collectors.toList());
-        List<SingleAnalysisVo> jd = map.get("jd").stream().collect(Collectors.toList());
-        ff.forEach(f -> {
-            TurbineInfoDay tb = col.get(f.getRecorddate());
-            f.setFdl(NumberUtil.round(tb.getRfdl() / 1000, 2).doubleValue());
-            f.setFs(NumberUtil.round(tb.getPjfs(), 2).doubleValue());
-        });
-        ws.forEach(w -> {
-            TurbineInfoDay tb = col.get(w.getRecorddate());
-            w.setSlss(NumberUtil.round(tb.getSlss() / 1000, 2).doubleValue());
-            w.setXnss(NumberUtil.round(tb.getXnss() / 1000, 2).doubleValue());
-            w.setXdss(NumberUtil.round(tb.getXdss() / 1000, 2).doubleValue());
-            w.setJxss(NumberUtil.round(tb.getJhjxss() / 1000, 2).doubleValue());
-            w.setGzss(NumberUtil.round(tb.getGzss() / 1000, 2).doubleValue());
-        });
-        jd.forEach(j -> {
-            TurbineInfoDay tb = col.get(j.getRecorddate());
-            j.setJfpl(NumberUtil.round(tb.getJfpl(), 2).doubleValue());
-            j.setDjxs(NumberUtil.round(tb.getDjMin() / 60, 2).doubleValue());
-        });
+        List<SingleAnalysisVo> jdList = map.get("jd");
+        if (jdList != null && !jdList.isEmpty()) {
+            jdList.removeIf(j -> {
+                if (j == null || j.getRecorddate() == null) return true;
+                TurbineInfoDay tb = col.get(j.getRecorddate());
+                if (tb == null) return true;
+                Double jfpl = tb.getJfpl();
+                j.setJfpl(NumberUtil.round(jfpl != null ? jfpl : 0, 2).doubleValue());
+                Double djMin = tb.getDjMin();
+                j.setDjxs(NumberUtil.round(djMin != null ? djMin / 60 : 0, 2).doubleValue());
+                return false;
+            });
+        }
 
         return map;
     }