比对模式的检测报告生成和下载
This commit is contained in:
@@ -44,6 +44,7 @@ import com.njcn.gather.system.dictionary.service.IDictDataService;
|
|||||||
import com.njcn.gather.system.dictionary.service.IDictTypeService;
|
import com.njcn.gather.system.dictionary.service.IDictTypeService;
|
||||||
import com.njcn.gather.type.pojo.po.DevType;
|
import com.njcn.gather.type.pojo.po.DevType;
|
||||||
import com.njcn.gather.type.service.IDevTypeService;
|
import com.njcn.gather.type.service.IDevTypeService;
|
||||||
|
import com.njcn.gather.user.user.pojo.po.SysUser;
|
||||||
import com.njcn.gather.user.user.service.ISysUserService;
|
import com.njcn.gather.user.user.service.ISysUserService;
|
||||||
import com.njcn.web.factory.PageFactory;
|
import com.njcn.web.factory.PageFactory;
|
||||||
import com.njcn.web.utils.ExcelUtil;
|
import com.njcn.web.utils.ExcelUtil;
|
||||||
@@ -353,9 +354,13 @@ public class PqDevServiceImpl extends ServiceImpl<PqDevMapper, PqDev> implements
|
|||||||
pqDevVO.setDevKey(EncryptionUtil.decoderString(1, pqDevVO.getDevKey()));
|
pqDevVO.setDevKey(EncryptionUtil.decoderString(1, pqDevVO.getDevKey()));
|
||||||
}
|
}
|
||||||
if (StrUtil.isNotBlank(pqDevVO.getCheckBy())) {
|
if (StrUtil.isNotBlank(pqDevVO.getCheckBy())) {
|
||||||
pqDevVO.setCheckBy(userService.getById(pqDevVO.getCheckBy()).getName());
|
SysUser sysUser = userService.getById(pqDevVO.getCheckBy());
|
||||||
|
if (ObjectUtil.isNotNull(sysUser)) {
|
||||||
|
pqDevVO.setCheckBy(sysUser.getName());
|
||||||
|
} else {
|
||||||
|
pqDevVO.setCheckBy(pqDevVO.getCheckBy());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DevType devType = devTypeService.getById(pqDevVO.getDevType());
|
DevType devType = devTypeService.getById(pqDevVO.getDevType());
|
||||||
if (ObjectUtil.isNotNull(devType)) {
|
if (ObjectUtil.isNotNull(devType)) {
|
||||||
pqDevVO.setDevChns(devType.getDevChns());
|
pqDevVO.setDevChns(devType.getDevChns());
|
||||||
|
|||||||
@@ -111,4 +111,5 @@ public interface IPqMonitorService extends IService<PqMonitor> {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Integer getDevCheckResult(String devId);
|
Integer getDevCheckResult(String devId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ import java.util.Objects;
|
|||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
public enum DataSourceEnum {
|
public enum DataSourceEnum {
|
||||||
REAL_DATA("real", "3s实时数据"),
|
REAL_DATA("real", "3s数据(150周波数据)"),
|
||||||
|
|
||||||
MINUTE_STATISTICS_MAX("max", "分钟统计数据-最大"),
|
MINUTE_STATISTICS_MAX("max", "分钟统计数据-最大值"),
|
||||||
MINUTE_STATISTICS_MIN("min", "分钟统计数据-最小"),
|
MINUTE_STATISTICS_MIN("min", "分钟统计数据-最小值"),
|
||||||
MINUTE_STATISTICS_AVG("avg", "分钟统计数据-平均"),
|
MINUTE_STATISTICS_AVG("avg", "分钟统计数据-平均值"),
|
||||||
MINUTE_STATISTICS_CP95("cp95", "分钟统计数据-CP95"),
|
MINUTE_STATISTICS_CP95("cp95", "分钟统计数据-CP95值"),
|
||||||
WAVE_DATA("wave_data", "录波");
|
WAVE_DATA("wave_data", "录波数据");
|
||||||
|
|
||||||
private String value;
|
private String value;
|
||||||
private String msg;
|
private String msg;
|
||||||
|
|||||||
@@ -189,4 +189,20 @@ public interface IAdPlanService extends IService<AdPlan> {
|
|||||||
*/
|
*/
|
||||||
boolean importSubPlanDataZip(MultipartFile file, String patternId, HttpServletResponse response);
|
boolean importSubPlanDataZip(MultipartFile file, String patternId, HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出计划检测结果数据
|
||||||
|
*
|
||||||
|
* @param planId
|
||||||
|
* @param devIds
|
||||||
|
* @param report
|
||||||
|
* @param response
|
||||||
|
*/
|
||||||
|
void exportPlanCheckDataZip(String planId, List<String> devIds, Integer report, HttpServletResponse response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比对模式下计划的检测大项获取
|
||||||
|
* @param planId 计划ID
|
||||||
|
* @return 检测项集合
|
||||||
|
*/
|
||||||
|
List<String> getScriptListContrast(String planId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import cn.hutool.core.util.ObjectUtil;
|
|||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.core.util.ZipUtil;
|
import cn.hutool.core.util.ZipUtil;
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import cn.hutool.json.JSONConfig;
|
||||||
import cn.hutool.json.JSONUtil;
|
import cn.hutool.json.JSONUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
@@ -22,6 +23,7 @@ import com.njcn.common.pojo.enums.common.DataStateEnum;
|
|||||||
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
|
||||||
import com.njcn.common.pojo.exception.BusinessException;
|
import com.njcn.common.pojo.exception.BusinessException;
|
||||||
import com.njcn.common.pojo.poi.PullDown;
|
import com.njcn.common.pojo.poi.PullDown;
|
||||||
|
import com.njcn.gather.detection.pojo.po.AdPair;
|
||||||
import com.njcn.gather.detection.service.IAdPariService;
|
import com.njcn.gather.detection.service.IAdPariService;
|
||||||
import com.njcn.gather.device.mapper.PqDevMapper;
|
import com.njcn.gather.device.mapper.PqDevMapper;
|
||||||
import com.njcn.gather.device.pojo.enums.*;
|
import com.njcn.gather.device.pojo.enums.*;
|
||||||
@@ -78,6 +80,7 @@ import com.njcn.gather.system.dictionary.pojo.po.DictType;
|
|||||||
import com.njcn.gather.system.dictionary.service.IDictDataService;
|
import com.njcn.gather.system.dictionary.service.IDictDataService;
|
||||||
import com.njcn.gather.system.dictionary.service.IDictTreeService;
|
import com.njcn.gather.system.dictionary.service.IDictTreeService;
|
||||||
import com.njcn.gather.system.dictionary.service.IDictTypeService;
|
import com.njcn.gather.system.dictionary.service.IDictTypeService;
|
||||||
|
import com.njcn.gather.tools.report.model.constant.ReportConstant;
|
||||||
import com.njcn.gather.type.pojo.po.DevType;
|
import com.njcn.gather.type.pojo.po.DevType;
|
||||||
import com.njcn.gather.type.service.IDevTypeService;
|
import com.njcn.gather.type.service.IDevTypeService;
|
||||||
import com.njcn.gather.user.user.pojo.po.SysUser;
|
import com.njcn.gather.user.user.pojo.po.SysUser;
|
||||||
@@ -1880,6 +1883,186 @@ public class AdPlanServiceImpl extends ServiceImpl<AdPlanMapper, AdPlan> impleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exportPlanCheckDataZip(String planId, List<String> devIds, Integer report, HttpServletResponse response) {
|
||||||
|
AdPlanCheckDataVO planCheckDataVO = new AdPlanCheckDataVO();
|
||||||
|
// 获取检测计划基本数据
|
||||||
|
AdPlan plan = this.getById(planId);
|
||||||
|
planCheckDataVO.setPlan(plan);
|
||||||
|
// 获取检测计划绑定的被检设备数据
|
||||||
|
List<PqDev> devList = pqDevService.list(new LambdaQueryWrapper<PqDev>().eq(PqDev::getPlanId, planId).in(PqDev::getId, devIds));
|
||||||
|
if (CollUtil.isEmpty(devList)) {
|
||||||
|
throw new BusinessException(CommonResponseEnum.FAIL, "选择的被检设备不存在");
|
||||||
|
}
|
||||||
|
planCheckDataVO.setDevList(devList);
|
||||||
|
List<String> devIdList = devList.stream().map(PqDev::getId).collect(Collectors.toList());
|
||||||
|
// 被检设备状态统计
|
||||||
|
List<PqDevSub> devSubList = pqDevSubService.list(new LambdaQueryWrapper<PqDevSub>().in(PqDevSub::getDevId, devIdList));
|
||||||
|
planCheckDataVO.setDevSubList(devSubList);
|
||||||
|
// 被检设备监测点信息
|
||||||
|
List<PqMonitor> monitorList = pqMonitorService.list(new LambdaQueryWrapper<PqMonitor>().in(PqMonitor::getDevId, devIdList));
|
||||||
|
planCheckDataVO.setMonitorList(monitorList);
|
||||||
|
// devMonitorId = 被检设备ID+通道号
|
||||||
|
List<String> devMonitorIds = new ArrayList<>();
|
||||||
|
for (PqDev dev : devList) {
|
||||||
|
List<String> channelNoList = StrUtil.split(dev.getInspectChannel(), StrUtil.COMMA);
|
||||||
|
for (String channelNo : channelNoList) {
|
||||||
|
devMonitorIds.add(dev.getId() + StrUtil.UNDERLINE + channelNo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
planCheckDataVO.setDevMonitorIds(devMonitorIds);
|
||||||
|
// 设备通道匹对关系
|
||||||
|
List<AdPair> pairList = adPairService.list(new LambdaQueryWrapper<AdPair>().eq(AdPair::getPlanId, planId).in(AdPair::getDevMonitorId, devMonitorIds));
|
||||||
|
planCheckDataVO.setPairList(pairList);
|
||||||
|
// 获取计划检测结果数据表以及数据
|
||||||
|
Integer code = plan.getCode();
|
||||||
|
List<String> dataTableNames = CollUtil.newArrayList("ad_harmonic_" + code, "ad_non_harmonic_" + code, "ad_harmonic_result_" + code, "ad_non_harmonic_result_" + code);
|
||||||
|
|
||||||
|
// 创建临时目录用于存储txt文件
|
||||||
|
File tempDataDir = FileUtil.mkdir(FileUtil.getTmpDirPath() + "plan_data_" + System.currentTimeMillis() + "/");
|
||||||
|
List<File> dataFiles = new ArrayList<>();
|
||||||
|
int dataBatch = 0;
|
||||||
|
if (CollUtil.isNotEmpty(pairList)) {
|
||||||
|
for (String dataTableName : dataTableNames) {
|
||||||
|
// 创建数据文件
|
||||||
|
String fileName = dataTableName.replace("_" + code, "") + ".txt";
|
||||||
|
File dataFile = FileUtil.file(tempDataDir, fileName);
|
||||||
|
// 确保文件存在
|
||||||
|
FileUtil.touch(dataFile);
|
||||||
|
|
||||||
|
// 初始化写入标志,用于判断是否已写入字段名
|
||||||
|
boolean isFirstWrite = true;
|
||||||
|
|
||||||
|
// 分页查询,避免一次性加载大量数据
|
||||||
|
int pageSize = 10000; // 每页查询10000条记录
|
||||||
|
int offset = 0;
|
||||||
|
List<Map<String, Object>> pageData;
|
||||||
|
do {
|
||||||
|
dataBatch += 1;
|
||||||
|
String paginatedSql = buildPaginatedQuery(dataTableName, devMonitorIds, pageSize, offset);
|
||||||
|
pageData = jdbcTemplate.queryForList(paginatedSql);
|
||||||
|
|
||||||
|
// 将当前页数据追加到文件中
|
||||||
|
if (CollUtil.isNotEmpty(pageData)) {
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
|
||||||
|
// 如果是第一次写入,先写入字段名
|
||||||
|
if (isFirstWrite) {
|
||||||
|
// 获取字段名
|
||||||
|
Map<String, Object> firstRow = pageData.get(0);
|
||||||
|
List<String> fieldNames = new ArrayList<>(firstRow.keySet());
|
||||||
|
|
||||||
|
// 写入字段名作为第一行
|
||||||
|
content.append(StrUtil.join("\t", fieldNames)).append(System.lineSeparator());
|
||||||
|
isFirstWrite = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 写入数据行
|
||||||
|
for (Map<String, Object> data : pageData) {
|
||||||
|
List<Object> values = new ArrayList<>(data.values());
|
||||||
|
content.append(StrUtil.join("\t", values)).append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 追加内容到文件
|
||||||
|
FileUtil.appendUtf8String(content.toString(), dataFile);
|
||||||
|
}
|
||||||
|
offset += pageSize;
|
||||||
|
} while (pageData.size() == pageSize); // 如果查询结果少于pageSize,说明已经查询完所有数据
|
||||||
|
|
||||||
|
// 如果文件存在且不为空,则添加到数据文件列表中
|
||||||
|
if (FileUtil.exist(dataFile) && FileUtil.size(dataFile) > 0) {
|
||||||
|
dataFiles.add(dataFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
planCheckDataVO.setDataBatch(dataBatch);
|
||||||
|
|
||||||
|
// 导出数据.zip文件
|
||||||
|
String jsonStr = JSONUtil.toJsonStr(planCheckDataVO, new JSONConfig().setIgnoreNullValue(false));
|
||||||
|
try {
|
||||||
|
// 创建临时目录
|
||||||
|
File tempDir = FileUtil.mkdir(FileUtil.getTmpDirPath() + "export_" + System.currentTimeMillis() + "/");
|
||||||
|
|
||||||
|
// 创建 JSON 文件
|
||||||
|
String jsonFileName = plan.getName() + ".json";
|
||||||
|
File jsonFile = FileUtil.file(tempDir, jsonFileName);
|
||||||
|
FileUtil.writeUtf8String(jsonStr, jsonFile);
|
||||||
|
|
||||||
|
// 创建 ZIP 文件
|
||||||
|
String zipFileName = URLEncoder.encode(plan.getName() + "_检测数据.zip", "UTF-8");
|
||||||
|
File zipFile = FileUtil.file(tempDir, zipFileName);
|
||||||
|
|
||||||
|
// 创建一个临时目录存放所有文件
|
||||||
|
File tempZipDir = FileUtil.mkdir(FileUtil.getTmpDirPath() + "temp_plan_check_data_" + System.currentTimeMillis() + "/");
|
||||||
|
// 复制json文件到临时目录
|
||||||
|
FileUtil.copy(jsonFile, tempZipDir, true);
|
||||||
|
|
||||||
|
// 复制数据txt文件到临时目录
|
||||||
|
for (File dataFile : dataFiles) {
|
||||||
|
FileUtil.copy(dataFile, tempZipDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加检测报告文件
|
||||||
|
if (ObjectUtil.isNotNull(report) && report.equals(1)) {
|
||||||
|
for (PqDev dev : devList) {
|
||||||
|
DevType devType = devTypeService.getById(dev.getDevType());
|
||||||
|
String dirPath = reportPath.concat(File.separator).concat(devType.getName());
|
||||||
|
File reportFile = new File(dirPath.concat(File.separator).concat(dev.getCreateId()).concat(ReportConstant.DOCX));
|
||||||
|
// 如果reportFile存在,则将reportFile中的文件添加到已有的zip文件中
|
||||||
|
if (FileUtil.exist(reportFile)) {
|
||||||
|
// 复制reportFile到临时目录
|
||||||
|
FileUtil.copy(reportFile, tempZipDir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新创建zip文件,包含所有文件
|
||||||
|
ZipUtil.zip(tempZipDir.getAbsolutePath(), zipFile.getAbsolutePath());
|
||||||
|
|
||||||
|
// 删除临时目录
|
||||||
|
FileUtil.del(tempZipDir);
|
||||||
|
FileUtil.del(tempDataDir);
|
||||||
|
|
||||||
|
// 设置响应头
|
||||||
|
response.reset();
|
||||||
|
response.setContentType("application/octet-stream;charset=UTF-8");
|
||||||
|
response.setHeader("Content-Disposition", "attachment; filename=\"" + zipFileName + "\"");
|
||||||
|
|
||||||
|
// 将 ZIP 文件写入响应
|
||||||
|
ServletOutputStream os = response.getOutputStream();
|
||||||
|
FileUtil.writeToStream(zipFile, os);
|
||||||
|
os.flush();
|
||||||
|
os.close();
|
||||||
|
|
||||||
|
// 删除临时文件
|
||||||
|
FileUtil.del(tempDir);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("导出计划检测数据.zip文件失败: ", e);
|
||||||
|
throw new BusinessException(CommonResponseEnum.FAIL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比对模式下计划的检测项获取
|
||||||
|
* @param planId 计划ID
|
||||||
|
* @return 检测项
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public List<String> getScriptListContrast(String planId) {
|
||||||
|
List<String> scriptList = new ArrayList<>();
|
||||||
|
AdPlan adPlan = this.baseMapper.selectById(planId);
|
||||||
|
String pattern = adPlan.getPattern();
|
||||||
|
DictData dictData = dictDataService.getDictDataById(pattern);
|
||||||
|
if (ObjectUtil.isNotNull(dictData)) {
|
||||||
|
if(dictData.getCode().equalsIgnoreCase("Contrast")){
|
||||||
|
String[] items = adPlan.getTestItem().split(",");
|
||||||
|
scriptList = new ArrayList<>(Arrays.asList(items));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return scriptList;
|
||||||
|
}
|
||||||
|
|
||||||
// 构建分页查询SQL
|
// 构建分页查询SQL
|
||||||
private String buildPaginatedQuery(String tableName, List<String> devMonitorIds, int limit, int offset) {
|
private String buildPaginatedQuery(String tableName, List<String> devMonitorIds, int limit, int offset) {
|
||||||
StringBuilder sql = new StringBuilder("SELECT * FROM " + tableName);
|
StringBuilder sql = new StringBuilder("SELECT * FROM " + tableName);
|
||||||
|
|||||||
@@ -35,5 +35,8 @@ public class DevReportParam implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String devId;
|
private String devId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量下载时传递的被检设备id列表
|
||||||
|
*/
|
||||||
private List<String> devIdList;
|
private List<String> devIdList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ public interface PowerConstant {
|
|||||||
*/
|
*/
|
||||||
List<String> T_PHASE = Arrays.asList("VOLTAGE", "IMBV", "IMBA", "FREQ");
|
List<String> T_PHASE = Arrays.asList("VOLTAGE", "IMBV", "IMBA", "FREQ");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* T相指标存B相字段
|
||||||
|
*/
|
||||||
|
List<String> TB_PHASE = Arrays.asList("IMBV", "IMBA");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 有次数的指标
|
* 有次数的指标
|
||||||
@@ -39,6 +44,12 @@ public interface PowerConstant {
|
|||||||
*/
|
*/
|
||||||
List<Integer> DATA_RANGE = Arrays.asList(1, 2);
|
List<Integer> DATA_RANGE = Arrays.asList(1, 2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* abc相别
|
||||||
|
*/
|
||||||
|
List<String> PHASE_ABC = Arrays.asList("a", "b", "c");
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 暂态符号
|
* 暂态符号
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -30,6 +30,12 @@ public enum BaseReportKeyEnum {
|
|||||||
MONTH("month","月份"),
|
MONTH("month","月份"),
|
||||||
DAY("day","日"),
|
DAY("day","日"),
|
||||||
YEAR_MONTH_DAY("year-month-day","年-月-日"),
|
YEAR_MONTH_DAY("year-month-day","年-月-日"),
|
||||||
|
REPORT_DATE("reportDate","年-月-日"),
|
||||||
|
SUB_NAME("subName","变电站"),
|
||||||
|
CHECK_BY("checkBy","检测人"),
|
||||||
|
AUDIT_BY("auditBy","负责人、审核人"),
|
||||||
|
ERROR_SYS_NAME("errorSysName","误差体系"),
|
||||||
|
CREATE_DATE("createDate","生产日期"),
|
||||||
TEMPERATURE("temp","温度"),
|
TEMPERATURE("temp","温度"),
|
||||||
HUMIDITY("hum","相对湿度"),
|
HUMIDITY("hum","相对湿度"),
|
||||||
DELEGATE("delegate","委托方");
|
DELEGATE("delegate","委托方");
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ public enum ItemReportKeyEnum {
|
|||||||
NAME_DETAIL("nameDetail", "检测项详细,比如:频率测量准确度"),
|
NAME_DETAIL("nameDetail", "检测项详细,比如:频率测量准确度"),
|
||||||
INFLUENCE("influence", "影响量的描述,比如额定工作条件、谐波对电压的影响等等"),
|
INFLUENCE("influence", "影响量的描述,比如额定工作条件、谐波对电压的影响等等"),
|
||||||
ERROR_SCOPE("errorScope", "误差范围,注:在段落中时需加上(),表格中无需添加"),
|
ERROR_SCOPE("errorScope", "误差范围,注:在段落中时需加上(),表格中无需添加"),
|
||||||
|
A_ERROR_SCOPE("a_errorScope", "A级误差,比如:±0.1%Un\n(±0.05774),需要换行,电压需要转为幅值"),
|
||||||
|
NUM_OF_DATA("numOfData", "有效数据组数"),
|
||||||
|
PHASE("phase", "相别"),
|
||||||
ERROR_SCOPE_MAG("errorScopeMag", "特征幅值:误差范围"),
|
ERROR_SCOPE_MAG("errorScopeMag", "特征幅值:误差范围"),
|
||||||
ERROR_SCOPE_DUR("errorScopeDur", "持续时间:误差范围"),
|
ERROR_SCOPE_DUR("errorScopeDur", "持续时间:误差范围"),
|
||||||
SCRIPT_DETAIL("scriptDetail", "脚本输出明细。比如:基波电压UN=57.74V,f=50Hz,谐波含有率Uh=10%UN=5.774V"),
|
SCRIPT_DETAIL("scriptDetail", "脚本输出明细。比如:基波电压UN=57.74V,f=50Hz,谐波含有率Uh=10%UN=5.774V"),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ public enum PowerIndexEnum {
|
|||||||
|
|
||||||
UNKNOWN("UNKNOWN", "未知指标"),
|
UNKNOWN("UNKNOWN", "未知指标"),
|
||||||
FREQ("FREQ", "频率"),
|
FREQ("FREQ", "频率"),
|
||||||
|
LINE_TITLE("LINE_TITLE", "测量回路"),
|
||||||
V("V", "电压"),
|
V("V", "电压"),
|
||||||
I("I", "电流"),
|
I("I", "电流"),
|
||||||
P("P", "功率"),
|
P("P", "功率"),
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package com.njcn.gather.report.pojo.result;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hongawen
|
||||||
|
* @version 1.0
|
||||||
|
* @data 2025/9/18 13:22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ContrastTestResult implements Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指标CODE
|
||||||
|
*/
|
||||||
|
private String scriptCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 指标名称
|
||||||
|
*/
|
||||||
|
private String scriptName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否谐波类
|
||||||
|
*/
|
||||||
|
private boolean isHarmonic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否合格
|
||||||
|
*/
|
||||||
|
private String result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 特殊情况的一些描述
|
||||||
|
* 比如:存在无法比较时,比如谐波类存在标准和被检均为0的情况
|
||||||
|
*/
|
||||||
|
private String specialCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 非谐波类检测结果
|
||||||
|
* 相别 -- 占位符名称 -- 占位符值
|
||||||
|
*/
|
||||||
|
Map<String,Map<String,String>> checkResultNonHarmonic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 谐波类检测结果
|
||||||
|
* 次数 -- 相别 -- 占位符名称 -- 占位符值
|
||||||
|
*/
|
||||||
|
List<Map<String,Map<String,Map<String,String>>>> checkResultHarmonic;
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@ import javax.validation.constraints.NotNull;
|
|||||||
* @data 2025-09-10
|
* @data 2025-09-10
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class MonitorResultVO {
|
public class MonitorResultVO implements Comparable<MonitorResultVO> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监测点id
|
* 监测点id
|
||||||
@@ -69,4 +69,21 @@ public class MonitorResultVO {
|
|||||||
@ApiModelProperty(value = "数据源类型", required = true)
|
@ApiModelProperty(value = "数据源类型", required = true)
|
||||||
@NotBlank(message = DetectionValidMessage.DEV_MONITOR_RESULT_TYPE_NOT_BLANK)
|
@NotBlank(message = DetectionValidMessage.DEV_MONITOR_RESULT_TYPE_NOT_BLANK)
|
||||||
private String resultType;
|
private String resultType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据线路号排序
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(MonitorResultVO other) {
|
||||||
|
if (this.monitorNum == null && other.monitorNum == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (this.monitorNum == null) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (other.monitorNum == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return this.monitorNum.compareTo(other.monitorNum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
package com.njcn.gather.result.service;
|
package com.njcn.gather.result.service;
|
||||||
|
|
||||||
|
import com.njcn.gather.device.pojo.vo.PqDevVO;
|
||||||
|
import com.njcn.gather.report.pojo.DevReportParam;
|
||||||
|
import com.njcn.gather.report.pojo.result.ContrastTestResult;
|
||||||
import com.njcn.gather.report.pojo.result.SingleTestResult;
|
import com.njcn.gather.report.pojo.result.SingleTestResult;
|
||||||
import com.njcn.gather.result.pojo.param.ResultParam;
|
import com.njcn.gather.result.pojo.param.ResultParam;
|
||||||
import com.njcn.gather.result.pojo.vo.*;
|
import com.njcn.gather.result.pojo.vo.*;
|
||||||
import com.njcn.gather.script.pojo.vo.PqScriptDtlDataVO;
|
import com.njcn.gather.script.pojo.vo.PqScriptDtlDataVO;
|
||||||
|
import com.njcn.gather.system.dictionary.pojo.po.DictTree;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -88,13 +92,6 @@ public interface IResultService {
|
|||||||
*/
|
*/
|
||||||
SingleTestResult getFinalContent(List<PqScriptDtlDataVO> checkDataVOList, String planCode, String devId, Integer lineNo, List<String> tableKeys);
|
SingleTestResult getFinalContent(List<PqScriptDtlDataVO> checkDataVOList, String planCode, String devId, Integer lineNo, List<String> tableKeys);
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取段落中指定的key对应的值
|
|
||||||
*
|
|
||||||
* @param itemCode 测试大项code
|
|
||||||
* @param pKeys 待填充的值
|
|
||||||
*/
|
|
||||||
Map<String, String> getParagraphKeysValue(String itemCode, List<String> pKeys);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取比对式表单头
|
* 获取比对式表单头
|
||||||
@@ -128,4 +125,14 @@ public interface IResultService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<ContrastTestItemVO> getCheckItem(String devId, String chnNum, Integer num);
|
List<ContrastTestItemVO> getCheckItem(String devId, String chnNum, Integer num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取设备比对式结果,用于出比对检测的报告
|
||||||
|
* @param devReportParam 设备报告参数
|
||||||
|
* @param pqDevVO 设备信息 省去一次sql查询
|
||||||
|
* @return 该设备的比对式结果
|
||||||
|
*/
|
||||||
|
Map<Integer, List<ContrastTestResult>> getContrastResultForReport(DevReportParam devReportParam, PqDevVO pqDevVO);
|
||||||
|
|
||||||
|
ContrastTestResult getContrastResultHarm(MonitorResultVO monitorResultVO, List<String> scriptId, Integer planCode, DictTree dictTree);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.njcn.gather.result.service.impl;
|
|||||||
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
import cn.afterturn.easypoi.excel.entity.ExportParams;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.date.DatePattern;
|
import cn.hutool.core.date.DatePattern;
|
||||||
import cn.hutool.core.text.StrPool;
|
import cn.hutool.core.text.StrPool;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
@@ -34,6 +35,7 @@ import com.njcn.gather.device.pojo.enums.CommonEnum;
|
|||||||
import com.njcn.gather.device.pojo.enums.PatternEnum;
|
import com.njcn.gather.device.pojo.enums.PatternEnum;
|
||||||
import com.njcn.gather.device.pojo.po.PqDev;
|
import com.njcn.gather.device.pojo.po.PqDev;
|
||||||
import com.njcn.gather.device.pojo.po.PqStandardDev;
|
import com.njcn.gather.device.pojo.po.PqStandardDev;
|
||||||
|
import com.njcn.gather.device.pojo.vo.PqDevVO;
|
||||||
import com.njcn.gather.device.service.IPqDevService;
|
import com.njcn.gather.device.service.IPqDevService;
|
||||||
import com.njcn.gather.device.service.IPqStandardDevService;
|
import com.njcn.gather.device.service.IPqStandardDevService;
|
||||||
import com.njcn.gather.err.service.IPqErrSysService;
|
import com.njcn.gather.err.service.IPqErrSysService;
|
||||||
@@ -45,10 +47,12 @@ import com.njcn.gather.plan.pojo.po.AdPlanTestConfig;
|
|||||||
import com.njcn.gather.plan.service.IAdPlanService;
|
import com.njcn.gather.plan.service.IAdPlanService;
|
||||||
import com.njcn.gather.plan.service.IAdPlanTestConfigService;
|
import com.njcn.gather.plan.service.IAdPlanTestConfigService;
|
||||||
import com.njcn.gather.pojo.enums.DetectionResponseEnum;
|
import com.njcn.gather.pojo.enums.DetectionResponseEnum;
|
||||||
|
import com.njcn.gather.report.pojo.DevReportParam;
|
||||||
import com.njcn.gather.report.pojo.constant.PowerConstant;
|
import com.njcn.gather.report.pojo.constant.PowerConstant;
|
||||||
import com.njcn.gather.report.pojo.enums.AffectEnum;
|
import com.njcn.gather.report.pojo.enums.AffectEnum;
|
||||||
import com.njcn.gather.report.pojo.enums.ItemReportKeyEnum;
|
import com.njcn.gather.report.pojo.enums.ItemReportKeyEnum;
|
||||||
import com.njcn.gather.report.pojo.enums.PowerIndexEnum;
|
import com.njcn.gather.report.pojo.enums.PowerIndexEnum;
|
||||||
|
import com.njcn.gather.report.pojo.result.ContrastTestResult;
|
||||||
import com.njcn.gather.report.pojo.result.SingleTestResult;
|
import com.njcn.gather.report.pojo.result.SingleTestResult;
|
||||||
import com.njcn.gather.result.pojo.enums.ResultUnitEnum;
|
import com.njcn.gather.result.pojo.enums.ResultUnitEnum;
|
||||||
import com.njcn.gather.result.pojo.param.ResultParam;
|
import com.njcn.gather.result.pojo.param.ResultParam;
|
||||||
@@ -1520,43 +1524,6 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
return JSONUtil.toBean(filedValue, DetectionData.class);
|
return JSONUtil.toBean(filedValue, DetectionData.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取段落中指定的key对应的值,目前主要为测试大项名称服务,通过code匹配
|
|
||||||
*
|
|
||||||
* @param itemCode 测试大项code
|
|
||||||
* @param pKeys 待填充的值
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getParagraphKeysValue(String itemCode, List<String> pKeys) {
|
|
||||||
Map<String, String> map = new HashMap<>();
|
|
||||||
if (CollUtil.isNotEmpty(pKeys)) {
|
|
||||||
for (String pKey : pKeys) {
|
|
||||||
ItemReportKeyEnum reportKeyEnum = ItemReportKeyEnum.getByKey(pKey);
|
|
||||||
if (Objects.nonNull(reportKeyEnum)) {
|
|
||||||
if (reportKeyEnum.getKey().equals(ItemReportKeyEnum.NAME.getKey())) {
|
|
||||||
PowerIndexEnum indexEnum = PowerIndexEnum.getByKey(itemCode);
|
|
||||||
if (Objects.nonNull(indexEnum)) {
|
|
||||||
map.put(reportKeyEnum.getKey(), indexEnum.getDesc());
|
|
||||||
} else {
|
|
||||||
log.error("电能指标枚举未找到测试项");
|
|
||||||
}
|
|
||||||
} else if (reportKeyEnum.getKey().equals(ItemReportKeyEnum.NAME_DETAIL.getKey())) {
|
|
||||||
PowerIndexEnum indexEnum = PowerIndexEnum.getByKey(itemCode);
|
|
||||||
if (Objects.nonNull(indexEnum)) {
|
|
||||||
map.put(reportKeyEnum.getKey(), indexEnum.getDesc().concat("测量准确度"));
|
|
||||||
} else {
|
|
||||||
log.error("电能指标枚举未找到测试项");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log.error("段落枚举未找到占用符");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FormContentVO getContrastFormContent(ResultParam.QueryParam queryParam) {
|
public FormContentVO getContrastFormContent(ResultParam.QueryParam queryParam) {
|
||||||
FormContentVO formContentVO = new FormContentVO();
|
FormContentVO formContentVO = new FormContentVO();
|
||||||
@@ -1843,6 +1810,798 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取对比结果
|
||||||
|
*
|
||||||
|
* @param devReportParam 设备报告参数
|
||||||
|
* @param pqDevVO 设备信息 省去一次sql查询
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<Integer, List<ContrastTestResult>> getContrastResultForReport(DevReportParam devReportParam, PqDevVO pqDevVO) {
|
||||||
|
Map<Integer/*回路号*/, List<ContrastTestResult>> finalContent = new LinkedHashMap<>();
|
||||||
|
List<ContrastTestResult> contrastTestResults = new ArrayList<>();
|
||||||
|
// 获取该设备下参与测试的回路(已有检测结论的)
|
||||||
|
List<MonitorResultVO> monitorResultVOS = this.getMonitorResult(devReportParam.getDevId());
|
||||||
|
if (CollectionUtil.isNotEmpty(monitorResultVOS)) {
|
||||||
|
Collections.sort(monitorResultVOS);
|
||||||
|
// 获取该计划下所有的检测指标,注:如果用户应用的是录波数据,频率这个指标不用出结果,因为当前的算法无法得出合理的结果
|
||||||
|
List<String> scriptList = adPlanService.getScriptListContrast(devReportParam.getPlanId());
|
||||||
|
// 对测试项按字典表排个序
|
||||||
|
scriptList = dictTreeService.sort(scriptList);
|
||||||
|
|
||||||
|
AdPlan adPlan = adPlanService.getById(devReportParam.getPlanId());
|
||||||
|
if (CollectionUtil.isNotEmpty(scriptList)) {
|
||||||
|
for (MonitorResultVO monitorResultVO : monitorResultVOS) {
|
||||||
|
int monitorNum = monitorResultVO.getMonitorNum();
|
||||||
|
// 看看当前这个回路结论的来源,可能是某次的实时数据、某次的测试下的某次录波数据、某次统计数据
|
||||||
|
for (String scriptId : scriptList) {
|
||||||
|
// 获取该指标的code,需要判断是否为谐波还是非谐波的指标
|
||||||
|
DictTree dictTree = dictTreeService.getById(scriptId);
|
||||||
|
// 本处的scriptId为父级,我需要获取自己
|
||||||
|
List<String> subScriptIds = dictTreeService.getChildIds(scriptId);
|
||||||
|
String scriptCode = dictTree.getCode();
|
||||||
|
if (PowerConstant.TIME.contains(scriptCode)) {
|
||||||
|
// 谐波类,谐波类稍微特殊一点,存在2~50次的数据,所以需要特殊处理
|
||||||
|
ContrastTestResult contrastTestResult = getContrastResultHarm(monitorResultVO, subScriptIds, adPlan.getCode(), dictTree);
|
||||||
|
if (Objects.nonNull(contrastTestResult)) {
|
||||||
|
contrastTestResults.add(contrastTestResult);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 非谐波类,非谐波需要注意T相和三相
|
||||||
|
ContrastTestResult contrastTestResult = getContrastResultNonHarm(monitorResultVO, subScriptIds, adPlan.getCode(), dictTree);
|
||||||
|
if (Objects.nonNull(contrastTestResult)) {
|
||||||
|
contrastTestResults.add(contrastTestResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finalContent.put(monitorNum, contrastTestResults);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return finalContent;
|
||||||
|
}
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取谐波类数据的结果数据
|
||||||
|
*
|
||||||
|
* @param monitorResultVO 数据来源信息
|
||||||
|
* @param subScriptIds 实际检测指标id
|
||||||
|
* @param planCode 计划code,表名需要
|
||||||
|
* @param dictTree 测试指标信息
|
||||||
|
* @return 结果数据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ContrastTestResult getContrastResultHarm(MonitorResultVO monitorResultVO, List<String> subScriptIds, Integer planCode, DictTree dictTree) {
|
||||||
|
ContrastHarmonicResult result = contrastHarmonicService.getContrastResultHarm(planCode, monitorResultVO.getMonitorId(), subScriptIds, monitorResultVO.getResultType(), Integer.parseInt(monitorResultVO.getWhichTime()));
|
||||||
|
// 收集组数数据
|
||||||
|
int numOfData = contrastHarmonicService.getNumOfData(planCode, monitorResultVO.getMonitorId(), subScriptIds, monitorResultVO.getResultType(), Integer.parseInt(monitorResultVO.getWhichTime()));
|
||||||
|
if (Objects.nonNull(result)) {
|
||||||
|
// 谐波类的获取2~50次的数据
|
||||||
|
ContrastTestResult contrastTestResult = new ContrastTestResult();
|
||||||
|
contrastTestResult.setScriptCode(dictTree.getCode());
|
||||||
|
contrastTestResult.setScriptName(dictTree.getName());
|
||||||
|
contrastTestResult.setHarmonic(true);
|
||||||
|
|
||||||
|
// 判断是否为间谐波
|
||||||
|
boolean isInterHarmonic = "HSV".equals(dictTree.getCode()) || "HSI".equals(dictTree.getCode());
|
||||||
|
|
||||||
|
// 根据指标代码确定小数位数
|
||||||
|
Integer decimalPlaces = getDecimalPlacesByScriptCode(dictTree.getCode());
|
||||||
|
|
||||||
|
// 默认结果是符合的,后续解析过程中存在不符合的,则改为不符合
|
||||||
|
// 构建谐波数据结果Map: 次数 -> 相别 -> List<Map<占位符名称, 占位符值>>
|
||||||
|
List<Map<String, Map<String, Map<String, String>>>> harmonicResult = new ArrayList<>();
|
||||||
|
List<String> allResult = new ArrayList<>();
|
||||||
|
|
||||||
|
// 收集特殊情况信息
|
||||||
|
Map<Integer, List<String>> zeroFilteredMap = new LinkedHashMap<>(); // 双零过滤的次数和相别
|
||||||
|
Map<Integer, Map<String, List<String>>> unComparableMap = new LinkedHashMap<>(); // 无法比较的次数和相别(按组数分组)
|
||||||
|
Map<Integer, Map<String, List<String>>> unqualifiedMap = new LinkedHashMap<>(); // 不符合的次数和相别(按组数分组)
|
||||||
|
int totalDataPoints = 0; // 统计总的数据点数
|
||||||
|
int zeroFilteredPoints = 0; // 统计双零过滤的数据点数
|
||||||
|
|
||||||
|
// 遍历 2~50 次谐波
|
||||||
|
for (int harmNum = 2; harmNum <= 50; harmNum++) {
|
||||||
|
String harmKey = String.valueOf(harmNum);
|
||||||
|
Map<String, Map<String, Map<String, String>>> checkResultHarmonic = new LinkedHashMap<>();
|
||||||
|
List<String> zeroFilteredPhases = new ArrayList<>(); // 当前次数被过滤的相别
|
||||||
|
|
||||||
|
try {
|
||||||
|
Map<String, Map<String, String>> phaseData = new LinkedHashMap<>();
|
||||||
|
boolean hasNonZeroData = false; // 标记是否有非双零数据
|
||||||
|
|
||||||
|
for (String phase : PowerConstant.PHASE_ABC) {
|
||||||
|
Field field = result.getClass().getDeclaredField(phase + "Value" + harmKey);
|
||||||
|
field.setAccessible(true);
|
||||||
|
String valueJson = (String) field.get(result);
|
||||||
|
Map<String, String> singlePhaseData = parseHarmonicPhaseData(valueJson, phase.toUpperCase() + "相", harmNum, numOfData, dictTree.getCode(), decimalPlaces);
|
||||||
|
|
||||||
|
if (CollUtil.isNotEmpty(singlePhaseData)) {
|
||||||
|
totalDataPoints++; // 统计总数据点
|
||||||
|
|
||||||
|
// 检查是否为双零情况
|
||||||
|
String standardVal = singlePhaseData.get(ItemReportKeyEnum.STANDARD.getKey());
|
||||||
|
String testVal = singlePhaseData.get(ItemReportKeyEnum.TEST.getKey());
|
||||||
|
|
||||||
|
// 判断是否为双零(标准值和被检值都为0或"0.0"或"0")
|
||||||
|
boolean isZeroFiltered = isZeroValue(standardVal) && isZeroValue(testVal);
|
||||||
|
|
||||||
|
if (isZeroFiltered) {
|
||||||
|
zeroFilteredPoints++; // 统计双零点
|
||||||
|
// 双零情况,记录但不加入结果判定
|
||||||
|
zeroFilteredPhases.add(phase.toUpperCase() + "相");
|
||||||
|
// 将结果改为特殊标记,不参与整体结论判定
|
||||||
|
singlePhaseData.put(ItemReportKeyEnum.RESULT.getKey(), "双零过滤");
|
||||||
|
} else {
|
||||||
|
// 有非双零数据
|
||||||
|
hasNonZeroData = true;
|
||||||
|
// 非双零情况,正常处理结果
|
||||||
|
String resultTemp = singlePhaseData.get(ItemReportKeyEnum.RESULT.getKey());
|
||||||
|
if (StrUtil.isNotBlank(resultTemp)) {
|
||||||
|
allResult.add(resultTemp);
|
||||||
|
|
||||||
|
// 收集特殊情况
|
||||||
|
if ("无法比较".equals(resultTemp)) {
|
||||||
|
String numOfDataStr = singlePhaseData.get(ItemReportKeyEnum.NUM_OF_DATA.getKey());
|
||||||
|
unComparableMap.computeIfAbsent(harmNum, k -> new LinkedHashMap<>())
|
||||||
|
.computeIfAbsent(numOfDataStr, k -> new ArrayList<>())
|
||||||
|
.add(phase.toUpperCase() + "相");
|
||||||
|
} else if ("不符合".equals(resultTemp)) {
|
||||||
|
String numOfDataStr = singlePhaseData.get(ItemReportKeyEnum.NUM_OF_DATA.getKey());
|
||||||
|
unqualifiedMap.computeIfAbsent(harmNum, k -> new LinkedHashMap<>())
|
||||||
|
.computeIfAbsent(numOfDataStr, k -> new ArrayList<>())
|
||||||
|
.add(phase.toUpperCase() + "相");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
phaseData.put(phase.toUpperCase() + "相", singlePhaseData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 记录当前次数的双零过滤情况
|
||||||
|
if (!zeroFilteredPhases.isEmpty()) {
|
||||||
|
zeroFilteredMap.put(harmNum, zeroFilteredPhases);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只有当该次谐波有非双零数据时,才添加到结果集中
|
||||||
|
if (hasNonZeroData) {
|
||||||
|
checkResultHarmonic.put(harmKey, phaseData);
|
||||||
|
// 如果该次谐波有数据,添加到结果Map中
|
||||||
|
if (CollUtil.isNotEmpty(checkResultHarmonic)) {
|
||||||
|
harmonicResult.add(checkResultHarmonic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
log.warn("获取第{}次谐波数据失败: {}", harmNum, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否所有数据都是双零
|
||||||
|
boolean allDataIsZero = (totalDataPoints > 0 && totalDataPoints == zeroFilteredPoints);
|
||||||
|
|
||||||
|
// 生成specialCase描述
|
||||||
|
String specialCase = generateHarmonicSpecialCase(zeroFilteredMap, unComparableMap, unqualifiedMap,
|
||||||
|
totalDataPoints, zeroFilteredPoints, isInterHarmonic);
|
||||||
|
|
||||||
|
// 设置检测结果
|
||||||
|
String overallResult;
|
||||||
|
if (allDataIsZero) {
|
||||||
|
// 如果所有数据都是双零,结果为符合
|
||||||
|
overallResult = "符合";
|
||||||
|
} else {
|
||||||
|
// 根据所有相数据的结果判断总体结论
|
||||||
|
overallResult = determineOverallResult(allResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
contrastTestResult.setResult(overallResult);
|
||||||
|
contrastTestResult.setSpecialCase(specialCase);
|
||||||
|
contrastTestResult.setCheckResultHarmonic(harmonicResult);
|
||||||
|
|
||||||
|
return contrastTestResult;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断值是否为零
|
||||||
|
* @param value 字符串值
|
||||||
|
* @return 是否为零
|
||||||
|
*/
|
||||||
|
private boolean isZeroValue(String value) {
|
||||||
|
if (StrUtil.isBlank(value) || "/".equals(value) || "null".equals(value)) {
|
||||||
|
return false; // 空值或无效值不算零
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
double d = Double.parseDouble(value);
|
||||||
|
return d == 0.0;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成谐波类特殊情况描述
|
||||||
|
* @param zeroFilteredMap 双零过滤的次数和相别
|
||||||
|
* @param unComparableMap 无法比较的次数和相别
|
||||||
|
* @param unqualifiedMap 不符合的次数和相别
|
||||||
|
* @param totalDataPoints 总数据点数
|
||||||
|
* @param zeroFilteredPoints 双零过滤的数据点数
|
||||||
|
* @param isInterHarmonic 是否为间谐波
|
||||||
|
* @return 特殊情况描述
|
||||||
|
*/
|
||||||
|
private String generateHarmonicSpecialCase(Map<Integer, List<String>> zeroFilteredMap,
|
||||||
|
Map<Integer, Map<String, List<String>>> unComparableMap,
|
||||||
|
Map<Integer, Map<String, List<String>>> unqualifiedMap,
|
||||||
|
int totalDataPoints, int zeroFilteredPoints,
|
||||||
|
boolean isInterHarmonic) {
|
||||||
|
StringBuilder specialCaseDesc = new StringBuilder();
|
||||||
|
boolean hasZeroFiltered = false;
|
||||||
|
boolean allZero = false;
|
||||||
|
|
||||||
|
// 1. 检查双零过滤情况
|
||||||
|
if (!zeroFilteredMap.isEmpty()) {
|
||||||
|
hasZeroFiltered = true;
|
||||||
|
// 判断是否所有数据都是双零
|
||||||
|
allZero = (totalDataPoints > 0 && totalDataPoints == zeroFilteredPoints);
|
||||||
|
|
||||||
|
if (allZero) {
|
||||||
|
// 所有次数的所有相别都是双零,直接返回
|
||||||
|
specialCaseDesc.append("注:因所有谐波次数的标准值与被检值均为0,检测结论为符合。");
|
||||||
|
return specialCaseDesc.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 处理无法比较情况
|
||||||
|
if (!unComparableMap.isEmpty()) {
|
||||||
|
if (specialCaseDesc.length() > 0) {
|
||||||
|
specialCaseDesc.append(" ");
|
||||||
|
} else {
|
||||||
|
specialCaseDesc.append("注:");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并相同情况的次数和相别
|
||||||
|
Map<String, Map<String, List<Integer>>> groupedUnComparable = new LinkedHashMap<>();
|
||||||
|
for (Map.Entry<Integer, Map<String, List<String>>> harmEntry : unComparableMap.entrySet()) {
|
||||||
|
Integer harmNum = harmEntry.getKey();
|
||||||
|
for (Map.Entry<String, List<String>> dataEntry : harmEntry.getValue().entrySet()) {
|
||||||
|
String numOfData = dataEntry.getKey();
|
||||||
|
List<String> phases = dataEntry.getValue();
|
||||||
|
String phaseKey = String.join("、", phases);
|
||||||
|
groupedUnComparable.computeIfAbsent(numOfData, k -> new LinkedHashMap<>())
|
||||||
|
.computeIfAbsent(phaseKey, k -> new ArrayList<>())
|
||||||
|
.add(harmNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成描述
|
||||||
|
for (Map.Entry<String, Map<String, List<Integer>>> dataEntry : groupedUnComparable.entrySet()) {
|
||||||
|
for (Map.Entry<String, List<Integer>> phaseEntry : dataEntry.getValue().entrySet()) {
|
||||||
|
String phases = phaseEntry.getKey();
|
||||||
|
List<Integer> harmNums = phaseEntry.getValue();
|
||||||
|
specialCaseDesc.append("第").append(formatHarmNumbers(harmNums, isInterHarmonic)).append("次谐波");
|
||||||
|
specialCaseDesc.append(phases).append("无样本数据满足误差比较的前置条件,无法执行有效性判定。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 处理不符合情况
|
||||||
|
if (!unqualifiedMap.isEmpty()) {
|
||||||
|
if (specialCaseDesc.length() > 0) {
|
||||||
|
specialCaseDesc.append(" ");
|
||||||
|
} else {
|
||||||
|
specialCaseDesc.append("注:");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新组织数据结构:收集所有相同组数的次数-相别组合
|
||||||
|
Map<String, List<String>> groupedByNumOfData = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, Map<String, List<String>>> harmEntry : unqualifiedMap.entrySet()) {
|
||||||
|
Integer harmNum = harmEntry.getKey();
|
||||||
|
for (Map.Entry<String, List<String>> dataEntry : harmEntry.getValue().entrySet()) {
|
||||||
|
String numOfData = dataEntry.getKey();
|
||||||
|
List<String> phases = dataEntry.getValue();
|
||||||
|
|
||||||
|
// 如果一个次数下有多个相别,合并成一个描述
|
||||||
|
String harmPhaseDesc;
|
||||||
|
String displayHarmNum = getDisplayHarmNumber(harmNum, isInterHarmonic);
|
||||||
|
if (phases.size() == 1) {
|
||||||
|
harmPhaseDesc = "第" + displayHarmNum + "次谐波" + phases.get(0);
|
||||||
|
} else {
|
||||||
|
harmPhaseDesc = "第" + displayHarmNum + "次谐波" + String.join("、", phases);
|
||||||
|
}
|
||||||
|
groupedByNumOfData.computeIfAbsent(numOfData, k -> new ArrayList<>())
|
||||||
|
.add(harmPhaseDesc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成描述
|
||||||
|
for (Map.Entry<String, List<String>> entry : groupedByNumOfData.entrySet()) {
|
||||||
|
String numOfData = entry.getKey();
|
||||||
|
List<String> harmPhaseList = entry.getValue();
|
||||||
|
|
||||||
|
// 合并描述:第4次谐波A相、B相、C相、第32次谐波A相、第44次谐波C相
|
||||||
|
specialCaseDesc.append(String.join("、", harmPhaseList));
|
||||||
|
specialCaseDesc.append("收集有效组数为").append(numOfData)
|
||||||
|
.append("组,误差计算结果不符合误差标准要求。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 最后添加双零过滤的笼统描述(如果有部分双零)
|
||||||
|
if (hasZeroFiltered && !allZero) {
|
||||||
|
if (specialCaseDesc.length() > 0) {
|
||||||
|
specialCaseDesc.append(" ");
|
||||||
|
} else {
|
||||||
|
specialCaseDesc.append("注:");
|
||||||
|
}
|
||||||
|
specialCaseDesc.append("表格不展示标准值与被检值均为0的数据。");
|
||||||
|
}
|
||||||
|
|
||||||
|
return specialCaseDesc.length() > 0 ? specialCaseDesc.toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取显示用的谐波次数
|
||||||
|
* @param harmNum 原始次数(2-50)
|
||||||
|
* @param isInterHarmonic 是否为间谐波
|
||||||
|
* @return 显示用的次数字符串
|
||||||
|
*/
|
||||||
|
private String getDisplayHarmNumber(int harmNum, boolean isInterHarmonic) {
|
||||||
|
if (isInterHarmonic) {
|
||||||
|
// 间谐波:2->1.5, 3->2.5, 4->3.5 ... 50->49.5
|
||||||
|
double displayNum = harmNum - 0.5;
|
||||||
|
// 如果是整数则显示整数,否则显示小数
|
||||||
|
if (displayNum == (int) displayNum) {
|
||||||
|
return String.valueOf((int) displayNum);
|
||||||
|
}
|
||||||
|
return String.valueOf(displayNum);
|
||||||
|
}
|
||||||
|
return String.valueOf(harmNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化谐波次数列表
|
||||||
|
* @param harmNumbers 谐波次数列表
|
||||||
|
* @param isInterHarmonic 是否为间谐波
|
||||||
|
* @return 格式化的字符串,如"2、3、5"或"2-5、7、9-11"(间谐波为"1.5、2.5、3.5")
|
||||||
|
*/
|
||||||
|
private String formatHarmNumbers(List<Integer> harmNumbers, boolean isInterHarmonic) {
|
||||||
|
if (harmNumbers.isEmpty()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
if (harmNumbers.size() == 1) {
|
||||||
|
return getDisplayHarmNumber(harmNumbers.get(0), isInterHarmonic);
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(harmNumbers);
|
||||||
|
|
||||||
|
if (isInterHarmonic) {
|
||||||
|
// 间谐波不使用范围表示,直接用顿号分隔
|
||||||
|
List<String> displayNumbers = new ArrayList<>();
|
||||||
|
for (Integer harmNum : harmNumbers) {
|
||||||
|
displayNumbers.add(getDisplayHarmNumber(harmNum, true));
|
||||||
|
}
|
||||||
|
return String.join("、", displayNumbers);
|
||||||
|
} else {
|
||||||
|
// 普通谐波使用范围表示
|
||||||
|
List<String> parts = new ArrayList<>();
|
||||||
|
int start = harmNumbers.get(0);
|
||||||
|
int end = start;
|
||||||
|
|
||||||
|
for (int i = 1; i < harmNumbers.size(); i++) {
|
||||||
|
int current = harmNumbers.get(i);
|
||||||
|
if (current == end + 1) {
|
||||||
|
end = current;
|
||||||
|
} else {
|
||||||
|
if (start == end) {
|
||||||
|
parts.add(String.valueOf(start));
|
||||||
|
} else if (end - start == 1) {
|
||||||
|
parts.add(start + "、" + end);
|
||||||
|
} else {
|
||||||
|
parts.add(start + "-" + end);
|
||||||
|
}
|
||||||
|
start = current;
|
||||||
|
end = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理最后一组
|
||||||
|
if (start == end) {
|
||||||
|
parts.add(String.valueOf(start));
|
||||||
|
} else if (end - start == 1) {
|
||||||
|
parts.add(start + "、" + end);
|
||||||
|
} else {
|
||||||
|
parts.add(start + "-" + end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return String.join("、", parts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取非谐波类数据的结果数据
|
||||||
|
*
|
||||||
|
* @param monitorResultVO 数据来源信息
|
||||||
|
* @param subScriptId 实际检测指标id
|
||||||
|
* @param planCode 计划code,表名需要
|
||||||
|
* @param dictTree 测试指标信息
|
||||||
|
* @return 结果数据
|
||||||
|
*/
|
||||||
|
private ContrastTestResult getContrastResultNonHarm(MonitorResultVO monitorResultVO, List<String> subScriptId, Integer planCode, DictTree dictTree) {
|
||||||
|
ContrastNonHarmonicResult result = contrastNonHarmonicService.getContrastResultHarm(planCode, monitorResultVO.getMonitorId(), subScriptId, monitorResultVO.getResultType(), Integer.parseInt(monitorResultVO.getWhichTime()));
|
||||||
|
// 收集组数数据
|
||||||
|
int numOfData = contrastNonHarmonicService.getNumOfData(planCode, monitorResultVO.getMonitorId(), subScriptId, monitorResultVO.getResultType(), Integer.parseInt(monitorResultVO.getWhichTime()));
|
||||||
|
if (Objects.nonNull(result)) {
|
||||||
|
// 非谐波类
|
||||||
|
ContrastTestResult contrastTestResult = new ContrastTestResult();
|
||||||
|
contrastTestResult.setScriptCode(dictTree.getCode());
|
||||||
|
contrastTestResult.setScriptName(dictTree.getName());
|
||||||
|
contrastTestResult.setHarmonic(false);
|
||||||
|
List<String> allResult = new ArrayList<>();
|
||||||
|
Map<String, Map<String, String>> checkResultNonHarmonic = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
// 根据指标代码确定小数位数
|
||||||
|
Integer decimalPlaces = getDecimalPlacesByScriptCode(dictTree.getCode());
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 非谐波的需要注意是否为T相还是ABC三相的
|
||||||
|
if (PowerConstant.T_PHASE.contains(dictTree.getCode())) {
|
||||||
|
Field field;
|
||||||
|
if (PowerConstant.TB_PHASE.contains(dictTree.getCode())) {
|
||||||
|
field = result.getClass().getDeclaredField("bValue");
|
||||||
|
} else {
|
||||||
|
field = result.getClass().getDeclaredField("tValue");
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
String valueJson = (String) field.get(result);
|
||||||
|
Map<String, String> singlePhaseData = parseNonHarmonicPhaseData(valueJson, "T相", numOfData, dictTree.getCode(), decimalPlaces);
|
||||||
|
checkResultNonHarmonic.put("T相", singlePhaseData);
|
||||||
|
if (CollUtil.isNotEmpty(singlePhaseData)) {
|
||||||
|
String resultTemp = singlePhaseData.get(ItemReportKeyEnum.RESULT.getKey());
|
||||||
|
if (StrUtil.isNotBlank(resultTemp)) {
|
||||||
|
allResult.add(resultTemp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ABC三相
|
||||||
|
for (String phase : PowerConstant.PHASE_ABC) {
|
||||||
|
Field field = result.getClass().getDeclaredField(phase + "Value");
|
||||||
|
field.setAccessible(true);
|
||||||
|
String valueJson = (String) field.get(result);
|
||||||
|
Map<String, String> singlePhaseData = parseNonHarmonicPhaseData(valueJson, phase.toUpperCase() + "相", numOfData, dictTree.getCode(), decimalPlaces);
|
||||||
|
checkResultNonHarmonic.put(phase.toUpperCase() + "相", singlePhaseData);
|
||||||
|
if (CollUtil.isNotEmpty(singlePhaseData)) {
|
||||||
|
String resultTemp = singlePhaseData.get(ItemReportKeyEnum.RESULT.getKey());
|
||||||
|
if (StrUtil.isNotBlank(resultTemp)) {
|
||||||
|
allResult.add(resultTemp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 specialCase 描述
|
||||||
|
StringBuilder specialCaseDesc = new StringBuilder();
|
||||||
|
List<String> unComparablePhases = new ArrayList<>();
|
||||||
|
Map<String, List<String>> unqualifiedPhasesMap = new LinkedHashMap<>(); // 按组数分组
|
||||||
|
|
||||||
|
// 遍历每个相别的结果,收集特殊情况信息
|
||||||
|
for (Map.Entry<String, Map<String, String>> entry : checkResultNonHarmonic.entrySet()) {
|
||||||
|
String phase = entry.getKey();
|
||||||
|
Map<String, String> phaseData = entry.getValue();
|
||||||
|
String phaseResult = phaseData.get(ItemReportKeyEnum.RESULT.getKey());
|
||||||
|
|
||||||
|
if ("无法比较".equals(phaseResult)) {
|
||||||
|
unComparablePhases.add(phase);
|
||||||
|
} else if ("不符合".equals(phaseResult)) {
|
||||||
|
String numOfDataStr = phaseData.get(ItemReportKeyEnum.NUM_OF_DATA.getKey());
|
||||||
|
// 按组数分组存储相别
|
||||||
|
unqualifiedPhasesMap.computeIfAbsent(numOfDataStr, k -> new ArrayList<>()).add(phase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成无法比较的描述
|
||||||
|
if (!unComparablePhases.isEmpty()) {
|
||||||
|
specialCaseDesc.append("注:");
|
||||||
|
if (unComparablePhases.size() == 1) {
|
||||||
|
specialCaseDesc.append(unComparablePhases.get(0));
|
||||||
|
} else {
|
||||||
|
specialCaseDesc.append(String.join("、", unComparablePhases));
|
||||||
|
}
|
||||||
|
specialCaseDesc.append("无样本数据满足误差比较的前置条件,无法执行有效性判定。");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成不符合的描述(合并相同组数的相别)
|
||||||
|
if (!unqualifiedPhasesMap.isEmpty()) {
|
||||||
|
if (specialCaseDesc.length() > 0) {
|
||||||
|
specialCaseDesc.append(" ");
|
||||||
|
} else {
|
||||||
|
specialCaseDesc.append("注:");
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, List<String>> entry : unqualifiedPhasesMap.entrySet()) {
|
||||||
|
String numOfDataStr = entry.getKey();
|
||||||
|
List<String> phases = entry.getValue();
|
||||||
|
if (phases.size() == 1) {
|
||||||
|
specialCaseDesc.append(phases.get(0));
|
||||||
|
} else {
|
||||||
|
specialCaseDesc.append(String.join("、", phases));
|
||||||
|
}
|
||||||
|
specialCaseDesc.append("收集有效组数为").append(numOfDataStr).append("组,误差计算结果不符合误差标准要求。");
|
||||||
|
if (unqualifiedPhasesMap.size() > 1) {
|
||||||
|
specialCaseDesc.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置检测结果 - 根据所有相数据的结果判断总体结论
|
||||||
|
String overallResult = determineOverallResult(allResult);
|
||||||
|
contrastTestResult.setResult(overallResult);
|
||||||
|
contrastTestResult.setSpecialCase(specialCaseDesc.length() > 0 ? specialCaseDesc.toString() : null);
|
||||||
|
contrastTestResult.setCheckResultNonHarmonic(checkResultNonHarmonic);
|
||||||
|
return contrastTestResult;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("获取{}数据失败", dictTree.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析非谐波数据
|
||||||
|
*
|
||||||
|
* @param valueJson JSON格式的数据
|
||||||
|
* @param phase 相别标识
|
||||||
|
* @param numOfData 收集组数
|
||||||
|
* @param scriptCode 脚本代码,用于判断是否需要特殊格式化
|
||||||
|
* @param decimalPlaces 小数位数,null则不格式化
|
||||||
|
* @return 解析后的数据列表
|
||||||
|
*/
|
||||||
|
private Map<String, String> parseNonHarmonicPhaseData(String valueJson, String phase, int numOfData, String scriptCode, Integer decimalPlaces) {
|
||||||
|
try {
|
||||||
|
// 解析JSON数据,假设是 DetectionData 对象列表
|
||||||
|
List<DetectionData> dataList = JSON.parseArray(valueJson, DetectionData.class);
|
||||||
|
Map<String, String> dataMap = new LinkedHashMap<>();
|
||||||
|
if (CollUtil.isNotEmpty(dataList)) {
|
||||||
|
DetectionData detectionData = dataList.get(0);
|
||||||
|
|
||||||
|
// 相别
|
||||||
|
dataMap.put(ItemReportKeyEnum.PHASE.getKey(), phase);
|
||||||
|
// 有效组数 todo... 目前是对齐组数
|
||||||
|
dataMap.put(ItemReportKeyEnum.NUM_OF_DATA.getKey(), String.valueOf(numOfData));
|
||||||
|
|
||||||
|
// 标准值 - 根据参数决定是否格式化
|
||||||
|
String standardValue = String.valueOf(detectionData.getResultData());
|
||||||
|
if (decimalPlaces != null && detectionData.getResultData() != null) {
|
||||||
|
standardValue = formatSignificantDigits(detectionData.getResultData(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.STANDARD.getKey(), standardValue);
|
||||||
|
|
||||||
|
// 被检值 - 根据参数决定是否格式化
|
||||||
|
String testValue = String.valueOf(detectionData.getData());
|
||||||
|
if (decimalPlaces != null && detectionData.getData() != null) {
|
||||||
|
testValue = formatSignificantDigits(detectionData.getData(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.TEST.getKey(), testValue);
|
||||||
|
|
||||||
|
// 误差 - 根据参数决定是否格式化
|
||||||
|
String errorValue = String.valueOf(detectionData.getErrorData());
|
||||||
|
if (decimalPlaces != null && detectionData.getErrorData() != null) {
|
||||||
|
errorValue = formatSignificantDigits(detectionData.getErrorData().doubleValue(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.ERROR.getKey(), errorValue);
|
||||||
|
|
||||||
|
// 误差范围 - 根据参数决定是否格式化
|
||||||
|
String errorScope = String.valueOf(detectionData.getRadius());
|
||||||
|
if (decimalPlaces != null && detectionData.getRadius() != null) {
|
||||||
|
errorScope = formatErrorRange(detectionData.getRadius(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.A_ERROR_SCOPE.getKey(), errorScope);
|
||||||
|
|
||||||
|
// 结论
|
||||||
|
dataMap.put(ItemReportKeyEnum.RESULT.getKey(), getTestResult(detectionData.getIsData()));
|
||||||
|
} else {
|
||||||
|
// 相别
|
||||||
|
dataMap.put(ItemReportKeyEnum.PHASE.getKey(), phase);
|
||||||
|
// 有效组数
|
||||||
|
dataMap.put(ItemReportKeyEnum.NUM_OF_DATA.getKey(), String.valueOf(0));
|
||||||
|
// 标准值
|
||||||
|
dataMap.put(ItemReportKeyEnum.STANDARD.getKey(), "/");
|
||||||
|
// 被检值
|
||||||
|
dataMap.put(ItemReportKeyEnum.TEST.getKey(), "/");
|
||||||
|
// 误差
|
||||||
|
dataMap.put(ItemReportKeyEnum.ERROR.getKey(), "/");
|
||||||
|
// 误差范围
|
||||||
|
dataMap.put(ItemReportKeyEnum.A_ERROR_SCOPE.getKey(), "/");
|
||||||
|
// 结论
|
||||||
|
dataMap.put(ItemReportKeyEnum.RESULT.getKey(), "无法比较");
|
||||||
|
}
|
||||||
|
return dataMap;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("获取数据失败");
|
||||||
|
|
||||||
|
}
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据所有相数据的检测结果判断总体指标结论
|
||||||
|
* 判断原则:所有都符合就符合,有一个不符合就不符合,如果所有都是无法比较就无法比较
|
||||||
|
*
|
||||||
|
* @param allResult 所有相数据的检测结果集合
|
||||||
|
* @return 总体指标结论
|
||||||
|
*/
|
||||||
|
private String determineOverallResult(List<String> allResult) {
|
||||||
|
if (CollUtil.isEmpty(allResult)) {
|
||||||
|
return "无法比较";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 统计各种结果的数量
|
||||||
|
// 是否有不符合
|
||||||
|
boolean hasUnqualified = false;
|
||||||
|
// 是否有符合
|
||||||
|
boolean hasQualified = false;
|
||||||
|
// 是否有无法比较
|
||||||
|
boolean hasUncomparable = false;
|
||||||
|
|
||||||
|
for (String result : allResult) {
|
||||||
|
if ("不符合".equals(result)) {
|
||||||
|
hasUnqualified = true;
|
||||||
|
} else if ("符合".equals(result)) {
|
||||||
|
hasQualified = true;
|
||||||
|
} else if ("无法比较".equals(result)) {
|
||||||
|
hasUncomparable = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按照优先级判断:有一个不符合就不符合
|
||||||
|
if (hasUnqualified) {
|
||||||
|
return "不符合";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有不符合,且有符合的,就是符合
|
||||||
|
if (hasQualified) {
|
||||||
|
return "符合";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果全部都是无法比较
|
||||||
|
if (hasUncomparable) {
|
||||||
|
return "无法比较";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回无法比较(理论上不会到这里)
|
||||||
|
return "无法比较";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析谐波相数据
|
||||||
|
*
|
||||||
|
* @param jsonData JSON格式的数据
|
||||||
|
* @param phase 相别标识
|
||||||
|
* @param harmNum 谐波次数
|
||||||
|
* @param numOfData 收集组数
|
||||||
|
* @param scriptCode 脚本代码,用于判断是否需要特殊格式化
|
||||||
|
* @param decimalPlaces 小数位数,null则不格式化
|
||||||
|
* @return 解析后的数据列表
|
||||||
|
*/
|
||||||
|
private Map<String, String> parseHarmonicPhaseData(String jsonData, String phase, int harmNum, int numOfData, String scriptCode, Integer decimalPlaces) {
|
||||||
|
try {
|
||||||
|
// 解析JSON数据,假设是 DetectionData 对象列表
|
||||||
|
List<DetectionData> dataList = JSON.parseArray(jsonData, DetectionData.class);
|
||||||
|
Map<String, String> dataMap = new LinkedHashMap<>();
|
||||||
|
if (CollUtil.isNotEmpty(dataList)) {
|
||||||
|
DetectionData detectionData = dataList.get(0);
|
||||||
|
// 次数
|
||||||
|
dataMap.put(ItemReportKeyEnum.TIME.getKey(), String.valueOf(harmNum));
|
||||||
|
// 相别
|
||||||
|
dataMap.put(ItemReportKeyEnum.PHASE.getKey(), phase);
|
||||||
|
// 有效组数 todo... 目前是对齐组数
|
||||||
|
dataMap.put(ItemReportKeyEnum.NUM_OF_DATA.getKey(), String.valueOf(numOfData));
|
||||||
|
|
||||||
|
// 标准值 - 根据参数决定是否格式化
|
||||||
|
String standardValue = String.valueOf(detectionData.getResultData());
|
||||||
|
if (decimalPlaces != null && detectionData.getResultData() != null) {
|
||||||
|
standardValue = formatSignificantDigits(detectionData.getResultData(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.STANDARD.getKey(), standardValue);
|
||||||
|
|
||||||
|
// 被检值 - 根据参数决定是否格式化
|
||||||
|
String testValue = String.valueOf(detectionData.getData());
|
||||||
|
if (decimalPlaces != null && detectionData.getData() != null) {
|
||||||
|
testValue = formatSignificantDigits(detectionData.getData(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.TEST.getKey(), testValue);
|
||||||
|
|
||||||
|
// 误差 - 根据参数决定是否格式化
|
||||||
|
String errorValue = String.valueOf(detectionData.getErrorData());
|
||||||
|
if (decimalPlaces != null && detectionData.getErrorData() != null) {
|
||||||
|
errorValue = formatSignificantDigits(detectionData.getErrorData().doubleValue(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.ERROR.getKey(), errorValue);
|
||||||
|
|
||||||
|
// 误差范围 - 根据参数决定是否格式化
|
||||||
|
String errorScope = String.valueOf(detectionData.getRadius());
|
||||||
|
if (decimalPlaces != null && detectionData.getRadius() != null) {
|
||||||
|
errorScope = formatErrorRange(detectionData.getRadius(), decimalPlaces);
|
||||||
|
}
|
||||||
|
dataMap.put(ItemReportKeyEnum.A_ERROR_SCOPE.getKey(), errorScope);
|
||||||
|
|
||||||
|
// 结论
|
||||||
|
dataMap.put(ItemReportKeyEnum.RESULT.getKey(), getTestResult(detectionData.getIsData()));
|
||||||
|
} else {
|
||||||
|
// 次数
|
||||||
|
dataMap.put(ItemReportKeyEnum.TIME.getKey(), String.valueOf(harmNum));
|
||||||
|
// 相别
|
||||||
|
dataMap.put(ItemReportKeyEnum.PHASE.getKey(), phase);
|
||||||
|
// 有效组数
|
||||||
|
dataMap.put(ItemReportKeyEnum.NUM_OF_DATA.getKey(), "0");
|
||||||
|
// 标准值
|
||||||
|
dataMap.put(ItemReportKeyEnum.STANDARD.getKey(), "/");
|
||||||
|
// 被检值
|
||||||
|
dataMap.put(ItemReportKeyEnum.TEST.getKey(), "/");
|
||||||
|
// 误差
|
||||||
|
dataMap.put(ItemReportKeyEnum.ERROR.getKey(), "/");
|
||||||
|
// 误差范围
|
||||||
|
dataMap.put(ItemReportKeyEnum.A_ERROR_SCOPE.getKey(), "/");
|
||||||
|
// 结论
|
||||||
|
dataMap.put(ItemReportKeyEnum.RESULT.getKey(), "无法比较");
|
||||||
|
}
|
||||||
|
return dataMap;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析{}第{}次谐波数据失败: {}", phase, harmNum, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new HashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否有不合格的数据
|
||||||
|
*
|
||||||
|
* @param dataList 数据列表
|
||||||
|
* @return true表示有不合格数据
|
||||||
|
*/
|
||||||
|
private boolean hasUnqualifiedData(List<Map<String, String>> dataList) {
|
||||||
|
if (CollUtil.isEmpty(dataList)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Map<String, String> data : dataList) {
|
||||||
|
String resultFlag = data.get("resultFlag");
|
||||||
|
// resultFlag: 1-合格,2-不合格,4-无法比较
|
||||||
|
if ("2".equals(resultFlag)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取检测结果
|
||||||
|
*
|
||||||
|
* @param monitorResultVO 回路检测结论信息
|
||||||
|
*/
|
||||||
|
private String getTestResult(MonitorResultVO monitorResultVO) {
|
||||||
|
Integer checkResult = monitorResultVO.getCheckResult();
|
||||||
|
return getTestResult(checkResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取检测结果
|
||||||
|
*
|
||||||
|
* @param checkResult 回路检测结论信息
|
||||||
|
*/
|
||||||
|
private String getTestResult(Integer checkResult) {
|
||||||
|
switch (checkResult) {
|
||||||
|
case 2:
|
||||||
|
return "不符合";
|
||||||
|
case 4:
|
||||||
|
return "无法比较";
|
||||||
|
default:
|
||||||
|
// 因为只有 1、2、4,所以这里直接返回符合
|
||||||
|
return "符合";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, List<RawResultDataVO>> getResultMap(DictTree dictTree, List<String> adTypeList, String monitorId, String unit, Integer num, Integer waveNum, Boolean isWave, String code) {
|
private Map<String, List<RawResultDataVO>> getResultMap(DictTree dictTree, List<String> adTypeList, String monitorId, String unit, Integer num, Integer waveNum, Boolean isWave, String code) {
|
||||||
Map<String, List<RawResultDataVO>> resultMap = new LinkedHashMap<>();
|
Map<String, List<RawResultDataVO>> resultMap = new LinkedHashMap<>();
|
||||||
|
|
||||||
@@ -2511,4 +3270,129 @@ public class ResultServiceImpl implements IResultService {
|
|||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化数值,保留指定的小数位数
|
||||||
|
*
|
||||||
|
* @param value 原始数值
|
||||||
|
* @param decimalPlaces 小数位数
|
||||||
|
* @return 格式化后的字符串
|
||||||
|
*/
|
||||||
|
private String formatSignificantDigits(double value, int decimalPlaces) {
|
||||||
|
if (value == 0.0) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用BigDecimal进行精确计算
|
||||||
|
BigDecimal bd = new BigDecimal(String.valueOf(value));
|
||||||
|
|
||||||
|
// 保留指定的小数位数,四舍五入
|
||||||
|
bd = bd.setScale(decimalPlaces, BigDecimal.ROUND_HALF_UP);
|
||||||
|
|
||||||
|
// 移除末尾的零(可选,根据需要决定是否保留)
|
||||||
|
String result = bd.stripTrailingZeros().toPlainString();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化误差范围,将 "-0.057735~0.057735" 格式化为 "±0.05774"
|
||||||
|
*
|
||||||
|
* @param radiusValue 误差范围值(通常是正数,表示±范围)
|
||||||
|
* @return 格式化后的误差范围字符串
|
||||||
|
*/
|
||||||
|
private String formatErrorRange(double radiusValue) {
|
||||||
|
return formatErrorRangeWithDecimalPlaces(radiusValue, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化误差范围,支持自定义小数位数
|
||||||
|
*
|
||||||
|
* @param radiusValue 误差范围值(通常是正数,表示±范围)
|
||||||
|
* @param decimalPlaces 小数位数
|
||||||
|
* @return 格式化后的误差范围字符串
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* 格式化误差范围字符串,支持处理"-0.05~0.05"格式并转换为"±0.05"格式
|
||||||
|
*
|
||||||
|
* @param errorRange 误差范围字符串
|
||||||
|
* @param decimalPlaces 小数位数
|
||||||
|
* @return 格式化后的误差范围
|
||||||
|
*/
|
||||||
|
private String formatErrorRange(String errorRange, Integer decimalPlaces) {
|
||||||
|
if (errorRange == null || decimalPlaces == null) {
|
||||||
|
return errorRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 尝试直接解析为数字
|
||||||
|
double radiusValue = Double.parseDouble(errorRange);
|
||||||
|
return formatErrorRangeWithDecimalPlaces(radiusValue, decimalPlaces);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 处理"-0.05~0.05"这种格式
|
||||||
|
if (errorRange.contains("~")) {
|
||||||
|
String[] parts = errorRange.split("~");
|
||||||
|
if (parts.length == 2) {
|
||||||
|
try {
|
||||||
|
double minValue = Double.parseDouble(parts[0].trim());
|
||||||
|
double maxValue = Double.parseDouble(parts[1].trim());
|
||||||
|
// 取绝对值的最大值作为范围
|
||||||
|
double absMax = Math.max(Math.abs(minValue), Math.abs(maxValue));
|
||||||
|
return formatErrorRangeWithDecimalPlaces(absMax, decimalPlaces);
|
||||||
|
} catch (NumberFormatException ex) {
|
||||||
|
log.warn("无法解析误差范围格式: {}", errorRange);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果无法解析,返回原值
|
||||||
|
return errorRange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatErrorRangeWithDecimalPlaces(double radiusValue, int decimalPlaces) {
|
||||||
|
if (radiusValue == 0.0) {
|
||||||
|
return "±0";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取绝对值并保留指定小数位数
|
||||||
|
double absValue = Math.abs(radiusValue);
|
||||||
|
String formattedValue = formatSignificantDigits(absValue, decimalPlaces);
|
||||||
|
|
||||||
|
return "±" + formattedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据指标代码获取对应的小数位数
|
||||||
|
*
|
||||||
|
* @param scriptCode 指标代码
|
||||||
|
* @return 小数位数,null表示不格式化
|
||||||
|
*/
|
||||||
|
private Integer getDecimalPlacesByScriptCode(String scriptCode) {
|
||||||
|
if (scriptCode == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (scriptCode) {
|
||||||
|
// 保留2位小数
|
||||||
|
case "FREQ": // 频率
|
||||||
|
return 2;
|
||||||
|
// 保留3位小数
|
||||||
|
case "I": // 电流
|
||||||
|
return 3;
|
||||||
|
// 保留4位小数
|
||||||
|
case "IMBV": // 电压不平衡度
|
||||||
|
case "IMBA": // 电流不平衡度
|
||||||
|
return 4;
|
||||||
|
// 保留5位小数
|
||||||
|
case "V": // 电压
|
||||||
|
case "HV": // 电压谐波
|
||||||
|
case "HI": // 电流谐波
|
||||||
|
case "HP": // 功率谐波
|
||||||
|
case "HSV": // 电压间谐波
|
||||||
|
case "HSI": // 电流间谐波
|
||||||
|
return 5;
|
||||||
|
// 其他指标不格式化
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,16 @@ public class AnalysisServiceStreamTest {
|
|||||||
private ICompareWaveService compareWaveServiceImpl;
|
private ICompareWaveService compareWaveServiceImpl;
|
||||||
|
|
||||||
// 测试文件路径 - 请根据实际情况修改
|
// 测试文件路径 - 请根据实际情况修改
|
||||||
private static final String SOURCE_CFG_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.239\\PQ_PQLD1_000251_20250904_145126_769.cfg";
|
private static final String SOURCE_CFG_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.239\\PQ_PQLD1_000574_20250910_135244_231.cfg";
|
||||||
private static final String SOURCE_DAT_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.239\\PQ_PQLD1_000251_20250904_145126_769.dat";
|
private static final String SOURCE_DAT_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.239\\PQ_PQLD1_000574_20250910_135244_231.dat";
|
||||||
private static final String TARGET_CFG_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.238\\PQ_PQLD2_000099_20250904_145126_750.cfg";
|
private static final String TARGET_CFG_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.238\\PQ_PQLD2_000508_20250910_135244_197.cfg";
|
||||||
private static final String TARGET_DAT_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.238\\PQ_PQLD2_000099_20250904_145126_750.dat";
|
private static final String TARGET_DAT_PATH = "C:\\Users\\hongawen\\Desktop\\Event\\192.168.1.238\\PQ_PQLD2_000508_20250910_135244_197.dat";
|
||||||
|
|
||||||
|
|
||||||
|
// private static final String SOURCE_CFG_PATH = "F:\\hatch\\wavecompare\\数据比对\\统计数据1\\B码\\217\\PQMonitor_PQM1_000006_20200430_115517_889.cfg";
|
||||||
|
// private static final String SOURCE_DAT_PATH = "F:\\hatch\\wavecompare\\数据比对\\统计数据1\\B码\\217\\PQMonitor_PQM1_000006_20200430_115517_889.dat";
|
||||||
|
// private static final String TARGET_CFG_PATH = "F:\\hatch\\wavecompare\\数据比对\\统计数据1\\B码\\216\\PQMonitor_PQM1_000006_20200430_115515_479.cfg";
|
||||||
|
// private static final String TARGET_DAT_PATH = "F:\\hatch\\wavecompare\\数据比对\\统计数据1\\B码\\216\\PQMonitor_PQM1_000006_20200430_115515_479.dat";
|
||||||
|
|
||||||
// 输出路径
|
// 输出路径
|
||||||
private static final String OUTPUT_PATH = "./test-output/";
|
private static final String OUTPUT_PATH = "./test-output/";
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.njcn.gather.storage.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.njcn.gather.storage.pojo.po.ContrastHarmonicResult;
|
import com.njcn.gather.storage.pojo.po.ContrastHarmonicResult;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,4 +34,27 @@ public interface ContrastHarmonicService extends IService<ContrastHarmonicResult
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
List<ContrastHarmonicResult> listAllResultData(String code, Integer num, Integer waveNum, Boolean isWave, String devId, List<String> adTypeList);
|
List<ContrastHarmonicResult> listAllResultData(String code, Integer num, Integer waveNum, Boolean isWave, String devId, List<String> adTypeList);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取谐波检测项的比对结果
|
||||||
|
* @param planCode 计划code
|
||||||
|
* @param monitorId 监测点ID
|
||||||
|
* @param scriptId 指标id
|
||||||
|
* @param resultType 结果类型
|
||||||
|
* @param time 第几次检测
|
||||||
|
* @return 检测结果
|
||||||
|
*/
|
||||||
|
ContrastHarmonicResult getContrastResultHarm(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去原始表获取总次数
|
||||||
|
* @param planCode 计划code
|
||||||
|
* @param monitorId 监测点ID
|
||||||
|
* @param scriptId 指标id
|
||||||
|
* @param resultType 结果类型
|
||||||
|
* @param time 第几次检测
|
||||||
|
* @return 数据组数
|
||||||
|
*/
|
||||||
|
int getNumOfData(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.njcn.gather.storage.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import com.njcn.gather.storage.pojo.po.ContrastNonHarmonicResult;
|
import com.njcn.gather.storage.pojo.po.ContrastNonHarmonicResult;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,4 +40,27 @@ public interface ContrastNonHarmonicService extends IService<ContrastNonHarmonic
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
List<ContrastNonHarmonicResult> listAllResultData(String code, Integer num, Integer waveNum, Boolean isWave, String devId, List<String> adTypeList);
|
List<ContrastNonHarmonicResult> listAllResultData(String code, Integer num, Integer waveNum, Boolean isWave, String devId, List<String> adTypeList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取非谐波检测项的比对结果
|
||||||
|
* @param planCode 计划code
|
||||||
|
* @param monitorId 监测点ID
|
||||||
|
* @param scriptId 指标id
|
||||||
|
* @param resultType 结果类型
|
||||||
|
* @param time 第几次检测
|
||||||
|
* @return 检测结果
|
||||||
|
*/
|
||||||
|
ContrastNonHarmonicResult getContrastResultHarm(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去原始表获取总次数
|
||||||
|
* @param planCode 计划code
|
||||||
|
* @param monitorId 监测点ID
|
||||||
|
* @param scriptId 指标id
|
||||||
|
* @param resultType 结果类型
|
||||||
|
* @param time 第几次检测
|
||||||
|
* @return 数据组数
|
||||||
|
*/
|
||||||
|
int getNumOfData(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.njcn.gather.storage.service.impl;
|
package com.njcn.gather.storage.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.github.yulichang.wrapper.MPJLambdaWrapper;
|
||||||
import com.njcn.db.mybatisplus.handler.DynamicTableNameHandler;
|
import com.njcn.db.mybatisplus.handler.DynamicTableNameHandler;
|
||||||
import com.njcn.gather.storage.mapper.ContrastHarmonicMappper;
|
import com.njcn.gather.storage.mapper.ContrastHarmonicMappper;
|
||||||
import com.njcn.gather.storage.pojo.po.ContrastHarmonicResult;
|
import com.njcn.gather.storage.pojo.po.ContrastHarmonicResult;
|
||||||
@@ -11,6 +13,7 @@ import com.njcn.gather.storage.service.ContrastHarmonicService;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,6 +48,9 @@ public class ContrastHarmonicServiceImpl extends ServiceImpl<ContrastHarmonicMap
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* todo... 缺少统计的数据获取逻辑
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<ContrastHarmonicResult> listAllResultData(String code, Integer num, Integer waveNum, Boolean isWave, String devId, List<String> adTypeList) {
|
public List<ContrastHarmonicResult> listAllResultData(String code, Integer num, Integer waveNum, Boolean isWave, String devId, List<String> adTypeList) {
|
||||||
String prefix = "ad_harmonic_result_" + code;
|
String prefix = "ad_harmonic_result_" + code;
|
||||||
@@ -65,4 +71,72 @@ public class ContrastHarmonicServiceImpl extends ServiceImpl<ContrastHarmonicMap
|
|||||||
DynamicTableNameHandler.remove();
|
DynamicTableNameHandler.remove();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param planCode 计划code
|
||||||
|
* @param monitorId 监测点ID
|
||||||
|
* @param scriptId 指标id
|
||||||
|
* @param resultType 结果类型
|
||||||
|
* @param time 第几次检测
|
||||||
|
* @return 检测结果
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ContrastHarmonicResult getContrastResultHarm(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time) {
|
||||||
|
boolean isWave = resultType.contains("wave_data");
|
||||||
|
int waveTime = 1;
|
||||||
|
if (isWave) {
|
||||||
|
// 说明是要进一步拆解type,查询录波的数据
|
||||||
|
// 从 wave_data_1 格式中提取录波次数
|
||||||
|
String[] parts = resultType.split("_");
|
||||||
|
if (parts.length > 2) {
|
||||||
|
waveTime = Integer.parseInt(parts[parts.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<ContrastHarmonicResult> result = this.listAllResultData(String.valueOf(planCode), time, waveTime, isWave, monitorId, scriptId);
|
||||||
|
if (CollectionUtil.isNotEmpty(result)) {
|
||||||
|
return result.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去原始表获取总次数
|
||||||
|
* @param planCode 计划code
|
||||||
|
* @param monitorId 监测点ID
|
||||||
|
* @param scriptId 指标id
|
||||||
|
* @param resultType 结果类型
|
||||||
|
* @param time 第几次检测
|
||||||
|
* @return 数据组数
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getNumOfData(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time) {
|
||||||
|
String prefix = "ad_harmonic_" + planCode;
|
||||||
|
DynamicTableNameHandler.setTableName(prefix);
|
||||||
|
boolean isWave = resultType.contains("wave_data");
|
||||||
|
int waveTime = 1;
|
||||||
|
if (isWave) {
|
||||||
|
// 说明是要进一步拆解type,查询录波的数据
|
||||||
|
// 从 wave_data_1 格式中提取录波次数
|
||||||
|
String[] parts = resultType.split("_");
|
||||||
|
if (parts.length > 2) {
|
||||||
|
waveTime = Integer.parseInt(parts[parts.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LambdaQueryChainWrapper<ContrastHarmonicResult> wrapper = this.lambdaQuery()
|
||||||
|
.eq(ContrastHarmonicResult::getDevMonitorId, monitorId)
|
||||||
|
.in(ContrastHarmonicResult::getAdType, scriptId)
|
||||||
|
.eq(ContrastHarmonicResult::getFlag, 0)
|
||||||
|
.eq(ContrastHarmonicResult::getNum, time);
|
||||||
|
if(isWave){
|
||||||
|
wrapper.eq(ContrastHarmonicResult::getDataType, "wave_data")
|
||||||
|
.eq(ContrastHarmonicResult::getWaveNum, waveTime);
|
||||||
|
}else{
|
||||||
|
wrapper.eq(ContrastHarmonicResult::getDataType, resultType);
|
||||||
|
}
|
||||||
|
// 执行查询并统计满足条件的记录数
|
||||||
|
int count = wrapper.count();
|
||||||
|
DynamicTableNameHandler.remove();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.njcn.gather.storage.service.impl;
|
package com.njcn.gather.storage.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
@@ -11,6 +12,7 @@ import com.njcn.gather.storage.service.ContrastNonHarmonicService;
|
|||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,4 +67,54 @@ public class ContrastNonHarmonicServiceImpl extends ServiceImpl<ContrastNonHarmo
|
|||||||
DynamicTableNameHandler.remove();
|
DynamicTableNameHandler.remove();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContrastNonHarmonicResult getContrastResultHarm(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time) {
|
||||||
|
boolean isWave = resultType.contains("wave_data");
|
||||||
|
int waveTime = 1;
|
||||||
|
if (isWave) {
|
||||||
|
// 说明是要进一步拆解type,查询录波的数据
|
||||||
|
// 从 wave_data_1 格式中提取录波次数
|
||||||
|
String[] parts = resultType.split("_");
|
||||||
|
if (parts.length > 2) {
|
||||||
|
waveTime = Integer.parseInt(parts[parts.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<ContrastNonHarmonicResult> result = this.listAllResultData(String.valueOf(planCode), time, waveTime, isWave, monitorId, scriptId);
|
||||||
|
if (CollectionUtil.isNotEmpty(result)) {
|
||||||
|
return result.get(0);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumOfData(Integer planCode, String monitorId, List<String> scriptId, String resultType, int time) {
|
||||||
|
String prefix = "ad_non_harmonic_" + planCode;
|
||||||
|
DynamicTableNameHandler.setTableName(prefix);
|
||||||
|
boolean isWave = resultType.contains("wave_data");
|
||||||
|
int waveTime = 1;
|
||||||
|
if (isWave) {
|
||||||
|
// 说明是要进一步拆解type,查询录波的数据
|
||||||
|
// 从 wave_data_1 格式中提取录波次数
|
||||||
|
String[] parts = resultType.split("_");
|
||||||
|
if (parts.length > 2) {
|
||||||
|
waveTime = Integer.parseInt(parts[parts.length - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LambdaQueryChainWrapper<ContrastNonHarmonicResult> wrapper = this.lambdaQuery()
|
||||||
|
.eq(ContrastNonHarmonicResult::getDevMonitorId, monitorId)
|
||||||
|
.in(ContrastNonHarmonicResult::getAdType, scriptId)
|
||||||
|
.eq(ContrastNonHarmonicResult::getFlag, 0)
|
||||||
|
.eq(ContrastNonHarmonicResult::getNum, time);
|
||||||
|
if(isWave){
|
||||||
|
wrapper.eq(ContrastNonHarmonicResult::getDataType, "wave_data")
|
||||||
|
.eq(ContrastNonHarmonicResult::getWaveNum, waveTime);
|
||||||
|
}else{
|
||||||
|
wrapper.eq(ContrastNonHarmonicResult::getDataType, resultType);
|
||||||
|
}
|
||||||
|
// 执行查询并统计满足条件的记录数
|
||||||
|
int count = wrapper.count();
|
||||||
|
DynamicTableNameHandler.remove();
|
||||||
|
return count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,4 +62,25 @@ public interface IDictTreeService extends IService<DictTree> {
|
|||||||
DictTree getDictTreeByCode(String code);
|
DictTree getDictTreeByCode(String code);
|
||||||
|
|
||||||
List<DictTree> listByFatherIds(List<String> fatherIdList);
|
List<DictTree> listByFatherIds(List<String> fatherIdList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取父级字典树
|
||||||
|
* @param id 字典树ID
|
||||||
|
* @return 父级字典树
|
||||||
|
*/
|
||||||
|
DictTree queryParentById(String id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据id获取所有子节点的ID
|
||||||
|
* @param scriptId 字典树ID
|
||||||
|
* @return 所有子节点ID
|
||||||
|
*/
|
||||||
|
List<String> getChildIds(String scriptId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 测试项排个序
|
||||||
|
* @param scriptList 测试项
|
||||||
|
* @return 有序的测试项
|
||||||
|
*/
|
||||||
|
List<String> sort(List<String> scriptList);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.njcn.gather.system.dictionary.service.impl;
|
package com.njcn.gather.system.dictionary.service.impl;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
import cn.hutool.core.text.StrPool;
|
import cn.hutool.core.text.StrPool;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@@ -20,6 +21,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@@ -146,6 +148,38 @@ public class DictTreeServiceImpl extends ServiceImpl<DictTreeMapper, DictTree> i
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DictTree queryParentById(String id) {
|
||||||
|
DictTree temp = this.lambdaQuery().eq(DictTree::getId, id).eq(DictTree::getState, DictConst.ENABLE).one();
|
||||||
|
return this.lambdaQuery().eq(DictTree::getId, temp.getPid()).one();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getChildIds(String scriptId) {
|
||||||
|
List<DictTree> subTree = this.lambdaQuery().eq(DictTree::getPid, scriptId)
|
||||||
|
.eq(DictTree::getState, DictConst.ENABLE)
|
||||||
|
.list();
|
||||||
|
if(CollectionUtil.isNotEmpty(subTree)){
|
||||||
|
return subTree.stream().map(DictTree::getId).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> sort(List<String> scriptList) {
|
||||||
|
if (CollectionUtil.isEmpty(scriptList)) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.lambdaQuery()
|
||||||
|
.in(DictTree::getId, scriptList)
|
||||||
|
.orderByAsc(DictTree::getSort)
|
||||||
|
.list()
|
||||||
|
.stream()
|
||||||
|
.map(DictTree::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
private void checkRepeat(DictTreeParam dictTreeParam, boolean isExcludeSelf) {
|
private void checkRepeat(DictTreeParam dictTreeParam, boolean isExcludeSelf) {
|
||||||
LambdaQueryWrapper<DictTree> wrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<DictTree> wrapper = new LambdaQueryWrapper<>();
|
||||||
wrapper.eq(DictTree::getPid, dictTreeParam.getPid()) // 同一父节点下不能有相同的code
|
wrapper.eq(DictTree::getPid, dictTreeParam.getPid()) // 同一父节点下不能有相同的code
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user