diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsReportExportController.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsReportExportController.java new file mode 100644 index 00000000..3a83276f --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/controller/PgsReportExportController.java @@ -0,0 +1,2026 @@ +package org.dromara.progress.controller; + +import cn.dev33.satoken.annotation.SaIgnore; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.commons.io.IOUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.ss.util.RegionUtil; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; +import org.dromara.common.core.enums.FormatsType; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.DateUtils; +import org.dromara.common.web.core.BaseController; +import org.dromara.manager.weathermanager.WeatherConstant; +import org.dromara.manager.weathermanager.WeatherManager; +import org.dromara.manager.weathermanager.vo.WeatherVo; +import org.dromara.progress.domain.dto.export.ReportExportDto; +import org.dromara.progress.domain.vo.export.*; +import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryByDayVo; +import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryDayTotalVo; +import org.dromara.progress.domain.vo.progresscategory.PgsProgressCategoryDetailByDayVo; +import org.dromara.progress.service.IPgsProgressCategoryService; +import org.dromara.progress.service.IPgsProgressPlanService; +import org.dromara.project.domain.BusProject; +import org.dromara.project.service.IBusProjectService; +import org.dromara.quality.domain.QltQualityInspection; +import org.dromara.quality.service.IQltQualityInspectionService; +import org.dromara.safety.domain.HseSafetyInspection; +import org.dromara.safety.service.IHseSafetyInspectionService; +import org.dromara.system.domain.vo.SysOssVo; +import org.dromara.system.service.ISysOssService; +import org.springframework.scheduling.annotation.Async; +import org.springframework.validation.annotation.Validated; +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.mvc.method.annotation.StreamingResponseBody; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.URL; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +@Validated +@RestController +@RequestMapping("/progress/export") +public class PgsReportExportController extends BaseController { + + + @Resource + private IPgsProgressCategoryService pgsProgressCategoryService; + @Resource + private IBusProjectService projectService; + @Resource + private IQltQualityInspectionService qltQualityInspectionService; + @Resource + private IHseSafetyInspectionService safetyInspectionService; + @Resource + private ISysOssService ossService; + + @Resource + private WeatherManager weatherManager; + + + public static final List IMAGE_SUFFIX = Arrays.asList(".png",".jpg",".jpeg"); + + @SaIgnore + @GetMapping("/dayReport") + public void getStreamData(ReportExportDto dto, HttpServletResponse response) { + try { + // 设置响应头,指定文件类型和下载文件名 + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setHeader("Content-Disposition", "attachment; filename=project-report.xlsx"); + + // 获取数据并导出Excel + PgsProgressCategoryDayTotalVo progressCategoryByDay = pgsProgressCategoryService.getProgressCategoryByDay(dto.getProjectId(), DateUtils.parseLocalDateTime(FormatsType.YYYY_MM_DD, dto.getDate())); + + // 修改数据组装方式,返回 List> + List> projectDataList = getProjectDataListAsRows(progressCategoryByDay); + + ParamData paramData = getParamData(dto); + // 导出Excel到响应输出流 + exportProjectExcel(response.getOutputStream(), projectDataList, paramData); + + response.getOutputStream().flush(); + } catch (IOException e) { + throw new RuntimeException("导出Excel失败", e); + } + } + + + +// public static void main(String[] args) { +// // 导出路径 +// String exportPath = "C:\\Users\\YuanJie\\Desktop\\test.xlsx"; +// PgsProgressCategoryDayTotalVo progressCategoryDayTotalVo = getProgressCategoryDayTotalVo(); +// List projectDataList = getProjectDataList(progressCategoryDayTotalVo); +// +// try (FileOutputStream fos = new FileOutputStream(exportPath)) { +// exportProjectExcel(fos, projectDataList); +// System.out.println("Excel导出成功!文件路径:" + exportPath); +// } catch (IOException e) { +// System.err.println("导出失败:" + e.getMessage()); +// } +// } + + + + public static void exportProjectExcel(OutputStream outputStream, List> projectDataList, ParamData paramData) throws IOException { + try (Workbook workbook = new XSSFWorkbook()) { + Sheet sheet = workbook.createSheet("项目日志"); + + // 样式定义 + CellStyle wrapTitleStyle = createWrapTitleStyle(workbook); + CellStyle titleStyle = createTitleStyle(workbook); + CellStyle contentStyle = createContentStyle(workbook); + CellStyle headerStyle = createHeaderStyle(workbook); + CellStyle leftHeaderStyle = createLeftHeaderStyle(workbook); // 左对齐表头样式 + + // 行偏移量,用于跟踪当前写入的行位置 + int currentRowOffset = 0; + + // 遍历每一行数据 + for (int rowIndex = 0; rowIndex < projectDataList.size(); rowIndex++) { + List rowData = projectDataList.get(rowIndex); + + // 计算该行数据需要的最大行数 + int maxRowsInThisLine = 0; + + // 为该行中的每个项目生成数据(按列排列) + for (int projectIndex = 0; projectIndex < rowData.size(); projectIndex++) { + int columnOffset = projectIndex * 14; // 每个项目13列,间隔1列 + ProjectData projectData = rowData.get(projectIndex); + + // 导出单个项目数据 + int projectRows = exportSingleProject(sheet, workbook, projectData, currentRowOffset, columnOffset, + wrapTitleStyle, titleStyle, contentStyle, headerStyle, leftHeaderStyle, paramData); + + maxRowsInThisLine = Math.max(maxRowsInThisLine, projectRows); + } + + // 更新行偏移量,为下一行数据预留空间 + currentRowOffset += maxRowsInThisLine + 1; // 加1行间隔 + } + + // 设置列宽 + int maxColumns = 0; + for (List rowData : projectDataList) { + maxColumns = Math.max(maxColumns, rowData.size() * 14); + } + + int columnWidth = (int) (9.85 * 256); + for (int i = 0; i < maxColumns; i++) { + sheet.setColumnWidth(i, columnWidth); + } + + workbook.write(outputStream); + } + } + + // 为单个项目导出数据的方法 + // 为单个项目导出数据的方法 + private static int exportSingleProject(Sheet sheet, Workbook workbook, ProjectData projectData, + int rowOffset, // 改为行偏移 + int columnOffset, // 保留列偏移 + CellStyle wrapTitleStyle, CellStyle titleStyle, + CellStyle contentStyle, CellStyle headerStyle, + CellStyle leftHeaderStyle, ParamData paramData) { + List progressList = projectData.getProgressList(); + List participantList = projectData.getParticipantList(); + List equipmentEntryList = projectData.getEquipmentEntryList(); + List materialList = projectData.getMaterialList(); + List inspectionList = projectData.getInspectionList(); + String projectName = projectData.getProjectName(); + String projectDate = projectData.getProjectDate(); + + // ============================================== + // 1. 第一行:A1-M1合并(加上行偏移量和列偏移量) + // ============================================== + CellRangeAddress titleRegion = new CellRangeAddress(0 + rowOffset, 0 + rowOffset, 0 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, titleRegion, + projectName + "\n日期: " + paramData.getDate(), + wrapTitleStyle); + drawBorderForRegion(sheet, titleRegion, workbook); + Row titleRow = sheet.getRow(0 + rowOffset); + if (titleRow == null) { + titleRow = sheet.createRow(0 + rowOffset); + } + titleRow.setHeightInPoints(45); + + // ============================================== + // 2. 部门区域:A2-B3合并(加上行偏移量和列偏移量) + // ============================================== + CellRangeAddress deptRegion = new CellRangeAddress(1 + rowOffset, 2 + rowOffset, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, deptRegion, "部门", titleStyle); + drawBorderForRegion(sheet, deptRegion, workbook); + + // ============================================== + // 3. 部门名称:C2-F3合并 + // ============================================== + CellRangeAddress deptNameRegion = new CellRangeAddress(1 + rowOffset, 2 + rowOffset, 2 + columnOffset, 5 + columnOffset); + mergeAndFill(sheet, deptNameRegion, "田东公司项目建设管理部", contentStyle); + drawBorderForRegion(sheet, deptNameRegion, workbook); + + // ============================================== + // 4. 记录人:G2-I2合并 + // ============================================== + CellRangeAddress recorderRegion = new CellRangeAddress(1 + rowOffset, 1 + rowOffset, 6 + columnOffset, 8 + columnOffset); + mergeAndFill(sheet, recorderRegion, "记录人", titleStyle); + drawBorderForRegion(sheet, recorderRegion, workbook); + + // ============================================== + // 5. 记录人名称:J2-M2合并 + // ============================================== + CellRangeAddress recorderNameRegion = new CellRangeAddress(1 + rowOffset, 1 + rowOffset, 9 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, recorderNameRegion, paramData.getRecorder(), contentStyle); + drawBorderForRegion(sheet, recorderNameRegion, workbook); + + // ============================================== + // 6. 气温:G3-I3合并 + // ============================================== + CellRangeAddress tempRegion = new CellRangeAddress(2 + rowOffset, 2 + rowOffset, 6 + columnOffset, 8 + columnOffset); + mergeAndFill(sheet, tempRegion, "气温", titleStyle); + drawBorderForRegion(sheet, tempRegion, workbook); + + // ============================================== + // 7. 气温值:J3-M3合并 + // ============================================== + CellRangeAddress tempValueRegion = new CellRangeAddress(2 + rowOffset, 2 + rowOffset, 9 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, tempValueRegion, paramData.getTemp(), contentStyle); + drawBorderForRegion(sheet, tempValueRegion, workbook); + + // ============================================== + // 8. 天气:A4-B4合并 + // ============================================== + CellRangeAddress weatherRegion = new CellRangeAddress(3 + rowOffset, 3 + rowOffset, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, weatherRegion, "天气", titleStyle); + drawBorderForRegion(sheet, weatherRegion, workbook); + + // ============================================== + // 9. 白天:C4-D4合并 + // ============================================== + CellRangeAddress dayRegion = new CellRangeAddress(3 + rowOffset, 3 + rowOffset, 2 + columnOffset, 3 + columnOffset); + mergeAndFill(sheet, dayRegion, "白天", titleStyle); + drawBorderForRegion(sheet, dayRegion, workbook); + + // ============================================== + // 10. 白天天气:E4-F4合并 + // ============================================== + CellRangeAddress dayWeatherRegion = new CellRangeAddress(3 + rowOffset, 3 + rowOffset, 4 + columnOffset, 5 + columnOffset); + mergeAndFill(sheet, dayWeatherRegion, paramData.getDayWeather(), contentStyle); + drawBorderForRegion(sheet, dayWeatherRegion, workbook); + + // ============================================== + // 11. 夜晚:G4-I4合并 + // ============================================== + CellRangeAddress nightRegion = new CellRangeAddress(3 + rowOffset, 3 + rowOffset, 6 + columnOffset, 8 + columnOffset); + mergeAndFill(sheet, nightRegion, "夜晚", titleStyle); + drawBorderForRegion(sheet, nightRegion, workbook); + + // ============================================== + // 12. 夜晚天气:J4-M4合并 + // ============================================== + CellRangeAddress nightWeatherRegion = new CellRangeAddress(3 + rowOffset, 3 + rowOffset, 9 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, nightWeatherRegion, paramData.getNightWeather(), contentStyle); + drawBorderForRegion(sheet, nightWeatherRegion, workbook); + + // ============================================== + // 13. 项目简介:A5-B5合并 + // ============================================== + CellRangeAddress introRegion = new CellRangeAddress(4 + rowOffset, 4 + rowOffset, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, introRegion, "项目简介", titleStyle); + drawBorderForRegion(sheet, introRegion, workbook); + + // ============================================== + // 14. 项目简介内容:C5-M5合并 + // ============================================== + CellRangeAddress introContentRegion = new CellRangeAddress(4 + rowOffset, 4 + rowOffset, 2 + columnOffset, 12 + columnOffset); + String introContent = "田东县乡村振兴分布式光伏项目(一期)眉定项目位于百色市田东县那拔镇,项目备案容量为15MW,现计划装机容量为15.06MW,土地使用权面积217.36亩,可实施的交流容量约为15.06MW。"; + mergeAndFill(sheet, introContentRegion, introContent, contentStyle); + drawBorderForRegion(sheet, introContentRegion, workbook); + Row introRow = sheet.getRow(4 + rowOffset); + if (introRow == null) { + introRow = sheet.createRow(4 + rowOffset); + } + introRow.setHeightInPoints(60); + + // ============================================== + // 15. 光伏场区标题行(C6-M6合并) + // ============================================== + CellRangeAddress fieldTitleRegion = new CellRangeAddress(5 + rowOffset, 5 + rowOffset, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, fieldTitleRegion, "光伏场区", headerStyle); + drawBorderForRegion(sheet, fieldTitleRegion, workbook); + Row fieldTitleRow = sheet.getRow(5 + rowOffset); + if (fieldTitleRow == null) { + fieldTitleRow = sheet.createRow(5 + rowOffset); + } + fieldTitleRow.setHeightInPoints(25); + + // ============================================== + // 16. 表头行(第7行,索引6) + // ============================================== + int headerRowNum = 6 + rowOffset; + Row headerRow = sheet.getRow(headerRowNum); + if (headerRow == null) { + headerRow = sheet.createRow(headerRowNum); + } + + // C7:序号 + Cell c7 = headerRow.createCell(2 + columnOffset); + c7.setCellValue("序号"); + c7.setCellStyle(headerStyle); + CellRangeAddress c7Region = new CellRangeAddress(headerRowNum, headerRowNum, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, c7Region, workbook); + + // D7-E7:项目 + CellRangeAddress projectRegion = new CellRangeAddress(headerRowNum, headerRowNum, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, projectRegion, "项目", headerStyle); + drawBorderForRegion(sheet, projectRegion, workbook); + + // F7:设计值 + Cell f7 = headerRow.createCell(5 + columnOffset); + f7.setCellValue("设计值"); + f7.setCellStyle(headerStyle); + CellRangeAddress f7Region = new CellRangeAddress(headerRowNum, headerRowNum, 5 + columnOffset, 5 + columnOffset); + drawBorderForRegion(sheet, f7Region, workbook); + + // G7-H7:今日施工计划 + CellRangeAddress planRegion = new CellRangeAddress(headerRowNum, headerRowNum, 6 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, planRegion, "今日施工计划", headerStyle); + drawBorderForRegion(sheet, planRegion, workbook); + + // I7-J7:今日施工完成情况 + CellRangeAddress completeRegion = new CellRangeAddress(headerRowNum, headerRowNum, 8 + columnOffset, 9 + columnOffset); + mergeAndFill(sheet, completeRegion, "今日施工完成情况", headerStyle); + drawBorderForRegion(sheet, completeRegion, workbook); + + // K7:累计完成工程量 + Cell k7 = headerRow.createCell(10 + columnOffset); + k7.setCellValue("累计完成工程量"); + k7.setCellStyle(headerStyle); + CellRangeAddress k7Region = new CellRangeAddress(headerRowNum, headerRowNum, 10 + columnOffset, 10 + columnOffset); + drawBorderForRegion(sheet, k7Region, workbook); + + // L7-M7:施工形象及进度 + CellRangeAddress processRegion = new CellRangeAddress(headerRowNum, headerRowNum, 11 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, processRegion, "施工形象及进度", headerStyle); + drawBorderForRegion(sheet, processRegion, workbook); + + headerRow.setHeightInPoints(25); + + // ============================================== + // 17. 动态填充进度数据 + // ============================================== + int lastDataRow = headerRowNum; // 记录最后一行数据的行索引 + if (progressList != null && !progressList.isEmpty()) { + int dataStartRow = headerRowNum + 1; // 数据从第8行开始(索引7) + + for (int i = 0; i < progressList.size(); i++) { + ProgressData data = progressList.get(i); + int rowNum = dataStartRow + i; + lastDataRow = rowNum; // 更新最后一行索引 + Row dataRow = sheet.getRow(rowNum); + if (dataRow == null) { + dataRow = sheet.createRow(rowNum); + } + + // C列:序号 + Cell cCell = dataRow.createCell(2 + columnOffset); + cCell.setCellValue(data.getNum()); + cCell.setCellStyle(contentStyle); + drawBorderForCell(sheet, rowNum, 2 + columnOffset, 2 + columnOffset, workbook); + + // D-E列:项目 + CellRangeAddress projectDataRegion = new CellRangeAddress(rowNum, rowNum, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, projectDataRegion, data.getProject(), contentStyle); + drawBorderForRegion(sheet, projectDataRegion, workbook); + + // F列:设计值 + Cell fCell = dataRow.createCell(5 + columnOffset); + fCell.setCellValue(data.getDesign()); + fCell.setCellStyle(contentStyle); + drawBorderForCell(sheet, rowNum, 5 + columnOffset, 5 + columnOffset, workbook); + + // G-H列:今日施工计划 + CellRangeAddress planDataRegion = new CellRangeAddress(rowNum, rowNum, 6 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, planDataRegion, data.getPlan(), contentStyle); + drawBorderForRegion(sheet, planDataRegion, workbook); + + // I-J列:今日施工完成情况 + CellRangeAddress completeDataRegion = new CellRangeAddress(rowNum, rowNum, 8 + columnOffset, 9 + columnOffset); + mergeAndFill(sheet, completeDataRegion, data.getComplete(), contentStyle); + drawBorderForRegion(sheet, completeDataRegion, workbook); + + // K列:累计完成工程量 + Cell kCell = dataRow.createCell(10 + columnOffset); + kCell.setCellValue(data.getTotal()); + kCell.setCellStyle(contentStyle); + drawBorderForCell(sheet, rowNum, 10 + columnOffset, 10 + columnOffset, workbook); + + // L-M列:施工形象及进度 + CellRangeAddress processDataRegion = new CellRangeAddress(rowNum, rowNum, 11 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, processDataRegion, data.getProcess(), contentStyle); + drawBorderForRegion(sheet, processDataRegion, workbook); + + dataRow.setHeightInPoints(20); + } + } + + // ============================================== + // 18. 情况说明行(动态数据下一行) + // ============================================== + int noteRowNum = lastDataRow + 1; + Row noteRow = sheet.getRow(noteRowNum); + if (noteRow == null) { + noteRow = sheet.createRow(noteRowNum); + } + + // C-E列合并:情况说明 + CellRangeAddress noteTitleRegion = new CellRangeAddress(noteRowNum, noteRowNum, 2 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, noteTitleRegion, "情况说明", headerStyle); + drawBorderForRegion(sheet, noteTitleRegion, workbook); + + // F-M列合并:无 + CellRangeAddress noteContentRegion = new CellRangeAddress(noteRowNum, noteRowNum, 5 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, noteContentRegion, "无", contentStyle); + drawBorderForRegion(sheet, noteContentRegion, workbook); + + noteRow.setHeightInPoints(25); + + // ============================================== + // 19. A6到情况说明行的B列纵向合并(含内容) + // ============================================== + int startMergeRow = 5 + rowOffset; // A6对应行索引5 + int endMergeRow = noteRowNum; // 情况说明行的行索引 + CellRangeAddress aColumnRegion = new CellRangeAddress(startMergeRow, endMergeRow, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, aColumnRegion, "施工部位\n施工内容\n施工形象\n及进度", titleStyle); + drawBorderForRegion(sheet, aColumnRegion, workbook); + + // 调整A-B列合并区域行高(适配4行文本) + int totalHeight = 0; + for (int i = startMergeRow; i <= endMergeRow; i++) { + Row row = sheet.getRow(i); + if (row != null) { + totalHeight += row.getHeightInPoints(); + } + } + int rowCount = endMergeRow - startMergeRow + 1; + int baseHeight = 20; + int extraHeight = (int) (totalHeight - rowCount * baseHeight); // 额外高度分配给首行 + Row firstRow = sheet.getRow(startMergeRow); + if (firstRow != null) { + firstRow.setHeightInPoints(baseHeight + extraHeight); + } + for (int i = startMergeRow + 1; i <= endMergeRow; i++) { + Row row = sheet.getRow(i); + if (row != null) { + row.setHeightInPoints(baseHeight); + } + } + + // ============================================== + // 20. 现场质量行(情况说明行下一行) + // ============================================== + int qualityRowNum = noteRowNum + 1; + Row qualityRow = sheet.getRow(qualityRowNum); + if (qualityRow == null) { + qualityRow = sheet.createRow(qualityRowNum); + } + + // A-B列合并:现场质量 + CellRangeAddress qualityTitleRegion = new CellRangeAddress(qualityRowNum, qualityRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, qualityTitleRegion, "现场质量", titleStyle); + drawBorderForRegion(sheet, qualityTitleRegion, workbook); + + // C-M列合并:质量正常.可控。 + CellRangeAddress qualityContentRegion = new CellRangeAddress(qualityRowNum, qualityRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, qualityContentRegion, paramData.getQuality(), contentStyle); + drawBorderForRegion(sheet, qualityContentRegion, workbook); + + qualityRow.setHeightInPoints(25); + + // ============================================== + // 21. 现场安全行(现场质量行下一行) + // ============================================== + int safetyRowNum = qualityRowNum + 1; + Row safetyRow = sheet.getRow(safetyRowNum); + if (safetyRow == null) { + safetyRow = sheet.createRow(safetyRowNum); + } + + // A-B列合并:现场安全\n安全巡检 + CellRangeAddress safetyTitleRegion = new CellRangeAddress(safetyRowNum, safetyRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, safetyTitleRegion, "现场安全\n安全巡检", titleStyle); + drawBorderForRegion(sheet, safetyTitleRegion, workbook); + + // C-M列合并:安全正常.可控。 + CellRangeAddress safetyContentRegion = new CellRangeAddress(safetyRowNum, safetyRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, safetyContentRegion, paramData.getSafety(), contentStyle); + drawBorderForRegion(sheet, safetyContentRegion, workbook); + + safetyRow.setHeightInPoints(30); // 适配两行文本 + + // ============================================== + // 22. 施工现场情况说明行(现场安全行下一行) + // ============================================== + int siteRowNum = safetyRowNum + 1; + Row siteRow = sheet.getRow(siteRowNum); + if (siteRow == null) { + siteRow = sheet.createRow(siteRowNum); + } + + // A-B列合并:施工现场 + CellRangeAddress siteTitleRegion = new CellRangeAddress(siteRowNum, siteRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, siteTitleRegion, "施工现场", titleStyle); + drawBorderForRegion(sheet, siteTitleRegion, workbook); + + // C-E列合并:情况说明 + CellRangeAddress siteSubTitleRegion = new CellRangeAddress(siteRowNum, siteRowNum, 2 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, siteSubTitleRegion, "情况说明", headerStyle); + drawBorderForRegion(sheet, siteSubTitleRegion, workbook); + + // F-M列合并:详细内容 + String siteContent = "一.光伏区施工情况\n" + + "1.1#、3#、5#方阵支架、组件安装;\n" + + "2.2#方阵直流电缆敷设。\n\n" + + "二.验收情况\n" + + "今日无验收。"; + CellRangeAddress siteContentRegion = new CellRangeAddress(siteRowNum, siteRowNum, 5 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, siteContentRegion, siteContent, contentStyle); + drawBorderForRegion(sheet, siteContentRegion, workbook); + + siteRow.setHeightInPoints(100); // 适配多行文本 + + // ============================================== + // 23. 施工问题及处理情况行(施工现场行下一行) + // ============================================== + int problemRowNum = siteRowNum + 1; + Row problemRow = sheet.getRow(problemRowNum); + if (problemRow == null) { + problemRow = sheet.createRow(problemRowNum); + } + + // A-B列合并:施工问题及处理情况 + CellRangeAddress problemTitleRegion = new CellRangeAddress(problemRowNum, problemRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, problemTitleRegion, "施工问题及处理情况", titleStyle); + drawBorderForRegion(sheet, problemTitleRegion, workbook); + + // C-M列合并:坡度较大,合理安排人员采取有效防护措施。 + CellRangeAddress problemContentRegion = new CellRangeAddress(problemRowNum, problemRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, problemContentRegion, "坡度较大,合理安排人员采取有效防护措施。", contentStyle); + drawBorderForRegion(sheet, problemContentRegion, workbook); + + problemRow.setHeightInPoints(30); // 适配可能的换行 + + // ============================================== + // 24. 设计供图或技术核定行(施工问题行下一行) + // ============================================== + int designRowNum = problemRowNum + 1; + Row designRow = sheet.getRow(designRowNum); + if (designRow == null) { + designRow = sheet.createRow(designRowNum); + } + + // A-B列合并:设计供图或技术核定 + CellRangeAddress designTitleRegion = new CellRangeAddress(designRowNum, designRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, designTitleRegion, "设计供图或技术核定", titleStyle); + drawBorderForRegion(sheet, designTitleRegion, workbook); + + // C-M列合并:施工图满足现场施工 + CellRangeAddress designContentRegion = new CellRangeAddress(designRowNum, designRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, designContentRegion, "施工图满足现场施工", contentStyle); + drawBorderForRegion(sheet, designContentRegion, workbook); + + designRow.setHeightInPoints(25); + + // ============================================== + // 25. 参建单位人员标题行(设计核定行下一行) + // ============================================== + int participantTitleRow = designRowNum + 1; + Row titleRow2 = sheet.getRow(participantTitleRow); + if (titleRow2 == null) { + titleRow2 = sheet.createRow(participantTitleRow); + } + + // C-D列合并:参建单位 + CellRangeAddress unitRegion = new CellRangeAddress(participantTitleRow, participantTitleRow, 2 + columnOffset, 3 + columnOffset); + mergeAndFill(sheet, unitRegion, "参建单位", headerStyle); + drawBorderForRegion(sheet, unitRegion, workbook); + + // E列:经理班子人员(不合并) + Cell leaderCell = titleRow2.createCell(4 + columnOffset); + leaderCell.setCellValue("经理班子人员"); + leaderCell.setCellStyle(headerStyle); + CellRangeAddress leaderRegion = new CellRangeAddress(participantTitleRow, participantTitleRow, 4 + columnOffset, 4 + columnOffset); + drawBorderForRegion(sheet, leaderRegion, workbook); + + // F-G列合并:主要管理技术人员 + CellRangeAddress managerRegion = new CellRangeAddress(participantTitleRow, participantTitleRow, 5 + columnOffset, 6 + columnOffset); + mergeAndFill(sheet, managerRegion, "主要管理技术人员", headerStyle); + drawBorderForRegion(sheet, managerRegion, workbook); + + // H列:其他人员(不合并) + Cell otherCell = titleRow2.createCell(7 + columnOffset); + otherCell.setCellValue("其他人员"); + otherCell.setCellStyle(headerStyle); + CellRangeAddress otherRegion = new CellRangeAddress(participantTitleRow, participantTitleRow, 7 + columnOffset, 7 + columnOffset); + drawBorderForRegion(sheet, otherRegion, workbook); + + // I-M列合并:备注 + CellRangeAddress remarkRegion1 = new CellRangeAddress(participantTitleRow, participantTitleRow, 8 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, remarkRegion1, "备注", headerStyle); + drawBorderForRegion(sheet, remarkRegion1, workbook); + + titleRow2.setHeightInPoints(25); + + // ============================================== + // 26. 动态填充参建单位人员数据 + // ============================================== + int lastParticipantRow = participantTitleRow; // 记录参建单位数据最后一行 + if (participantList != null && !participantList.isEmpty()) { + int dataStartRow = participantTitleRow + 1; + + for (int i = 0; i < participantList.size(); i++) { + ParticipantData data = participantList.get(i); + int rowNum = dataStartRow + i; + lastParticipantRow = rowNum; + Row dataRow = sheet.getRow(rowNum); + if (dataRow == null) { + dataRow = sheet.createRow(rowNum); + } + + // C-D列:参建单位 + CellRangeAddress unitDataRegion = new CellRangeAddress(rowNum, rowNum, 2 + columnOffset, 3 + columnOffset); + mergeAndFill(sheet, unitDataRegion, data.getUnit(), contentStyle); + drawBorderForRegion(sheet, unitDataRegion, workbook); + + // E列:经理班子人员 + Cell leaderDataCell = dataRow.createCell(4 + columnOffset); + leaderDataCell.setCellValue(data.getLeader()); + leaderDataCell.setCellStyle(contentStyle); + CellRangeAddress leaderDataRegion = new CellRangeAddress(rowNum, rowNum, 4 + columnOffset, 4 + columnOffset); + drawBorderForRegion(sheet, leaderDataRegion, workbook); + + // F-G列:主要管理技术人员 + CellRangeAddress managerDataRegion = new CellRangeAddress(rowNum, rowNum, 5 + columnOffset, 6 + columnOffset); + mergeAndFill(sheet, managerDataRegion, data.getManager(), contentStyle); + drawBorderForRegion(sheet, managerDataRegion, workbook); + + // H列:其他人员 + Cell otherDataCell = dataRow.createCell(7 + columnOffset); + otherDataCell.setCellValue(data.getOther()); + otherDataCell.setCellStyle(contentStyle); + CellRangeAddress otherDataRegion = new CellRangeAddress(rowNum, rowNum, 7 + columnOffset, 7 + columnOffset); + drawBorderForRegion(sheet, otherDataRegion, workbook); + + // I-M列:备注 + CellRangeAddress remarkDataRegion1 = new CellRangeAddress(rowNum, rowNum, 8 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, remarkDataRegion1, data.getRemark(), contentStyle); + drawBorderForRegion(sheet, remarkDataRegion1, workbook); + + dataRow.setHeightInPoints(22); + } + } + + // ============================================== + // 27. AB列纵向合并(参建单位标题行到数据结束行) + // ============================================== + CellRangeAddress participantABRegion = new CellRangeAddress( + participantTitleRow, // 开始行:参建单位标题行 + lastParticipantRow, // 结束行:参建单位数据最后一行 + 0 + columnOffset, 1 + columnOffset // A-B列 + ); + mergeAndFill(sheet, participantABRegion, + "参建单位主要管理.技术人员及劳务人员到位情况", + titleStyle); + drawBorderForRegion(sheet, participantABRegion, workbook); + + // 调整AB列合并区域行高(适配文本) + int participantRowCount = lastParticipantRow - participantTitleRow + 1; + int participantTotalHeight = 0; + for (int i = participantTitleRow; i <= lastParticipantRow; i++) { + Row row = sheet.getRow(i); + if (row != null) { + participantTotalHeight += row.getHeightInPoints(); + } + } + int participantBaseHeight = 25; + int participantExtraHeight = (int) (participantTotalHeight - participantRowCount * participantBaseHeight); + Row participantTitleRowObj = sheet.getRow(participantTitleRow); + if (participantTitleRowObj != null) { + participantTitleRowObj.setHeightInPoints(participantBaseHeight + participantExtraHeight); + } + for (int i = participantTitleRow + 1; i <= lastParticipantRow; i++) { + Row row = sheet.getRow(i); + if (row != null) { + row.setHeightInPoints(participantBaseHeight); + } + } + + // ============================================== + // 28. 施工机械标题行(参建单位数据行下一行) + // 第一行:C-M合并输入"光伏场区工程:"(左对齐) + // ============================================== + int machineTitleRow = lastParticipantRow + 1; + Row machineTitle = sheet.getRow(machineTitleRow); + if (machineTitle == null) { + machineTitle = sheet.createRow(machineTitleRow); + } + + // C-M列合并:光伏场区工程:(左对齐) + CellRangeAddress machineHeaderRegion = new CellRangeAddress(machineTitleRow, machineTitleRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, machineHeaderRegion, "光伏场区工程:", leftHeaderStyle); + drawBorderForRegion(sheet, machineHeaderRegion, workbook); + + machineTitle.setHeightInPoints(25); + + // ============================================== + // 29. 施工机械数据行(标题行下一行) + // C-D合并:机械/设备数量;E-M合并:设备清单(逗号分隔) + // ============================================== + int machineDataRow = machineTitleRow + 1; + Row machineData = sheet.getRow(machineDataRow); + if (machineData == null) { + machineData = sheet.createRow(machineDataRow); + } + + // C-D列合并:机械/设备数量 + CellRangeAddress machineCountRegion = new CellRangeAddress(machineDataRow, machineDataRow, 2 + columnOffset, 3 + columnOffset); + mergeAndFill(sheet, machineCountRegion, "机械/设备数量", headerStyle); + drawBorderForRegion(sheet, machineCountRegion, workbook); + + // E-M列合并:设备清单(逗号分隔) + String equipmentListStr = "RTK-0、清孔工具-0、电动扳手-20、小蜜蜂-0"; + CellRangeAddress equipmentRegion = new CellRangeAddress(machineDataRow, machineDataRow, 4 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, equipmentRegion, equipmentListStr, contentStyle); + drawBorderForRegion(sheet, equipmentRegion, workbook); + + machineData.setHeightInPoints(25); // 单行显示无需过高行高 + + // ============================================== + // 30. AB列纵向合并(施工机械标题行到数据行) + // 输入:施工机械及设备投入情况 + // ============================================== + CellRangeAddress machineABRegion = new CellRangeAddress( + machineTitleRow, // 开始行:机械标题行 + machineDataRow, // 结束行:机械数据行 + 0 + columnOffset, 1 + columnOffset // A-B列 + ); + mergeAndFill(sheet, machineABRegion, "施工机械及设备投入情况", titleStyle); + drawBorderForRegion(sheet, machineABRegion, workbook); + + // 调整AB列合并区域行高 + Row machineTitleRowObj = sheet.getRow(machineTitleRow); + Row machineDataRowObj = sheet.getRow(machineDataRow); + float machineTotalHeight = 0; + if (machineTitleRowObj != null) { + machineTotalHeight += machineTitleRowObj.getHeightInPoints(); + } + if (machineDataRowObj != null) { + machineTotalHeight += machineDataRowObj.getHeightInPoints(); + } + // 分配高度确保文本垂直居中 + if (machineTitleRowObj != null) { + machineTitleRowObj.setHeightInPoints(25); + } + if (machineDataRowObj != null) { + machineDataRowObj.setHeightInPoints(machineTotalHeight - 25); + } + + // ============================================== + // 31. 设备进场情况标题行(机械数据行下一行) + // 记录此行为AB列合并的起始行 + // ============================================== + int equipmentTitleRow = machineDataRow + 1; // AB列合并起始行 + Row equipmentTitle = sheet.getRow(equipmentTitleRow); + if (equipmentTitle == null) { + equipmentTitle = sheet.createRow(equipmentTitleRow); + } + + // C-M列合并:主要设备进场情况:(左对齐) + CellRangeAddress equipmentHeaderRegion = new CellRangeAddress(equipmentTitleRow, equipmentTitleRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, equipmentHeaderRegion, "主要设备进场情况:", leftHeaderStyle); + drawBorderForRegion(sheet, equipmentHeaderRegion, workbook); + + equipmentTitle.setHeightInPoints(20); + + // ============================================== + // 32. 设备进场情况表头行(标题行下一行) + // ============================================== + int equipmentHeaderRow = equipmentTitleRow + 1; + Row eqHeaderRow = sheet.getRow(equipmentHeaderRow); + if (eqHeaderRow == null) { + eqHeaderRow = sheet.createRow(equipmentHeaderRow); + } + + // C列:序号 + Cell eqC = eqHeaderRow.createCell(2 + columnOffset); + eqC.setCellValue("序号"); + eqC.setCellStyle(headerStyle); + CellRangeAddress eqCRegion = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, eqCRegion, workbook); + + // D-E列:项目 + CellRangeAddress eqProjectRegion = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, eqProjectRegion, "项目", headerStyle); + drawBorderForRegion(sheet, eqProjectRegion, workbook); + + // F列:数量 + Cell eqF = eqHeaderRow.createCell(5 + columnOffset); + eqF.setCellValue("数量"); + eqF.setCellStyle(headerStyle); + CellRangeAddress eqFRegion = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 5 + columnOffset, 5 + columnOffset); + drawBorderForRegion(sheet, eqFRegion, workbook); + + // G-H列:生产情况 + CellRangeAddress eqProductionRegion = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 6 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, eqProductionRegion, "生产情况", headerStyle); + drawBorderForRegion(sheet, eqProductionRegion, workbook); + + // I-J列:今日进场情况 + CellRangeAddress eqEntryRegion = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 8 + columnOffset, 9 + columnOffset); + mergeAndFill(sheet, eqEntryRegion, "今日进场情况", headerStyle); + drawBorderForRegion(sheet, eqEntryRegion, workbook); + + // K列:累计进场情况 + Cell eqK = eqHeaderRow.createCell(10 + columnOffset); + eqK.setCellValue("累计进场情况"); + eqK.setCellStyle(headerStyle); + CellRangeAddress eqKRegion = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 10 + columnOffset, 10 + columnOffset); + drawBorderForRegion(sheet, eqKRegion, workbook); + + // L-M列:备注 + CellRangeAddress remarkRegion2 = new CellRangeAddress(equipmentHeaderRow, equipmentHeaderRow, 11 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, remarkRegion2, "备注", headerStyle); + drawBorderForRegion(sheet, remarkRegion2, workbook); + + eqHeaderRow.setHeightInPoints(20); + + // ============================================== + // 33. 动态填充设备进场数据 + // ============================================== + int lastEquipmentRow = equipmentHeaderRow; // 记录设备数据最后一行 + if (equipmentEntryList != null && !equipmentEntryList.isEmpty()) { + int dataStartRow = equipmentHeaderRow + 1; + + for (int i = 0; i < equipmentEntryList.size(); i++) { + EquipmentEntryData data = equipmentEntryList.get(i); + int rowNum = dataStartRow + i; + lastEquipmentRow = rowNum; + Row dataRow = sheet.getRow(rowNum); + if (dataRow == null) { + dataRow = sheet.createRow(rowNum); + } + + // C列:序号 + Cell noCell = dataRow.createCell(2 + columnOffset); + noCell.setCellValue(data.getNo()); + noCell.setCellStyle(contentStyle); + CellRangeAddress noRegion = new CellRangeAddress(rowNum, rowNum, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, noRegion, workbook); + + // D-E列:项目 + CellRangeAddress eqProjectDataRegion = new CellRangeAddress(rowNum, rowNum, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, eqProjectDataRegion, data.getProject(), contentStyle); + drawBorderForRegion(sheet, eqProjectDataRegion, workbook); + + // F列:数量 + Cell numCell = dataRow.createCell(5 + columnOffset); + numCell.setCellValue(data.getNum()); + numCell.setCellStyle(contentStyle); + CellRangeAddress numRegion = new CellRangeAddress(rowNum, rowNum, 5 + columnOffset, 5 + columnOffset); + drawBorderForRegion(sheet, numRegion, workbook); + + // G-H列:生产情况 + CellRangeAddress productionRegion = new CellRangeAddress(rowNum, rowNum, 6 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, productionRegion, data.getProduction(), contentStyle); + drawBorderForRegion(sheet, productionRegion, workbook); + + // I-J列:今日进场情况 + CellRangeAddress entryRegion = new CellRangeAddress(rowNum, rowNum, 8 + columnOffset, 9 + columnOffset); + mergeAndFill(sheet, entryRegion, data.getEntry(), contentStyle); + drawBorderForRegion(sheet, entryRegion, workbook); + + // K列:累计进场情况 + Cell totalEntryCell = dataRow.createCell(10 + columnOffset); + totalEntryCell.setCellValue(data.getTotalEntry()); + totalEntryCell.setCellStyle(contentStyle); + CellRangeAddress totalEntryRegion = new CellRangeAddress(rowNum, rowNum, 10 + columnOffset, 10 + columnOffset); + drawBorderForRegion(sheet, totalEntryRegion, workbook); + + // L-M列:备注 + CellRangeAddress remarkDataRegion2 = new CellRangeAddress(rowNum, rowNum, 11 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, remarkDataRegion2, data.getRemark(), contentStyle); + drawBorderForRegion(sheet, remarkDataRegion2, workbook); + + dataRow.setHeightInPoints(20); + } + } + + // ============================================== + // 34. 设备情况说明行(设备进场数据行下一行) + // ============================================== + int equipmentNoteRow = lastEquipmentRow + 1; + Row eqNoteRow = sheet.getRow(equipmentNoteRow); + if (eqNoteRow == null) { + eqNoteRow = sheet.createRow(equipmentNoteRow); + } + + // C-E列合并:情况说明 + CellRangeAddress eqNoteTitleRegion = new CellRangeAddress(equipmentNoteRow, equipmentNoteRow, 2 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, eqNoteTitleRegion, "情况说明", headerStyle); + drawBorderForRegion(sheet, eqNoteTitleRegion, workbook); + + // F-M列合并:待生产 + CellRangeAddress eqNoteContentRegion = new CellRangeAddress(equipmentNoteRow, equipmentNoteRow, 5 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, eqNoteContentRegion, "待生产", contentStyle); + drawBorderForRegion(sheet, eqNoteContentRegion, workbook); + + eqNoteRow.setHeightInPoints(20); + + // ============================================== + // 35. 主要材料进场情况标题行(情况说明行下一行) + // ============================================== + int materialTitleRow = equipmentNoteRow + 1; + Row materialTitle = sheet.getRow(materialTitleRow); + if (materialTitle == null) { + materialTitle = sheet.createRow(materialTitleRow); + } + + CellRangeAddress materialHeaderRegion = new CellRangeAddress(materialTitleRow, materialTitleRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, materialHeaderRegion, "主要材料进场情况:", leftHeaderStyle); + drawBorderForRegion(sheet, materialHeaderRegion, workbook); + + materialTitle.setHeightInPoints(20); + + // ============================================== + // 36. 光伏场区工程标题行(主要材料标题行下一行) + // ============================================== + int materialSubTitleRow = materialTitleRow + 1; + Row materialSubTitle = sheet.getRow(materialSubTitleRow); + if (materialSubTitle == null) { + materialSubTitle = sheet.createRow(materialSubTitleRow); + } + + CellRangeAddress materialSubHeaderRegion = new CellRangeAddress(materialSubTitleRow, materialSubTitleRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, materialSubHeaderRegion, "1.光伏场区工程:", leftHeaderStyle); + drawBorderForRegion(sheet, materialSubHeaderRegion, workbook); + + materialSubTitle.setHeightInPoints(20); + + // ============================================== + // 37. 材料进场情况表头行(光伏场区工程标题行下一行) + // ============================================== + int materialHeaderRow = materialSubTitleRow + 1; + Row materialHeader = sheet.getRow(materialHeaderRow); + if (materialHeader == null) { + materialHeader = sheet.createRow(materialHeaderRow); + } + + // C列:序号 + Cell materialC = materialHeader.createCell(2 + columnOffset); + materialC.setCellValue("序号"); + materialC.setCellStyle(headerStyle); + CellRangeAddress materialCRegion = new CellRangeAddress(materialHeaderRow, materialHeaderRow, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, materialCRegion, workbook); + + // D-E列:材料名称 + CellRangeAddress materialNameRegion = new CellRangeAddress(materialHeaderRow, materialHeaderRow, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, materialNameRegion, "材料名称", headerStyle); + drawBorderForRegion(sheet, materialNameRegion, workbook); + + // F列:设计值 + Cell materialF = materialHeader.createCell(5 + columnOffset); + materialF.setCellValue("设计值"); + materialF.setCellStyle(headerStyle); + CellRangeAddress materialFRegion = new CellRangeAddress(materialHeaderRow, materialHeaderRow, 5 + columnOffset, 5 + columnOffset); + drawBorderForRegion(sheet, materialFRegion, workbook); + + // G-L列:进场情况 + CellRangeAddress materialEntryRegion = new CellRangeAddress(materialHeaderRow, materialHeaderRow, 6 + columnOffset, 11 + columnOffset); + mergeAndFill(sheet, materialEntryRegion, "进场情况", headerStyle); + drawBorderForRegion(sheet, materialEntryRegion, workbook); + + // M列:送检记录 + Cell materialM = materialHeader.createCell(12 + columnOffset); + materialM.setCellValue("送检记录"); + materialM.setCellStyle(headerStyle); + CellRangeAddress materialMRegion = new CellRangeAddress(materialHeaderRow, materialHeaderRow, 12 + columnOffset, 12 + columnOffset); + drawBorderForRegion(sheet, materialMRegion, workbook); + + materialHeader.setHeightInPoints(20); + + // ============================================== + // 38. 动态填充材料进场数据 + // ============================================== + int lastMaterialRow = materialHeaderRow; // 记录材料数据最后一行 + if (materialList != null && !materialList.isEmpty()) { + int dataStartRow = materialHeaderRow + 1; + + for (int i = 0; i < materialList.size(); i++) { + MaterialEntryData data = materialList.get(i); + int rowNum = dataStartRow + i; + lastMaterialRow = rowNum; + Row dataRow = sheet.getRow(rowNum); + if (dataRow == null) { + dataRow = sheet.createRow(rowNum); + } + + // C列:序号 + Cell noCell = dataRow.createCell(2 + columnOffset); + noCell.setCellValue(data.getNo()); + noCell.setCellStyle(contentStyle); + CellRangeAddress noRegion = new CellRangeAddress(rowNum, rowNum, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, noRegion, workbook); + + // D-E列:材料名称 + CellRangeAddress nameRegion = new CellRangeAddress(rowNum, rowNum, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, nameRegion, data.getMaterialName(), contentStyle); + drawBorderForRegion(sheet, nameRegion, workbook); + + // F列:设计值 + Cell designCell = dataRow.createCell(5 + columnOffset); + designCell.setCellValue(data.getDesignValue()); + designCell.setCellStyle(contentStyle); + CellRangeAddress designRegion = new CellRangeAddress(rowNum, rowNum, 5 + columnOffset, 5 + columnOffset); + drawBorderForRegion(sheet, designRegion, workbook); + + // G-L列:进场情况 + CellRangeAddress entryRegion = new CellRangeAddress(rowNum, rowNum, 6 + columnOffset, 11 + columnOffset); + mergeAndFill(sheet, entryRegion, data.getEntryStatus(), contentStyle); + drawBorderForRegion(sheet, entryRegion, workbook); + + // M列:送检记录 + Cell inspectionCell = dataRow.createCell(12 + columnOffset); + inspectionCell.setCellValue(data.getInspection()); + inspectionCell.setCellStyle(contentStyle); + CellRangeAddress inspectionRegion = new CellRangeAddress(rowNum, rowNum, 12 + columnOffset, 12 + columnOffset); + drawBorderForRegion(sheet, inspectionRegion, workbook); + + dataRow.setHeightInPoints(20); + } + } + + // ============================================== + // 39. 主要材料送检情况标题行(材料进场数据行下一行) + // ============================================== + int inspectionTitleRow = lastMaterialRow + 1; + Row inspectionTitle = sheet.getRow(inspectionTitleRow); + if (inspectionTitle == null) { + inspectionTitle = sheet.createRow(inspectionTitleRow); + } + + CellRangeAddress inspectionHeaderRegion = new CellRangeAddress(inspectionTitleRow, inspectionTitleRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, inspectionHeaderRegion, "主要材料送检情况:", leftHeaderStyle); + drawBorderForRegion(sheet, inspectionHeaderRegion, workbook); + + inspectionTitle.setHeightInPoints(20); + + // ============================================== + // 40. 材料送检情况表头行(标题行下一行) + // 列布局:C=序号, D-E=材料名称, F-G=用材部位, + // H-J=送检机构, K-M=送检记录 + // ============================================== + int inspectionHeaderRow = inspectionTitleRow + 1; + Row inspectionHeader = sheet.getRow(inspectionHeaderRow); + if (inspectionHeader == null) { + inspectionHeader = sheet.createRow(inspectionHeaderRow); + } + + // C列:序号 + Cell inspC = inspectionHeader.createCell(2 + columnOffset); + inspC.setCellValue("序号"); + inspC.setCellStyle(headerStyle); + CellRangeAddress inspCRegion = new CellRangeAddress(inspectionHeaderRow, inspectionHeaderRow, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, inspCRegion, workbook); + + // D-E列:材料名称 + CellRangeAddress inspNameRegion = new CellRangeAddress(inspectionHeaderRow, inspectionHeaderRow, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, inspNameRegion, "材料名称", headerStyle); + drawBorderForRegion(sheet, inspNameRegion, workbook); + + // F-G列:用材部位 + CellRangeAddress inspPartRegion = new CellRangeAddress(inspectionHeaderRow, inspectionHeaderRow, 5 + columnOffset, 6 + columnOffset); + mergeAndFill(sheet, inspPartRegion, "用材部位", headerStyle); + drawBorderForRegion(sheet, inspPartRegion, workbook); + + // H-J列:送检机构 + CellRangeAddress inspOrgRegion = new CellRangeAddress(inspectionHeaderRow, inspectionHeaderRow, 7 + columnOffset, 9 + columnOffset); + mergeAndFill(sheet, inspOrgRegion, "送检机构", headerStyle); + drawBorderForRegion(sheet, inspOrgRegion, workbook); + + // K-M列:送检记录 + CellRangeAddress inspRecordRegion = new CellRangeAddress(inspectionHeaderRow, inspectionHeaderRow, 10 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, inspRecordRegion, "送检记录", headerStyle); + drawBorderForRegion(sheet, inspRecordRegion, workbook); + + inspectionHeader.setHeightInPoints(20); + + // ============================================== + // 41. 动态填充材料送检数据 + // ============================================== + int lastInspectionRow = inspectionHeaderRow; // 记录送检数据最后一行 + if (inspectionList != null && !inspectionList.isEmpty()) { + int dataStartRow = inspectionHeaderRow + 1; + + for (int i = 0; i < inspectionList.size(); i++) { + MaterialInspectionData data = inspectionList.get(i); + int rowNum = dataStartRow + i; + lastInspectionRow = rowNum; + Row dataRow = sheet.getRow(rowNum); + if (dataRow == null) { + dataRow = sheet.createRow(rowNum); + } + + // C列:序号 + Cell noCell = dataRow.createCell(2 + columnOffset); + noCell.setCellValue(data.getNo()); + noCell.setCellStyle(contentStyle); + CellRangeAddress noRegion = new CellRangeAddress(rowNum, rowNum, 2 + columnOffset, 2 + columnOffset); + drawBorderForRegion(sheet, noRegion, workbook); + + // D-E列:材料名称 + CellRangeAddress nameRegion = new CellRangeAddress(rowNum, rowNum, 3 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, nameRegion, data.getMaterialName(), contentStyle); + drawBorderForRegion(sheet, nameRegion, workbook); + + // F-G列:用材部位 + CellRangeAddress partRegion = new CellRangeAddress(rowNum, rowNum, 5 + columnOffset, 6 + columnOffset); + mergeAndFill(sheet, partRegion, data.getUsePart(), contentStyle); + drawBorderForRegion(sheet, partRegion, workbook); + + // H-J列:送检机构 + CellRangeAddress orgRegion = new CellRangeAddress(rowNum, rowNum, 7 + columnOffset, 9 + columnOffset); + mergeAndFill(sheet, orgRegion, data.getInspectionOrg(), contentStyle); + drawBorderForRegion(sheet, orgRegion, workbook); + + // K-M列:送检记录 + CellRangeAddress recordRegion = new CellRangeAddress(rowNum, rowNum, 10 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, recordRegion, data.getInspectionRecord(), contentStyle); + drawBorderForRegion(sheet, recordRegion, workbook); + + dataRow.setHeightInPoints(20); + } + } + + // ============================================== + // 42. 材料送检情况说明行(送检数据行下一行) + // ============================================== + int inspectionNoteRow = lastInspectionRow + 1; // 最终的情况说明行 + Row inspNoteRow = sheet.getRow(inspectionNoteRow); + if (inspNoteRow == null) { + inspNoteRow = sheet.createRow(inspectionNoteRow); + } + + // C-E列合并:情况说明 + CellRangeAddress inspNoteTitleRegion = new CellRangeAddress(inspectionNoteRow, inspectionNoteRow, 2 + columnOffset, 4 + columnOffset); + mergeAndFill(sheet, inspNoteTitleRegion, "情况说明", headerStyle); + drawBorderForRegion(sheet, inspNoteTitleRegion, workbook); + + // F-M列合并:无 + CellRangeAddress inspNoteContentRegion = new CellRangeAddress(inspectionNoteRow, inspectionNoteRow, 5 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, inspNoteContentRegion, "无", contentStyle); + drawBorderForRegion(sheet, inspNoteContentRegion, workbook); + + inspNoteRow.setHeightInPoints(20); + + // ============================================== + // 关键调整:AB列从设备进场标题行到最终情况说明行合并 + // 开始行:设备进场情况标题行(equipmentTitleRow) + // 结束行:材料送检情况说明行(inspectionNoteRow) + // 合并后标题:主要材料.设备进场情况及送检记录 + // ============================================== + CellRangeAddress finalABRegion = new CellRangeAddress( + equipmentTitleRow, // 开始行:主要设备进场情况标题行 + inspectionNoteRow, // 结束行:最终情况说明行 + 0 + columnOffset, 1 + columnOffset // A-B列 + ); + mergeAndFill(sheet, finalABRegion, "主要材料.设备进场情况及送检记录", titleStyle); + drawBorderForRegion(sheet, finalABRegion, workbook); + + // 调整合并区域行高 + int totalRowCount = inspectionNoteRow - equipmentTitleRow + 1; + float totalRegionHeight = 0; + for (int i = equipmentTitleRow; i <= inspectionNoteRow; i++) { + Row row = sheet.getRow(i); + if (row != null) { + totalRegionHeight += row.getHeightInPoints(); + } + } + float baseHeight1 = 20; + float extraHeight1 = totalRegionHeight - totalRowCount * baseHeight1; + Row equipmentTitleRowObj = sheet.getRow(equipmentTitleRow); + if (equipmentTitleRowObj != null) { + equipmentTitleRowObj.setHeightInPoints(baseHeight1 + (int) extraHeight1); + } + for (int i = equipmentTitleRow + 1; i <= inspectionNoteRow; i++) { + Row row = sheet.getRow(i); + if (row != null) { + row.setHeightInPoints(baseHeight1); + } + } + + // ============================================== + // 43. 并网手续办理情况行 + // ============================================== + int sxNoteRow = inspectionNoteRow + 1; + Row sxRow = sheet.getRow(sxNoteRow); + if (sxRow == null) { + sxRow = sheet.createRow(sxNoteRow); + } + + // A-B列合并:并网手续办理情况 + CellRangeAddress sxTitleRegion = new CellRangeAddress(sxNoteRow, sxNoteRow, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, sxTitleRegion, "并网手续办理情况", titleStyle); + drawBorderForRegion(sheet, sxTitleRegion, workbook); + + // C-M列合并:今日无 + CellRangeAddress sxContentRegion = new CellRangeAddress(sxNoteRow, sxNoteRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, sxContentRegion, "今日无", contentStyle); + drawBorderForRegion(sheet, sxContentRegion, workbook); + + sxRow.setHeightInPoints(30); // 适配可能的换行 + + // ============================================== + // 44. 现场是否存在危险源(并说明,如:物理危害.人为因素.自然因素.环境因素等现场问题)行 + // ============================================== + int wxNoteRow = sxNoteRow + 1; + Row wxRow = sheet.getRow(wxNoteRow); + if (wxRow == null) { + wxRow = sheet.createRow(wxNoteRow); + } + + // A-B列合并:现场是否存在危险源(并说明,如:物理危害.人为因素.自然因素.环境因素等现场问题) + CellRangeAddress wxTitleRegion = new CellRangeAddress(wxNoteRow, wxNoteRow, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, wxTitleRegion, "现场是否存在危险源(并说明,如:物理危害.人为因素.自然因素.环境因素等现场问题)", titleStyle); + drawBorderForRegion(sheet, wxTitleRegion, workbook); + + // C-M列合并:部分区域坡度较大。 + CellRangeAddress wxContentRegion = new CellRangeAddress(wxNoteRow, wxNoteRow, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, wxContentRegion, "部分区域坡度较大。", contentStyle); + drawBorderForRegion(sheet, wxContentRegion, workbook); + + wxRow.setHeightInPoints(30); // 适配可能的换行 + + // ============================================== + // 45. 现场施工照片行 + // ============================================== + + int photoRowNum = wxNoteRow + 1; + Row photoRow = sheet.getRow(photoRowNum); + if (photoRow == null) { + photoRow = sheet.createRow(photoRowNum); + } + + // C-H列合并:现场施工照片标题 + CellRangeAddress photoTitleRegion = new CellRangeAddress(photoRowNum, photoRowNum, 2 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, photoTitleRegion, "", titleStyle); + drawBorderForRegion(sheet, photoTitleRegion, workbook); + + // I-M列合并:图片展示区域 + CellRangeAddress photoImageRegion = new CellRangeAddress(photoRowNum, photoRowNum, 8 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, photoImageRegion, "", contentStyle); + drawBorderForRegion(sheet, photoImageRegion, workbook); + + photoRow.setHeightInPoints(200); // 设置较高行高以适应图片 + + // 插入图片到C-H区域 + if(paramData.getImgUrls1() != null && !paramData.getImgUrls1().isEmpty()){ + insertImageFromUrl(sheet, workbook, + paramData.getImgUrls1().getFirst(), + photoRowNum, photoRowNum + 1, 2 + columnOffset, 8 + columnOffset); + + } + + if(paramData.getImgUrls1() != null && paramData.getImgUrls1().size()>1){ + insertImageFromUrl(sheet, workbook, + paramData.getImgUrls1().getLast(), + photoRowNum, photoRowNum + 1, 8 + columnOffset, 13 + columnOffset); + + } + + // ============================================== + // 46. 照片名字行 + // ============================================== + int photoNameRowNum = photoRowNum + 1; + Row photoNameRow = sheet.getRow(photoNameRowNum); + if (photoNameRow == null) { + photoNameRow = sheet.createRow(photoNameRowNum); + } + + // A-B列合并:与上一行的A-B列合并(现场施工照片区域) + CellRangeAddress photoNameABRegion = new CellRangeAddress(photoRowNum, photoNameRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, photoNameABRegion, "现场施工照片", titleStyle); + drawBorderForRegion(sheet, photoNameABRegion, workbook); + + // C-H列合并:输入1#方阵组件安装 + CellRangeAddress photoName1Region = new CellRangeAddress(photoNameRowNum, photoNameRowNum, 2 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, photoName1Region, "1#", contentStyle); + drawBorderForRegion(sheet, photoName1Region, workbook); + + // I-M列合并:输入5#方阵支架安装 + CellRangeAddress photoName2Region = new CellRangeAddress(photoNameRowNum, photoNameRowNum, 8 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, photoName2Region, "2#", contentStyle); + drawBorderForRegion(sheet, photoName2Region, workbook); + + photoNameRow.setHeightInPoints(25); // 设置行高 + + // ============================================== + // 47. 现场施工照片行(第二组) + // ============================================== + int photoRowNum2 = photoNameRowNum + 1; + Row photoRow2 = sheet.getRow(photoRowNum2); + if (photoRow2 == null) { + photoRow2 = sheet.createRow(photoRowNum2); + } + + // C-H列合并:现场施工照片标题 + CellRangeAddress photoTitleRegion2 = new CellRangeAddress(photoRowNum2, photoRowNum2, 2 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, photoTitleRegion2, "", titleStyle); + drawBorderForRegion(sheet, photoTitleRegion2, workbook); + + // I-M列合并:图片展示区域 + CellRangeAddress photoImageRegion2 = new CellRangeAddress(photoRowNum2, photoRowNum2, 8 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, photoImageRegion2, "", contentStyle); + drawBorderForRegion(sheet, photoImageRegion2, workbook); + + photoRow2.setHeightInPoints(200); // 设置较高行高以适应图片 + + // 插入图片到C-H区域 + if(paramData.getImgUrls2() != null && !paramData.getImgUrls2().isEmpty()){ + insertImageFromUrl(sheet, workbook, + paramData.getImgUrls2().getFirst(), + photoRowNum, photoRowNum2 + 1, 2 + columnOffset, 8 + columnOffset); + + } + + if(paramData.getImgUrls2() != null && paramData.getImgUrls2().size()>1){ + insertImageFromUrl(sheet, workbook, + paramData.getImgUrls2().getLast(), + photoRowNum, photoRowNum2 + 1, 8 + columnOffset, 13 + columnOffset); + + } + +// // 插入图片到C-H区域 +// insertImageFromUrl(sheet, workbook, +// "http://xny.yj-3d.com:9000/xinnengyuan/2025/11/13/7cbef6181831427a8472ac1e9daafea4.png", +// photoRowNum2, photoRowNum2 + 1, 2 + columnOffset, 8 + columnOffset); +// +// // 可以添加第二个图片到I-M区域 +// insertImageFromUrl(sheet, workbook, +// "http://xny.yj-3d.com:9000/xinnengyuan/2025/11/13/7cbef6181831427a8472ac1e9daafea4.png", +// photoRowNum2, photoRowNum2 + 1, 8 + columnOffset, 13 + columnOffset); + + // ============================================== + // 48. 照片名字行(第二组) + // ============================================== + int photoNameRowNum2 = photoRowNum2 + 1; + Row photoNameRow2 = sheet.getRow(photoNameRowNum2); + if (photoNameRow2 == null) { + photoNameRow2 = sheet.createRow(photoNameRowNum2); + } + + // A-B列合并:与上一行的A-B列合并(现场施工照片区域) + CellRangeAddress photoNameABRegion2 = new CellRangeAddress(photoRowNum2, photoNameRowNum2, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, photoNameABRegion2, "现场施工照片", titleStyle); + drawBorderForRegion(sheet, photoNameABRegion2, workbook); + + // C-H列合并:输入2#方阵组件安装 + CellRangeAddress photoName3Region = new CellRangeAddress(photoNameRowNum2, photoNameRowNum2, 2 + columnOffset, 7 + columnOffset); + mergeAndFill(sheet, photoName3Region, "3#", contentStyle); + drawBorderForRegion(sheet, photoName3Region, workbook); + + // I-M列合并:输入3#方阵支架安装 + CellRangeAddress photoName4Region = new CellRangeAddress(photoNameRowNum2, photoNameRowNum2, 8 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, photoName4Region, "4#", contentStyle); + drawBorderForRegion(sheet, photoName4Region, workbook); + + photoNameRow2.setHeightInPoints(25); // 设置行高 + + + + // ============================================== + // 49. 明天工作计划 + // ============================================== + int tomorrowPlanRowNum = photoNameRowNum2 + 1; + Row tomorrowPlanRow = sheet.getRow(tomorrowPlanRowNum); + if (tomorrowPlanRow == null) { + tomorrowPlanRow = sheet.createRow(tomorrowPlanRowNum); + } + + // A-B列合并 + CellRangeAddress tomorrowABRegion = new CellRangeAddress(tomorrowPlanRowNum, tomorrowPlanRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, tomorrowABRegion, "明天工作计划", titleStyle); + drawBorderForRegion(sheet, tomorrowABRegion, workbook); + + // C-M列合并:输入工作计划内容 + String tomorrowPlanContent = "支架、组件安装37人,计划完成支架8组,组件7组;\n直流电缆敷设15人,计划完成3500米。"; + CellRangeAddress tomorrowContentRegion = new CellRangeAddress(tomorrowPlanRowNum, tomorrowPlanRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, tomorrowContentRegion, tomorrowPlanContent, contentStyle); + drawBorderForRegion(sheet, tomorrowContentRegion, workbook); + + tomorrowPlanRow.setHeightInPoints(40); // 设置行高以适应多行文本 + + // ============================================== + // 50. 其他事项 + // ============================================== + int otherMattersRowNum = tomorrowPlanRowNum + 1; + Row otherMattersRow = sheet.getRow(otherMattersRowNum); + if (otherMattersRow == null) { + otherMattersRow = sheet.createRow(otherMattersRowNum); + } + + // A-B列合并 + CellRangeAddress otherABRegion = new CellRangeAddress(otherMattersRowNum, otherMattersRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, otherABRegion, "其他事项", titleStyle); + drawBorderForRegion(sheet, otherABRegion, workbook); + + // C-M列合并 + CellRangeAddress otherContentRegion = new CellRangeAddress(otherMattersRowNum, otherMattersRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, otherContentRegion, "无", contentStyle); + drawBorderForRegion(sheet, otherContentRegion, workbook); + + otherMattersRow.setHeightInPoints(25); // 设置行高 + + // ============================================== + // 51. 现场人员 + // ============================================== + int sitePersonnelRowNum = otherMattersRowNum + 1; + Row sitePersonnelRow = sheet.getRow(sitePersonnelRowNum); + if (sitePersonnelRow == null) { + sitePersonnelRow = sheet.createRow(sitePersonnelRowNum); + } + + // A-B列合并 + CellRangeAddress personnelABRegion = new CellRangeAddress(sitePersonnelRowNum, sitePersonnelRowNum, 0 + columnOffset, 1 + columnOffset); + mergeAndFill(sheet, personnelABRegion, "现场人员", titleStyle); + drawBorderForRegion(sheet, personnelABRegion, workbook); + + // C-M列合并 + CellRangeAddress personnelContentRegion = new CellRangeAddress(sitePersonnelRowNum, sitePersonnelRowNum, 2 + columnOffset, 12 + columnOffset); + mergeAndFill(sheet, personnelContentRegion, "1.管理人员2人;\n" + + "2.支架、组件安装36人;\n" + + "3.直流电缆敷设15人;\n" + + "4.无人机飞手2人;\n" + + "5.合计55人。", contentStyle); + drawBorderForRegion(sheet, personnelContentRegion, workbook); + + sitePersonnelRow.setHeightInPoints(25); // 设置行高 + + // 调整内容行高 + for (int i = 1 + rowOffset; i <= 3 + rowOffset; i++) { + Row row = sheet.getRow(i); + if (row != null) { + row.setHeightInPoints(25); + } + } + + return sitePersonnelRowNum - rowOffset + 1; // 返回该项目使用的行数(相对于起始行) + } + + // 样式创建工具方法 + private static CellStyle createWrapTitleStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setBold(true); + font.setFontHeightInPoints((short) 14); + style.setFont(font); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setWrapText(true); + return style; + } + + private static CellStyle createTitleStyle(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.setWrapText(true); + return style; + } + + private static CellStyle createContentStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setWrapText(true); + return style; + } + + private static CellStyle createHeaderStyle(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.setWrapText(true); + return style; + } + + private static CellStyle createLeftHeaderStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + Font font = workbook.createFont(); + font.setBold(true); + style.setFont(font); + style.setAlignment(HorizontalAlignment.LEFT); + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setWrapText(true); + return style; + } + + // 合并单元格并填充内容 + private static void mergeAndFill(Sheet sheet, CellRangeAddress region, String value, CellStyle style) { + int rowNum = region.getFirstRow(); + int colNum = region.getFirstColumn(); + Row row = sheet.getRow(rowNum); + if (row == null) { + row = sheet.createRow(rowNum); + } + Cell cell = row.createCell(colNum); + cell.setCellValue(value); + cell.setCellStyle(style); + sheet.addMergedRegion(region); + } + + // 为合并区域绘制边框 + private static void drawBorderForRegion(Sheet sheet, CellRangeAddress region, Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + + RegionUtil.setBorderTop(BorderStyle.THIN, region, sheet); + RegionUtil.setBorderBottom(BorderStyle.THIN, region, sheet); + RegionUtil.setBorderLeft(BorderStyle.THIN, region, sheet); + RegionUtil.setBorderRight(BorderStyle.THIN, region, sheet); + } + + // 为单个单元格绘制边框 + private static void drawBorderForCell(Sheet sheet, int rowNum, int firstCol, int lastCol, Workbook workbook) { + CellRangeAddress region = new CellRangeAddress(rowNum, rowNum, firstCol, lastCol); + drawBorderForRegion(sheet, region, workbook); + } + + /** + * 从URL下载图片并插入到指定区域 + */ + private static void insertImageFromUrl(Sheet sheet, Workbook workbook, String imageUrl, + int firstRow, int lastRow, int firstCol, int lastCol) { + try { + // 下载图片数据 + URL url = new URL(imageUrl); + try (InputStream inputStream = url.openStream()) { + byte[] imageBytes = IOUtils.toByteArray(inputStream); + + // 确定图片类型 + int pictureType = Workbook.PICTURE_TYPE_PNG; + if (imageUrl.toLowerCase().endsWith(".jpg") || imageUrl.toLowerCase().endsWith(".jpeg")) { + pictureType = Workbook.PICTURE_TYPE_JPEG; + } + + // 将图片添加到工作簿 + int pictureIdx = workbook.addPicture(imageBytes, pictureType); + + // 创建绘图对象 + Drawing drawing = sheet.createDrawingPatriarch(); + + // 创建锚点 + CreationHelper helper = workbook.getCreationHelper(); + ClientAnchor anchor = helper.createClientAnchor(); + anchor.setCol1(firstCol); + anchor.setCol2(lastCol); + anchor.setRow1(firstRow); + anchor.setRow2(lastRow); + + // 插入图片 + drawing.createPicture(anchor, pictureIdx); + + System.out.println("成功插入图片: " + imageUrl); + } + } catch (Exception e) { + System.err.println("插入图片失败: " + e.getMessage()); + // 如果插入失败,在单元格中显示错误信息 + Row row = sheet.getRow(firstRow); + if (row == null) row = sheet.createRow(firstRow); + Cell cell = row.createCell(firstCol); + cell.setCellValue("图片加载失败"); + } + } + + + + + //数据组装 + public static List getProjectDataList(PgsProgressCategoryDayTotalVo totalVo) { + + List projectDataList = new ArrayList<>(); + List subProjectList = totalVo.getSubProjectList(); + int maxPhotovoltaicAreaLength = getMaxPhotovoltaicAreaLength(subProjectList); + for (PgsProgressCategoryByDayVo vo : subProjectList) { + ProjectData projectData = new ProjectData(); + projectData.setProjectName(vo.getProjectName()); + List progressList = new ArrayList<>(); + + List photovoltaicArea = vo.getPhotovoltaicArea(); + int num = 1; + for (PgsProgressCategoryDetailByDayVo vo1 : photovoltaicArea) { + ProgressData progressData = new ProgressData(); + progressData.setNum(num); + progressData.setProject(vo1.getName()+"("+vo1.getUnit()+")"); + progressData.setDesign(vo1.getTotal().toString()); + progressData.setPlan(vo1.getConstructionPlan().toString()); + progressData.setComplete(vo1.getConstructionCompleted().toString()); + progressData.setTotal(vo1.getCompleted().toString()); + progressData.setProcess(vo1.getCompletedPercentage().toString()); + progressList.add(progressData); + num++; + } + if(photovoltaicArea.size() < maxPhotovoltaicAreaLength){ + for (int i = 0; i < maxPhotovoltaicAreaLength - photovoltaicArea.size(); i++) { + ProgressData progressData = new ProgressData(); + progressData.setNum(num); + progressData.setProject(""); + progressData.setDesign(""); + progressData.setPlan(""); + progressData.setComplete(""); + progressData.setTotal(""); + progressData.setProcess(""); + progressList.add(progressData); + } + } + projectData.setProgressList(progressList); + + List participantList= new ArrayList<>(); + List equipmentEntryList= new ArrayList<>(); + List materialList= new ArrayList<>(); + List inspectionList= new ArrayList<>(); + participantList.add(new ParticipantData("", "","", "","")); + equipmentEntryList.add(new EquipmentEntryData("","","","","","","")); + materialList.add(new MaterialEntryData("","","","","")); + inspectionList.add(new MaterialInspectionData("","","","","")); + + projectData.setParticipantList(participantList); + projectData.setEquipmentEntryList(equipmentEntryList); + projectData.setMaterialList(materialList); + projectData.setInspectionList(inspectionList); + + System.out.println(projectData); + + projectDataList.add(projectData); + } + + return projectDataList; + } + + public static int getMaxPhotovoltaicAreaLength(List subProjectList) { + // 初始化最大值为0(若所有项目的photovoltaicArea都为null,结果为0) + int maxLength = 0; + + if (subProjectList == null) { + return maxLength; // 集合为null时返回0 + } + + for (PgsProgressCategoryByDayVo project : subProjectList) { + // 获取当前项目的photovoltaicArea + List pvArea = project.getPhotovoltaicArea(); + + // 计算当前photovoltaicArea的长度(为null时按0处理) + int currentLength = (pvArea == null) ? 0 : pvArea.size(); + + // 更新最大值 + if (currentLength > maxLength) { + maxLength = currentLength; + } + } + + return maxLength; + } + + + + public ParamData getParamData(ReportExportDto dto){ + ParamData paramData = new ParamData(); + String originalDate = dto.getDate(); + // 解析原始字符串为Date对象,再格式化为目标字符串 + LocalDate localDate = DateUtils.parseLocalDateTime(FormatsType.YYYY_MM_DD, originalDate); + String format = LocalDateTimeUtil.format(localDate, "yyyy年-MM月-dd日"); + + + BusProject project = projectService.getById(dto.getProjectId()); + + List list = qltQualityInspectionService.lambdaQuery() + .eq(QltQualityInspection::getProjectId, project.getId()) + .between(QltQualityInspection::getCreateTime, localDate.atStartOfDay(), localDate.atTime(23, 59, 59)) + .orderByDesc(QltQualityInspection::getCreateTime) + .list(); + + List list1 = safetyInspectionService.lambdaQuery() + .eq(HseSafetyInspection::getProjectId, project.getId()) + .between(HseSafetyInspection::getCheckTime, localDate.atStartOfDay(), localDate.atTime(23, 59, 59)) + .orderByDesc(HseSafetyInspection::getCreateTime) + .list(); + + //查找图片 + List qltImgList = new ArrayList<>(); + List list2 = list.stream().map(QltQualityInspection::getInspectionImgFile).toList(); + for (String s : list2) { + if (s != null && !s.isEmpty()) { + String[] split = s.split(","); + //转成Long + List longs = Arrays.stream(split).map(Long::valueOf).toList(); + qltImgList.addAll(longs); + } + } + + List hseImgList = new ArrayList<>(); + List list3 = list1.stream().map(HseSafetyInspection::getCheckFile).toList(); + for (String s : list3) { + if (s != null && !s.isEmpty()) { + String[] split = s.split(","); + //转成Long + List longs = Arrays.stream(split).map(Long::valueOf).toList(); + hseImgList.addAll(longs); + } + } + List imgUrls1 = new ArrayList<>(); + if(CollectionUtil.isNotEmpty(qltImgList)){ + List sysOssVos = ossService.listByIds(qltImgList); + for (SysOssVo sysOssVo : sysOssVos){ + if(!IMAGE_SUFFIX.contains(sysOssVo.getFileSuffix())){ + continue; + } + imgUrls1.add(sysOssVo.getUrl()); + } + paramData.setImgUrls1(imgUrls1); + } + + List imgUrls2 = new ArrayList<>(); + if(CollectionUtil.isNotEmpty(hseImgList)){ + List sysOssVos = ossService.listByIds(hseImgList); + for (SysOssVo sysOssVo : sysOssVos){ + if(!IMAGE_SUFFIX.contains(sysOssVo.getFileSuffix())){ + continue; + } + imgUrls2.add(sysOssVo.getUrl()); + } + paramData.setImgUrls2(imgUrls2); + } + List weatherList = weatherManager.getWeatherListVo(project.getLng(), project.getLat(), WeatherConstant.THREE_DAYS_WEATHER_PATH); + WeatherVo first = weatherList.getFirst(); + + paramData.setDate(format); + paramData.setRecorder(dto.getPerson()); + if(first != null){ + paramData.setTemp(first.getTempMin()+ "℃~"+ first.getTempMax() + "℃"); + paramData.setDayWeather(first.getDayStatus()); + paramData.setNightWeather(first.getNightStatus()); + } + if(CollectionUtil.isNotEmpty(list)){ + String collect = list.stream().map(QltQualityInspection::getInspectionResult).collect(Collectors.joining(",")); + paramData.setQuality(collect); + } + if(CollectionUtil.isNotEmpty(list1)){ + String collect = list1.stream().map(HseSafetyInspection::getInspectionResult).collect(Collectors.joining(",")); + paramData.setSafety(collect); + } + + return paramData; + } + + + + // 新的数据组装方法,将数据按行组织 + public static List> getProjectDataListAsRows(PgsProgressCategoryDayTotalVo totalVo) { + List> result = new ArrayList<>(); + + if (totalVo != null && totalVo.getSubProjectList() != null) { + List rowProjects = new ArrayList<>(); + + // 将所有项目放在同一行中 + List subProjectList = totalVo.getSubProjectList(); + int maxPhotovoltaicAreaLength = getMaxPhotovoltaicAreaLength(subProjectList); + + for (PgsProgressCategoryByDayVo vo : subProjectList) { + ProjectData projectData = new ProjectData(); + projectData.setProjectName(vo.getProjectName()); + List progressList = new ArrayList<>(); + + List photovoltaicArea = vo.getPhotovoltaicArea(); + int num = 1; + for (PgsProgressCategoryDetailByDayVo vo1 : photovoltaicArea) { + ProgressData progressData = new ProgressData(); + progressData.setNum(num); + progressData.setProject(vo1.getName()+"("+vo1.getUnit()+")"); + progressData.setDesign(vo1.getTotal().toString()); + progressData.setPlan(vo1.getConstructionPlan().toString()); + progressData.setComplete(vo1.getConstructionCompleted().toString()); + progressData.setTotal(vo1.getCompleted().toString()); + progressData.setProcess(vo1.getCompletedPercentage().toString()); + progressList.add(progressData); + num++; + } + + if(photovoltaicArea.size() < maxPhotovoltaicAreaLength){ + for (int i = 0; i < maxPhotovoltaicAreaLength - photovoltaicArea.size(); i++) { + ProgressData progressData = new ProgressData(); + progressData.setNum(num); + progressData.setProject(""); + progressData.setDesign(""); + progressData.setPlan(""); + progressData.setComplete(""); + progressData.setTotal(""); + progressData.setProcess(""); + progressList.add(progressData); + } + } + projectData.setProgressList(progressList); + + List participantList= new ArrayList<>(); + List equipmentEntryList= new ArrayList<>(); + List materialList= new ArrayList<>(); + List inspectionList= new ArrayList<>(); + participantList.add(new ParticipantData("", "","", "","")); + equipmentEntryList.add(new EquipmentEntryData("","","","","","","")); + materialList.add(new MaterialEntryData("","","","","")); + inspectionList.add(new MaterialInspectionData("","","","","")); + + projectData.setParticipantList(participantList); + projectData.setEquipmentEntryList(equipmentEntryList); + projectData.setMaterialList(materialList); + projectData.setInspectionList(inspectionList); + + rowProjects.add(projectData); + } + + // 将所有项目作为一行添加到结果中 + result.add(rowProjects); + } + if (totalVo != null && totalVo.getProject() != null) { + + PgsProgressCategoryByDayVo project = totalVo.getProject(); + + //升压站 + List sy = new ArrayList<>(); + ProjectData projectData = new ProjectData(); + projectData.setProjectName("升压站"); + List progressList = new ArrayList<>(); + + List boosterStation = project.getBoosterStation(); + int num = 1; + for (PgsProgressCategoryDetailByDayVo vo1 : boosterStation) { + ProgressData progressData = new ProgressData(); + progressData.setNum(num); + progressData.setProject(vo1.getName()+"("+vo1.getUnit()+")"); + progressData.setDesign(vo1.getTotal().toString()); + progressData.setPlan(vo1.getConstructionPlan().toString()); + progressData.setComplete(vo1.getConstructionCompleted().toString()); + progressData.setTotal(vo1.getCompleted().toString()); + progressData.setProcess(vo1.getCompletedPercentage().toString()); + progressList.add(progressData); + num++; + } + projectData.setProgressList(progressList); + + List participantList= new ArrayList<>(); + List equipmentEntryList= new ArrayList<>(); + List materialList= new ArrayList<>(); + List inspectionList= new ArrayList<>(); + participantList.add(new ParticipantData("", "","", "","")); + equipmentEntryList.add(new EquipmentEntryData("","","","","","","")); + materialList.add(new MaterialEntryData("","","","","")); + inspectionList.add(new MaterialInspectionData("","","","","")); + + projectData.setParticipantList(participantList); + projectData.setEquipmentEntryList(equipmentEntryList); + projectData.setMaterialList(materialList); + projectData.setInspectionList(inspectionList); + + sy.add(projectData); + result.add(sy); + + //集电线路 + List jd = new ArrayList<>(); + ProjectData jdProjectData = new ProjectData(); + jdProjectData.setProjectName("集电线路"); + List jdProgressList = new ArrayList<>(); + + List collectingLine = project.getCollectingLine(); + int jdNum = 1; + for (PgsProgressCategoryDetailByDayVo vo1 : collectingLine) { + ProgressData progressData = new ProgressData(); + progressData.setNum(jdNum); + progressData.setProject(vo1.getName()+"("+vo1.getUnit()+")"); + progressData.setDesign(vo1.getTotal().toString()); + progressData.setPlan(vo1.getConstructionPlan().toString()); + progressData.setComplete(vo1.getConstructionCompleted().toString()); + progressData.setTotal(vo1.getCompleted().toString()); + progressData.setProcess(vo1.getCompletedPercentage().toString()); + jdProgressList.add(progressData); + jdNum++; + } + projectData.setProgressList(jdProgressList); + + List jdParticipantList= new ArrayList<>(); + List jdEquipmentEntryList= new ArrayList<>(); + List jdMaterialList= new ArrayList<>(); + List jdInspectionList= new ArrayList<>(); + jdParticipantList.add(new ParticipantData("", "","", "","")); + jdEquipmentEntryList.add(new EquipmentEntryData("","","","","","","")); + jdMaterialList.add(new MaterialEntryData("","","","","")); + jdInspectionList.add(new MaterialInspectionData("","","","","")); + + projectData.setParticipantList(jdParticipantList); + projectData.setEquipmentEntryList(jdEquipmentEntryList); + projectData.setMaterialList(jdMaterialList); + projectData.setInspectionList(jdInspectionList); + + jd.add(jdProjectData); + result.add(jd); + + //送出线路 + List sc = new ArrayList<>(); + ProjectData scProjectData = new ProjectData(); + scProjectData.setProjectName("送出线路"); + List scProgressList = new ArrayList<>(); + + List sendLine = project.getSendLine(); + int scNum = 1; + for (PgsProgressCategoryDetailByDayVo vo1 : sendLine) { + ProgressData progressData = new ProgressData(); + progressData.setNum(scNum); + progressData.setProject(vo1.getName()+"("+vo1.getUnit()+")"); + progressData.setDesign(vo1.getTotal().toString()); + progressData.setPlan(vo1.getConstructionPlan().toString()); + progressData.setComplete(vo1.getConstructionCompleted().toString()); + progressData.setTotal(vo1.getCompleted().toString()); + progressData.setProcess(vo1.getCompletedPercentage().toString()); + scProgressList.add(progressData); + scNum++; + } + projectData.setProgressList(scProgressList); + + List scParticipantList= new ArrayList<>(); + List scEquipmentEntryList= new ArrayList<>(); + List scMaterialList= new ArrayList<>(); + List scInspectionList= new ArrayList<>(); + scParticipantList.add(new ParticipantData("", "","", "","")); + scEquipmentEntryList.add(new EquipmentEntryData("","","","","","","")); + scMaterialList.add(new MaterialEntryData("","","","","")); + scInspectionList.add(new MaterialInspectionData("","","","","")); + + projectData.setParticipantList(scParticipantList); + projectData.setEquipmentEntryList(scEquipmentEntryList); + projectData.setMaterialList(scMaterialList); + projectData.setInspectionList(scInspectionList); + + sc.add(scProjectData); + result.add(sc); + + //其他工程 + List qt = new ArrayList<>(); + ProjectData qtProjectData = new ProjectData(); + qtProjectData.setProjectName("其他工程"); + List qtProgressList = new ArrayList<>(); + + List otherProject = project.getOtherProject(); + int qtNum = 1; + for (PgsProgressCategoryDetailByDayVo vo1 : otherProject) { + ProgressData progressData = new ProgressData(); + progressData.setNum(qtNum); + progressData.setProject(vo1.getName()+"("+vo1.getUnit()+")"); + progressData.setDesign(vo1.getTotal().toString()); + progressData.setPlan(vo1.getConstructionPlan().toString()); + progressData.setComplete(vo1.getConstructionCompleted().toString()); + progressData.setTotal(vo1.getCompleted().toString()); + progressData.setProcess(vo1.getCompletedPercentage().toString()); + qtProgressList.add(progressData); + qtNum++; + } + projectData.setProgressList(qtProgressList); + + List qtParticipantList= new ArrayList<>(); + List qtEquipmentEntryList= new ArrayList<>(); + List qtMaterialList= new ArrayList<>(); + List qtInspectionList= new ArrayList<>(); + qtParticipantList.add(new ParticipantData("", "","", "","")); + qtEquipmentEntryList.add(new EquipmentEntryData("","","","","","","")); + qtMaterialList.add(new MaterialEntryData("","","","","")); + qtInspectionList.add(new MaterialInspectionData("","","","","")); + + projectData.setParticipantList(qtParticipantList); + projectData.setEquipmentEntryList(qtEquipmentEntryList); + projectData.setMaterialList(qtMaterialList); + projectData.setInspectionList(qtInspectionList); + + qt.add(qtProjectData); + result.add(qt); + + + } + + return result; + } + + + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/dto/export/ReportExportDto.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/dto/export/ReportExportDto.java new file mode 100644 index 00000000..1e1a6092 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/dto/export/ReportExportDto.java @@ -0,0 +1,16 @@ +package org.dromara.progress.domain.dto.export; + + +import lombok.Data; + +@Data +public class ReportExportDto { + private Long projectId; + + /** + * 日期 yyyy-mm-dd + */ + private String date; + + private String person; +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/EquipmentEntryData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/EquipmentEntryData.java new file mode 100644 index 00000000..3228664e --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/EquipmentEntryData.java @@ -0,0 +1,32 @@ +package org.dromara.progress.domain.vo.export; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class EquipmentEntryData { + private String no; // 序号 + private String project; // 项目 + private String num; // 数量 + private String production; // 生产情况 + private String entry; // 今日进场情况 + private String totalEntry; // 累计进场情况 + private String remark; // 备注 + + + // 生成模拟数据 + public static List generateMockData() { + List dataList = new ArrayList<>(); + dataList.add(new EquipmentEntryData("1", "光伏支架", "3200组", "正常生产", "50组", "1200组", "符合质量标准")); + dataList.add(new EquipmentEntryData("2", "光伏组件", "56000块", "正常生产", "750块", "22000块", "符合质量标准")); + dataList.add(new EquipmentEntryData("3", "逆变器", "30台", "生产中", "0台", "10台", "预计下周进场")); + return dataList; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/MaterialEntryData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/MaterialEntryData.java new file mode 100644 index 00000000..85a1efd0 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/MaterialEntryData.java @@ -0,0 +1,31 @@ +package org.dromara.progress.domain.vo.export; + + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MaterialEntryData { + private String no; // 序号 + private String materialName;// 材料名称 + private String designValue; // 设计值 + private String entryStatus; // 进场情况 + private String inspection; // 送检记录 + + // 生成模拟数据 + public static List generateMockData() { + List dataList = new ArrayList<>(); + dataList.add(new MaterialEntryData("1", "光伏电缆", "5000米", "今日进场1000米,累计3000米", "已送检,合格")); + dataList.add(new MaterialEntryData("2", "水泥", "200吨", "今日进场50吨,累计150吨", "已送检,合格")); + dataList.add(new MaterialEntryData("3", "钢筋", "100吨", "未进场,预计明日到货", "待送检")); + dataList.add(new MaterialEntryData("4", "预埋件", "2000个", "今日进场500个,累计1500个", "已送检,合格")); + return dataList; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/MaterialInspectionData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/MaterialInspectionData.java new file mode 100644 index 00000000..45d09b97 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/MaterialInspectionData.java @@ -0,0 +1,32 @@ +package org.dromara.progress.domain.vo.export; + + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class MaterialInspectionData { + private String no; // 序号 + private String materialName;// 材料名称 + private String usePart; // 用材部位 + private String inspectionOrg; // 送检机构 + private String inspectionRecord; // 送检记录 + + + // 生成模拟数据 + public static List generateMockData() { + List dataList = new ArrayList<>(); + dataList.add(new MaterialInspectionData("1", "光伏电缆", "方阵连接", "广西质检中心", "2025-11-05送检,2025-11-06合格")); + dataList.add(new MaterialInspectionData("2", "水泥", "基础浇筑", "百色市质检所", "2025-11-04送检,2025-11-05合格")); + dataList.add(new MaterialInspectionData("3", "钢筋", "支架固定", "广西质检中心", "待送检,预计2025-11-08送检")); + dataList.add(new MaterialInspectionData("4", "预埋件", "基础连接", "百色市质检所", "2025-11-03送检,2025-11-04合格")); + return dataList; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ParamData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ParamData.java new file mode 100644 index 00000000..aefe4a72 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ParamData.java @@ -0,0 +1,58 @@ +package org.dromara.progress.domain.vo.export; + +import lombok.Data; + +import java.util.List; + +@Data +public class ParamData { + + /** + * 项目简介 + */ + private String projectIntro; + + /** + * 记录人 + */ + private String date; + + /** + * 记录人 + */ + private String recorder; + + /** + * 气温 + */ + private String temp; + /** + * 白天天气 + */ + private String dayWeather; + /** + * 夜晚天气 + */ + private String nightWeather; + /** + * 现场质量 + */ + private String quality = "质量正常.可控。"; + /** + * 现场安全 + */ + private String safety = "安全正常.可控。"; + + /** + * 图片地址 + */ + private List imgUrls1; + + /** + * 图片地址 + */ + private List imgUrls2; + + + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ParticipantData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ParticipantData.java new file mode 100644 index 00000000..21593beb --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ParticipantData.java @@ -0,0 +1,30 @@ +package org.dromara.progress.domain.vo.export; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ParticipantData { + private String unit; // 参建单位 + private String leader; // 经理班子人员 + private String manager; // 主要管理技术人员 + private String other; // 其他人员 + private String remark; // 备注 + + + // 生成模拟数据 + public static List generateMockData() { + List dataList = new ArrayList<>(); + dataList.add(new ParticipantData("田东公司项目建设管理部", "3人", "8人", "12人", "正常")); + dataList.add(new ParticipantData("XX施工单位", "2人", "5人", "30人", "部分人员轮休")); + dataList.add(new ParticipantData("XX监理单位", "1人", "2人", "0人", "正常")); + return dataList; + } +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ProgressData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ProgressData.java new file mode 100644 index 00000000..65b6691e --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ProgressData.java @@ -0,0 +1,34 @@ +package org.dromara.progress.domain.vo.export; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.ArrayList; +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProgressData { + private int num; // 序号 + private String project; // 项目 + private String design; // 设计值 + private String plan; // 今日施工计划 + private String complete; // 今日施工完成情况 + private String total; // 累计完成工程量 + private String process; // 施工形象及进度 + + + + public static List generateMockData() { + List dataList = new ArrayList<>(); + dataList.add(new ProgressData(1, "土地流转(亩)", "217.36", "50", "45", "180", "已完成82.8%")); + dataList.add(new ProgressData(2, "清表(亩)", "217.36", "40", "38", "150", "已完成69%")); + dataList.add(new ProgressData(3, "支架安装(组)", "3200", "50", "45", "1200", "已完成37.5%")); + dataList.add(new ProgressData(4, "组件安装(块)", "56000", "800", "750", "22000", "已完成39.3%")); + return dataList; + } + +} diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ProjectData.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ProjectData.java new file mode 100644 index 00000000..6a2562e0 --- /dev/null +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/progress/domain/vo/export/ProjectData.java @@ -0,0 +1,23 @@ +// ProjectData.java +package org.dromara.progress.domain.vo.export; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ProjectData { + private List progressList; + private List participantList; + private List equipmentEntryList; + private List materialList; + private List inspectionList; + private String projectName; // 项目名称 + private String projectDate; // 项目日期 + +} + diff --git a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/HseViolationRecord.java b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/HseViolationRecord.java index 0af19df4..52fd80eb 100644 --- a/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/HseViolationRecord.java +++ b/xinnengyuan/ruoyi-modules/ruoyi-system/src/main/java/org/dromara/safety/domain/HseViolationRecord.java @@ -125,4 +125,25 @@ public class HseViolationRecord extends BaseEntity { */ private String remark; + + /** + * 任务批号 + */ + private String jobKey; + + /** + * 任务批号 + */ + private Integer version; + + /** + * 验证人id + */ + private Long validatorId; + + /** + * 验证人名字 + */ + private String validatorName; + }