|
|
@ -25,12 +25,17 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTblWidth; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
import javax.naming.NamingEnumeration; |
|
|
|
import java.io.FileInputStream; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.math.BigInteger; |
|
|
|
import java.text.SimpleDateFormat; |
|
|
|
import java.time.LocalDate; |
|
|
|
import java.time.LocalDateTime; |
|
|
|
import java.time.LocalTime; |
|
|
|
import java.time.format.DateTimeFormatter; |
|
|
|
import java.time.temporal.TemporalAdjusters; |
|
|
|
import java.util.*; |
|
|
|
import java.time.ZoneId; |
|
|
|
import java.util.regex.Matcher; |
|
|
@ -417,16 +422,103 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
@Override |
|
|
|
public Map<Integer, Long> accidentTimeAnalysis(DcSdhsEventQuery dcSdhsEventQuery) { |
|
|
|
public Map<String, Long> accidentTimeAnalysis(DcSdhsEventQuery dcSdhsEventQuery) { |
|
|
|
List<DcSdhsEvent> cacheList = redisCache.getCacheList(RedisKeyConstants.SDHS_EVENT); |
|
|
|
// 将查询开始时间和结束时间转换为 LocalDateTime
|
|
|
|
ZoneId zoneId = ZoneId.systemDefault(); // 获取系统默认时区
|
|
|
|
LocalDateTime queryStart = dcSdhsEventQuery.getStartTime().toInstant().atZone(zoneId).toLocalDateTime(); |
|
|
|
LocalDateTime queryEnd = dcSdhsEventQuery.getEndTime().toInstant().atZone(zoneId).toLocalDateTime(); |
|
|
|
if (dcSdhsEventQuery.getType().equals("2")) { |
|
|
|
// 将查询开始时间和结束时间转换为 LocalDateTime
|
|
|
|
LocalDateTime queryStart = dcSdhsEventQuery.getStartTime().toInstant().atZone(zoneId).toLocalDateTime(); |
|
|
|
// LocalDateTime endTime = dcSdhsEventQuery.getEndTime().toInstant().atZone(zoneId).toLocalDateTime();
|
|
|
|
// 计算当天的结束时间
|
|
|
|
LocalDateTime queryEnd = queryStart.withHour(23).withMinute(59).withSecond(59); |
|
|
|
List<DcSdhsEvent> filteredEvents = getDcSdhsEvents(dcSdhsEventQuery, cacheList, zoneId, queryStart, queryEnd); |
|
|
|
// 按小时分组并统计每个小时内的事件数量
|
|
|
|
Map<String, Long> hourlyCounts = filteredEvents.stream() |
|
|
|
.collect( |
|
|
|
Collectors.groupingBy( |
|
|
|
event -> String.format("%02d", event.getStartTime().toInstant().atZone(zoneId).toLocalDateTime().getHour()), |
|
|
|
Collectors.counting() |
|
|
|
) |
|
|
|
); |
|
|
|
|
|
|
|
// 确保所有小时都出现在结果中
|
|
|
|
for (int hour = 0; hour <= 23; hour++) { |
|
|
|
String hourString = String.format("%02d", hour); |
|
|
|
hourlyCounts.merge(hourString, 0L, Long::sum); |
|
|
|
} |
|
|
|
return hourlyCounts; |
|
|
|
} else if (dcSdhsEventQuery.getType().equals("1")) { |
|
|
|
// 将查询开始时间和结束时间转换为 LocalDateTime
|
|
|
|
LocalDateTime queryStart = dcSdhsEventQuery.getStartTime().toInstant().atZone(zoneId).toLocalDateTime(); |
|
|
|
// 获取该月的最后一天
|
|
|
|
LocalDate lastDayOfMonth = queryStart.toLocalDate().with(TemporalAdjusters.lastDayOfMonth()); |
|
|
|
// 构建该月的最后一刻(23:59:59)
|
|
|
|
LocalDateTime endOfMonth = LocalDateTime.of(lastDayOfMonth, LocalTime.MAX); |
|
|
|
List<DcSdhsEvent> filteredEvents = getDcSdhsEvents(dcSdhsEventQuery, cacheList, zoneId, queryStart, endOfMonth); |
|
|
|
// 定义日期格式
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd"); |
|
|
|
// 按天分组并统计每一天内的事件数量
|
|
|
|
Map<String, Long> dailyCounts = filteredEvents.stream() |
|
|
|
.collect( |
|
|
|
Collectors.groupingBy( |
|
|
|
event -> event.getStartTime().toInstant().atZone(zoneId).toLocalDate().format(formatter), |
|
|
|
Collectors.counting() |
|
|
|
) |
|
|
|
); |
|
|
|
// 确保所有日期都出现在结果中
|
|
|
|
LocalDate queryStartLocalDate = queryStart.toLocalDate(); |
|
|
|
LocalDate queryEndLocalDate = endOfMonth.toLocalDate(); |
|
|
|
|
|
|
|
// 确保所有日期都出现在结果中
|
|
|
|
for (LocalDate date = queryStartLocalDate; date.isBefore(queryEndLocalDate.plusDays(1)); date = date.plusDays(1)) { |
|
|
|
String dateString = date.format(formatter); |
|
|
|
dailyCounts.merge(dateString, 0L, Long::sum); |
|
|
|
} |
|
|
|
return dailyCounts; |
|
|
|
}else { |
|
|
|
// 将查询开始时间和结束时间转换为 LocalDateTime
|
|
|
|
LocalDateTime queryStart = dcSdhsEventQuery.getStartTime().toInstant().atZone(zoneId).toLocalDateTime(); |
|
|
|
// 获取该年的最后一天
|
|
|
|
LocalDate lastDayOfYear = queryStart.toLocalDate().with(TemporalAdjusters.lastDayOfYear()); |
|
|
|
// 构建该年的最后一刻(23:59:59)
|
|
|
|
LocalDateTime endOfYear = LocalDateTime.of(lastDayOfYear, LocalTime.MAX); |
|
|
|
List<DcSdhsEvent> filteredEvents = getDcSdhsEvents(dcSdhsEventQuery, cacheList, zoneId, queryStart, endOfYear); |
|
|
|
// 定义日期格式
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM"); |
|
|
|
// 按月分组并统计每个月内的事件数量
|
|
|
|
Map<String, Long> monthlyCounts = filteredEvents.stream() |
|
|
|
.collect( |
|
|
|
Collectors.groupingBy( |
|
|
|
event -> event.getStartTime().toInstant().atZone(zoneId).toLocalDate().format(formatter), |
|
|
|
Collectors.counting() |
|
|
|
) |
|
|
|
); |
|
|
|
|
|
|
|
// 确保所有月份都出现在结果中
|
|
|
|
LocalDate queryEnd = endOfYear.toLocalDate().plusMonths(1); // 确保包含结束月份
|
|
|
|
LocalDate currentMonth = queryStart.toLocalDate(); |
|
|
|
while (currentMonth.isBefore(queryEnd)) { |
|
|
|
String monthString = currentMonth.format(formatter); |
|
|
|
monthlyCounts.merge(monthString, 0L, Long::sum); |
|
|
|
currentMonth = currentMonth.plusMonths(1); |
|
|
|
} |
|
|
|
return monthlyCounts; |
|
|
|
} |
|
|
|
|
|
|
|
// 在指定时间范围内的事件
|
|
|
|
String direction = dcSdhsEventQuery.getDirection(); // 获取方向查询参数
|
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* // 在指定时间范围内的事件
|
|
|
|
* @param dcSdhsEventQuery |
|
|
|
* @param cacheList |
|
|
|
* @param zoneId |
|
|
|
* @param queryStart |
|
|
|
* @param queryEnd |
|
|
|
* @return |
|
|
|
*/ |
|
|
|
private static List<DcSdhsEvent> getDcSdhsEvents(DcSdhsEventQuery dcSdhsEventQuery, List<DcSdhsEvent> cacheList, ZoneId zoneId, LocalDateTime queryStart, LocalDateTime queryEnd) { |
|
|
|
|
|
|
|
String direction = dcSdhsEventQuery.getDirection(); // 获取方向查询参数
|
|
|
|
List<DcSdhsEvent> filteredEvents = cacheList.stream() |
|
|
|
.filter(event -> { |
|
|
|
LocalDateTime eventTime = event.getStartTime().toInstant().atZone(zoneId).toLocalDateTime(); |
|
|
@ -442,22 +534,7 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
} |
|
|
|
}) |
|
|
|
.collect(Collectors.toList()); |
|
|
|
|
|
|
|
// 按小时分组并统计每个小时内的事件数量
|
|
|
|
Map<Integer, Long> hourlyCounts = filteredEvents.stream() |
|
|
|
.collect( |
|
|
|
Collectors.groupingBy( |
|
|
|
event -> event.getStartTime().toInstant().atZone(zoneId).toLocalDateTime().getHour(), |
|
|
|
Collectors.counting() |
|
|
|
) |
|
|
|
); |
|
|
|
|
|
|
|
// 小时都出现在结果中,如果不存在设为 0
|
|
|
|
for (int hour = 0; hour <= 23; hour++) { |
|
|
|
hourlyCounts.merge(hour, 0L, Long::sum); |
|
|
|
} |
|
|
|
|
|
|
|
return hourlyCounts; |
|
|
|
return filteredEvents; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
@ -468,24 +545,39 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
@Override |
|
|
|
public void exportAccidentTimeAnalysis(XWPFDocument doc,DcSdhsEventQuery dcSdhsEventQuery) { |
|
|
|
|
|
|
|
Map<Integer, Long> currentYearData = accidentTimeAnalysis(dcSdhsEventQuery); |
|
|
|
Map<String, Long> currentYearData = accidentTimeAnalysis(dcSdhsEventQuery); |
|
|
|
// 获取一年前的日期
|
|
|
|
Date startTime = dcSdhsEventQuery.getStartTime(); |
|
|
|
Date endTime = dcSdhsEventQuery.getEndTime(); |
|
|
|
// 使用 Calendar 计算一年前的时间
|
|
|
|
Calendar calendar = Calendar.getInstance(); |
|
|
|
calendar.setTime(startTime); // 设置当前时间为 startTime
|
|
|
|
calendar.add(Calendar.YEAR, -1); // 减去一年
|
|
|
|
Date oneYearAgoStart = calendar.getTime(); // 一年前的开始时间
|
|
|
|
calendar.setTime(endTime); // 设置当前时间为 endTime
|
|
|
|
calendar.add(Calendar.YEAR, -1); // 减去一年
|
|
|
|
Date oneYearAgoEnd = calendar.getTime(); // 一年前的结束时间
|
|
|
|
dcSdhsEventQuery.setStartTime(oneYearAgoStart); |
|
|
|
dcSdhsEventQuery.setEndTime(oneYearAgoEnd); |
|
|
|
Map<Integer, Long> lastYearData = accidentTimeAnalysis(dcSdhsEventQuery); |
|
|
|
Map<String, Long> lastYearData = accidentTimeAnalysis(dcSdhsEventQuery); |
|
|
|
String type = dcSdhsEventQuery.getType(); |
|
|
|
int rows=0; |
|
|
|
String stingType= ""; |
|
|
|
String name= ""; |
|
|
|
if (type.equals("2")){ |
|
|
|
rows=25; |
|
|
|
stingType="点"; |
|
|
|
name= "wordTemplate/accidentTimeAnalysis.docx"; |
|
|
|
}else if (type.equals("1")){ |
|
|
|
rows=32; |
|
|
|
stingType="日"; |
|
|
|
name= "wordTemplate/accidentTimeDayAnalysis.docx"; |
|
|
|
|
|
|
|
}else { |
|
|
|
rows=13; |
|
|
|
stingType="月"; |
|
|
|
name= "wordTemplate/accidentTimeMonthAnalysis.docx"; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 创建表格
|
|
|
|
XWPFTable table = doc.createTable(25,3); |
|
|
|
XWPFTable table = doc.createTable(rows,3); |
|
|
|
CTTblWidth infoTableWidth = table.getCTTbl().addNewTblPr().addNewTblW(); |
|
|
|
infoTableWidth.setType(STTblWidth.DXA); |
|
|
|
infoTableWidth.setW(BigInteger.valueOf(UniversalEnum.NINE_THOUSAND_AND_SEVENTY_TWO.getNumber())); |
|
|
@ -494,19 +586,36 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
setTableFonts(table.getRow(0).getCell(0), "时段"); |
|
|
|
setTableFonts(table.getRow(0).getCell(1), "今年同期"); |
|
|
|
setTableFonts(table.getRow(0).getCell(2), "去年同期"); |
|
|
|
|
|
|
|
// 定义一个从数字到日期字符串的映射
|
|
|
|
Map<Integer, String> indexToDateMap = new HashMap<>(); |
|
|
|
for (int i = 0; i <= 32; i++) { |
|
|
|
String dateString = String.format("%02d", i); |
|
|
|
indexToDateMap.put(i, dateString); |
|
|
|
} |
|
|
|
String dayString=""; |
|
|
|
// 填充表格数据
|
|
|
|
for (int i = 0; i < 24; i++) { |
|
|
|
setTableFonts(table.getRow(i + 1).getCell(0), (i ) + "点"); |
|
|
|
Long currentYearValue = currentYearData.getOrDefault(i, 0L); |
|
|
|
for (int i = 0; i < rows-1; i++) { |
|
|
|
|
|
|
|
if (type.equals("2")){ |
|
|
|
dayString = indexToDateMap.get(i); // 获取 i 对应的日期字符串
|
|
|
|
}else { |
|
|
|
dayString = indexToDateMap.get(i+1); // 获取 i 对应的日期字符串
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
setTableFonts(table.getRow(i + 1).getCell(0), (dayString ) + stingType); |
|
|
|
Long currentYearValue = currentYearData.getOrDefault(dayString, 0L); |
|
|
|
setTableFonts(table.getRow(i + 1).getCell(1), String.valueOf(currentYearValue)); |
|
|
|
Long lastYearValue = lastYearData.getOrDefault(i, 0L); |
|
|
|
Long lastYearValue = lastYearData.getOrDefault(dayString, 0L); |
|
|
|
setTableFonts(table.getRow(i + 1).getCell(2), String.valueOf(lastYearValue)); |
|
|
|
} |
|
|
|
|
|
|
|
// 图表部分
|
|
|
|
try { |
|
|
|
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("wordTemplate/accidentTimeAnalysis.docx"); |
|
|
|
|
|
|
|
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(name); |
|
|
|
|
|
|
|
|
|
|
|
XWPFDocument copiedTemplate = new XWPFDocument(inputStream); |
|
|
|
|
|
|
|
List<XWPFChart> charts = copiedTemplate.getCharts(); |
|
|
@ -514,8 +623,14 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
XSSFWorkbook workbook = chart.getWorkbook(); |
|
|
|
XSSFSheet sheet = workbook.getSheetAt(UniversalEnum.ZERO.getNumber()); |
|
|
|
// 更新图表数据
|
|
|
|
for (int i = UniversalEnum.ZERO.getNumber(); i < 24; i++){ |
|
|
|
sheet.getRow(i + 1).getCell(0).setCellValue((i) + "点"); |
|
|
|
for (int i = UniversalEnum.ZERO.getNumber(); i < rows-1; i++){ |
|
|
|
if (type.equals("2")){ |
|
|
|
dayString = indexToDateMap.get(i); // 获取 i 对应的日期字符串
|
|
|
|
}else { |
|
|
|
dayString = indexToDateMap.get(i+1); // 获取 i 对应的日期字符串
|
|
|
|
|
|
|
|
} |
|
|
|
sheet.getRow(i + 1).getCell(0).setCellValue((dayString) + stingType); |
|
|
|
int rowIndex = i + UniversalEnum.ONE.getNumber(); // 计算行索引
|
|
|
|
Row row = sheet.getRow(rowIndex); |
|
|
|
if (row == null) { |
|
|
@ -529,9 +644,8 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
// 通常情况下,getCell 会创建新的单元格,但这里我们显式地检查以防万一
|
|
|
|
cell = row.createCell(UniversalEnum.ONE.getNumber(), CellType.NUMERIC); |
|
|
|
} |
|
|
|
|
|
|
|
// 设置单元格的值
|
|
|
|
sheet.getRow(i + 1).getCell(1).setCellValue(currentYearData.get(i)); |
|
|
|
sheet.getRow(i + 1).getCell(1).setCellValue(currentYearData.get(dayString)); |
|
|
|
int rowIndexTwo = i +1+ UniversalEnum.ONE.getNumber(); // 计算行索引
|
|
|
|
Row rowTwo = sheet.getRow(rowIndexTwo); |
|
|
|
if (rowTwo == null) { |
|
|
@ -545,7 +659,7 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
// 通常情况下,getCell 会创建新的单元格,但这里我们显式地检查以防万一
|
|
|
|
cell = row.createCell(UniversalEnum.TWO.getNumber(), CellType.NUMERIC); |
|
|
|
} |
|
|
|
sheet.getRow(i + 1).getCell(2).setCellValue(lastYearData.get(i)); |
|
|
|
sheet.getRow(i + 1).getCell(2).setCellValue(lastYearData.get(dayString)); |
|
|
|
//sheet.getRow(i+UniversalEnum.ONE.getNumber()).getCell(UniversalEnum.ONE.getNumber()).setCellValue(Long.parseLong(entries.get(i).getValue().toString()));
|
|
|
|
} |
|
|
|
/* for (int i = 0; i < 24; i++) { |
|
|
@ -554,7 +668,9 @@ public class DcSdhsEventServiceImpl implements IDcSdhsEventService { |
|
|
|
sheet.getRow(i + 1).getCell(1).setCellValue(currentYearData.get(i)); |
|
|
|
sheet.getRow(i + 1).getCell(2).setCellValue(lastYearData.get(i)); |
|
|
|
}*/ |
|
|
|
|
|
|
|
for (int i=sheet.getLastRowNum();i> currentYearData.size();i--){ |
|
|
|
sheet.removeRow(sheet.getRow(i)); |
|
|
|
} |
|
|
|
// 更新图表
|
|
|
|
PoiUtil.wordExportChar(chart, "事故时间分析", new String[]{"今年同期", "去年同期"}, sheet); |
|
|
|
|
|
|
|