From b76890d3af57e405c37cc27cf930057f76b8fca9 Mon Sep 17 00:00:00 2001 From: wangxy <1481820854@qq.com> Date: Wed, 23 Apr 2025 14:32:18 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E8=87=AA=E6=9F=A5=E8=87=AA=E8=AF=84?= =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/check/CheckReportController.java | 28 +++ .../system/check/checknum/checknum.html | 14 +- .../system/checkReport/checkReport.html | 13 + .../common/utils/poi/MultiSheetExcelUtil.java | 233 ++++++++++++++++++ 4 files changed, 287 insertions(+), 1 deletion(-) create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/MultiSheetExcelUtil.java diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/check/CheckReportController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/check/CheckReportController.java index 39808356..2d7e44fa 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/check/CheckReportController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/check/CheckReportController.java @@ -6,9 +6,11 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.utils.poi.MultiSheetExcelUtil; import com.ruoyi.system.domain.check.TdCheckReport; import com.ruoyi.system.domain.check.dto.CheckReportDTO; import com.ruoyi.system.domain.check.dto.TdCheckReportDTO; +import com.ruoyi.system.domain.check.dto.TdCheckTypeDTO; import com.ruoyi.web.controller.manager.CheckReportManager; import com.ruoyi.web.controller.manager.SysAreaManager; import org.apache.shiro.authz.annotation.RequiresPermissions; @@ -17,6 +19,10 @@ import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.ArrayList; import java.util.List; /** @@ -76,6 +82,28 @@ public class CheckReportController extends BaseController { return util.exportExcel(tdCheckReports, "检查报告管理数据"); } + + @RequiresPermissions("system:check:exportDetail") + @Log(title = "检查报告", businessType = BusinessType.EXPORT) + @GetMapping("/exportDetail") + public void exportDetail(@RequestParam String checkId, HttpServletResponse response) throws IOException { + // 1. 查询主表数据 + TdCheckReportDTO tdCheckReportDTO = checkReportManager.getTdCheckReportDTO(checkId); + tdCheckReportDTO.setFramework(sysAreaManager.getAreaName(tdCheckReportDTO.getFramework())); + tdCheckReportDTO.setArea(sysAreaManager.getAreaName(tdCheckReportDTO.getArea())); + List mainList = new ArrayList<>(); + mainList.add(tdCheckReportDTO); + // 2. 初始化导出工具 + MultiSheetExcelUtil excelUtil = new MultiSheetExcelUtil(); + String fileName = URLEncoder.encode(tdCheckReportDTO.getCheckId() + ".xlsx", "UTF-8"); + excelUtil.initExport(response, fileName); + // 3. 导出主表数据 + excelUtil.createSheet(mainList, "检查信息", TdCheckReportDTO.class); + excelUtil.createSheet(tdCheckReportDTO.getCheckTypeDTOS(), "自查类信息", TdCheckTypeDTO.class); + // 5. 完成导出 + excelUtil.finishExport(); + } + /** * 新增检查报告 */ diff --git a/ruoyi-admin/src/main/resources/templates/system/check/checknum/checknum.html b/ruoyi-admin/src/main/resources/templates/system/check/checknum/checknum.html index a1731ac1..7c06fc03 100644 --- a/ruoyi-admin/src/main/resources/templates/system/check/checknum/checknum.html +++ b/ruoyi-admin/src/main/resources/templates/system/check/checknum/checknum.html @@ -108,7 +108,8 @@ diff --git a/ruoyi-admin/src/main/resources/templates/system/checkReport/checkReport.html b/ruoyi-admin/src/main/resources/templates/system/checkReport/checkReport.html index 5d769c64..04b33c27 100644 --- a/ruoyi-admin/src/main/resources/templates/system/checkReport/checkReport.html +++ b/ruoyi-admin/src/main/resources/templates/system/checkReport/checkReport.html @@ -81,6 +81,7 @@ var selfCheckFlag = [[${@permission.hasPermi('system:check:selfcheck')}]]; var removeFlag = [[${@permission.hasPermi('system:check:remove')}]]; var checkStateDatas = [[${@dict.getType('sys_check_state')}]]; + var exportDetailFlag = [[${@permission.hasPermi('system:check:exportDetail')}]]; var prefix = ctx + "system/checkReport"; let datas = [] $.ajax({ @@ -169,6 +170,7 @@ align: 'center', formatter: function(value, row, index) { var actions = []; + actions.push('导出 '); actions.push('详情 '); actions.push('编辑 '); actions.push('删除'); @@ -243,6 +245,17 @@ function openEdit(id){ $.modal.openTab("修改" + table.options.modalName, prefix + '/edit' + '/' + id); } + + + function exportDetail(checkId) { + $.modal.confirm("确定导出吗?", function() { + $.modal.loading("正在导出数据,请稍候..."); + window.location.href = prefix + '/exportDetail?checkId=' + checkId; + setTimeout(function() { + $.modal.closeLoading(); + }, 800); + }); + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/MultiSheetExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/MultiSheetExcelUtil.java new file mode 100644 index 00000000..2d7bdf1d --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/MultiSheetExcelUtil.java @@ -0,0 +1,233 @@ +package com.ruoyi.common.utils.poi; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.utils.StringUtils; +import org.apache.poi.ss.usermodel.*; +import org.apache.poi.xssf.streaming.SXSSFWorkbook; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.lang.reflect.Field; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +/** + * ClassName: MultiSheetExcelUtil + * Package: com.ruoyi.common.utils.poi + * Description: +* @Author wangxy +* @Create 2025/4/23 14:24 +* @Version 1.0 +*/public class MultiSheetExcelUtil { + + private Workbook workbook; + private HttpServletResponse response; + private String fileName; + + public MultiSheetExcelUtil() { + this.workbook = new SXSSFWorkbook(); + } + + public void initExport(HttpServletResponse response, String fileName) { + this.response = response; + this.fileName = fileName; + } + + public void createSheet(List list, String sheetName, Class clazz) { + Sheet sheet = workbook.createSheet(sheetName); + List fields = getFields(clazz); // 使用新版getFields + createTitleRow(sheet, fields); + fillDataRows(sheet, list, fields); + } + + + public void finishExport() throws IOException { + try { + String encodedFileName = encodeFilename(fileName); + response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName); + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); + workbook.write(response.getOutputStream()); + } finally { + if (workbook != null) { + ((SXSSFWorkbook) workbook).dispose(); + } + } + } + + // 新增的编码方法 + private String encodeFilename(String filename) { + try { + return URLEncoder.encode(filename, "UTF-8").replace("+", "%20"); + } catch (UnsupportedEncodingException e) { + return filename; + } + } + + + private static class FieldMeta { + private final Field field; // 反射字段对象 + private final String title; // 表头名称(@Excel.name) + private final String dateFormat; // 日期格式(@Excel.dateFormat) + private final int sort; // 排序(@Excel.sort) + + public FieldMeta(Field field, String title, String dateFormat, int sort) { + this.field = field; + this.title = title; + this.dateFormat = dateFormat; + this.sort = sort; + this.field.setAccessible(true); // 提前设置可访问 + } + + // Getter 方法 + public Field getField() { return field; } + public String getTitle() { return title; } + public String getDateFormat() { return dateFormat; } + public int getSort() { return sort; } + } + + /** + * 获取所有带@Excel注解的字段(包含父类) + */ + private static List getFields(Class clazz) { + List fields = new ArrayList<>(); + + // 递归获取所有字段(包括父类) + Class currentClass = clazz; + while (currentClass != null) { + for (Field field : currentClass.getDeclaredFields()) { + Excel excelAnno = field.getAnnotation(Excel.class); + if (excelAnno != null) { + fields.add(new FieldMeta( + field, + excelAnno.name(), + excelAnno.dateFormat(), + excelAnno.sort() + )); + } + } + currentClass = currentClass.getSuperclass(); + } + + // 按sort排序 + fields.sort(Comparator.comparingInt(FieldMeta::getSort)); + return fields; + } + + + private void setCellValue(Cell cell, Object value, FieldMeta meta) { + if (value == null) { + cell.setCellValue(""); + return; + } + // 处理日期类型 + if (value instanceof Date) { + String format = StringUtils.isNotEmpty(meta.getDateFormat()) + ? meta.getDateFormat() + : "yyyy-MM-dd"; // 默认格式 + + CellStyle style = workbook.createCellStyle(); + style.setDataFormat( + workbook.getCreationHelper() + .createDataFormat() + .getFormat(format) + ); + cell.setCellValue((Date) value); + cell.setCellStyle(style); + } + // 处理数字类型 + else if (value instanceof Number) { + cell.setCellValue(((Number) value).doubleValue()); + } + // 其他类型 + else { + cell.setCellValue(value.toString()); + } + } + + /** + * 创建带样式的表头 + */ + private CellStyle createHeaderStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + // 背景色 + style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + // 边框 + style.setBorderTop(BorderStyle.THIN); + style.setBorderBottom(BorderStyle.THIN); + style.setBorderLeft(BorderStyle.THIN); + style.setBorderRight(BorderStyle.THIN); + // 字体 + Font font = workbook.createFont(); + font.setColor(IndexedColors.BLACK.getIndex()); + font.setFontName("Arial"); + font.setFontHeightInPoints((short) 12); + font.setBold(true); + style.setFont(font); + // 对齐方式 + style.setAlignment(HorizontalAlignment.CENTER); + style.setVerticalAlignment(VerticalAlignment.CENTER); + + return style; + } + + /** + * 创建数据行的样式(可选) + */ + private CellStyle createDataStyle(Workbook workbook) { + CellStyle style = workbook.createCellStyle(); + // 设置边框 + style.setVerticalAlignment(VerticalAlignment.CENTER); + style.setBorderRight(BorderStyle.THIN); + style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderLeft(BorderStyle.THIN); + style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderTop(BorderStyle.THIN); + style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setBorderBottom(BorderStyle.THIN); + style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex()); + style.setFillPattern(FillPatternType.SOLID_FOREGROUND); + // 设置自动换行(可选) + //style.setWrapText(true); + return style; + } + + + private void createTitleRow(Sheet sheet, List fields) { + Row headerRow = sheet.createRow(0); + CellStyle headerStyle = createHeaderStyle(workbook); + + for (int i = 0; i < fields.size(); i++) { + Cell cell = headerRow.createCell(i); + cell.setCellValue(fields.get(i).getTitle()); + cell.setCellStyle(headerStyle); + sheet.setColumnWidth(i, 6000); // 默认列宽 + } + } + + + private void fillDataRows(Sheet sheet, List list, List fields) { + CellStyle dataStyle = createDataStyle(workbook); + int rowNum = 1; + for (T item : list) { + Row row = sheet.createRow(rowNum++); + for (int i = 0; i < fields.size(); i++) { + FieldMeta meta = fields.get(i); + Cell cell = row.createCell(i); + try { + // 直接通过缓存的Field对象获取值 + Object value = meta.getField().get(item); + cell.setCellStyle(dataStyle); + setCellValue(cell, value, meta); // 传递FieldMeta对象 + } catch (IllegalAccessException e) { + cell.setCellValue("N/A"); + } + } + } + } + +}