指标库:保存原子指标
This commit is contained in:
parent
bec249ced3
commit
0a682ac155
@ -53,4 +53,11 @@ public class TargetController {
|
||||
String result = targetService.getResult(params);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
@Operation(summary = "保存指标")
|
||||
@PostMapping("/saveTarget")
|
||||
public R<?> saveTarget(@RequestBody JSONObject params) {
|
||||
targetService.saveTarget(params);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ public class Monitor {
|
||||
* 目标值
|
||||
*/
|
||||
@TableField(value = "target")
|
||||
private String target;
|
||||
private Double target;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -1,13 +1,25 @@
|
||||
package iet.ustb.sf.service;
|
||||
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author hyy
|
||||
* @description 针对表【mbgk_target_data】的数据库操作Service
|
||||
* @createDate 2025-08-05 15:40:32
|
||||
*/
|
||||
* @author hyy
|
||||
* @description 针对表【mbgk_target_data】的数据库操作Service
|
||||
* @createDate 2025-08-05 15:40:32
|
||||
*/
|
||||
public interface TargetDataService extends IService<TargetData> {
|
||||
|
||||
/**
|
||||
* 更新历史数据
|
||||
*
|
||||
* @param target 指标
|
||||
* @param strArr xShow, cycle, setDate, start, end
|
||||
* @param map 关联的指标数据
|
||||
* @return 结果
|
||||
*/
|
||||
TargetData updateHistory(Target target, String[] strArr, Map<String, TargetData> map);
|
||||
}
|
||||
|
@ -19,4 +19,6 @@ public interface TargetService extends IService<Target> {
|
||||
List<String> searchColumn(JSONObject params);
|
||||
|
||||
String getResult(JSONObject params);
|
||||
|
||||
void saveTarget(JSONObject params);
|
||||
}
|
||||
|
54
src/main/java/iet/ustb/sf/service/UtilService.java
Normal file
54
src/main/java/iet/ustb/sf/service/UtilService.java
Normal file
@ -0,0 +1,54 @@
|
||||
package iet.ustb.sf.service;
|
||||
|
||||
import iet.ustb.sf.domain.Monitor;
|
||||
import iet.ustb.sf.domain.Rule;
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* UtilService
|
||||
*
|
||||
* @author huangge1199
|
||||
* @since 2025/8/7 15:11:03
|
||||
*/
|
||||
public interface UtilService {
|
||||
|
||||
/**
|
||||
* 获取指定周期的对应日期 xShow, cycle, setDate, start, end
|
||||
*
|
||||
* @param date 日期
|
||||
* @param cycle 周期
|
||||
* @return 结果
|
||||
*/
|
||||
String[] getCurrentCycleDataByCycle(Date date, String cycle);
|
||||
|
||||
/**
|
||||
* 计算表达式结果
|
||||
*
|
||||
* @param expression 表达式
|
||||
* @return 结果
|
||||
*/
|
||||
double getEvalResult(String expression);
|
||||
|
||||
/**
|
||||
* 该规则是否触发
|
||||
*
|
||||
* @param rule 规则信息
|
||||
* @param target 指标信息
|
||||
* @param targetData 指标数据
|
||||
* @return 结果
|
||||
*/
|
||||
boolean isWarn(Rule rule, Target target, TargetData targetData);
|
||||
|
||||
/**
|
||||
* 获取初始化监控数据
|
||||
*
|
||||
* @param targetData 指标数据
|
||||
* @param target 指标信息
|
||||
* @param rule 规则信息
|
||||
* @return 结果
|
||||
*/
|
||||
Monitor getInitMonitor(TargetData targetData, Target target, Rule rule);
|
||||
}
|
@ -1,20 +1,171 @@
|
||||
package iet.ustb.sf.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
|
||||
import iet.ustb.sf.domain.*;
|
||||
import iet.ustb.sf.mapper.MonitorMapper;
|
||||
import iet.ustb.sf.mapper.RuleMapper;
|
||||
import iet.ustb.sf.mapper.TargetMapper;
|
||||
import iet.ustb.sf.service.TargetDataService;
|
||||
import iet.ustb.sf.mapper.TargetDataMapper;
|
||||
import iet.ustb.sf.service.UtilService;
|
||||
import iet.ustb.sf.util.CheckUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author hyy
|
||||
* @description 针对表【mbgk_target_data】的数据库操作Service实现
|
||||
* @createDate 2025-08-05 15:40:32
|
||||
*/
|
||||
* @author hyy
|
||||
* @description 针对表【mbgk_target_data】的数据库操作Service实现
|
||||
* @createDate 2025-08-05 15:40:32
|
||||
*/
|
||||
@Service
|
||||
public class TargetDataServiceImpl extends ServiceImpl<TargetDataMapper, TargetData>
|
||||
implements TargetDataService{
|
||||
implements TargetDataService {
|
||||
|
||||
@Resource
|
||||
private TargetDataMapper targetDataMapper;
|
||||
|
||||
@Resource
|
||||
private TargetMapper targetMapper;
|
||||
|
||||
@Resource
|
||||
private UtilService utilService;
|
||||
|
||||
@Resource
|
||||
private MonitorMapper monitorMapper;
|
||||
|
||||
@Resource
|
||||
private RuleMapper ruleMapper;
|
||||
|
||||
@Override
|
||||
public TargetData updateHistory(Target target, String[] strArr, Map<String, TargetData> map) {
|
||||
String xShow = strArr[0];
|
||||
QueryWrapper<TargetData> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("target_id", target.getId());
|
||||
queryWrapper.eq("x_show", xShow);
|
||||
TargetData targetData = targetDataMapper.selectOne(queryWrapper);
|
||||
if (targetData != null && targetData.getId() != null) {
|
||||
return targetData;
|
||||
}
|
||||
double result;
|
||||
if (target.getType() < 2) {
|
||||
List<Map<String, Object>> list = SqlRunner.db().selectList(target.getResultSql(), strArr[3], strArr[4]);
|
||||
result = Double.parseDouble(list.get(0).get("result").toString());
|
||||
} else {
|
||||
String exprStr = target.getResultSql();
|
||||
String[] expressionList = exprStr.split(",");
|
||||
List<String> opList = Arrays.asList("+", "-", "*", "/", "(", ")");
|
||||
List<String> idList = new ArrayList<>();
|
||||
for (String expression : expressionList) {
|
||||
if (!opList.contains(expression) && !idList.contains(expression)) {
|
||||
idList.add(expression);
|
||||
}
|
||||
}
|
||||
List<Target> targetList = targetMapper.selectByIds(idList);
|
||||
exprStr = exprStr.replaceAll(",", "");
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
for (Target child : targetList) {
|
||||
double val;
|
||||
if (map.containsKey(child.getId())) {
|
||||
val = map.get(child.getId()).getVal();
|
||||
} else {
|
||||
TargetData tmp = updateHistory(child, strArr, map);
|
||||
map.put(child.getId(), tmp);
|
||||
val = tmp.getVal();
|
||||
}
|
||||
exprStr = exprStr.replaceAll(child.getId(), val + "");
|
||||
}
|
||||
result = utilService.getEvalResult(exprStr);
|
||||
}
|
||||
|
||||
Date now = new Date();
|
||||
try {
|
||||
targetData = TargetData.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.targetId(target.getId())
|
||||
.setDate(new SimpleDateFormat("yyyy-MM-dd").parse(strArr[2]))
|
||||
.xShow(xShow)
|
||||
.cycle(strArr[1])
|
||||
.createTime(now)
|
||||
.updateTime(now)
|
||||
.val(CheckUtils.roundToDecimalPlaces(result, 6))
|
||||
.targetCycle(target.getCycle())
|
||||
.build();
|
||||
targetDataMapper.insert(targetData);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
saveMonitor(targetData);
|
||||
return targetData;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新的指标数据添加监控数据
|
||||
*
|
||||
* @param targetData 指标数据
|
||||
*/
|
||||
public void saveMonitor(TargetData targetData) {
|
||||
double val = targetData.getVal();
|
||||
String targetId = targetData.getTargetId();
|
||||
|
||||
Target target = targetMapper.selectById(targetId);
|
||||
Date now = new Date();
|
||||
|
||||
QueryWrapper<Monitor> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("target_id", target.getId());
|
||||
queryWrapper.eq("x_show", targetData.getXShow());
|
||||
monitorMapper.delete(queryWrapper);
|
||||
|
||||
Monitor monitor = Monitor.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.targetId(targetId)
|
||||
.name(target.getName())
|
||||
.type(target.getType())
|
||||
.topic(target.getTopic())
|
||||
.organization(target.getOrganization())
|
||||
.level(target.getLevel())
|
||||
.unit(target.getUnit())
|
||||
.val(val)
|
||||
.warnLevel(999)
|
||||
.setDate(targetData.getSetDate())
|
||||
.xShow(targetData.getXShow())
|
||||
.createTime(now)
|
||||
.updateTime(now)
|
||||
.build();
|
||||
|
||||
List<Rule> ruleList = ruleMapper.selectList(new QueryWrapper<Rule>().eq("target_id", target.getId()));
|
||||
if (ruleList == null || ruleList.isEmpty()) {
|
||||
monitorMapper.insert(monitor);
|
||||
return;
|
||||
}
|
||||
|
||||
List<Monitor> monitorList = new ArrayList<>();
|
||||
monitorList.add(monitor);
|
||||
|
||||
boolean bl = false;
|
||||
Rule oneRule = null;
|
||||
for (Rule rule : ruleList) {
|
||||
if (oneRule == null || oneRule.getWarnLevel() > rule.getWarnLevel()) {
|
||||
oneRule = rule;
|
||||
}
|
||||
bl = utilService.isWarn(rule, target, targetData);
|
||||
if (bl) {
|
||||
monitorList.add(utilService.getInitMonitor(targetData, target, rule));
|
||||
}
|
||||
}
|
||||
if (!bl) {
|
||||
Monitor mbgkMonitor = utilService.getInitMonitor(targetData, target, oneRule);
|
||||
mbgkMonitor.setWarnLevel(998);
|
||||
monitorList.add(mbgkMonitor);
|
||||
}
|
||||
monitorMapper.insert(monitorList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package iet.ustb.sf.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
@ -9,21 +8,22 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
|
||||
import iet.ustb.sf.domain.Category;
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
import iet.ustb.sf.domain.TargetOption;
|
||||
import iet.ustb.sf.exception.ErrorCode;
|
||||
import iet.ustb.sf.exception.ThrowUtils;
|
||||
import iet.ustb.sf.mapper.CategoryMapper;
|
||||
import iet.ustb.sf.mapper.TargetDataMapper;
|
||||
import iet.ustb.sf.service.TargetDataService;
|
||||
import iet.ustb.sf.service.TargetService;
|
||||
import iet.ustb.sf.mapper.TargetMapper;
|
||||
import iet.ustb.sf.service.UtilService;
|
||||
import iet.ustb.sf.util.CheckUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.val;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -42,6 +42,15 @@ public class TargetServiceImpl extends ServiceImpl<TargetMapper, Target>
|
||||
@Resource
|
||||
private CategoryMapper categoryMapper;
|
||||
|
||||
@Resource
|
||||
private TargetDataMapper targetDataMapper;
|
||||
|
||||
@Resource
|
||||
private TargetDataService targetDataService;
|
||||
|
||||
@Resource
|
||||
private UtilService utilService;
|
||||
|
||||
@Override
|
||||
public IPage<Target> getTargetsByCategory(JSONObject params) {
|
||||
int pageIndex = Optional.ofNullable(params.getInteger("pageIndex")).orElse(1);
|
||||
@ -94,6 +103,178 @@ public class TargetServiceImpl extends ServiceImpl<TargetMapper, Target>
|
||||
return list.get(0).get(result.getColumnName()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void saveTarget(JSONObject params) {
|
||||
Target target = params.getJSONObject("target").toJavaObject(Target.class);
|
||||
List<TargetOption> showList = params.getJSONArray("show").toJavaList(TargetOption.class);
|
||||
List<TargetOption> searchList = params.getJSONArray("search").toJavaList(TargetOption.class);
|
||||
TargetOption result = params.getJSONObject("result").toJavaObject(TargetOption.class);
|
||||
|
||||
checkTarget(target);
|
||||
String columns = showList.stream().map(TargetOption::getColumnName).collect(Collectors.joining(","));
|
||||
CheckUtils.checkColumns(columns, target.getTableName());
|
||||
CheckUtils.checkSearchOption(searchList, target.getTableName());
|
||||
CheckUtils.checkResultOption(result, target.getTableName());
|
||||
|
||||
Date now = new Date();
|
||||
target.setSearchSql(getSearchSql(showList, searchList, target.getTableName()));
|
||||
params.put("tableName", target.getTableName());
|
||||
target.setResultSql(getResultSql(params));
|
||||
target.setUpdateTime(now);
|
||||
|
||||
Map<String, List<TargetOption>> optionsMap = showList.stream()
|
||||
.peek(option -> {
|
||||
option.setTargetId(target.getId());
|
||||
if (option.getCreateTime() == null) {
|
||||
option.setCreateTime(now);
|
||||
}
|
||||
option.setUpdateTime(now);
|
||||
})
|
||||
.collect(Collectors.groupingBy(TargetOption::getColumnName));
|
||||
|
||||
String cycle = null;
|
||||
for (TargetOption option : searchList) {
|
||||
List<TargetOption> options = optionsMap.get(option.getColumnName());
|
||||
if (options != null && !options.isEmpty()) {
|
||||
TargetOption ori = options.get(0);
|
||||
ori.setOp(ori.getOp() + "," + option.getOp());
|
||||
ori.setFun(option.getFun());
|
||||
ori.setVal(option.getVal());
|
||||
if ("1".equals(option.getOp()) && option.getType() == 1) {
|
||||
if (cycle == null) {
|
||||
cycle = option.getFun();
|
||||
continue;
|
||||
}
|
||||
ThrowUtils.throwIf(!cycle.equals(option.getFun()), ErrorCode.PARAMS_ERROR, "日期类型的周期不一致!");
|
||||
}
|
||||
}
|
||||
}
|
||||
ThrowUtils.throwIf(StringUtils.isEmpty(cycle), ErrorCode.PARAMS_ERROR, "缺少时间条件,无法保存!");
|
||||
target.setCycle(cycle);
|
||||
|
||||
if (target.getId() == null) {
|
||||
target.setId(UUID.randomUUID().toString());
|
||||
target.setCreateTime(now);
|
||||
if (!StringUtils.isEmpty(target.getCategoryId())) {
|
||||
categoryDeal(null, target);
|
||||
}
|
||||
targetMapper.insert(target);
|
||||
saveDate(target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指标变动后,指标数据处理
|
||||
*
|
||||
* @param target 指标
|
||||
*/
|
||||
private void saveDate(Target target) {
|
||||
targetDataMapper.delete(new QueryWrapper<TargetData>().eq("target_id", target.getId()));
|
||||
String[] strArr = utilService.getCurrentCycleDataByCycle(new Date(), target.getCycle());
|
||||
targetDataService.updateHistory(target, strArr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指标变动,处理对应的分类
|
||||
*
|
||||
* @param oldTarget 旧指标
|
||||
* @param newTarget 新指标
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void categoryDeal(Target oldTarget, Target newTarget) {
|
||||
if (oldTarget == null && newTarget == null) {
|
||||
return;
|
||||
}
|
||||
Set<String> oldList = oldTarget == null ? new HashSet<>() : getOrganizationList(oldTarget.getOrganization());
|
||||
Set<String> newList = newTarget == null ? new HashSet<>() : getOrganizationList(newTarget.getOrganization());
|
||||
|
||||
String tagetId = oldTarget == null ? newTarget.getId() : oldTarget.getId();
|
||||
String categoryId = oldTarget == null ? newTarget.getCategoryId() : oldTarget.getCategoryId();
|
||||
QueryWrapper<Target> query = new QueryWrapper<>();
|
||||
query.eq("category_id", categoryId);
|
||||
query.ne("id", tagetId);
|
||||
List<Target> targetList = targetMapper.selectList(query);
|
||||
Set<String> set = new HashSet<>();
|
||||
for (Target target : targetList) {
|
||||
set.addAll(getOrganizationList(target.getOrganization()));
|
||||
}
|
||||
|
||||
Category category = categoryMapper.selectById(categoryId);
|
||||
Set<String> organizationSet = getOrganizationList(category.getOrganization());
|
||||
|
||||
Iterator<String> iterator = newList.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
String news = iterator.next();
|
||||
if (!oldList.isEmpty() && oldList.contains(news)) {
|
||||
oldList.remove(news);
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
if (!set.contains(news)) {
|
||||
organizationSet.add(news);
|
||||
}
|
||||
}
|
||||
for (String old : oldList) {
|
||||
if (!set.contains(old)) {
|
||||
organizationSet.remove(old);
|
||||
}
|
||||
}
|
||||
category.setOrganization(String.join(",", organizationSet));
|
||||
categoryMapper.insertOrUpdate(category);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把用逗号拼接的组织字符串转为set集合
|
||||
*
|
||||
* @param organization 组织字符串
|
||||
* @return set组织集合
|
||||
*/
|
||||
private Set<String> getOrganizationList(String organization) {
|
||||
Set<String> set = new HashSet<>();
|
||||
if (StringUtils.isEmpty(organization)) {
|
||||
return set;
|
||||
}
|
||||
if (organization.contains(",")) {
|
||||
set.addAll(Arrays.asList(organization.split(",")));
|
||||
} else {
|
||||
set.add(organization);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接列表查询SQL
|
||||
*
|
||||
* @param showList 查询集合
|
||||
* @param searchList 条件集合
|
||||
* @param tableName 表名
|
||||
* @return SQL
|
||||
*/
|
||||
private String getSearchSql(List<TargetOption> showList, List<TargetOption> searchList, String tableName) {
|
||||
return "SELECT " + showList.stream().map(TargetOption::getColumnName).collect(Collectors.joining(","))
|
||||
+ " FROM " + tableName + " WHERE " + getWhereSql(searchList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 指标空值校验
|
||||
*
|
||||
* @param target 指标
|
||||
*/
|
||||
private void checkTarget(Target target) {
|
||||
CheckUtils.checkEmpty(target.getName(), "指标名称");
|
||||
QueryWrapper<Target> query = new QueryWrapper<>();
|
||||
query.eq("name", target.getName());
|
||||
Target nameCheck = targetMapper.selectOne(query);
|
||||
boolean bl = nameCheck != null && (target.getId() == null || !nameCheck.getId().equals(target.getId()));
|
||||
ThrowUtils.throwIf(bl, ErrorCode.PARAMS_ERROR, "指标名称不能重复!");
|
||||
CheckUtils.checkEmpty(String.valueOf(target.getType()), "类型");
|
||||
CheckUtils.checkEmpty(String.valueOf(target.getIsKey()), "是否启用");
|
||||
CheckUtils.checkEmpty(target.getOrganization(), "组织");
|
||||
CheckUtils.checkEmpty(target.getTopic(), "主题");
|
||||
CheckUtils.checkTableName(target.getTableName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 拼接结果sql
|
||||
*
|
||||
@ -107,8 +288,8 @@ public class TargetServiceImpl extends ServiceImpl<TargetMapper, Target>
|
||||
CheckUtils.checkSearchOption(searchList, tableName);
|
||||
TargetOption result = params.getJSONObject("result").toJavaObject(TargetOption.class);
|
||||
CheckUtils.checkResultOption(result, tableName);
|
||||
return "SELECT ROUND(" + result.getFun() + "(CAST(" + result.getColumnName() + " AS DOUBLE)), 6) AS " +
|
||||
result.getColumnName() + " FROM " + tableName + " WHERE " + getWhereSql(searchList);
|
||||
return "SELECT ROUND(" + result.getFun() + "(CAST(" + result.getColumnName() + " AS DOUBLE)), 6) AS result " +
|
||||
"FROM " + tableName + " WHERE " + getWhereSql(searchList);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -122,66 +303,8 @@ public class TargetServiceImpl extends ServiceImpl<TargetMapper, Target>
|
||||
for (TargetOption option : searchList) {
|
||||
int type = option.getType();
|
||||
if (type == 1) {
|
||||
String start, end;
|
||||
LocalDate day = LocalDate.now();
|
||||
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
switch (option.getFun()) {
|
||||
case "yesterday":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(1).format(dtf);
|
||||
break;
|
||||
case "week":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(1).with(DayOfWeek.MONDAY).format(dtf);
|
||||
break;
|
||||
case "lastWeek":
|
||||
day = day.minusDays(1).with(DayOfWeek.MONDAY);
|
||||
start = day.minusDays(7).format(dtf);
|
||||
end = day.format(dtf);
|
||||
break;
|
||||
case "nearlyWeek":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(7).format(dtf);
|
||||
break;
|
||||
case "month":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(1).withDayOfMonth(1).format(dtf);
|
||||
break;
|
||||
case "lastMonth":
|
||||
day = day.withDayOfMonth(1);
|
||||
end = day.format(dtf);
|
||||
start = day.minusMonths(1).format(dtf);
|
||||
break;
|
||||
case "nearlyMonth":
|
||||
end = day.format(dtf);
|
||||
start = day.minusDays(30).format(dtf);
|
||||
break;
|
||||
case "product":
|
||||
end = day.format(dtf);
|
||||
day = day.minusDays(1);
|
||||
if (day.getDayOfMonth() < 26) {
|
||||
start = day.minusMonths(1).withDayOfMonth(26).format(dtf);
|
||||
} else {
|
||||
start = day.withDayOfMonth(26).format(dtf);
|
||||
}
|
||||
break;
|
||||
case "lastProduct":
|
||||
day = day.minusDays(1);
|
||||
if (day.getDayOfMonth() < 26) {
|
||||
day = day.minusMonths(1).withDayOfMonth(26);
|
||||
} else {
|
||||
day = day.withDayOfMonth(26);
|
||||
}
|
||||
end = day.format(dtf);
|
||||
start = day.minusMonths(1).format(dtf);
|
||||
break;
|
||||
default:
|
||||
start = "";
|
||||
end = "";
|
||||
break;
|
||||
}
|
||||
sql.append(option.getColumnName()).append(" >= '").append(start).append("' and ")
|
||||
.append(option.getColumnName()).append(" < '").append(end).append("' and ");
|
||||
sql.append(option.getColumnName()).append(" >= {0} and ")
|
||||
.append(option.getColumnName()).append(" < {1} and ");
|
||||
} else if (type == 2) {
|
||||
sql.append(getIsNullSql(option));
|
||||
} else {
|
||||
|
337
src/main/java/iet/ustb/sf/service/impl/UtilServiceImpl.java
Normal file
337
src/main/java/iet/ustb/sf/service/impl/UtilServiceImpl.java
Normal file
@ -0,0 +1,337 @@
|
||||
package iet.ustb.sf.service.impl;
|
||||
|
||||
import iet.ustb.sf.domain.Monitor;
|
||||
import iet.ustb.sf.domain.Rule;
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
import iet.ustb.sf.exception.ErrorCode;
|
||||
import iet.ustb.sf.exception.MyException;
|
||||
import iet.ustb.sf.service.UtilService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* UtilServiceImpl
|
||||
*
|
||||
* @author huangge1199
|
||||
* @since 2025/8/7 15:11:27
|
||||
*/
|
||||
@Service
|
||||
public class UtilServiceImpl implements UtilService {
|
||||
|
||||
@Override
|
||||
public String[] getCurrentCycleDataByCycle(Date date, String cycle) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.setTime(date);
|
||||
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
||||
calendar.set(Calendar.MINUTE, 0);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||
String xShow, showCycle, setDate, start, end;
|
||||
end = sdf.format(calendar.getTime());
|
||||
|
||||
switch (cycle) {
|
||||
case "yesterday":
|
||||
calendar.add(Calendar.DATE, -1);
|
||||
xShow = sdf.format(calendar.getTime());
|
||||
showCycle = "day";
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
break;
|
||||
case "nearlyWeek":
|
||||
calendar.add(Calendar.DATE, -1);
|
||||
xShow = sdf.format(calendar.getTime());
|
||||
showCycle = "day";
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
calendar.add(Calendar.DATE, -6);
|
||||
start = sdf.format(calendar.getTime());
|
||||
break;
|
||||
case "nearlyMonth":
|
||||
calendar.add(Calendar.DATE, -1);
|
||||
xShow = sdf.format(calendar.getTime());
|
||||
showCycle = "day";
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
calendar.add(Calendar.DATE, -29);
|
||||
start = sdf.format(calendar.getTime());
|
||||
break;
|
||||
case "week":
|
||||
case "lastWeek":
|
||||
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) {
|
||||
calendar.add(Calendar.DATE, -7);
|
||||
} else {
|
||||
if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
|
||||
calendar.add(Calendar.DATE, -7);
|
||||
}
|
||||
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
|
||||
if ("lastWeek".equals(cycle)) {
|
||||
end = sdf.format(calendar.getTime());
|
||||
calendar.add(Calendar.DATE, -7);
|
||||
}
|
||||
}
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
if (calendar.get(Calendar.WEEK_OF_YEAR) == 1) {
|
||||
calendar.add(Calendar.YEAR, 1);
|
||||
}
|
||||
xShow = calendar.get(Calendar.YEAR) + "-" + String.format("%02d", calendar.get(Calendar.WEEK_OF_YEAR));
|
||||
showCycle = "week";
|
||||
break;
|
||||
case "month":
|
||||
case "lastMonth":
|
||||
if (calendar.get(Calendar.DAY_OF_MONTH) == 1) {
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
xShow = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
} else {
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
||||
if ("lastMonth".equals(cycle)) {
|
||||
end = sdf.format(calendar.getTime());
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
}
|
||||
xShow = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
}
|
||||
showCycle = "month";
|
||||
break;
|
||||
case "product":
|
||||
if (calendar.get(Calendar.DAY_OF_MONTH) <= 26) {
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 26);
|
||||
xShow = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
} else {
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 26);
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
calendar.add(Calendar.MONTH, 1);
|
||||
xShow = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
|
||||
}
|
||||
showCycle = "product";
|
||||
break;
|
||||
case "lastProduct":
|
||||
if (calendar.get(Calendar.DAY_OF_MONTH) < 26) {
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
}
|
||||
calendar.set(Calendar.DAY_OF_MONTH, 26);
|
||||
xShow = new SimpleDateFormat("yyyy-MM").format(calendar.getTime());
|
||||
end = sdf.format(calendar.getTime());
|
||||
calendar.add(Calendar.MONTH, -1);
|
||||
setDate = sdf.format(calendar.getTime());
|
||||
start = sdf.format(calendar.getTime());
|
||||
showCycle = "product";
|
||||
break;
|
||||
default:
|
||||
xShow = null;
|
||||
showCycle = null;
|
||||
setDate = null;
|
||||
start = null;
|
||||
end = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return new String[]{xShow, showCycle, setDate, start, end};
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEvalResult(String expression) {
|
||||
expression = replaceFunction(expression, "SUM", this::sum);
|
||||
expression = replaceFunction(expression, "AVG", this::avg);
|
||||
expression = replaceFunction(expression, "MIN", this::min);
|
||||
expression = replaceFunction(expression, "MAX", this::max);
|
||||
expression = replaceFunction(expression, "COUNT", this::count);
|
||||
expression = replaceFunction(expression, "MEDIAN", this::median);
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName("javascript");
|
||||
double result;
|
||||
try {
|
||||
result = Double.parseDouble(engine.eval(expression).toString());
|
||||
} catch (ScriptException e) {
|
||||
throw new MyException(ErrorCode.SYSTEM_ERROR, "表达式错误");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWarn(Rule rule, Target target, TargetData targetData) {
|
||||
double targetVal = rule.getTarget();
|
||||
double val = targetData.getVal();
|
||||
double rate = rule.getRate();
|
||||
switch (rule.getOp()) {
|
||||
case ">":
|
||||
if (val > targetVal + targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "<":
|
||||
if (val < targetVal - targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ">=":
|
||||
if (val >= targetVal + targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "<=":
|
||||
if (val <= targetVal - targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "=":
|
||||
if (val == targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "!=":
|
||||
if (val != targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case "between":
|
||||
if (val > targetVal - targetVal * rate && val < targetVal + targetVal * rate) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Monitor getInitMonitor(TargetData targetData, Target target, Rule rule) {
|
||||
Date now = new Date();
|
||||
return Monitor.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.targetId(targetData.getTargetId())
|
||||
.ruleId(rule.getId())
|
||||
.name(target.getName())
|
||||
.type(target.getType())
|
||||
.topic(target.getTopic())
|
||||
.organization(target.getOrganization())
|
||||
.level(target.getLevel())
|
||||
.cycle(rule.getCycle())
|
||||
.unit(target.getUnit())
|
||||
.target(rule.getTarget())
|
||||
.val(targetData.getVal())
|
||||
.warnLevel(rule.getWarnLevel())
|
||||
.setDate(targetData.getSetDate())
|
||||
.xShow(targetData.getXShow())
|
||||
.createTime(now)
|
||||
.updateTime(now)
|
||||
.warnType(rule.getType())
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理函数方法
|
||||
*
|
||||
* @param expression 字符串表达式
|
||||
* @param functionName 方法名
|
||||
* @param function 计数方法的值
|
||||
* @return 结果
|
||||
*/
|
||||
private String replaceFunction(String expression, String functionName, Function<double[], Double> function) {
|
||||
Pattern pattern = Pattern.compile(functionName + "\\(([^)]+)\\)");
|
||||
Matcher matcher = pattern.matcher(expression);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (matcher.find()) {
|
||||
String numbers = matcher.group(1);
|
||||
double result = function.apply(parseNumbers(numbers));
|
||||
matcher.appendReplacement(sb, String.valueOf(result));
|
||||
}
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将以逗号分割的数字字符串转为数值数组
|
||||
*
|
||||
* @param numbers 以逗号分割的数字字符串
|
||||
* @return 结果
|
||||
*/
|
||||
private double[] parseNumbers(String numbers) {
|
||||
return Arrays.stream(numbers.split(",")).mapToDouble(Double::parseDouble).toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 求和
|
||||
*
|
||||
* @param numbers 数字集合
|
||||
* @return 结果
|
||||
*/
|
||||
private double sum(double[] numbers) {
|
||||
return Arrays.stream(numbers).sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* 平均值
|
||||
*
|
||||
* @param numbers 数字集合
|
||||
* @return 结果
|
||||
*/
|
||||
private double avg(double[] numbers) {
|
||||
return sum(numbers) / numbers.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 最小值
|
||||
*
|
||||
* @param numbers 数字集合
|
||||
* @return 结果
|
||||
*/
|
||||
private double min(double[] numbers) {
|
||||
return Arrays.stream(numbers).min().orElse(Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 最大值
|
||||
*
|
||||
* @param numbers 数字集合
|
||||
* @return 结果
|
||||
*/
|
||||
private double max(double[] numbers) {
|
||||
return Arrays.stream(numbers).max().orElse(Double.NaN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计数
|
||||
*
|
||||
* @param numbers 数字集合
|
||||
* @return 结果
|
||||
*/
|
||||
private double count(double[] numbers) {
|
||||
return numbers.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 中位数
|
||||
*
|
||||
* @param numbers 数字集合
|
||||
* @return 结果
|
||||
*/
|
||||
private double median(double[] numbers) {
|
||||
Arrays.sort(numbers);
|
||||
int length = numbers.length;
|
||||
if (length % 2 == 0) {
|
||||
return (numbers[length / 2 - 1] + numbers[length / 2]) / 2.0;
|
||||
} else {
|
||||
return numbers[length / 2];
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,8 @@ import iet.ustb.sf.exception.ThrowUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
@ -151,4 +153,17 @@ public class CheckUtils {
|
||||
ThrowUtils.throwIf(!funList.contains(fun), ErrorCode.PARAMS_ERROR, "方法错误!");
|
||||
checkColumns(option.getColumnName(), tableName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保留指定位小数
|
||||
*
|
||||
* @param value 传入值
|
||||
* @param round 保留位数
|
||||
* @return 结果值
|
||||
*/
|
||||
public static double roundToDecimalPlaces(Double value, int round) {
|
||||
BigDecimal bd = new BigDecimal(value);
|
||||
bd = bd.setScale(round, RoundingMode.HALF_UP);
|
||||
return bd.doubleValue();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user