白蚁-日志管理-excel导出
parent
a9466ce01b
commit
a89571643c
|
|
@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gunshi.core.result.R;
|
||||
import com.gunshi.project.hsz.entity.dto.ExportCommonDto;
|
||||
import com.gunshi.project.hsz.entity.so.ByLogPageSo;
|
||||
import com.gunshi.project.hsz.model.ByLog;
|
||||
import com.gunshi.project.hsz.model.ByLogDetail;
|
||||
|
|
@ -16,6 +17,7 @@ import com.gunshi.project.hsz.validate.markers.Update;
|
|||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
|
@ -105,4 +107,12 @@ public class ByLogController extends AbstractCommonFileController {
|
|||
public String getGroupId() {
|
||||
return "byLog";
|
||||
}
|
||||
|
||||
@Operation(description = "日志导出")
|
||||
@PostMapping("/export")
|
||||
public void export(@RequestBody ExportCommonDto dto, HttpServletResponse response) {
|
||||
List<ByLog> byLogs = byLogService.selectByIds(dto.getIds());
|
||||
|
||||
byLogService.exportToExcel(byLogs,response);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,4 +30,15 @@ public interface ByLogDetailMapper extends BaseMapper<ByLogDetail> {
|
|||
""")
|
||||
List<ByLogDetail> selectDetail(@Param("logId") Long id,@Param("dto") ByLogPageSo pageSo);
|
||||
|
||||
@Select("""
|
||||
select t1.id,t1.by_log_id,t1.pre_place_detail_id as ppdi,t1.pre_person,t1.pre_method,t1.pre_effect,
|
||||
t2.detail_name as ppdn,t3.id as ppi,t3.pre_name as ppn
|
||||
from by_log_detail t1
|
||||
join pre_place_detail t2
|
||||
on t1.pre_place_detail_id = t2.id
|
||||
join pre_place t3
|
||||
on t2.pre_id = t3.id
|
||||
where t1.by_log_id = #{logId}
|
||||
""")
|
||||
List<ByLogDetail> selectDetailList(@Param("logId") Long id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,16 +6,25 @@ import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
|||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.gunshi.project.hsz.entity.so.ByLogPageSo;
|
||||
import com.gunshi.project.hsz.mapper.AppVersionRecordMapper;
|
||||
import com.gunshi.project.hsz.mapper.ByLogDetailMapper;
|
||||
import com.gunshi.project.hsz.mapper.ByLogMapper;
|
||||
import com.gunshi.project.hsz.model.*;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.ibatis.executor.BatchResult;
|
||||
import org.apache.poi.ss.usermodel.*;
|
||||
import org.apache.poi.ss.util.CellRangeAddress;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
|
@ -64,4 +73,268 @@ public class ByLogService extends ServiceImpl<ByLogMapper, ByLog> {
|
|||
}
|
||||
return byLogPage;
|
||||
}
|
||||
|
||||
public List<ByLog> selectByIds(List<Long> ids) {
|
||||
LambdaQueryWrapper<ByLog> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.in(ByLog::getId, ids);
|
||||
List<ByLog> byLogs = this.baseMapper.selectList(queryWrapper);
|
||||
byLogs.stream().forEach(o ->{
|
||||
List<ByLogDetail> details = byLogDetailMapper.selectDetailList(o.getId());
|
||||
o.setDetails(details);
|
||||
});
|
||||
return byLogs;
|
||||
}
|
||||
// 核心导出方法(无冗余)
|
||||
public void exportToExcel(List<ByLog> byLogs, HttpServletResponse response) {
|
||||
Workbook workbook = new XSSFWorkbook();
|
||||
Sheet sheet = workbook.createSheet("白蚁防治日志");
|
||||
|
||||
// 1. 合并创建所有样式(原5个样式方法→1个)
|
||||
StyleGroup styles = createAllStyles(workbook);
|
||||
|
||||
// 2. 创建标题行(逻辑不变)
|
||||
createHeaderRow(sheet, styles.headerStyle);
|
||||
|
||||
// 3. 填充数据(序号计数器直接在循环内维护,减少参数传递)
|
||||
fillDataWithMerge(sheet, styles, byLogs);
|
||||
|
||||
// 4. 调整列宽(逻辑不变)
|
||||
adjustColumnWidth(sheet);
|
||||
|
||||
// 5. 响应处理(逻辑不变)
|
||||
String fileName = "白蚁-日志管理" + System.currentTimeMillis();
|
||||
try {
|
||||
setResponseHeaders(response, fileName);
|
||||
workbook.write(response.getOutputStream());
|
||||
workbook.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class StyleGroup {
|
||||
CellStyle headerStyle;
|
||||
CellStyle dataStyle;
|
||||
CellStyle detailStyle;
|
||||
CellStyle dateStyle;
|
||||
CellStyle dateTimeStyle; // 原分散创建,现在统一封装
|
||||
|
||||
StyleGroup(CellStyle headerStyle, CellStyle dataStyle, CellStyle detailStyle,
|
||||
CellStyle dateStyle, CellStyle dateTimeStyle) {
|
||||
this.headerStyle = headerStyle;
|
||||
this.dataStyle = dataStyle;
|
||||
this.detailStyle = detailStyle;
|
||||
this.dateStyle = dateStyle;
|
||||
this.dateTimeStyle = dateTimeStyle;
|
||||
}
|
||||
}
|
||||
|
||||
// 统一创建所有样式(原createHeaderStyle/createDataStyle等合并)
|
||||
private StyleGroup createAllStyles(Workbook workbook) {
|
||||
// 1. 基础数据样式
|
||||
CellStyle dataStyle = workbook.createCellStyle();
|
||||
dataStyle.setAlignment(HorizontalAlignment.CENTER);
|
||||
dataStyle.setVerticalAlignment(VerticalAlignment.CENTER);
|
||||
dataStyle.setBorderBottom(BorderStyle.THIN);
|
||||
dataStyle.setBorderTop(BorderStyle.THIN);
|
||||
dataStyle.setBorderLeft(BorderStyle.THIN);
|
||||
dataStyle.setBorderRight(BorderStyle.THIN);
|
||||
|
||||
// 2. 表头样式
|
||||
CellStyle headerStyle = workbook.createCellStyle();
|
||||
headerStyle.cloneStyleFrom(dataStyle);
|
||||
Font headerFont = workbook.createFont();
|
||||
headerFont.setBold(true);
|
||||
headerFont.setFontHeightInPoints((short) 12);
|
||||
headerStyle.setFont(headerFont);
|
||||
headerStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
||||
headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
||||
|
||||
// 3. 详情样式
|
||||
CellStyle detailStyle = workbook.createCellStyle();
|
||||
detailStyle.cloneStyleFrom(dataStyle);
|
||||
detailStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
detailStyle.setWrapText(true); // 自动换行
|
||||
|
||||
// 4. 日期样式
|
||||
CreationHelper createHelper = workbook.getCreationHelper();
|
||||
CellStyle dateStyle = workbook.createCellStyle();
|
||||
dateStyle.cloneStyleFrom(dataStyle);
|
||||
dateStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd"));
|
||||
|
||||
// 5. 日期时间样式
|
||||
CellStyle dateTimeStyle = workbook.createCellStyle();
|
||||
dateTimeStyle.cloneStyleFrom(dataStyle);
|
||||
dateTimeStyle.setDataFormat(createHelper.createDataFormat().getFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
|
||||
return new StyleGroup(headerStyle, dataStyle, detailStyle, dateStyle, dateTimeStyle);
|
||||
}
|
||||
|
||||
private void createHeaderRow(Sheet sheet, CellStyle headerStyle) {
|
||||
Row headerRow = sheet.createRow(0);
|
||||
String[] headers = {
|
||||
"序号", "日志名称", "防治日期", "填报时间", "总费用(元)", "备注",
|
||||
"防治部位", "防治点", "防治人员", "防治方法", "防治效果"
|
||||
};
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
Cell cell = headerRow.createCell(i);
|
||||
cell.setCellValue(headers[i]);
|
||||
cell.setCellStyle(headerStyle);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillDataWithMerge(Sheet sheet, StyleGroup styles, List<ByLog> dataList) {
|
||||
int currentRow = 1;
|
||||
int logSerialNumber = 1; // 序号
|
||||
|
||||
for (ByLog log : dataList) {
|
||||
int detailCount = log.getDetails() != null ? log.getDetails().size() : 0;
|
||||
int rowSpan = Math.max(detailCount, 1);
|
||||
Row row = sheet.createRow(currentRow);
|
||||
// 1. 序号
|
||||
Cell cell0 = row.createCell(0);
|
||||
cell0.setCellValue(logSerialNumber);
|
||||
cell0.setCellStyle(styles.dataStyle);
|
||||
if (rowSpan > 1) sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow + rowSpan - 1, 0, 0));
|
||||
|
||||
// 2. 日志名称
|
||||
Cell cell1 = row.createCell(1);
|
||||
cell1.setCellValue(log.getLogName() != null ? log.getLogName() : "");
|
||||
cell1.setCellStyle(styles.dataStyle);
|
||||
if (rowSpan > 1) sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow + rowSpan - 1, 1, 1));
|
||||
|
||||
// 3. 防治日期
|
||||
Cell cell2 = row.createCell(2);
|
||||
if (log.getPreDate() != null) {
|
||||
cell2.setCellValue(log.getPreDate());
|
||||
cell2.setCellStyle(styles.dateStyle);
|
||||
} else {
|
||||
cell2.setCellValue("");
|
||||
cell2.setCellStyle(styles.dataStyle);
|
||||
}
|
||||
if (rowSpan > 1) sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow + rowSpan - 1, 2, 2));
|
||||
|
||||
// 4. 填报时间
|
||||
Cell cell3 = row.createCell(3);
|
||||
if (log.getFillTime() != null) {
|
||||
cell3.setCellValue(log.getFillTime());
|
||||
cell3.setCellStyle(styles.dateTimeStyle); // 精简:不再临时创建样式
|
||||
} else {
|
||||
cell3.setCellValue("");
|
||||
cell3.setCellStyle(styles.dataStyle);
|
||||
}
|
||||
if (rowSpan > 1) sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow + rowSpan - 1, 3, 3));
|
||||
|
||||
// 5. 总费用
|
||||
Cell cell4 = row.createCell(4);
|
||||
CellStyle currencyStyle = sheet.getWorkbook().createCellStyle();
|
||||
currencyStyle.cloneStyleFrom(styles.dataStyle);
|
||||
currencyStyle.setDataFormat((short) 0x27); // 货币格式
|
||||
if (log.getTotalCost() != null) {
|
||||
cell4.setCellValue(log.getTotalCost().doubleValue());
|
||||
} else {
|
||||
cell4.setCellValue(0);
|
||||
}
|
||||
cell4.setCellStyle(currencyStyle);
|
||||
if (rowSpan > 1) sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow + rowSpan - 1, 4, 4));
|
||||
Cell cell5 = row.createCell(5);
|
||||
cell5.setCellValue(log.getRemark() != null ? log.getRemark() : "");
|
||||
cell5.setCellStyle(styles.dataStyle);
|
||||
if (rowSpan > 1) sheet.addMergedRegion(new CellRangeAddress(currentRow, currentRow + rowSpan - 1, 5, 5));
|
||||
|
||||
if (detailCount > 0) {
|
||||
fillDetailInfo(row, log.getDetails().get(0), styles.detailStyle);
|
||||
for (int i = 1; i < detailCount; i++) {
|
||||
Row detailRow = sheet.createRow(currentRow + i);
|
||||
for (int col = 0; col <= 5; col++) {
|
||||
Cell emptyCell = detailRow.createCell(col);
|
||||
emptyCell.setCellValue("");
|
||||
if (col == 2) {
|
||||
emptyCell.setCellStyle(styles.dateStyle); // 防治日期列:用日期样式
|
||||
} else if (col == 3) {
|
||||
emptyCell.setCellStyle(styles.dateTimeStyle); // 填报时间列:用日期时间样式
|
||||
} else if (col == 4) {
|
||||
emptyCell.setCellStyle(currencyStyle); // 总费用列:用货币样式
|
||||
} else {
|
||||
emptyCell.setCellStyle(styles.dataStyle); // 其他列:用基础数据样式
|
||||
}
|
||||
}
|
||||
fillDetailInfo(detailRow, log.getDetails().get(i), styles.detailStyle);
|
||||
}
|
||||
} else {
|
||||
for (int i = 6; i <= 10; i++) {
|
||||
Cell cell = row.createCell(i);
|
||||
cell.setCellValue("");
|
||||
cell.setCellStyle(styles.detailStyle);
|
||||
}
|
||||
}
|
||||
|
||||
currentRow += rowSpan;
|
||||
logSerialNumber++; // 序号自增
|
||||
}
|
||||
}
|
||||
|
||||
private void fillDetailInfo(Row row, ByLogDetail detail, CellStyle style) {
|
||||
createCell(row, 6, detail.getPpdn(), style); // 防治部位
|
||||
createCell(row, 7, detail.getPpn(), style); // 防治点
|
||||
createCell(row, 8, detail.getPrePerson(), style); // 防治人员
|
||||
createCell(row, 9, detail.getPreMethod(), style); // 防治方法
|
||||
createCell(row, 10, detail.getPreEffect(), style); // 防治效果
|
||||
}
|
||||
|
||||
private void createCell(Row row, int column, Object value, CellStyle style) {
|
||||
Cell cell = row.createCell(column);
|
||||
if (value == null) {
|
||||
cell.setCellValue("");
|
||||
} else if (value instanceof String) {
|
||||
cell.setCellValue((String) value);
|
||||
} else if (value instanceof Number) {
|
||||
// 精简:合并Long/Integer处理(Number是它们的父类)
|
||||
cell.setCellValue(value.toString());
|
||||
} else if (value instanceof BigDecimal) {
|
||||
cell.setCellValue(((BigDecimal) value).doubleValue());
|
||||
} else if (value instanceof Date) {
|
||||
cell.setCellValue((Date) value);
|
||||
// 日期样式统一(复用StyleGroup逻辑,此处简化)
|
||||
CellStyle dateCellStyle = row.getSheet().getWorkbook().createCellStyle();
|
||||
dateCellStyle.cloneStyleFrom(style);
|
||||
dateCellStyle.setDataFormat(row.getSheet().getWorkbook().getCreationHelper()
|
||||
.createDataFormat().getFormat("yyyy-MM-dd"));
|
||||
cell.setCellStyle(dateCellStyle);
|
||||
} else {
|
||||
cell.setCellValue(value.toString());
|
||||
}
|
||||
cell.setCellStyle(style);
|
||||
}
|
||||
|
||||
// 列宽调整(逻辑不变)
|
||||
private void adjustColumnWidth(Sheet sheet) {
|
||||
int[] columnWidths = {
|
||||
8 * 256, // 序号
|
||||
25 * 256, // 日志名称
|
||||
15 * 256, // 防治日期
|
||||
25 * 256, // 填报时间
|
||||
15 * 256, // 总费用
|
||||
30 * 256, // 备注
|
||||
20 * 256, // 防治部位
|
||||
20 * 256, // 防治点
|
||||
15 * 256, // 防治人员
|
||||
20 * 256, // 防治方法
|
||||
15 * 256 // 防治效果
|
||||
};
|
||||
for (int i = 0; i < columnWidths.length; i++) {
|
||||
sheet.setColumnWidth(i, columnWidths[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// 响应头设置(逻辑不变)
|
||||
private void setResponseHeaders(HttpServletResponse response, String fileName) throws IOException {
|
||||
String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
|
||||
.replaceAll("\\+", "%20");
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setHeader("Content-Disposition",
|
||||
"attachment; filename=\"" + encodedFileName + ".xlsx\"");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue