package com.ruoyi.energymeter.controller;
|
|
import com.ruoyi.framework.web.domain.AjaxResult;
|
import com.ruoyi.energymeter.service.EnergyMonitorService;
|
import com.ruoyi.energymeter.vo.EnergyCollectionVO;
|
import com.ruoyi.energymeter.vo.EnergyRealtimeVO;
|
import com.ruoyi.energymeter.vo.EnergyReportVO;
|
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
import jakarta.servlet.http.HttpServletResponse;
|
import lombok.RequiredArgsConstructor;
|
import org.apache.poi.ss.usermodel.BorderStyle;
|
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.CellStyle;
|
import org.apache.poi.ss.usermodel.FillPatternType;
|
import org.apache.poi.ss.usermodel.Font;
|
import org.apache.poi.ss.usermodel.HorizontalAlignment;
|
import org.apache.poi.ss.usermodel.IndexedColors;
|
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Sheet;
|
import org.apache.poi.ss.usermodel.VerticalAlignment;
|
import org.apache.poi.ss.usermodel.Workbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RestController;
|
|
import java.io.IOException;
|
import java.math.BigDecimal;
|
import java.net.URLEncoder;
|
import java.nio.charset.StandardCharsets;
|
import java.util.List;
|
|
/**
|
* 能耗数据采集、实时监控与统计报表接口。
|
*
|
* <p>菜单固定在前端路由,不写数据库菜单、不配角色权限;所有登录用户可见。</p>
|
*/
|
@RestController
|
@Tag(name = "能耗监控与统计")
|
@RequestMapping("/energyMeter")
|
@RequiredArgsConstructor
|
public class EnergyMonitorController {
|
|
private final EnergyMonitorService monitorService;
|
|
@GetMapping("/collection/overview")
|
@Operation(summary = "能耗数据采集概览:三类介质接入设备、归集进度与最近批次")
|
public AjaxResult collectionOverview() {
|
EnergyCollectionVO vo = monitorService.collection();
|
return AjaxResult.success(vo);
|
}
|
|
@GetMapping("/realtime/overview")
|
@Operation(summary = "能耗实时监控:三类介质最新用量、趋势与电表实时曲线")
|
public AjaxResult realtimeOverview(
|
@RequestParam(required = false) Long meterId) {
|
EnergyRealtimeVO vo = monitorService.realtime(meterId);
|
return AjaxResult.success(vo);
|
}
|
|
@GetMapping("/report/summary")
|
@Operation(summary = "能耗统计分析:按日/月、按介质/设备汇总")
|
public AjaxResult reportSummary(
|
@RequestParam(required = false) String startDate,
|
@RequestParam(required = false) String endDate,
|
@RequestParam(defaultValue = "DAY") String granularity,
|
@RequestParam(defaultValue = "ALL") String meterType,
|
@RequestParam(defaultValue = "MEDIUM") String dimension) {
|
EnergyReportVO vo = monitorService.report(startDate, endDate, granularity, meterType, dimension);
|
return AjaxResult.success(vo);
|
}
|
|
@RequestMapping(value = "/report/export", method = {RequestMethod.GET, RequestMethod.POST})
|
@Operation(summary = "能耗统计报表导出 Excel")
|
public void reportExport(@RequestParam(required = false) String startDate,
|
@RequestParam(required = false) String endDate,
|
@RequestParam(defaultValue = "DAY") String granularity,
|
@RequestParam(defaultValue = "ALL") String meterType,
|
HttpServletResponse response) throws IOException {
|
EnergyReportVO report = monitorService.report(startDate, endDate, granularity, meterType, "MEDIUM");
|
String fileName = URLEncoder.encode("能耗统计报表_" + report.getStart() + "_" + report.getEnd() + ".xlsx",
|
StandardCharsets.UTF_8).replace("+", "%20");
|
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
response.setCharacterEncoding("utf-8");
|
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
|
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
|
try (Workbook workbook = new XSSFWorkbook()) {
|
writeMediumSheet(workbook, report);
|
writeDeviceSheet(workbook, report);
|
workbook.write(response.getOutputStream());
|
}
|
}
|
|
/* ------------------------------------------------------------------ */
|
/* Excel */
|
/* ------------------------------------------------------------------ */
|
|
private void writeMediumSheet(Workbook workbook, EnergyReportVO report) {
|
Sheet sheet = workbook.createSheet("介质汇总");
|
CellStyle headStyle = headStyle(workbook);
|
CellStyle numberStyle = numberStyle(workbook);
|
CellStyle textStyle = textStyle(workbook);
|
|
String[] headers = {"统计周期", "水表用量(m³)", "电表用量(度)", "蒸汽表用量(m³)"};
|
Row head = sheet.createRow(0);
|
for (int i = 0; i < headers.length; i++) {
|
Cell cell = head.createCell(i);
|
cell.setCellValue(headers[i]);
|
cell.setCellStyle(headStyle);
|
}
|
|
int rowIndex = 1;
|
for (EnergyReportVO.PeriodRow row : report.getRows()) {
|
Row dataRow = sheet.createRow(rowIndex++);
|
dataRow.createCell(0).setCellValue(row.getPeriod());
|
dataRow.getCell(0).setCellStyle(textStyle);
|
writeNumber(dataRow, 1, row.getWater(), numberStyle);
|
writeNumber(dataRow, 2, row.getElectric(), numberStyle);
|
writeNumber(dataRow, 3, row.getGas(), numberStyle);
|
}
|
Row totalRow = sheet.createRow(rowIndex);
|
Cell totalLabel = totalRow.createCell(0);
|
totalLabel.setCellValue("合计");
|
totalLabel.setCellStyle(headStyle);
|
for (EnergyReportVO.MediumTotal total : report.getTotals()) {
|
int column = columnOf(total.getMeterType());
|
if (column > 0) {
|
writeNumber(totalRow, column, total.getTotal(), numberStyle);
|
}
|
}
|
sheet.setColumnWidth(0, 18 * 256);
|
for (int i = 1; i <= 3; i++) {
|
sheet.setColumnWidth(i, 20 * 256);
|
}
|
sheet.createFreezePane(0, 1);
|
sheet.setAutoFilter(new org.apache.poi.ss.util.CellRangeAddress(0, Math.max(0, rowIndex - 1), 0, 3));
|
}
|
|
private void writeDeviceSheet(Workbook workbook, EnergyReportVO report) {
|
Sheet sheet = workbook.createSheet("设备明细");
|
CellStyle headStyle = headStyle(workbook);
|
CellStyle numberStyle = numberStyle(workbook);
|
CellStyle textStyle = textStyle(workbook);
|
|
String[] headers = {"设备名称", "表号", "介质", "采集方式", "期间用量", "单位", "占介质比例(%)"};
|
Row head = sheet.createRow(0);
|
for (int i = 0; i < headers.length; i++) {
|
Cell cell = head.createCell(i);
|
cell.setCellValue(headers[i]);
|
cell.setCellStyle(headStyle);
|
}
|
|
int rowIndex = 1;
|
for (EnergyReportVO.DeviceRow row : report.getDevices()) {
|
Row dataRow = sheet.createRow(rowIndex++);
|
createText(dataRow, 0, row.getMeterName(), textStyle);
|
createText(dataRow, 1, row.getMeterAddress(), textStyle);
|
createText(dataRow, 2, row.getMeterTypeName(), textStyle);
|
createText(dataRow, 3, row.getSourceTypeName(), textStyle);
|
writeNumber(dataRow, 4, row.getTotal(), numberStyle);
|
createText(dataRow, 5, excelUnit(row.getUnit()), textStyle);
|
writeNumber(dataRow, 6, row.getShare(), numberStyle);
|
}
|
sheet.setColumnWidth(0, 24 * 256);
|
sheet.setColumnWidth(1, 22 * 256);
|
for (int i = 2; i <= 6; i++) {
|
sheet.setColumnWidth(i, 14 * 256);
|
}
|
sheet.createFreezePane(0, 1);
|
sheet.setAutoFilter(new org.apache.poi.ss.util.CellRangeAddress(0, Math.max(0, rowIndex - 1), 0, 6));
|
}
|
|
private int columnOf(String meterType) {
|
if ("WATER".equals(meterType)) {
|
return 1;
|
}
|
if ("ELECTRIC".equals(meterType)) {
|
return 2;
|
}
|
if ("GAS".equals(meterType)) {
|
return 3;
|
}
|
return 0;
|
}
|
|
/** 界面与报表统一用「度」,底层仍按 kWh 存储。 */
|
private String excelUnit(String unit) {
|
if ("kWh".equals(unit)) {
|
return "度";
|
}
|
if ("m3".equals(unit)) {
|
return "m³";
|
}
|
return unit;
|
}
|
|
private void createText(Row row, int column, String value, CellStyle style) {
|
Cell cell = row.createCell(column);
|
cell.setCellValue(value == null ? "" : value);
|
cell.setCellStyle(style);
|
}
|
|
private void writeNumber(Row row, int column, BigDecimal value, CellStyle style) {
|
Cell cell = row.createCell(column);
|
if (value != null) {
|
cell.setCellValue(value.doubleValue());
|
}
|
cell.setCellStyle(style);
|
}
|
|
private CellStyle headStyle(Workbook workbook) {
|
CellStyle style = baseStyle(workbook);
|
style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
|
style.setAlignment(HorizontalAlignment.CENTER);
|
Font font = workbook.createFont();
|
font.setBold(true);
|
style.setFont(font);
|
return style;
|
}
|
|
private CellStyle textStyle(Workbook workbook) {
|
CellStyle style = baseStyle(workbook);
|
style.setAlignment(HorizontalAlignment.LEFT);
|
return style;
|
}
|
|
private CellStyle numberStyle(Workbook workbook) {
|
CellStyle style = baseStyle(workbook);
|
style.setAlignment(HorizontalAlignment.RIGHT);
|
style.setDataFormat(workbook.createDataFormat().getFormat("#,##0.000"));
|
return style;
|
}
|
|
private CellStyle baseStyle(Workbook workbook) {
|
CellStyle style = workbook.createCellStyle();
|
style.setBorderTop(BorderStyle.THIN);
|
style.setBorderBottom(BorderStyle.THIN);
|
style.setBorderLeft(BorderStyle.THIN);
|
style.setBorderRight(BorderStyle.THIN);
|
style.setVerticalAlignment(VerticalAlignment.CENTER);
|
return style;
|
}
|
}
|