数据分析微调

This commit is contained in:
caozehui
2025-02-17 17:59:37 +08:00
parent 76ec26dca0
commit 0c012152bb
5 changed files with 205 additions and 157 deletions

View File

@@ -208,4 +208,12 @@ public interface IPqDevService extends IService<PqDev> {
* @param patternId 模式Id * @param patternId 模式Id
*/ */
void importCNDev(List<CNDevExcel> cnDevExcelList, String patternId); void importCNDev(List<CNDevExcel> cnDevExcelList, String patternId);
/**
* 根据计划id列表获取设备列表
*
* @param planIds
* @return
*/
List<PqDev> listByPlanIds(List<String> planIds);
} }

View File

@@ -593,7 +593,7 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
i = pqDev.getReCheckNum(); i = pqDev.getReCheckNum();
} else { } else {
checkState = CheckStateEnum.CHECKED.getValue(); checkState = CheckStateEnum.CHECKED.getValue();
i = pqDev.getReCheckNum() + 1; i = pqDev.getReCheckNum() + 1;
} }
this.update(new LambdaUpdateWrapper<PqDev>() this.update(new LambdaUpdateWrapper<PqDev>()
.set(PqDev::getReCheckNum, i) .set(PqDev::getReCheckNum, i)
@@ -760,6 +760,12 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
this.saveBatch(newDevList); this.saveBatch(newDevList);
} }
@Override
public List<PqDev> listByPlanIds(List<String> planIds) {
return this.lambdaQuery().in(PqDev::getPlanId, planIds).eq(PqDev::getState, DataStateEnum.ENABLE.getCode()).list();
}
/** /**
* 获取检测状态饼状图数据 * 获取检测状态饼状图数据
* *

View File

@@ -196,10 +196,10 @@ public class AdPlanController extends BaseController {
@PostMapping("/analyse") @PostMapping("/analyse")
@ApiOperation("检测数据分析") @ApiOperation("检测数据分析")
@ApiImplicitParam(name = "planId", value = "检测计划id", required = true) @ApiImplicitParam(name = "planId", value = "检测计划id", required = true)
public void analyse(String planId) { public void analyse(@RequestBody List<String> ids) {
String methodDescribe = getMethodDescribe("analyse"); String methodDescribe = getMethodDescribe("analyse");
LogUtil.njcnDebug(log, "{},查询数据为:{}", methodDescribe, planId); LogUtil.njcnDebug(log, "{},查询数据为:{}", methodDescribe, String.join(StrUtil.COMMA, ids));
adPlanService.analyse(planId); adPlanService.analyse(ids);
} }
} }

View File

@@ -114,7 +114,7 @@ public interface IAdPlanService extends IService<AdPlan> {
/** /**
* 数据分析 * 数据分析
* *
* @param planId * @param ids
*/ */
void analyse(String planId); void analyse(List<String> ids);
} }

View File

@@ -414,55 +414,85 @@ public class AdPlanServiceImpl extends ServiceImpl<AdPlanMapper, AdPlan> impleme
} }
@Override @Override
public void analyse(String planId) { public void analyse(List<String> ids) {
AdPlan adPlan = this.getById(planId); SysTestConfig config = sysTestConfigService.getOneConfig();
if (ObjectUtil.isNull(adPlan)) { if (ObjectUtil.isNotNull(config)) {
throw new BusinessException(PlanResponseEnum.PLAN_NOT_EXIST); Integer maxTime = config.getMaxTime();
} else { List<AdPlan> planList = this.listByIds(ids);
List<String[]> rows = new ArrayList<>();
SysTestConfig config = sysTestConfigService.getOneConfig(); Map<String, List<String[]>> sheets = new HashMap<>();
if (ObjectUtil.isNotNull(config)) {
String[] row1 = new String[]{adPlan.getName()};
rows.add(row1);
Integer maxTime = config.getMaxTime(); if (planList.size() > 1) {
String[] row2 = new String[maxTime + 1]; List<PqDev> allDevList = new ArrayList<>();
row2[0] = "\\"; for (AdPlan plan : planList) {
PqDevParam.QueryParam param = new PqDevParam.QueryParam(); PqDevParam.QueryParam queryParam = new PqDevParam.QueryParam();
param.setPlanId(planId); queryParam.setPlanId(plan.getId());
List<PqDev> devList = pqDevService.listByPlanId(param); List<PqDev> devList = pqDevService.listByPlanId(queryParam);
String[] row3 = new String[maxTime + 1]; devList = devList.stream().filter(x -> !x.getCheckResult().equals(CheckResultEnum.UNCHECKED.getValue())).collect(Collectors.toList());
row3[0] = "合格数量"; allDevList.addAll(devList);
String[] row4 = new String[maxTime + 1]; sheets.put(plan.getName(), getRows(plan.getName(), devList, maxTime));
row4[0] = "总数量";
String[] row5 = new String[maxTime + 1];
row5[0] = "合格率";
for (int i = 1; i <= maxTime; i++) {
row2[i] = i + "次检测";
int tempI = i;
List<PqDev> tempDevList = devList.stream().filter(dev -> dev.getReCheckNum().equals(tempI)).collect(Collectors.toList());
long total = tempDevList.stream().filter(dev -> dev.getCheckResult() != CheckResultEnum.UNCHECKED.getValue()).count();
long passCount = tempDevList.stream().filter(dev -> dev.getCheckResult() == CheckResultEnum.ACCORD.getValue()).count();
row3[i] = passCount + "";
row4[i] = total + "";
if (total != 0) {
row5[i] = String.format("%.2f%%", (float) passCount / total * 100);
} else {
row5[i] = "/";
}
} }
rows.add(row2); sheets.put("All", getRows("数据分析结果-所有计划", allDevList, maxTime));
rows.add(row3); } else {
rows.add(row4); AdPlan plan = planList.get(0);
rows.add(row5); PqDevParam.QueryParam queryParam = new PqDevParam.QueryParam();
exportPassRateExcel("分析结果.xlsx", maxTime, rows); queryParam.setPlanId(plan.getId());
List<PqDev> devList = pqDevService.listByPlanId(queryParam);
devList = devList.stream().filter(x -> !x.getCheckResult().equals(CheckResultEnum.UNCHECKED.getValue())).collect(Collectors.toList());
sheets.put(plan.getName(), getRows(plan.getName(), devList, maxTime));
} }
exportPassRateExcel("数据分析结果.xlsx", maxTime, sheets);
} }
} }
/**
* 获取行数据
*
* @param header 表头
* @param devList 设备列表
* @param maxTime 最大复检次数
* @return
*/
private List<String[]> getRows(String header, List<PqDev> devList, Integer maxTime) {
List<String[]> rows = new ArrayList<>();
String[] row1 = new String[]{header};
String[] row2 = new String[maxTime + 1];
row2[0] = "\\";
String[] row3 = new String[maxTime + 1];
row3[0] = "合格数量";
String[] row4 = new String[maxTime + 1];
row4[0] = "已检数量";
String[] row5 = new String[maxTime + 1];
row5[0] = "合格率";
long total = devList.size();
for (int i = 1; i <= maxTime; i++) {
row2[i] = i + "次检测";
int tempI = i;
List<PqDev> tempDevList = devList.stream().filter(dev -> dev.getReCheckNum() <= tempI).collect(Collectors.toList());
long passCount = tempDevList.stream().filter(dev -> dev.getCheckResult() == CheckResultEnum.ACCORD.getValue()).count();
row3[i] = passCount + "";
row4[i] = total + "";
if (total != 0) {
row5[i] = String.format("%.2f%%", (float) passCount / total * 100);
} else {
row5[i] = "/";
}
}
rows.add(row1);
rows.add(row2);
rows.add(row3);
rows.add(row4);
rows.add(row5);
return rows;
}
/** /**
* 逆向可视化 * 逆向可视化
* *
@@ -522,140 +552,144 @@ public class AdPlanServiceImpl extends ServiceImpl<AdPlanMapper, AdPlan> impleme
} }
} }
private void exportPassRateExcel(String fileName, Integer maxTime, List<String[]> rows) { private void exportPassRateExcel(String fileName, Integer maxTime, Map<String, List<String[]>> sheets) {
HttpServletResponse response = HttpServletUtil.getResponse(); HttpServletResponse response = HttpServletUtil.getResponse();
XSSFWorkbook wb = new XSSFWorkbook(); XSSFWorkbook wb = new XSSFWorkbook();
String sheetName = "Sheet1";
try (ServletOutputStream outputStream = response.getOutputStream()) { try (ServletOutputStream outputStream = response.getOutputStream()) {
fileName = URLEncoder.encode(fileName, CharsetUtil.UTF_8); fileName = URLEncoder.encode(fileName, CharsetUtil.UTF_8);
response.reset(); response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentType("application/octet-stream;charset=UTF-8"); response.setContentType("application/octet-stream;charset=UTF-8");
XSSFSheet sheet = wb.createSheet(sheetName); sheets.forEach((sheetName, rows) -> {
// 数据行 XSSFSheet sheet = wb.createSheet(sheetName);
CellStyle cellStyle = wb.createCellStyle();
cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
XSSFFont headerFont = wb.createFont();
headerFont.setFontName("Microsoft YaHei");
headerFont.setBold(true);
headerFont.setFontHeightInPoints((short) 14);
cellStyle.setFont(headerFont);
Row row0 = sheet.createRow(0);
Cell row0Cell0 = row0.createCell(0);
row0Cell0.setCellStyle(cellStyle);
row0Cell0.setCellValue(rows.get(0)[0]);
for (int i = 1; i < maxTime + 1; i++) {
row0.createCell(i);
}
CellRangeAddress mergedRegion = new CellRangeAddress(0, 0, 0, maxTime);
sheet.addMergedRegion(mergedRegion);
CellStyle commoncellStyle = wb.createCellStyle(); // 数据行
commoncellStyle.setAlignment(HorizontalAlignment.CENTER); CellStyle cellStyle = wb.createCellStyle();
commoncellStyle.setVerticalAlignment(VerticalAlignment.CENTER); cellStyle.setAlignment(HorizontalAlignment.CENTER);
cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
XSSFFont headerFont = wb.createFont();
headerFont.setFontName("Microsoft YaHei");
headerFont.setBold(true);
headerFont.setFontHeightInPoints((short) 14);
cellStyle.setFont(headerFont);
Row row0 = sheet.createRow(0);
Cell row0Cell0 = row0.createCell(0);
row0Cell0.setCellStyle(cellStyle);
row0Cell0.setCellValue(rows.get(0)[0]);
for (int i = 1; i < maxTime + 1; i++) {
row0.createCell(i);
}
CellRangeAddress mergedRegion = new CellRangeAddress(0, 0, 0, maxTime);
sheet.addMergedRegion(mergedRegion);
for (int i = 1; i < rows.size(); i++) { CellStyle commoncellStyle = wb.createCellStyle();
String[] row = rows.get(i); commoncellStyle.setAlignment(HorizontalAlignment.CENTER);
Row createRow = sheet.createRow(i); commoncellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
for (int j = 0; j < row.length; j++) {
Cell createCell = createRow.createCell(j);
if (j == 0 || i == 1) {
headerFont.setFontHeightInPoints((short) 11);
createCell.setCellStyle(cellStyle);
} else {
createCell.setCellStyle(commoncellStyle);
}
if ("\\".equals(row[j])) {
CreationHelper helper = wb.getCreationHelper();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
// 设置斜线的开始位置
anchor.setCol1(j);
anchor.setRow1(i);
// 设置斜线的结束位置
anchor.setCol2(j + 1);
anchor.setRow2(i + 1);
XSSFSimpleShape shape = drawing.createSimpleShape((XSSFClientAnchor) anchor);
// 设置形状类型为线型 for (int i = 1; i < rows.size(); i++) {
shape.setShapeType(ShapeTypes.LINE); String[] row = rows.get(i);
// 设置线宽 Row createRow = sheet.createRow(i);
shape.setLineWidth(0.5); for (int j = 0; j < row.length; j++) {
// 设置线的风格 Cell createCell = createRow.createCell(j);
shape.setLineStyle(0); if (j == 0 || i == 1) {
// 设置线的颜色 headerFont.setFontHeightInPoints((short) 11);
shape.setLineStyleColor(0, 0, 0); createCell.setCellStyle(cellStyle);
} else { } else {
createCell.setCellValue(row[j]); createCell.setCellStyle(commoncellStyle);
}
if ("\\".equals(row[j])) {
CreationHelper helper = wb.getCreationHelper();
XSSFDrawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
// 设置斜线的开始位置
anchor.setCol1(j);
anchor.setRow1(i);
// 设置斜线的结束位置
anchor.setCol2(j + 1);
anchor.setRow2(i + 1);
XSSFSimpleShape shape = drawing.createSimpleShape((XSSFClientAnchor) anchor);
// 设置形状类型为线型
shape.setShapeType(ShapeTypes.LINE);
// 设置线宽
shape.setLineWidth(0.5);
// 设置线的风格
shape.setLineStyle(0);
// 设置线的颜色
shape.setLineStyleColor(0, 0, 0);
} else {
createCell.setCellValue(row[j]);
}
} }
} }
}
// 条形图 // 条形图
XSSFDrawing drawing = sheet.createDrawingPatriarch(); XSSFDrawing drawing = sheet.createDrawingPatriarch();
// 前四个默认0[0,5]从0列5行开始;[6,16]:到6列16行结束 // 前四个默认0[0,5]从0列5行开始;[6,16]:到6列16行结束
// 默认宽度(14-8)*12 // 默认宽度(14-8)*12
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, maxTime + 1, 25); XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, maxTime + 1, 25);
// 创建一个chart对象 // 创建一个chart对象
XSSFChart chart = drawing.createChart(anchor); XSSFChart chart = drawing.createChart(anchor);
// 标题 // 标题
chart.setTitleText("检测结果分析"); chart.setTitleText("检测结果分析");
// 标题覆盖 // 标题覆盖
chart.setTitleOverlay(false); chart.setTitleOverlay(false);
// 图例位置 // 图例位置
XDDFChartLegend legend = chart.getOrAddLegend(); XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP); legend.setPosition(LegendPosition.TOP);
// 分类轴标(X轴),标题位置 // 分类轴标(X轴),标题位置
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM); XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle("检测次数"); bottomAxis.setTitle("检测次数");
// 值(Y轴)轴,标题位置 // 值(Y轴)轴,标题位置
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT); XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle("合格率(%)"); leftAxis.setTitle("合格率(%)");
// CellRangeAddress(起始行号,终止行号, 起始列号,终止列号) // CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
// 分类轴标(X轴)数据,单元格范围位置[1, 1]到[1, maxTime] // 分类轴标(X轴)数据,单元格范围位置[1, 1]到[1, maxTime]
XDDFDataSource<String> checkTimes = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, 1, 1, maxTime)); XDDFDataSource<String> checkTimes = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(1, 1, 1, maxTime));
// 数据 // 数据
String[] rateStrArr = rows.get(rows.size() - 1); String[] rateStrArr = rows.get(rows.size() - 1);
Double[] rateArr = new Double[maxTime]; Double[] rateArr = new Double[maxTime];
for (int i = 1; i < rateStrArr.length; i++) { for (int i = 1; i < rateStrArr.length; i++) {
if("/".equals(rateStrArr[i])){ if ("/".equals(rateStrArr[i])) {
rateArr[i - 1] = 0.00; rateArr[i - 1] = 0.00;
}else{ } else {
rateArr[i - 1] = Double.parseDouble(rateStrArr[i].replace("%", "")); rateArr[i - 1] = Double.parseDouble(rateStrArr[i].replace("%", ""));
}
} }
} XDDFNumericalDataSource<Double> rate = XDDFDataSourcesFactory.fromArray(rateArr);
XDDFNumericalDataSource<Double> rate = XDDFDataSourcesFactory.fromArray(rateArr);
// bar条形图 // bar条形图
XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis); XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN); leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
// 设置为可变颜色 // 设置为可变颜色
bar.setVaryColors(true);// 这里可变颜色要设置成true如果需要设置成自己想要的颜色则置为false然后在下面设置颜色 bar.setVaryColors(true);// 这里可变颜色要设置成true如果需要设置成自己想要的颜色则置为false然后在下面设置颜色
// 条形图方向,纵向/横向:纵向 // 条形图方向,纵向/横向:纵向
bar.setBarDirection(BarDirection.COL); bar.setBarDirection(BarDirection.COL);
// 图表加载数据条形图1 // 图表加载数据条形图1
bar.addSeries(checkTimes, rate); bar.addSeries(checkTimes, rate);
CTPlotArea plotArea = chart.getCTChart().getPlotArea(); CTPlotArea plotArea = chart.getCTChart().getPlotArea();
CTBarSer serArray = plotArea.getBarChartArray(0).getSerArray(0); CTBarSer serArray = plotArea.getBarChartArray(0).getSerArray(0);
serArray.addNewDLbls(); serArray.addNewDLbls();
serArray.getDLbls().addNewShowVal().setVal(true); serArray.getDLbls().addNewShowVal().setVal(true);
serArray.getDLbls().addNewShowLegendKey().setVal(false); serArray.getDLbls().addNewShowLegendKey().setVal(false);
serArray.getDLbls().addNewShowCatName().setVal(false); serArray.getDLbls().addNewShowCatName().setVal(false);
serArray.getDLbls().addNewShowSerName().setVal(false); serArray.getDLbls().addNewShowSerName().setVal(false);
// 打印图表的xml // 打印图表的xml
//System.out.println(chart.getCTChart()); //System.out.println(chart.getCTChart());
// 绘制
chart.plot(bar);
});
// 绘制
chart.plot(bar);
wb.write(outputStream); wb.write(outputStream);
wb.close(); wb.close();
} catch (IOException e) { } catch (IOException e) {