目标策划:获取指标参考数据
This commit is contained in:
parent
ece954b468
commit
4eb6562caa
@ -0,0 +1,36 @@
|
||||
package iet.ustb.sf.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import iet.ustb.sf.common.R;
|
||||
import iet.ustb.sf.service.TargetDataService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* TargetDataController
|
||||
*
|
||||
* @author huangge1199
|
||||
* @since 2025/8/12 9:19:23
|
||||
*/
|
||||
@Tag(name = "目标管控-指标监测")
|
||||
@RestController
|
||||
@RequestMapping("/mbgk/data")
|
||||
public class TargetDataController {
|
||||
|
||||
@Resource
|
||||
private TargetDataService targetDataService;
|
||||
|
||||
@Operation(summary = "获取指标参考数据")
|
||||
@PostMapping("/getExamleData")
|
||||
public R<Map<String, Object>> getExamleData(@RequestBody JSONObject params) {
|
||||
return R.ok(targetDataService.getData(params, 1));
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package iet.ustb.sf.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
@ -25,4 +26,6 @@ public interface TargetDataService extends IService<TargetData> {
|
||||
TargetData updateHistory(Target target, String[] strArr, Map<String, TargetData> map);
|
||||
|
||||
void saveTargetDate(Date date);
|
||||
|
||||
Map<String, Object> getData(JSONObject params, int type);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import iet.ustb.sf.domain.Rule;
|
||||
import iet.ustb.sf.domain.Target;
|
||||
import iet.ustb.sf.domain.TargetData;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
@ -25,6 +26,14 @@ public interface UtilService {
|
||||
*/
|
||||
String[] getCurrentCycleDataByCycle(Date date, String cycle);
|
||||
|
||||
/**
|
||||
* 获取日期所在的年-周
|
||||
*
|
||||
* @param date 日期
|
||||
* @return 结果
|
||||
*/
|
||||
String getYearWeek(LocalDate date);
|
||||
|
||||
/**
|
||||
* 计算表达式结果
|
||||
*
|
||||
|
@ -1,22 +1,30 @@
|
||||
package iet.ustb.sf.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.baomidou.mybatisplus.extension.toolkit.SqlRunner;
|
||||
import iet.ustb.sf.domain.*;
|
||||
import iet.ustb.sf.exception.ErrorCode;
|
||||
import iet.ustb.sf.exception.MyException;
|
||||
import iet.ustb.sf.mapper.*;
|
||||
import iet.ustb.sf.service.TargetDataService;
|
||||
import iet.ustb.sf.service.UtilService;
|
||||
import iet.ustb.sf.util.CheckUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -54,7 +62,7 @@ public class TargetDataServiceImpl extends ServiceImpl<TargetDataMapper, TargetD
|
||||
Date now = new Date();
|
||||
|
||||
Map<String, String[]> map = utilService.getCurrentCycleData(date);
|
||||
LocalDate day = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
LocalDate day = date.toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();
|
||||
for (String cycle : map.keySet()) {
|
||||
if (day.getDayOfWeek().getValue() > 1 && "lastWeek".equals(cycle)) {
|
||||
continue;
|
||||
@ -129,6 +137,309 @@ public class TargetDataServiceImpl extends ServiceImpl<TargetDataMapper, TargetD
|
||||
System.out.println("定时保存指标数据 end:" + endTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getData(JSONObject params, int type) {
|
||||
String targetId = params.getString("id");
|
||||
String start = params.getString("start");
|
||||
String end = params.getString("end");
|
||||
Integer n = params.getInteger("n");
|
||||
CheckUtils.checkEmpty(targetId, "指标ID");
|
||||
Target target = targetMapper.selectById(targetId);
|
||||
|
||||
if (n == null) {
|
||||
n = 7;
|
||||
}
|
||||
|
||||
if (StringUtils.isEmpty(start) && StringUtils.isEmpty(end)) {
|
||||
Map<String, String> cycleDate = getCycleData(target.getCycle(), n);
|
||||
start = cycleDate.get("start");
|
||||
end = cycleDate.get("end");
|
||||
} else if (!StringUtils.isEmpty(start) && !StringUtils.isEmpty(end)) {
|
||||
try {
|
||||
String[] strArrStart = getDataBySetDateAndCycle(LocalDate.parse(start), target.getCycle());
|
||||
start = strArrStart[3];
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new MyException(ErrorCode.PARAMS_ERROR, "开始日期格式错误或日期非法!");
|
||||
}
|
||||
try {
|
||||
String[] strArrEnd = getDataBySetDateAndCycle(LocalDate.parse(end), target.getCycle());
|
||||
if (LocalDate.parse(strArrEnd[4]).isBefore(LocalDate.parse(end))) {
|
||||
end = strArrEnd[4];
|
||||
}
|
||||
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new MyException(ErrorCode.PARAMS_ERROR, "结束日期格式错误或日期非法!");
|
||||
}
|
||||
} else {
|
||||
throw new MyException(ErrorCode.PARAMS_ERROR, "开始日期和结束日期不能一个有值一个没有值!");
|
||||
}
|
||||
|
||||
QueryWrapper<TargetData> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("target_id", targetId);
|
||||
queryWrapper.ge("set_date", start);
|
||||
queryWrapper.lt("set_date", end);
|
||||
List<TargetData> targetDatas = targetDataMapper.selectList(queryWrapper);
|
||||
targetDatas = getHistoryData(targetDatas, target, start, end);
|
||||
List<String> xData = new ArrayList<>();
|
||||
List<Double> data = new ArrayList<>();
|
||||
List<Double> oriData = new ArrayList<>();
|
||||
for (TargetData targetData : targetDatas) {
|
||||
xData.add(targetData.getXShow());
|
||||
data.add(targetData.getVal());
|
||||
oriData.add(targetData.getVal());
|
||||
}
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("start", start);
|
||||
map.put("end", end);
|
||||
map.put("max", Optional.of(data)
|
||||
.filter(list -> !list.isEmpty())
|
||||
.map(Collections::max)
|
||||
.map(value -> "" + CheckUtils.roundToDecimalPlaces(value, 4))
|
||||
.orElse("-"));
|
||||
map.put("avg", Optional.of(data)
|
||||
.filter(list -> !list.isEmpty())
|
||||
.map(list -> list.stream().mapToDouble(Double::doubleValue).average().orElse(Double.NaN))
|
||||
.map(value -> "" + CheckUtils.roundToDecimalPlaces(value, 4))
|
||||
.orElse("-"));
|
||||
map.put("medium", CheckUtils.roundToDecimalPlaces(getMedian(data), 4));
|
||||
map.put("min", Optional.of(data)
|
||||
.filter(list -> !list.isEmpty())
|
||||
.map(Collections::min)
|
||||
.map(value -> "" + CheckUtils.roundToDecimalPlaces(value, 4))
|
||||
.orElse("-"));
|
||||
map.put("xData", xData);
|
||||
map.put("data", data);
|
||||
map.put("cycle", getCycle(target));
|
||||
map.put("oriData", oriData);
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表中位数
|
||||
*
|
||||
* @param data 列表数据
|
||||
* @return 中位数
|
||||
*/
|
||||
private String getMedian(List<Double> data) {
|
||||
if (data.isEmpty()) {
|
||||
return "-";
|
||||
}
|
||||
List<Double> sortedData = data.stream()
|
||||
.sorted()
|
||||
.toList();
|
||||
int size = sortedData.size();
|
||||
double median;
|
||||
if (size % 2 == 0) {
|
||||
// 偶数个元素,返回中间两个元素的平均值
|
||||
median = (sortedData.get(size / 2 - 1) + sortedData.get(size / 2)) / 2.0;
|
||||
} else {
|
||||
// 奇数个元素,返回中间的元素
|
||||
median = sortedData.get(size / 2);
|
||||
}
|
||||
return String.valueOf(median);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定日期所在周期的 xShow, cycle, setDate, start, end
|
||||
*
|
||||
* @param localDate 日期
|
||||
* @param cycle 周期
|
||||
* @return 结果
|
||||
*/
|
||||
private String[] getDataBySetDateAndCycle(LocalDate localDate, String cycle) {
|
||||
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
String setDate = localDate.format(dtf);
|
||||
String xShow, showCycle, start, end;
|
||||
switch (cycle) {
|
||||
case "yesterday":
|
||||
case "nearlyWeek":
|
||||
case "nearlyMonth":
|
||||
showCycle = "day";
|
||||
xShow = localDate.format(dtf);
|
||||
end = localDate.plusDays(1).format(dtf);
|
||||
if ("yesterday".equals(cycle)) {
|
||||
start = localDate.format(dtf);
|
||||
} else if ("nearlyWeek".equals(cycle)) {
|
||||
start = localDate.minusDays(7).format(dtf);
|
||||
} else {
|
||||
start = localDate.minusDays(30).format(dtf);
|
||||
}
|
||||
break;
|
||||
case "week":
|
||||
case "lastWeek":
|
||||
showCycle = "week";
|
||||
xShow = utilService.getYearWeek(LocalDate.parse(setDate));
|
||||
start = localDate.format(dtf);
|
||||
end = localDate.plusDays(7).format(dtf);
|
||||
break;
|
||||
case "month":
|
||||
case "lastMonth":
|
||||
showCycle = "month";
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
|
||||
xShow = localDate.format(formatter);
|
||||
start = localDate.format(dtf);
|
||||
end = localDate.plusMonths(1).format(dtf);
|
||||
break;
|
||||
case "product":
|
||||
case "lastProduct":
|
||||
showCycle = "product";
|
||||
DateTimeFormatter productDtf = DateTimeFormatter.ofPattern("yyyy-MM");
|
||||
xShow = localDate.plusMonths(1).format(productDtf);
|
||||
start = localDate.format(dtf);
|
||||
end = localDate.plusMonths(1).format(dtf);
|
||||
break;
|
||||
default:
|
||||
xShow = null;
|
||||
showCycle = null;
|
||||
setDate = null;
|
||||
start = null;
|
||||
end = null;
|
||||
break;
|
||||
}
|
||||
|
||||
return new String[]{xShow, showCycle, setDate, start, end};
|
||||
}
|
||||
|
||||
/**
|
||||
* 补充时间范围内缺失的历史数据
|
||||
*
|
||||
* @param targetDataList 现有历史数据
|
||||
* @param target 指标
|
||||
* @param start 开始日期
|
||||
* @param end 结束日期
|
||||
* @return 补全的历史数据
|
||||
*/
|
||||
public List<TargetData> getHistoryData(
|
||||
List<TargetData> targetDataList,
|
||||
Target target,
|
||||
String start,
|
||||
String end) {
|
||||
LocalDate compareDate = LocalDate.parse(start);
|
||||
for (int i = 0; i < targetDataList.size(); i++) {
|
||||
LocalDate setDate = targetDataList.get(i).getSetDate()
|
||||
.toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();
|
||||
while (compareDate.isBefore(setDate)) {
|
||||
String[] strArr = getDataBySetDateAndCycle(compareDate, target.getCycle());
|
||||
targetDataList.add(i, updateHistory(target, strArr, new HashMap<>()));
|
||||
compareDate = getCompareDate(target, compareDate);
|
||||
i++;
|
||||
setDate = targetDataList.get(i).getSetDate()
|
||||
.toInstant().atZone(ZoneId.of("Asia/Shanghai")).toLocalDate();
|
||||
}
|
||||
compareDate = getCompareDate(target, compareDate);
|
||||
}
|
||||
while (compareDate.isBefore(LocalDate.parse(end))) {
|
||||
String[] strArr = getDataBySetDateAndCycle(compareDate, target.getCycle());
|
||||
if (LocalDate.parse(end).isBefore(LocalDate.parse(strArr[4]))) {
|
||||
strArr[4] = end;
|
||||
}
|
||||
targetDataList.add(updateHistory(target, strArr, new HashMap<>()));
|
||||
compareDate = getCompareDate(target, compareDate);
|
||||
}
|
||||
return targetDataList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个对比日期
|
||||
*
|
||||
* @param target 指标
|
||||
* @param compareDate 对比日期
|
||||
* @return 对比日期
|
||||
*/
|
||||
private LocalDate getCompareDate(Target target, LocalDate compareDate) {
|
||||
switch (target.getCycle()) {
|
||||
case "yesterday":
|
||||
case "nearlyMonth":
|
||||
case "nearlyWeek":
|
||||
compareDate = compareDate.plusDays(1);
|
||||
break;
|
||||
case "week":
|
||||
case "lastWeek":
|
||||
compareDate = compareDate.plusWeeks(1);
|
||||
break;
|
||||
case "month":
|
||||
case "lastMonth":
|
||||
case "product":
|
||||
case "lastProduct":
|
||||
compareDate = compareDate.plusMonths(1);
|
||||
break;
|
||||
}
|
||||
return compareDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取周期
|
||||
*
|
||||
* @param target 指标
|
||||
* @return 周期
|
||||
*/
|
||||
private String getCycle(Target target) {
|
||||
String cycle = "";
|
||||
if (Arrays.asList("yesterday", "nearlyWeek", "nearlyMonth").contains(target.getCycle())) {
|
||||
cycle = "day";
|
||||
} else if (Arrays.asList("week", "lastWeek").contains(target.getCycle())) {
|
||||
cycle = "week";
|
||||
} else if (Arrays.asList("month", "lastMonth").contains(target.getCycle())) {
|
||||
cycle = "month";
|
||||
} else if (Arrays.asList("product", "lastProduct").contains(target.getCycle())) {
|
||||
cycle = "product";
|
||||
}
|
||||
return cycle;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取前n个周期的开始结束日期
|
||||
*
|
||||
* @param cycle 周期
|
||||
* @return 结果map
|
||||
*/
|
||||
private Map<String, String> getCycleData(String cycle, int n) {
|
||||
LocalDate localDate = LocalDate.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
String end = localDate.format(formatter);
|
||||
if (Arrays.asList("yesterday", "nearlyWeek", "nearlyMonth").contains(cycle)) {
|
||||
localDate = localDate.minusDays(n);
|
||||
} else if (Arrays.asList("week", "lastWeek").contains(cycle)) {
|
||||
if (localDate.getDayOfWeek() == DayOfWeek.MONDAY) {
|
||||
localDate = localDate.minusWeeks(1);
|
||||
}
|
||||
localDate = localDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
|
||||
if ("lastWeek".equals(cycle)) {
|
||||
end = localDate.format(formatter);
|
||||
localDate = localDate.minusWeeks(1);
|
||||
}
|
||||
localDate = localDate.minusWeeks(n - 1);
|
||||
} else if (Arrays.asList("month", "lastMonth").contains(cycle)) {
|
||||
if (localDate.getDayOfMonth() == 1) {
|
||||
localDate = localDate.minusMonths(1);
|
||||
}
|
||||
localDate = localDate.withDayOfMonth(1);
|
||||
if ("lastMonth".equals(cycle)) {
|
||||
end = localDate.format(formatter);
|
||||
localDate = localDate.minusMonths(1);
|
||||
}
|
||||
localDate = localDate.minusMonths(n - 1);
|
||||
} else {
|
||||
if (localDate.getDayOfMonth() == 26) {
|
||||
localDate = localDate.minusMonths(1);
|
||||
}
|
||||
if (localDate.getDayOfMonth() >= 26) {
|
||||
localDate = localDate.withDayOfMonth(26);
|
||||
}
|
||||
if ("lastProduct".equals(cycle)) {
|
||||
end = localDate.format(formatter);
|
||||
localDate = localDate.minusMonths(1);
|
||||
}
|
||||
localDate = localDate.minusMonths(n - 1);
|
||||
}
|
||||
String start = localDate.format(formatter);
|
||||
Map<String, String> map = new HashMap<>(3);
|
||||
map.put("start", start);
|
||||
map.put("end", end);
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetData updateHistory(Target target, String[] strArr, Map<String, TargetData> map) {
|
||||
String xShow = strArr[0];
|
||||
@ -142,7 +453,11 @@ public class TargetDataServiceImpl extends ServiceImpl<TargetDataMapper, TargetD
|
||||
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());
|
||||
if (list.isEmpty() || list.get(0) == null || list.get(0).isEmpty()) {
|
||||
result = 0f;
|
||||
} else {
|
||||
result = Double.parseDouble(list.get(0).get("result").toString());
|
||||
}
|
||||
} else {
|
||||
String exprStr = target.getResultSql();
|
||||
String[] expressionList = exprStr.split(",");
|
||||
|
@ -13,6 +13,8 @@ import net.objecthunter.exp4j.ExpressionBuilder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.WeekFields;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
@ -86,7 +88,7 @@ public class UtilServiceImpl implements UtilService {
|
||||
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));
|
||||
xShow = getYearWeek(LocalDate.parse(setDate));
|
||||
showCycle = "week";
|
||||
break;
|
||||
case "month":
|
||||
@ -147,6 +149,21 @@ public class UtilServiceImpl implements UtilService {
|
||||
|
||||
return new String[]{xShow, showCycle, setDate, start, end};
|
||||
}
|
||||
@Override
|
||||
public String getYearWeek(LocalDate date) {
|
||||
WeekFields wf = WeekFields.ISO;
|
||||
|
||||
int weekNumber = date.get(wf.weekOfYear());
|
||||
int year = date.getYear();
|
||||
|
||||
if (date.getMonthValue() == 12 && weekNumber == 1) {
|
||||
year = year + 1;
|
||||
}
|
||||
|
||||
String weekStr = String.format("%02d", weekNumber);
|
||||
|
||||
return year + "-" + weekStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEvalResult(String expression) {
|
||||
|
Loading…
Reference in New Issue
Block a user