feat:自查自评导出

new-exam
wangxy 2 months ago
parent f65eba6ef3
commit b76890d3af

@ -6,9 +6,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil; 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.TdCheckReport;
import com.ruoyi.system.domain.check.dto.CheckReportDTO; import com.ruoyi.system.domain.check.dto.CheckReportDTO;
import com.ruoyi.system.domain.check.dto.TdCheckReportDTO; 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.CheckReportManager;
import com.ruoyi.web.controller.manager.SysAreaManager; import com.ruoyi.web.controller.manager.SysAreaManager;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -17,6 +19,10 @@ import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; 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; import java.util.List;
/** /**
@ -76,6 +82,28 @@ public class CheckReportController extends BaseController {
return util.exportExcel(tdCheckReports, "检查报告管理数据"); 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<TdCheckReportDTO> 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();
}
/** /**
* *
*/ */

@ -108,7 +108,8 @@
<th:block th:include="include :: element-js" /> <th:block th:include="include :: element-js" />
<th:block th:include="include :: echarts-js" /> <th:block th:include="include :: echarts-js" />
<script th:inline="javascript"> <script th:inline="javascript">
var detailFlag = [[${@permission.hasPermi('system:check:detail')}]] var detailFlag = [[${@permission.hasPermi('system:check:detail')}]];
var exportDetailFlag = [[${@permission.hasPermi('system:check:exportDetail')}]];
var prefix = ctx + "system/checknum"; var prefix = ctx + "system/checknum";
var app = new Vue({ var app = new Vue({
el: '#app', el: '#app',
@ -308,6 +309,7 @@
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-info btn-xs ' + exportDetailFlag + '" href="javascript:void(0)" onclick="exportDetail(\'' + row.checkId + '\')"><i class="fa fa-download"></i>导出</a> ');
actions.push('<a class="btn btn-success btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detailTab(\'' + row.checkId + '\')"><i class="fa fa-edit"></i>详情</a> '); actions.push('<a class="btn btn-success btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detailTab(\'' + row.checkId + '\')"><i class="fa fa-edit"></i>详情</a> ');
return actions.join(''); return actions.join('');
} }
@ -315,6 +317,16 @@
}; };
$.table.init(options); $.table.init(options);
}); });
function exportDetail(checkId) {
$.modal.confirm("确定导出吗?", function() {
$.modal.loading("正在导出数据,请稍候...");
window.location.href = prefixTable + '/exportDetail?checkId=' + checkId;
setTimeout(function() {
$.modal.closeLoading();
}, 800);
});
}
</script> </script>
</body> </body>
</html> </html>

@ -81,6 +81,7 @@
var selfCheckFlag = [[${@permission.hasPermi('system:check:selfcheck')}]]; var selfCheckFlag = [[${@permission.hasPermi('system:check:selfcheck')}]];
var removeFlag = [[${@permission.hasPermi('system:check:remove')}]]; var removeFlag = [[${@permission.hasPermi('system:check:remove')}]];
var checkStateDatas = [[${@dict.getType('sys_check_state')}]]; var checkStateDatas = [[${@dict.getType('sys_check_state')}]];
var exportDetailFlag = [[${@permission.hasPermi('system:check:exportDetail')}]];
var prefix = ctx + "system/checkReport"; var prefix = ctx + "system/checkReport";
let datas = [] let datas = []
$.ajax({ $.ajax({
@ -169,6 +170,7 @@
align: 'center', align: 'center',
formatter: function(value, row, index) { formatter: function(value, row, index) {
var actions = []; var actions = [];
actions.push('<a class="btn btn-info btn-xs ' + exportDetailFlag + '" href="javascript:void(0)" onclick="exportDetail(\'' + row.checkId + '\')"><i class="fa fa-download"></i>导出</a> ');
actions.push('<a class="btn btn-success btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detailTab(\'' + row.checkId + '\')"><i class="fa fa-edit"></i>详情</a> '); actions.push('<a class="btn btn-success btn-xs ' + detailFlag + '" href="javascript:void(0)" onclick="$.operate.detailTab(\'' + row.checkId + '\')"><i class="fa fa-edit"></i>详情</a> ');
actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="openEdit(\'' + row.checkId + '\')"><i class="fa fa-edit"></i>编辑</a> '); actions.push('<a class="btn btn-success btn-xs ' + editFlag + '" href="javascript:void(0)" onclick="openEdit(\'' + row.checkId + '\')"><i class="fa fa-edit"></i>编辑</a> ');
actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.checkId + '\')"><i class="fa fa-remove"></i>删除</a>'); actions.push('<a class="btn btn-danger btn-xs ' + removeFlag + '" href="javascript:void(0)" onclick="$.operate.remove(\'' + row.checkId + '\')"><i class="fa fa-remove"></i>删除</a>');
@ -243,6 +245,17 @@
function openEdit(id){ function openEdit(id){
$.modal.openTab("修改" + table.options.modalName, prefix + '/edit' + '/' + 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);
});
}
</script> </script>
</body> </body>
</html> </html>

@ -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 <T> void createSheet(List<T> list, String sheetName, Class<T> clazz) {
Sheet sheet = workbook.createSheet(sheetName);
List<FieldMeta> 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<FieldMeta> getFields(Class<?> clazz) {
List<FieldMeta> 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<FieldMeta> 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 <T> void fillDataRows(Sheet sheet, List<T> list, List<FieldMeta> 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");
}
}
}
}
}
Loading…
Cancel
Save