| | |
| | | package cn.iocoder.yudao.module.bi.service.decision; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.module.bi.dal.dataobject.decision.BiKpiValueHistoryDO; |
| | | import cn.iocoder.yudao.module.bi.dal.mysql.decision.BiKpiDefinitionMapper; |
| | | import cn.iocoder.yudao.module.bi.dal.dataobject.decision.BiKpiDefinitionDO; |
| | | import cn.iocoder.yudao.module.bi.dal.mysql.decision.BiKpiValueHistoryMapper; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | |
| | | /** |
| | |
| | | |
| | | @Resource |
| | | private BiKpiDefinitionMapper kpiMapper; |
| | | |
| | | @Resource |
| | | private BiKpiValueHistoryMapper kpiValueHistoryMapper; |
| | | |
| | | @Resource |
| | | private JdbcTemplate jdbcTemplate; |
| | |
| | | return executeKpiSql(kpi.getQuerySql()); |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, Object> getKpiTrend(String kpiCode, LocalDateTime beginTime, |
| | | LocalDateTime endTime, String periodType) { |
| | | BiKpiDefinitionDO kpi = kpiMapper.selectOne(BiKpiDefinitionDO::getCode, kpiCode); |
| | | Map<String, Object> result = new LinkedHashMap<>(); |
| | | result.put("kpiCode", kpiCode); |
| | | result.put("kpiName", kpi != null ? kpi.getName() : kpiCode); |
| | | result.put("category", kpi != null ? kpi.getCategory() : null); |
| | | result.put("unit", kpi != null ? kpi.getUnit() : null); |
| | | result.put("periodType", periodType != null ? periodType : "hour"); |
| | | |
| | | if (kpi == null) { |
| | | result.put("points", Collections.emptyList()); |
| | | return result; |
| | | } |
| | | |
| | | LocalDateTime begin = beginTime != null ? beginTime : |
| | | LocalDateTime.now().minusDays(30); |
| | | LocalDateTime end = endTime != null ? endTime : LocalDateTime.now(); |
| | | List<BiKpiValueHistoryDO> history = kpiValueHistoryMapper |
| | | .selectByKpiCodeAndTimeRange(kpiCode, begin, end); |
| | | |
| | | List<Map<String, Object>> points = new ArrayList<>(); |
| | | for (BiKpiValueHistoryDO h : history) { |
| | | Map<String, Object> p = new LinkedHashMap<>(); |
| | | p.put("time", h.getSnapshotTime()); |
| | | p.put("value", h.getKpiValue()); |
| | | points.add(p); |
| | | } |
| | | result.put("points", points); |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public Map<String, Object> getKpiCompare(String kpiCode) { |
| | | BiKpiDefinitionDO kpi = kpiMapper.selectOne(BiKpiDefinitionDO::getCode, kpiCode); |
| | | Map<String, Object> result = new LinkedHashMap<>(); |
| | | result.put("kpiCode", kpiCode); |
| | | result.put("kpiName", kpi != null ? kpi.getName() : kpiCode); |
| | | result.put("unit", kpi != null ? kpi.getUnit() : null); |
| | | |
| | | // 取最近 24 条快照(按时间倒序),最近一条为当前值 |
| | | List<BiKpiValueHistoryDO> recent = kpiValueHistoryMapper.selectRecentByKpiCode(kpiCode, 24); |
| | | if (CollUtil.isEmpty(recent)) { |
| | | result.put("currentValue", null); |
| | | result.put("previousValue", null); |
| | | result.put("changeRate", null); |
| | | result.put("avgValue", null); |
| | | result.put("maxValue", null); |
| | | result.put("minValue", null); |
| | | return result; |
| | | } |
| | | |
| | | // recent 为倒序,第 0 条最新 |
| | | BiKpiValueHistoryDO current = recent.get(0); |
| | | result.put("currentTime", current.getSnapshotTime()); |
| | | result.put("currentValue", current.getKpiValue()); |
| | | |
| | | if (recent.size() > 1) { |
| | | BiKpiValueHistoryDO previous = recent.get(1); |
| | | result.put("previousTime", previous.getSnapshotTime()); |
| | | result.put("previousValue", previous.getKpiValue()); |
| | | result.put("changeRate", calcChangeRate(previous.getKpiValue(), current.getKpiValue())); |
| | | } else { |
| | | result.put("previousValue", null); |
| | | result.put("changeRate", null); |
| | | } |
| | | |
| | | // 近 24 期统计汇总 |
| | | BigDecimal sum = BigDecimal.ZERO; |
| | | BigDecimal max = null; |
| | | BigDecimal min = null; |
| | | for (BiKpiValueHistoryDO h : recent) { |
| | | if (h.getKpiValue() == null) { |
| | | continue; |
| | | } |
| | | sum = sum.add(h.getKpiValue()); |
| | | max = max == null ? h.getKpiValue() : h.getKpiValue().max(max); |
| | | min = min == null ? h.getKpiValue() : h.getKpiValue().min(min); |
| | | } |
| | | result.put("periodCount", recent.size()); |
| | | if (recent.size() > 0) { |
| | | result.put("avgValue", sum.divide(BigDecimal.valueOf(recent.size()), 4, RoundingMode.HALF_UP)); |
| | | } else { |
| | | result.put("avgValue", BigDecimal.ZERO); |
| | | } |
| | | result.put("maxValue", max); |
| | | result.put("minValue", min); |
| | | return result; |
| | | } |
| | | |
| | | private BigDecimal calcChangeRate(BigDecimal previous, BigDecimal current) { |
| | | if (previous == null || current == null || previous.compareTo(BigDecimal.ZERO) == 0) { |
| | | return null; |
| | | } |
| | | return current.subtract(previous).divide(previous, 4, RoundingMode.HALF_UP) |
| | | .multiply(new BigDecimal("100")).setScale(2, RoundingMode.HALF_UP); |
| | | } |
| | | |
| | | /** |
| | | * 执行 KPI 查询 SQL |
| | | */ |