|
|
@@ -1,252 +0,0 @@
|
|
|
-package com.energy.manage.service.service.healthscores.impl;
|
|
|
-
|
|
|
-import com.energy.manage.common.po.windfield.WindFieldPO;
|
|
|
-import com.energy.manage.service.domain.vo.healthscores.HealthOverviewListVO;
|
|
|
-import com.energy.manage.service.domain.vo.healthscores.HealthOverviewVO;
|
|
|
-import com.energy.manage.service.domain.vo.healthscores.HealthscoresTendencyVO;
|
|
|
-import com.energy.manage.service.domain.vo.healthscores.HealthscoresWindVO;
|
|
|
-import com.energy.manage.service.mappers.healthscores.HealthscoresMapper;
|
|
|
-import com.energy.manage.service.mappers.windfield.WindFieldMapper;
|
|
|
-import com.energy.manage.service.service.healthscores.HealthscoresService;
|
|
|
-import groovy.util.logging.Slf4j;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.stereotype.Service;
|
|
|
-
|
|
|
-import java.time.LocalDate;
|
|
|
-import java.time.LocalDateTime;
|
|
|
-import java.time.format.DateTimeFormatter;
|
|
|
-import java.util.*;
|
|
|
-import java.util.stream.Collectors;
|
|
|
-import java.util.stream.Stream;
|
|
|
-
|
|
|
-@Service
|
|
|
-@Slf4j
|
|
|
-public class HealthscoresServiceImpl implements HealthscoresService {
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private HealthscoresMapper healthscoresMapper;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private WindFieldMapper windFieldMapper;
|
|
|
-
|
|
|
- // 通用日期格式化器(线程安全,可全局复用)
|
|
|
- private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
|
|
- private static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<HealthscoresWindVO> getHealthscoresWind(String fieldCode, String datatime) {
|
|
|
-
|
|
|
- String fieldId = null;
|
|
|
- if (!StringUtils.isEmpty(fieldCode)) {
|
|
|
- WindFieldPO po = new WindFieldPO();
|
|
|
- po.setFieldCode(fieldCode);
|
|
|
- WindFieldPO windFieldPO = windFieldMapper.selectOne(po);
|
|
|
- fieldId = windFieldPO.getFieldId();
|
|
|
- }
|
|
|
-
|
|
|
- String beginTime = null;
|
|
|
- String endTime = null;
|
|
|
- if (!StringUtils.isEmpty(datatime)) {
|
|
|
- beginTime = appendTimeToString(datatime, 00, 00, 00);
|
|
|
- endTime = appendTimeToString(datatime, 23, 59, 59);
|
|
|
- } else {
|
|
|
- beginTime = getYesterdayStartStr();
|
|
|
- endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
|
|
|
- }
|
|
|
-
|
|
|
- List<HealthscoresWindVO> list = healthscoresMapper.selectWindScoreList(fieldId, beginTime, endTime);
|
|
|
- return list;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public HealthOverviewVO getHealthOverview(String fieldCode, String datatime) {
|
|
|
-
|
|
|
- String fieldId = null;
|
|
|
- if (!StringUtils.isEmpty(fieldCode)) {
|
|
|
- WindFieldPO po = new WindFieldPO();
|
|
|
- po.setFieldCode(fieldCode);
|
|
|
- WindFieldPO windFieldPO = windFieldMapper.selectOne(po);
|
|
|
- fieldId = windFieldPO.getFieldId();
|
|
|
- }
|
|
|
-
|
|
|
- String beginTime = null;
|
|
|
- String endTime = null;
|
|
|
- if (!StringUtils.isEmpty(datatime)) {
|
|
|
- beginTime = appendTimeToString(datatime, 00, 00, 00);
|
|
|
- endTime = appendTimeToString(datatime, 23, 59, 59);
|
|
|
- } else {
|
|
|
- beginTime = getYesterdayStartStr();
|
|
|
- endTime = getYesterdayEnd().format(DATETIME_FORMATTER);
|
|
|
- }
|
|
|
-
|
|
|
- HealthOverviewVO healthOverviewVO = new HealthOverviewVO();
|
|
|
- HealthscoresWindVO healthscoresWind = healthscoresMapper.selectWindHealthscoresScore(fieldId, beginTime, endTime);
|
|
|
-
|
|
|
- if (healthscoresWind != null) {
|
|
|
- healthOverviewVO.setHealthscoresWindVO(healthscoresWind);
|
|
|
- }
|
|
|
- String year = String.valueOf(LocalDate.now().getYear());
|
|
|
- List<HealthOverviewListVO> overviewListVOS = healthscoresMapper.selectHealthOverviewList(year, fieldId, beginTime, endTime);
|
|
|
- healthOverviewVO.setHealthOverviewListVOList(overviewListVOS);
|
|
|
-
|
|
|
- return healthOverviewVO;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<HealthscoresTendencyVO> getLastDaysTrend(int day, String fieldId, String engineId) {
|
|
|
- // 1. 校验入参(非空)
|
|
|
- if (Objects.isNull(fieldId) || fieldId.isEmpty() || Objects.isNull(engineId) || engineId.isEmpty()) {
|
|
|
- throw new IllegalArgumentException("风场ID和风机ID不能为空");
|
|
|
- }
|
|
|
-
|
|
|
- // 1. 计算起止日期
|
|
|
- LocalDate[] range = getLastNDaysRange(day);
|
|
|
- LocalDate startDate = range[0];
|
|
|
- LocalDate endDate = range[1];
|
|
|
-
|
|
|
- // 3. 生成连续的365天日期序列(基础维度,确保每个日期都有记录)
|
|
|
- List<LocalDate> allDates = generateContinuousDates(startDate, endDate);
|
|
|
-
|
|
|
- // 4. 确定要查询的表名(按年份拆分,如healthscores_2025、healthscores_2026)
|
|
|
- List<String> tableNames = getValidTableNames(startDate, endDate);
|
|
|
-
|
|
|
- // 3. 跨表查询数据
|
|
|
- List<HealthscoresTendencyVO> hscoresLastays = healthscoresMapper.listHscoresLastays(fieldId, engineId, startDate, endDate, tableNames);
|
|
|
-
|
|
|
- // 6. 封装已有数据到Map(key=日期,value=评分数据,方便快速匹配)
|
|
|
- Map<LocalDate, HealthscoresTendencyVO> existDataMap = hscoresLastays.stream()
|
|
|
- .collect(Collectors.toMap(
|
|
|
- HealthscoresTendencyVO::getSourceDatetime,
|
|
|
- data -> data,
|
|
|
- (oldVal, newVal) -> oldVal
|
|
|
- ));
|
|
|
-
|
|
|
- // 7. 补0处理:遍历所有日期,缺失则新建(所有评分字段默认0)
|
|
|
- List<HealthscoresTendencyVO> finalResult = new ArrayList<>();
|
|
|
- for (LocalDate date : allDates) {
|
|
|
- HealthscoresTendencyVO score = existDataMap.getOrDefault(date, new HealthscoresTendencyVO(date));
|
|
|
- // 补全风场/风机ID(前端展示用)
|
|
|
- score.setFieldId(fieldId);
|
|
|
- score.setEngineId(engineId);
|
|
|
- finalResult.add(score);
|
|
|
- }
|
|
|
-
|
|
|
- return finalResult;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * ====================== 当前接口使用日期工具 ======================
|
|
|
- */
|
|
|
-
|
|
|
- /**
|
|
|
- * 给String类型的年月日拼接时分秒
|
|
|
- *
|
|
|
- * @param dateStr 年月日字符串(如 "2026-03-02")
|
|
|
- * @param hour 小时
|
|
|
- * @param minute 分钟
|
|
|
- * @param second 秒
|
|
|
- * @return 带时分秒的字符串(如 "2026-03-02 15:30:00")
|
|
|
- */
|
|
|
- private String appendTimeToString(String dateStr, int hour, int minute, int second) {
|
|
|
- // 1. 解析为LocalDate(校验日期合法性)
|
|
|
- LocalDate localDate = LocalDate.parse(dateStr, DATE_FORMATTER);
|
|
|
- // 2. 拼接时分秒为LocalDateTime
|
|
|
- LocalDateTime localDateTime = localDate.atTime(hour, minute, second);
|
|
|
- // 3. 格式化为字符串
|
|
|
- return localDateTime.format(DATETIME_FORMATTER);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 重载:获取昨天开始/结束时间的字符串格式
|
|
|
- */
|
|
|
- private String getYesterdayStartStr() {
|
|
|
- return getYesterdayStart().format(DATETIME_FORMATTER);
|
|
|
- }
|
|
|
-
|
|
|
- private String getYesterdayEndStr() {
|
|
|
- // 严格格式化为 23:59:59(去掉纳秒)
|
|
|
- return getYesterdayEnd().format(DATETIME_FORMATTER).substring(0, 19);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取昨天的开始时间(yyyy-MM-dd 00:00:00)
|
|
|
- *
|
|
|
- * @return LocalDateTime
|
|
|
- */
|
|
|
- private LocalDateTime getYesterdayStart() {
|
|
|
- // 1. 获取昨天的日期
|
|
|
- LocalDate yesterday = LocalDate.now().minusDays(1);
|
|
|
- // 2. 拼接 00:00:00 等价于 yesterday.atTime(0, 0, 0)
|
|
|
- return yesterday.atStartOfDay();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取昨天的结束时间(yyyy-MM-dd 23:59:59)
|
|
|
- *
|
|
|
- * @return LocalDateTime
|
|
|
- */
|
|
|
- private LocalDateTime getYesterdayEnd() {
|
|
|
- LocalDate yesterday = LocalDate.now().minusDays(1);
|
|
|
- // 拼接 23:59:59
|
|
|
- return yesterday.atTime(23, 59, 59);
|
|
|
- // 若需严格的23:59:59,用:yesterday.atTime(23, 59, 59)
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取近 N 天的开始、结束日期
|
|
|
- * 参数days 为需要查几天的数据
|
|
|
- */
|
|
|
- private LocalDate[] getLastNDaysRange(int days) {
|
|
|
- LocalDate endDate = LocalDate.now().minusDays(1);
|
|
|
- LocalDate startDate = endDate.minusDays(days-1);
|
|
|
- return new LocalDate[]{startDate, endDate};
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取日期范围内涉及的所有年份(最多2个)
|
|
|
- */
|
|
|
- private Set<Integer> getYearSet(LocalDate start, LocalDate end) {
|
|
|
- return Stream.of(start.getYear(), end.getYear())
|
|
|
- .collect(Collectors.toSet());
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 生成连续的日期序列(Java8 Stream实现)
|
|
|
- */
|
|
|
- private List<LocalDate> generateContinuousDates(LocalDate start, LocalDate end) {
|
|
|
- long days = java.time.temporal.ChronoUnit.DAYS.between(start, end);
|
|
|
- return Stream.iterate(start, date -> date.plusDays(1))
|
|
|
- .limit(days + 1) // +1 包含结束日期
|
|
|
- .collect(Collectors.toList());
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取合法的表名列表(防SQL注入,仅允许healthscores_+4位数字)
|
|
|
- */
|
|
|
- private List<String> getValidTableNames(LocalDate start, LocalDate end) {
|
|
|
- Set<String> tableNames = new HashSet<>();
|
|
|
- String tablePrefix = "healthscores_";
|
|
|
-
|
|
|
- // 遍历日期范围的所有年份
|
|
|
- int startYear = start.getYear();
|
|
|
- int endYear = end.getYear();
|
|
|
- for (int year = startYear; year <= endYear; year++) {
|
|
|
- tableNames.add(tablePrefix + year);
|
|
|
- }
|
|
|
-
|
|
|
- // 严格校验表名格式(防SQL注入)
|
|
|
- tableNames.forEach(name -> {
|
|
|
- if (!name.matches("^healthscores_\\d{4}$")) {
|
|
|
- throw new IllegalArgumentException("非法表名:" + name + "(仅允许healthscores_四位数字格式)");
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- return new ArrayList<>(tableNames);
|
|
|
- }
|
|
|
-
|
|
|
-}
|