package cn.shlanbao.qms.service.impl;
|
|
import cn.hutool.core.date.DateUtil;
|
import cn.shlanbao.qms.domain.LbBatch;
|
import cn.shlanbao.qms.domain.LbSensorResult;
|
import cn.shlanbao.qms.domain.LbTestResult;
|
import cn.shlanbao.qms.domain.bo.LbBatchBo;
|
import cn.shlanbao.qms.domain.vo.LbBatchVo;
|
import cn.shlanbao.qms.domain.vo.LbSensorResultVo;
|
import cn.shlanbao.qms.domain.vo.LbTestResultVo;
|
import cn.shlanbao.qms.mapper.LbBatchMapper;
|
import cn.shlanbao.qms.mapper.LbSensorResultMapper;
|
import cn.shlanbao.qms.mapper.LbTestResultMapper;
|
import cn.shlanbao.qms.service.ILbQualityService;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import lombok.RequiredArgsConstructor;
|
import org.dromara.common.core.utils.StringUtils;
|
import org.dromara.common.mybatis.core.page.PageQuery;
|
import org.dromara.common.mybatis.core.page.TableDataInfo;
|
import org.springframework.stereotype.Service;
|
import org.springframework.util.CollectionUtils;
|
|
import java.text.SimpleDateFormat;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
@RequiredArgsConstructor
|
@Service
|
public class LbQualityServiceImpl implements ILbQualityService {
|
private final LbBatchMapper batchMapper;
|
private final LbSensorResultMapper sensorResultMapper;
|
private final LbTestResultMapper testResultMapper;
|
|
@Override
|
public Map<String, Object> queryQualityHealth() {
|
Map<String, Object> result = new HashMap<>(2);
|
|
// 获取当前年份
|
int currentYear = DateUtil.year(DateUtil.date());
|
|
// 构建查询条件:查询当前年份的数据
|
QueryWrapper<LbSensorResult> queryWrapper = new QueryWrapper<>();
|
queryWrapper.likeRight("batch_code", String.valueOf(currentYear));
|
|
// 查询数据
|
List<LbSensorResultVo> sensorResultList = sensorResultMapper.selectVoList(queryWrapper);
|
|
if (CollectionUtils.isEmpty(sensorResultList)) {
|
result.put("xAxis", Collections.emptyList());
|
result.put("yAxis", Collections.emptyList());
|
return result;
|
}
|
|
// 按年月分组(batch_code前6位)
|
Map<String, List<LbSensorResultVo>> monthlyGroup = sensorResultList.stream()
|
.filter(vo -> vo != null && StringUtils.isNotBlank(vo.getBatchCode()))
|
.collect(Collectors.groupingBy(vo -> vo.getBatchCode().substring(0, 6)));
|
|
// 准备x轴和y轴数据
|
List<String> xAxis = new ArrayList<>();
|
List<Map<String, Object>> yAxis = new ArrayList<>();
|
|
// 处理每个月的数据
|
monthlyGroup.entrySet().stream()
|
.sorted(Map.Entry.comparingByKey())
|
.forEach(entry -> {
|
String monthKey = entry.getKey();
|
List<LbSensorResultVo> monthlyData = entry.getValue();
|
|
if (CollectionUtils.isEmpty(monthlyData)) {
|
return;
|
}
|
|
// 添加x轴数据
|
xAxis.add(monthKey.substring(4, 6) + "月");
|
|
// 计算合格率
|
long passCount = monthlyData.stream()
|
.filter(vo -> "OK".equalsIgnoreCase(vo.getJudgeResult()))
|
.count();
|
|
double passRate = (double) passCount / monthlyData.size();
|
|
// 添加y轴数据
|
Map<String, Object> monthData = new HashMap<>(1);
|
monthData.put("value", String.format("%.1f", (passRate * 10)));
|
yAxis.add(monthData);
|
});
|
|
result.put("xAxis", xAxis);
|
result.put("yAxis", yAxis);
|
|
return result;
|
|
}
|
|
@Override
|
public TableDataInfo<LbBatchVo> queryBatchList(LbBatchBo bo, PageQuery pageQuery) {
|
LambdaQueryWrapper<LbBatch> lqw = buildQueryWrapper(bo);
|
Page<LbBatchVo> result = batchMapper.selectVoPage(pageQuery.build(), lqw);
|
|
List<LbBatchVo> records = result.getRecords();
|
if (records.isEmpty()) {
|
return TableDataInfo.build(result);
|
}
|
|
List<String> batchCodes = records.stream()
|
.map(LbBatchVo::getBatchCode)
|
.collect(Collectors.toList());
|
|
LambdaQueryWrapper<LbSensorResult> sensorResultWrapper = new LambdaQueryWrapper<>();
|
sensorResultWrapper.in(LbSensorResult::getBatchCode, batchCodes);
|
|
List<LbSensorResultVo> sensorResultVoList = sensorResultMapper.selectVoList(sensorResultWrapper);
|
|
// 一次性统计OK和总数
|
Map<String, BatchStats> statsMap = sensorResultVoList.stream()
|
.collect(Collectors.groupingBy(
|
LbSensorResultVo::getBatchCode,
|
Collectors.collectingAndThen(
|
Collectors.toList(),
|
list -> {
|
long okCount = list.stream()
|
.filter(vo -> "OK".equals(vo.getJudgeResult()))
|
.count();
|
return new BatchStats(okCount, list.size());
|
}
|
)
|
));
|
|
// 批量设置统计结果
|
records.forEach(item -> {
|
BatchStats stats = statsMap.get(item.getBatchCode());
|
if (stats != null) {
|
item.setOkNum(stats.okCount);
|
item.setNgNum(stats.totalCount - stats.okCount);
|
} else {
|
// 如果没有相关检测结果,设置为0
|
item.setOkNum(0L);
|
item.setNgNum(item.getNum());
|
}
|
});
|
|
return TableDataInfo.build(result);
|
}
|
|
@Override
|
public Map<String, Object> queryPwbatchList() {
|
Map<String, Object> res = new HashMap<>(2);
|
// 准备x轴和y轴数据
|
List<String> xAxis = new ArrayList<>();
|
List<Object> yAxis = new ArrayList<>();
|
|
LambdaQueryWrapper<LbBatch> dateQuery = Wrappers.lambdaQuery();
|
dateQuery.select(LbBatch::getBatchTime)
|
.groupBy(LbBatch::getBatchTime)
|
.orderByDesc(LbBatch::getBatchTime) // 保持倒序查询最近7天
|
.last("LIMIT 30");
|
|
List<LbBatchVo> dateVos = batchMapper.selectVoList(dateQuery);
|
|
// 从 Vo 对象中提取 batchTime
|
List<Date> recentDates = dateVos.stream()
|
.map(LbBatchVo::getBatchTime)
|
.filter(Objects::nonNull)
|
.collect(Collectors.toList());
|
|
LambdaQueryWrapper<LbBatch> lqw = Wrappers.lambdaQuery();
|
lqw.in(LbBatch::getBatchTime, recentDates)
|
.orderByAsc(LbBatch::getBatchTime); // 这里改为正序,确保数据按日期顺序
|
|
List<LbBatchVo> records = batchMapper.selectVoList(lqw);
|
|
List<String> batchCodes = records.stream()
|
.map(LbBatchVo::getBatchCode)
|
.collect(Collectors.toList());
|
|
LambdaQueryWrapper<LbSensorResult> sensorResultWrapper = new LambdaQueryWrapper<>();
|
sensorResultWrapper.in(LbSensorResult::getBatchCode, batchCodes);
|
|
List<LbSensorResultVo> sensorResultVoList = sensorResultMapper.selectVoList(sensorResultWrapper);
|
|
// 计算每个日期的OK比例
|
Map<Date, Double> dateOkRatioMap = sensorResultVoList.stream()
|
.collect(Collectors.groupingBy(
|
result -> {
|
String batchCode = result.getBatchCode();
|
return records.stream()
|
.filter(record -> record.getBatchCode().equals(batchCode))
|
.findFirst()
|
.map(LbBatchVo::getBatchTime)
|
.orElse(null);
|
},
|
Collectors.collectingAndThen(
|
Collectors.toList(),
|
list -> {
|
long okCount = list.stream()
|
.filter(result -> "ok".equalsIgnoreCase(result.getJudgeResult()))
|
.count();
|
return list.size() > 0 ? (double) okCount / list.size() : 0.0;
|
}
|
)
|
))
|
.entrySet().stream()
|
.filter(entry -> entry.getKey() != null)
|
.sorted(Map.Entry.<Date, Double>comparingByKey()) // 改为正序排序
|
.collect(Collectors.toMap(
|
Map.Entry::getKey,
|
Map.Entry::getValue,
|
(e1, e2) -> e1,
|
LinkedHashMap::new
|
));
|
|
// 过滤掉yAxis小于80的数据
|
dateOkRatioMap.entrySet().stream()
|
.filter(entry -> {
|
double ratio = entry.getValue() * 100; // 转换为百分比
|
return ratio >= 80; // 只保留大于等于80的数据
|
})
|
.forEach(entry -> {
|
Date date = entry.getKey();
|
double ratio = entry.getValue() * 100; // 转换为百分比
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
xAxis.add(sdf.format(date));
|
yAxis.add(String.format("%.1f", ratio));
|
});
|
|
res.put("xAxis", xAxis);
|
res.put("yAxis", yAxis);
|
|
return res;
|
}
|
|
@Override
|
public Map<String, Object> queryNgrankList() {
|
Map<String, Object> res = new HashMap<>(2);
|
LambdaQueryWrapper<LbTestResult> lqwGroup = Wrappers.lambdaQuery();
|
lqwGroup.select(LbTestResult::getBatchCode)
|
.groupBy(LbTestResult::getBatchCode)
|
.orderByDesc(LbTestResult::getBatchCode)
|
.last("LIMIT 30");
|
|
List<LbTestResultVo> groupResultVos = testResultMapper.selectVoList(lqwGroup);
|
List<String> batchCodeList = groupResultVos.stream()
|
.map(LbTestResultVo::getBatchCode)
|
.collect(Collectors.toList());
|
LambdaQueryWrapper<LbTestResult> lqw = Wrappers.lambdaQuery();
|
lqw.in(LbTestResult::getBatchCode, batchCodeList);
|
lqw.eq(LbTestResult::getTestResult, "NG");
|
List<LbTestResultVo> testResultVos = testResultMapper.selectVoList(lqw);
|
// 1. 按testItem分组并统计数量(每行计为1)
|
Map<String, Long> countByTestItem = testResultVos.stream()
|
.filter(result -> "NG".equalsIgnoreCase(result.getTestResult()))
|
.collect(Collectors.groupingBy(
|
LbTestResultVo::getTestItem,
|
Collectors.counting()
|
));
|
|
// 2. 按数量降序排序并取前5大
|
List<Map.Entry<String, Long>> top5Entries = countByTestItem.entrySet().stream()
|
.sorted(Map.Entry.<String, Long>comparingByValue().reversed())
|
.limit(5)
|
.collect(Collectors.toList());
|
|
// 3. 生成xAxis和yAxis数组
|
String[] xAxis = top5Entries.stream()
|
.map(Map.Entry::getKey)
|
.toArray(String[]::new);
|
|
Long[] yAxis = top5Entries.stream()
|
.map(Map.Entry::getValue)
|
.toArray(Long[]::new);
|
|
res.put("xAxis", xAxis);
|
res.put("yAxis", yAxis);
|
return res;
|
}
|
|
// 内部统计类
|
private static class BatchStats {
|
long okCount;
|
long totalCount;
|
|
BatchStats(long okCount, long totalCount) {
|
this.okCount = okCount;
|
this.totalCount = totalCount;
|
}
|
}
|
|
|
private LambdaQueryWrapper<LbBatch> buildQueryWrapper(LbBatchBo bo) {
|
Map<String, Object> params = bo.getParams();
|
LambdaQueryWrapper<LbBatch> lqw = Wrappers.lambdaQuery();
|
lqw.eq(StringUtils.isNotBlank(bo.getBatchCode()), LbBatch::getBatchCode, bo.getBatchCode());
|
lqw.eq(StringUtils.isNotBlank(bo.getProdModel()), LbBatch::getProdModel, bo.getProdModel());
|
lqw.eq(StringUtils.isNotBlank(bo.getDeviceCode()), LbBatch::getDeviceCode, bo.getDeviceCode());
|
lqw.eq(bo.getUserId() != null, LbBatch::getUserId, bo.getUserId());
|
lqw.eq(bo.getNum() != null, LbBatch::getNum, bo.getNum());
|
lqw.orderByDesc(LbBatch::getBatchCode);
|
if (params != null && params.containsKey("startTime") && params.containsKey("endTime")) {
|
lqw.between(LbBatch::getBatchTime, params.get("startTime"), params.get("endTime"));
|
}
|
return lqw;
|
}
|
|
}
|