From ae0e1b7e8248a7be62ab850911acbac504e208c5 Mon Sep 17 00:00:00 2001 From: wangxy <1481820854@qq.com> Date: Fri, 18 Apr 2025 11:29:15 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E8=87=AA=E6=9F=A5=E8=87=AA=E8=AF=84?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=E5=AF=BC=E5=85=A5=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/check/CheckReportController.java | 30 +++- .../system/check/checknum/checknum.html | 45 +----- .../system/checkReport/checkReport.html | 45 +----- .../common/utils/poi/MultiSheetExcelUtil.java | 147 ++++++++++++++++++ .../domain/check/dto/TdCheckReportDTO.java | 10 ++ .../domain/check/dto/TdCheckTypeDTO.java | 8 + 6 files changed, 194 insertions(+), 91 deletions(-) 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 d63f1f2..ee1bdb0 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 io.swagger.annotations.ApiOperation; @@ -20,6 +22,7 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.util.ArrayList; import java.util.List; /** @@ -79,16 +82,37 @@ 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); + List mainList = new ArrayList<>(); + mainList.add(tdCheckReportDTO); + // 2. 初始化导出工具 + MultiSheetExcelUtil excelUtil = new MultiSheetExcelUtil(); + excelUtil.initExport(response, "主表与子表数据.xlsx"); + // 3. 导出主表数据 + excelUtil.createSheet(mainList, "主表数据", TdCheckReportDTO.class); + + excelUtil.createSheet(tdCheckReportDTO.getCheckTypeDTOS(), "子表数据", TdCheckTypeDTO.class); + // 5. 完成导出 + excelUtil.finishExport(); + } + + /** * 导出检查信息 * @param checkId * @param response * @throws IOException */ - @RequiresPermissions("system:check:exportDetail") @Log(title = "检查报告", businessType = BusinessType.EXPORT) - @GetMapping("/exportDetail") - public void exportDetail(@RequestParam String checkId, HttpServletResponse response) throws IOException { + @GetMapping("/exportDetail2") + public void exportDetail2(@RequestParam String checkId, HttpServletResponse response) throws IOException { checkReportManager.exportDetail(checkId, response); } 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 8ecc132..9d77e99 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 @@ -323,50 +323,7 @@ * 导出明细 */ function exportDetail(checkId) { - // 显示加载中提示 - $.modal.loading("正在生成导出文件,请稍候..."); - // 创建iframe - var iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - iframe.src = prefixTable + '/exportDetail?checkId=' + checkId; - // 记录开始时间 - var startTime = new Date().getTime(); - // 定时检查iframe状态 - var checkInterval = setInterval(function() { - try { - var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; - // 如果iframe内容加载完成 - if (iframeDoc.readyState === 'complete') { - clearInterval(checkInterval); - $.modal.closeLoading(); - // 检查是否是错误响应 - var responseText = iframeDoc.body.textContent || iframeDoc.body.innerText; - if (responseText && responseText.startsWith('{"code":500')) { - var result = JSON.parse(responseText); - $.modal.alertError(result.msg); - } - // 移除iframe - setTimeout(function() { - document.body.removeChild(iframe); - }, 100); - } - // 超时处理(10秒超时) - if (new Date().getTime() - startTime > 10000) { - clearInterval(checkInterval); - $.modal.closeLoading(); - document.body.removeChild(iframe); - $.modal.alertError("导出超时,请重试"); - } - } catch(e) { - // 跨域异常通常表示文件下载成功 - clearInterval(checkInterval); - $.modal.closeLoading(); - setTimeout(function() { - document.body.removeChild(iframe); - }, 100); - } - }, 200); - document.body.appendChild(iframe); + window.location.href = prefixTable + '/exportDetail?checkId=' + checkId; } 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 ed76fd0..7b443f7 100644 --- a/ruoyi-admin/src/main/resources/templates/system/checkReport/checkReport.html +++ b/ruoyi-admin/src/main/resources/templates/system/checkReport/checkReport.html @@ -251,50 +251,7 @@ * 导出明细 */ function exportDetail(checkId) { - // 显示加载中提示 - $.modal.loading("正在生成导出文件,请稍候..."); - // 创建iframe - var iframe = document.createElement('iframe'); - iframe.style.display = 'none'; - iframe.src = prefix + '/exportDetail?checkId=' + checkId; - // 记录开始时间 - var startTime = new Date().getTime(); - // 定时检查iframe状态 - var checkInterval = setInterval(function() { - try { - var iframeDoc = iframe.contentDocument || iframe.contentWindow.document; - // 如果iframe内容加载完成 - if (iframeDoc.readyState === 'complete') { - clearInterval(checkInterval); - $.modal.closeLoading(); - // 检查是否是错误响应 - var responseText = iframeDoc.body.textContent || iframeDoc.body.innerText; - if (responseText && responseText.startsWith('{"code":500')) { - var result = JSON.parse(responseText); - $.modal.alertError(result.msg); - } - // 移除iframe - setTimeout(function() { - document.body.removeChild(iframe); - }, 100); - } - // 超时处理(10秒超时) - if (new Date().getTime() - startTime > 10000) { - clearInterval(checkInterval); - $.modal.closeLoading(); - document.body.removeChild(iframe); - $.modal.alertError("导出超时,请重试"); - } - } catch(e) { - // 跨域异常通常表示文件下载成功 - clearInterval(checkInterval); - $.modal.closeLoading(); - setTimeout(function() { - document.body.removeChild(iframe); - }, 100); - } - }, 200); - document.body.appendChild(iframe); + window.location.href = prefix + '/exportDetail?checkId=' + checkId; } 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 0000000..8022a8e --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/MultiSheetExcelUtil.java @@ -0,0 +1,147 @@ +package com.ruoyi.common.utils.poi; + +import com.ruoyi.common.annotation.Excel; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +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.List; +import java.util.UUID; + +/** + * ClassName: MultiSheetExcelUtil + * Package: com.ruoyi.common.utils.poi + * Description: + * + * @Author wangxy + * @Create 2025/4/18 10:43 + * @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); + 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 List getFields(Class clazz) { + List fields = new ArrayList<>(); + Field[] declaredFields = clazz.getDeclaredFields(); + for (Field field : declaredFields) { + Excel excel = field.getAnnotation(Excel.class); + if (excel != null) { + fields.add(new Object[]{field.getName(), excel.name(), excel.readConverterExp(), excel.dictType(), excel.sort()}); + } + } + Class superClass = clazz.getSuperclass(); + while (superClass != null) { + Field[] superFields = superClass.getDeclaredFields(); + for (Field field : superFields) { + Excel excel = field.getAnnotation(Excel.class); + if (excel != null) { + fields.add(new Object[]{field.getName(), excel.name(), excel.readConverterExp(), excel.dictType(), excel.sort()}); + } + } + superClass = superClass.getSuperclass(); + } + fields.sort(Comparator.comparing(o -> (Integer) o[4])); + return fields; + } + + private void createTitleRow(Sheet sheet, List fields) { + Row row = sheet.createRow(0); + for (int i = 0; i < fields.size(); i++) { + Cell cell = row.createCell(i); + cell.setCellValue((String) fields.get(i)[1]); + } + } + + private void fillDataRows(Sheet sheet, List list, List fields) { + int rowNum = 1; + for (T item : list) { + Row row = sheet.createRow(rowNum++); + for (int i = 0; i < fields.size(); i++) { + Cell cell = row.createCell(i); + Object[] fieldInfo = fields.get(i); + String fieldName = (String) fieldInfo[0]; + Object value = getFieldValueByName(fieldName, item); + setCellValue(cell, value); + } + } + } + + private Object getFieldValueByName(String fieldName, Object obj) { + try { + Field field = obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + return field.get(obj); + } catch (Exception e) { + return null; + } + } + + private void setCellValue(Cell cell, Object value) { + if (value == null) { + cell.setCellValue(""); + } else if (value instanceof String) { + cell.setCellValue((String) value); + } else if (value instanceof Integer) { + cell.setCellValue((Integer) value); + } else if (value instanceof Long) { + cell.setCellValue((Long) value); + } else if (value instanceof Double) { + cell.setCellValue((Double) value); + } else if (value instanceof Boolean) { + cell.setCellValue((Boolean) value); + } else { + cell.setCellValue(value.toString()); + } + } + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckReportDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckReportDTO.java index 853b618..3fe25b5 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckReportDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckReportDTO.java @@ -2,6 +2,7 @@ package com.ruoyi.system.domain.check.dto; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; +import com.ruoyi.common.annotation.Excel; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -25,21 +26,25 @@ public class TdCheckReportDTO implements Serializable { /** * 报告人员 */ + @Excel(name = "检查人员") private String adduser; /** * 报告人单位 */ + @Excel(name = "检查单位") private String depart; /** * 检查开始时间 */ + @Excel(name = "检查开始时间", width = 30, dateFormat = "yyyy-MM-dd") private Date checkStartTime; /** * 检查结束时间 */ + @Excel(name = "检查结束时间", width = 30, dateFormat = "yyyy-MM-dd") private Date checkEndTime; /** @@ -50,11 +55,13 @@ public class TdCheckReportDTO implements Serializable { /** * 地区 */ + @Excel(name = "所属市州") private String area; /** * 市州 */ + @Excel(name = "所属区县") private String framework; /** @@ -76,16 +83,19 @@ public class TdCheckReportDTO implements Serializable { /** * 实有项目总分 */ + @Excel(name = "实有项目总分") private String totalScore; /** * 实有项目得分 */ + @Excel(name = "实有项目得分") private String realScore; /** * 得分占比 */ + @Excel(name = "得分占比") private String percentageScore; /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckTypeDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckTypeDTO.java index c5bc03f..331286a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckTypeDTO.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/check/dto/TdCheckTypeDTO.java @@ -2,6 +2,7 @@ package com.ruoyi.system.domain.check.dto; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; +import com.ruoyi.common.annotation.Excel; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; @@ -28,12 +29,14 @@ public class TdCheckTypeDTO implements Serializable { /** * 自查类 */ + private String checkType; /** * 自查类名称 */ + @Excel(name = "自查类") private String typeName; /** @@ -45,23 +48,27 @@ public class TdCheckTypeDTO implements Serializable { /** * 自查项 */ + @Excel(name = "自查项") private String checkItems; /** * 自查内容 */ + @Excel(name = "自查内容") private String typeContent; /** * 分值 */ + @Excel(name = "分值") private String score; /** * 得分 */ + @Excel(name = "得分") private String realScore; /** @@ -73,6 +80,7 @@ public class TdCheckTypeDTO implements Serializable { /** * 扣分标准 */ + @Excel(name = "扣分标准") private String deductionCriteria; /**