package cn.iocoder.yudao.module.bi.service.decision;
|
|
import cn.iocoder.yudao.module.bi.dal.mysql.decision.BiKpiDefinitionMapper;
|
import cn.iocoder.yudao.module.bi.dal.dataobject.decision.BiKpiDefinitionDO;
|
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.util.*;
|
|
/**
|
* 决策支持 KPI 聚合 Service 实现
|
*
|
* 通过 JdbcTemplate 跨模块执行聚合 SQL
|
*
|
* @author 超级管理员
|
*/
|
@Slf4j
|
@Service
|
public class BiDecisionKpiServiceImpl implements BiDecisionKpiService {
|
|
@Resource
|
private BiKpiDefinitionMapper kpiMapper;
|
|
@Resource
|
private JdbcTemplate jdbcTemplate;
|
|
@Override
|
public Map<String, Object> getKpiOverview() {
|
List<BiKpiDefinitionDO> kpis = kpiMapper.selectList();
|
List<Map<String, Object>> items = new ArrayList<>();
|
|
for (BiKpiDefinitionDO kpi : kpis) {
|
Map<String, Object> item = new LinkedHashMap<>();
|
item.put("code", kpi.getCode());
|
item.put("name", kpi.getName());
|
item.put("category", kpi.getCategory());
|
item.put("unit", kpi.getUnit());
|
item.put("chartType", kpi.getChartType());
|
item.put("status", kpi.getStatus());
|
|
// 执行查询获取当前值
|
BigDecimal value = executeKpiSql(kpi.getQuerySql());
|
item.put("value", value);
|
|
// 判断预警状态
|
String alertStatus = evaluateAlertStatus(kpi, value);
|
item.put("alertStatus", alertStatus);
|
|
items.add(item);
|
}
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
result.put("kpis", items);
|
result.put("total", items.size());
|
return result;
|
}
|
|
@Override
|
public Map<String, Object> getKpiDetail(String kpiCode) {
|
BiKpiDefinitionDO kpi = kpiMapper.selectOne(BiKpiDefinitionDO::getCode, kpiCode);
|
if (kpi == null) {
|
return Collections.emptyMap();
|
}
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
result.put("code", kpi.getCode());
|
result.put("name", kpi.getName());
|
result.put("unit", kpi.getUnit());
|
result.put("category", kpi.getCategory());
|
result.put("value", executeKpiSql(kpi.getQuerySql()));
|
|
return result;
|
}
|
|
@Override
|
public Map<String, Object> getKpiByCategory(String category) {
|
List<BiKpiDefinitionDO> kpis = kpiMapper.selectList(
|
BiKpiDefinitionDO::getCategory, category);
|
List<Map<String, Object>> items = new ArrayList<>();
|
|
for (BiKpiDefinitionDO kpi : kpis) {
|
Map<String, Object> item = new LinkedHashMap<>();
|
item.put("code", kpi.getCode());
|
item.put("name", kpi.getName());
|
item.put("unit", kpi.getUnit());
|
item.put("value", executeKpiSql(kpi.getQuerySql()));
|
items.add(item);
|
}
|
|
Map<String, Object> result = new LinkedHashMap<>();
|
result.put("category", category);
|
result.put("kpis", items);
|
return result;
|
}
|
|
@Override
|
public BigDecimal refreshKpi(String kpiCode) {
|
BiKpiDefinitionDO kpi = kpiMapper.selectOne(BiKpiDefinitionDO::getCode, kpiCode);
|
if (kpi == null) {
|
return BigDecimal.ZERO;
|
}
|
return executeKpiSql(kpi.getQuerySql());
|
}
|
|
/**
|
* 执行 KPI 查询 SQL
|
*/
|
private BigDecimal executeKpiSql(String querySql) {
|
if (querySql == null || querySql.isBlank()) {
|
return BigDecimal.ZERO;
|
}
|
try {
|
List<Map<String, Object>> result = jdbcTemplate.queryForList(querySql);
|
if (result.isEmpty()) {
|
return BigDecimal.ZERO;
|
}
|
// 取第一行第一列的值
|
Map<String, Object> row = result.get(0);
|
Object value = row.values().iterator().next();
|
if (value instanceof Number) {
|
return BigDecimal.valueOf(((Number) value).doubleValue());
|
}
|
return BigDecimal.ZERO;
|
} catch (Exception e) {
|
log.error("[executeKpiSql][SQL执行失败] {}", querySql, e);
|
return BigDecimal.ZERO;
|
}
|
}
|
|
/**
|
* 评估预警状态
|
*/
|
private String evaluateAlertStatus(BiKpiDefinitionDO kpi, BigDecimal value) {
|
if (kpi.getThresholdCritical() != null) {
|
int cmp = value.compareTo(kpi.getThresholdCritical());
|
boolean triggered = ">".equals(kpi.getComparisonOperator()) ? cmp > 0
|
: "<".equals(kpi.getComparisonOperator()) ? cmp < 0
|
: ">=".equals(kpi.getComparisonOperator()) ? cmp >= 0
|
: "<=".equals(kpi.getComparisonOperator()) ? cmp <= 0 : false;
|
if (triggered) {
|
return "critical";
|
}
|
}
|
if (kpi.getThresholdWarn() != null) {
|
int cmp = value.compareTo(kpi.getThresholdWarn());
|
boolean triggered = ">".equals(kpi.getComparisonOperator()) ? cmp > 0
|
: "<".equals(kpi.getComparisonOperator()) ? cmp < 0
|
: ">=".equals(kpi.getComparisonOperator()) ? cmp >= 0
|
: "<=".equals(kpi.getComparisonOperator()) ? cmp <= 0 : false;
|
if (triggered) {
|
return "warn";
|
}
|
}
|
return "normal";
|
}
|
|
}
|