package com.gunshi.project.hsz.service; import cn.hutool.poi.excel.ExcelWriter; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.gunshi.db.dto.DateTimeRangeSo; import com.gunshi.project.hsz.common.model.JcskSyR; import com.gunshi.project.hsz.common.model.vo.*; import com.gunshi.project.hsz.entity.dto.ArtificialJcskSyDeleteDto; import com.gunshi.project.hsz.common.model.so.JcskSyRPageSo; import com.gunshi.project.hsz.common.model.so.OsmoticDetailQuerySo; import com.gunshi.project.hsz.common.model.so.OsmoticQuerySo; import com.gunshi.project.hsz.entity.dto.ProjectSafeCalculateDto; import com.gunshi.project.hsz.entity.vo.*; import com.gunshi.project.hsz.common.mapper.JcskSlBMapper; import com.gunshi.project.hsz.mapper.JcskSyREightAmMapper; import com.gunshi.project.hsz.common.mapper.JcskSyRMapper; import com.gunshi.project.hsz.common.model.JcskSyB; import com.gunshi.project.hsz.model.*; import com.gunshi.project.hsz.util.*; import com.ruoyi.common.utils.StringUtils; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.net.URLEncoder; import java.text.SimpleDateFormat; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @Service @Slf4j @Transactional(rollbackFor = Exception.class) public class JcskSyRService extends ServiceImpl { @Autowired private JcskSyBService jcskSyBService; @Autowired private JcskGnssRService jcskGnssRService; @Autowired private JcskSlBMapper jcskSlBMapper; @Autowired private AttDamProfileService attDamProfileService; @Autowired private JcskSyREightAmMapper jcskSyREightAmMapper; @Autowired private SyRegressionDataService syRegressionDataService; @Autowired private SyDataCheckRuleService syDataCheckRuleService; public Page pageQuery(JcskSyRPageSo page) { Page res = this.baseMapper.queryPage(page.getPageSo().toPage(),page); return res; } // 使用更现代的日期时间API private Date parseDateSafe(String dateStr) { if (dateStr == null) return null; // 移除可能的时区信息 dateStr = dateStr.replace("T", " ").split("\\.")[0]; try { LocalDateTime localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); } catch (Exception e) { try { LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd")); return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); } catch (Exception e2) { throw new RuntimeException("无法解析日期: " + dateStr, e2); } } } public List listValue(Integer type) { List list; try { if(type == 1){ list = baseMapper.listValue(); }else { list = jcskSlBMapper.listValue(); //list = baseMapper.flowListValue(); } OsmoticQuerySo so = new OsmoticQuerySo(); List stationCodes = list.stream().map(JcskSyRVo::getStationCode).collect(Collectors.toList()); if(list.stream().filter(o->o.getTm() != null).collect(Collectors.toList()).size() > 0 ){ String maxTm = list.stream().filter(o->o.getTm() != null).max(Comparator.comparing(JcskSyRVo::getTm)).get().getTm().toString(); String minTm = list.stream().filter(o->o.getTm() != null).min(Comparator.comparing(JcskSyRVo::getTm)).get().getTm().toString(); so.setStationCodes(stationCodes); DateTimeRangeSo dateTimeRangeSo = new DateTimeRangeSo(); dateTimeRangeSo.setStart(parseDateSafe(minTm)); dateTimeRangeSo.setEnd(parseDateSafe(maxTm)); so.setDateTimeRangeSo(dateTimeRangeSo); List warnList = baseMapper.queryWarn(so); list.stream().map(o->{ if(o.getTm() != null && DateUtil.hoursBetweenDate(parseDateSafe(o.getTm().toString()), new Date()) > 48){ o.setFlag(1); } Boolean b = warnList.stream().filter(t->t.getStationCode().equals(o.getStationCode()) && t.getTm().equals(o.getTm())).findAny().isPresent(); if(b){ o.setStatus(1); } String stationCode = o.getStationCode(); LambdaQueryWrapper wq = new LambdaQueryWrapper(); wq.eq(JcskSyB::getDvcd, stationCode); List jcskSyBS = jcskSyBService.list(wq); if(!jcskSyBS.isEmpty()){ o.setProfileName(jcskSyBS.get(0).getDm().toString()); } return o; }).collect(Collectors.toList()); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } return list; } public List detailValue(OsmoticDetailQuerySo so) { List list; if(so.getType() == 1){ list = baseMapper.detailValue(so); }else{ list = jcskSlBMapper.detailValue(so); } if(so.getType() == 2){ return list; } OsmoticQuerySo osmoticQuerySo = new OsmoticQuerySo(); BeanUtils.copyProperties(so,osmoticQuerySo); List stRzVos = baseMapper.queryLineRz(osmoticQuerySo,jcskGnssRService.getStcd()); return bindPressDetail(list,stRzVos); } /** * 将时间转换为整点时间 * 例如:2024-10-14 15:30:00 → 2024-10-14 15:00:00 * 2024-10-14 15:45:25 → 2024-10-14 15:00:00 */ private String getHourTime(String timeStr) { try { if (timeStr == null || timeStr.length() < 16) { return timeStr; } // 假设时间格式为 "yyyy-MM-dd HH:mm:ss" // 取到小时部分,分钟和秒设为00 return timeStr.substring(0, 14) + "00:00"; } catch (Exception e) { return timeStr; } } private List bindPressDetail(List list, List stRzVos) { HashSet timeSet = new HashSet<>(); list.forEach(v -> timeSet.add(v.getTm())); stRzVos.forEach(v -> timeSet.add(v.getTm())); List result = new ArrayList<>(); timeSet.forEach(time -> { OsmoticPressDetailVo vo = new OsmoticPressDetailVo(); vo.setTm(time); result.add(vo); }); List resList = result.stream().map(vo -> { // 查询库水位数据:如果时间不是整点,使用整点时间查询 String hourTimeForRz = getHourTime(vo.getTm()); stRzVos.stream() .filter(rz -> hourTimeForRz.equals(rz.getTm())) .findFirst() .ifPresent(rz -> vo.setRz(rz.getRz())); // 匹配压力数据:使用原始时间 list.stream() .filter(press -> vo.getTm().equals(press.getTm())) .findFirst() .ifPresent(press -> vo.setValue(press.getValue())); return vo; }).collect(Collectors.toList()); // 修改为倒序排序 return resList.stream() .sorted(Comparator.comparing(OsmoticPressDetailVo::getTm).reversed()) .collect(Collectors.toList()); } public Map stat() { Map map = new HashMap<>(); List press = this.listValue(1); Integer pressSize = press.size(); Long pressWarn = press.stream().filter(o -> o.getStatus() == 1).collect(Collectors.counting()); List flow = this.listValue(2); Integer flowSize = flow.size(); Long flowWarn = flow.stream().filter(o -> o.getStatus() == 1).collect(Collectors.counting()); List shift = jcskGnssRService.listValue(); Integer shiftSize = shift.size(); Long shiftWarn = shift.stream().filter(o -> o.getXStatus() == 1 || o.getYStatus() ==1 || o.getHStatus() == 1).collect(Collectors.counting()); Integer size = pressSize + flowSize + shiftSize; Integer warn = Stream.of(pressWarn, flowWarn, shiftWarn).mapToInt(Long::intValue).sum(); map.put(warn,size); return map; } /** * 测值查询,管水位和库水位数据固定查询每日早8点 * @param osmoticQuerySo * @return */ public List queryValue(OsmoticQuerySo osmoticQuerySo, Integer year) { if(osmoticQuerySo.getType() == null) { osmoticQuerySo.setType(1); } List resList = new ArrayList<>(); if(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(osmoticQuerySo.getStationCodes())){ return resList; } String stcd = jcskGnssRService.getStcd(); Boolean isDesc = true; //查询测站降雨量 Map drpMap = new HashMap<>(); if(year != null){ isDesc = false; List drpList = baseMapper.queryDrp(year,stcd); drpMap = drpList.stream().collect(Collectors.toMap(StRzVo::getTm, StRzVo::getRz)); } List dateList = DateUtil.getDatesBetween(osmoticQuerySo.getDateTimeRangeSo().getStart(), osmoticQuerySo.getDateTimeRangeSo().getEnd(),isDesc); //查询库水位 List list = baseMapper.queryRz(osmoticQuerySo,stcd); Map rzMap = list.stream().collect(Collectors.toMap(StRzVo::getTm, StRzVo::getRz)); //查询测站管水位/渗流量 List valueList; if(osmoticQuerySo.getType() == 1){ //渗压数据 valueList = baseMapper.query8AmValue(osmoticQuerySo); }else{ //渗流数据 valueList = jcskSlBMapper.query8AmValue(osmoticQuerySo); } //数据处理 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); for(String str : dateList){ OsmoticStationVo2 vo = new OsmoticStationVo2(); vo.setTm(str); vo.setRz(rzMap.get(str)); vo.setDrp(drpMap.get(str)); List collect = valueList.stream() .filter(o -> { if (o.getTm() != null) { // 将Date格式化为yyyy-MM-dd字符串进行比较 String dateStr = o.getTm().substring(0,10); return str.equals(dateStr); } return false; }) .peek(o->o.setTm(str)) .collect(Collectors.toList()); vo.setList(collect); resList.add(vo); } return resList; } public List queryChart(OsmoticQuerySo osmoticQuerySo,Integer year) { List resList = new ArrayList<>(); List stationCodes = osmoticQuerySo.getStationCodes(); if(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(stationCodes)){ return resList; } String stcd = jcskGnssRService.getStcd(); //查询库水位 List list = baseMapper.queryRz2(osmoticQuerySo,stcd); Map rzMap = list.stream().collect(Collectors.toMap(StRzVo::getTm, StRzVo::getRz)); //查询测站管水位 List valueList; if(osmoticQuerySo.getType() == 1){ //渗压数据 valueList = baseMapper.queryValue(osmoticQuerySo); }else{ //渗流数据 valueList = jcskSlBMapper.queryValue(osmoticQuerySo); } //按测站分组 Map> map = valueList.stream().collect(Collectors.groupingBy(OsmoticValueVo2::getStationCode)); for(String code : stationCodes){ OsmoticChartVo2 vo = new OsmoticChartVo2(); vo.setCd(code); if(map.containsKey(code)){ List voList = map.get(code); OsmoticValueVo2 max = voList.stream().max(Comparator.comparing(OsmoticValueVo2::getValue)).get(); OsmoticValueVo2 min = voList.stream().min(Comparator.comparing(OsmoticValueVo2::getValue)).get(); vo.setCd(code); vo.setMaxValue(max.getValue()); vo.setMaxTm(max.getTm()); vo.setMinValue(min.getValue()); vo.setMinTm(min.getTm()); vo.setDiff(max.getValue().subtract(min.getValue())); if(year == null){ vo.setDetailVos(bindData(MyBeanUtil.collectionCopy(list,OsmoticChartDetailVo.class),MyBeanUtil.collectionCopy(voList,OsmoticChartDetailVo.class))); } }else { vo.setDetailVos(new ArrayList<>()); } if(vo.getDetailVos() != null){ for (OsmoticChartDetailVo detailVo : vo.getDetailVos()) { detailVo.setRz(rzMap.get(detailVo.getTm())); } }else{ vo.setDetailVos(new ArrayList<>()); } resList.add(vo); } //查询测站降雨量 List drpList; if(year != null){ drpList = baseMapper.queryDrp(year,stcd); OsmoticChartVo2 chartVo = new OsmoticChartVo2(); chartVo.setCd("rz"); if(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(list)){ StRzVo max = list.stream().max(Comparator.comparing(StRzVo::getRz)).get(); StRzVo min = list.stream().min(Comparator.comparing(StRzVo::getRz)).get(); chartVo.setMaxValue(max.getRz()); chartVo.setMaxTm(max.getTm()); chartVo.setMinValue(min.getRz()); chartVo.setMinTm(min.getTm()); chartVo.setDiff(max.getRz().subtract(min.getRz())); resList.add(chartVo); } if(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(drpList)){ OsmoticChartVo2 drpVo = new OsmoticChartVo2(); drpVo.setCd("drp"); StRzVo maxDrp = drpList.stream().max(Comparator.comparing(StRzVo::getRz)).get(); StRzVo minDrp = drpList.stream().min(Comparator.comparing(StRzVo::getRz)).get(); drpVo.setMaxValue(maxDrp.getRz()); drpVo.setMaxTm(maxDrp.getTm()); drpVo.setMinValue(minDrp.getRz()); drpVo.setMinTm(minDrp.getTm()); drpVo.setDiff(maxDrp.getRz().subtract(minDrp.getRz())); resList.add(drpVo); } } return resList; } //根据监测时间合并管水位和库水位数据 private List bindData(List tmRzList, List voList) { HashSet strings = new HashSet<>(); tmRzList.stream().forEach(v1 -> strings.add(v1.getTm())); voList.stream().forEach(v1 -> strings.add(v1.getTm())); List result = new ArrayList<>(); strings.stream().forEach(v1 ->{ OsmoticChartDetailVo v = new OsmoticChartDetailVo(); v.setTm(v1); result.add(v); }); List list = result.stream().map(v1 -> { tmRzList.stream().filter(v2 -> v1.getTm().equals(v2.getTm())).forEach(v2 -> { v1.setRz(v2.getRz()); }); voList.stream().filter(v2 -> v1.getTm().equals(v2.getTm())).forEach(v2 -> { v1.setValue(v2.getValue()); }); return v1; }).collect(Collectors.toList()); return list.stream().sorted(Comparator.comparing(OsmoticChartDetailVo::getTm)).collect(Collectors.toList()); } public List infiltraLine(OsmoticQuerySo osmoticQuerySo) { List resList = new ArrayList<>(); String stcd = jcskGnssRService.getStcd(); //查询库水位 //TODO 数据是每整点过五分监测一次(暂时修改,看后续实际数据来了之后会怎么样) List list = baseMapper.queryLineRz(osmoticQuerySo,stcd); Map rzMap = list.stream().collect(Collectors.toMap(StRzVo::getTm, StRzVo::getRz)); //查询测站管水位 List valueList = baseMapper.queryLineValue(osmoticQuerySo); //查询测站预警信息 List warnList = baseMapper.queryWarn(osmoticQuerySo); valueList.stream().map(vo->{ Boolean b = warnList.stream().filter(o->o.getStationCode().equals(vo.getStationCode()) && o.getTm().equals(vo.getTm())).findAny().isPresent(); if(b){ vo.setStatus(0); } return vo; }).collect(Collectors.toList()); HashSet dateList = new HashSet<>(); list.stream().forEach(v1 -> dateList.add(v1.getTm())); valueList.stream().forEach(v1 -> dateList.add(v1.getTm())); // 过滤出整点时间数据 List hourList = dateList.stream() .filter(tm -> tm.matches(".*:00:00$")) // 匹配以:00:00结尾的时间 .collect(Collectors.toList()); for(String str : hourList){ OsmoticStationVo2 vo = new OsmoticStationVo2(); vo.setTm(str); vo.setRz(rzMap.get(str)); List newList = valueList.stream().filter(o->str.equals(o.getTm())).collect(Collectors.toList()); vo.setList(newList); if(com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isNotEmpty(newList) && newList.stream().filter(o->o.getStatus() == 0).findAny().isPresent()){ vo.setStatus(0); } resList.add(vo); } return resList.stream().sorted(Comparator.comparing(OsmoticStationVo2::getTm).reversed()).collect(Collectors.toList()); } public void export(OsmoticQuerySo osmoticQuerySo, HttpServletResponse response) { //通过断面查询渗压设备 List stationCodes = osmoticQuerySo.getStationCodes(); //表头信息 List heads = new ArrayList<>(); heads.add("序号"); heads.add("时间"); heads.add("库水位(m)"); heads.addAll(stationCodes); heads.add("结果分析"); //表格数据 List resList = infiltraLine(osmoticQuerySo); List> list = new ArrayList<>(); for (int j = 0;j < resList.size(); j++) { OsmoticStationVo2 vo = resList.get(j); Map test = new LinkedHashMap<>(); test.put("t0",j+1); test.put("t1", vo.getTm()); test.put("t2", vo.getRz()); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); OsmoticValueVo2 valueVo = vo.getList().stream().filter(o->code.equals(o.getStationCode())).findFirst().orElse(null); test.put(code,valueVo != null ? valueVo.getValue() : ""); } test.put("t4", vo.getStatus() == 0 ? "异常":"正常"); list.add(test); } List> hs = new ArrayList<>(); for (String s : heads) { hs.add(Arrays.asList(s)); } ExcelUtil.exportExcel(hs, DataHandleUtil.tableData(list), "浸润线", response, "浸润线"); } private OsmoticQuerySo commonQueryHandle(OsmoticQuerySo osmoticQuerySo){ String year = osmoticQuerySo.getYear(); try { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date start = sdf.parse(year + "-01-01 00:00:00"); Date end = sdf.parse(year + "-12-31 23:59:59"); // 建议使用 23:59:59 DateTimeRangeSo so = new DateTimeRangeSo(); so.setStart(start); so.setEnd(end); osmoticQuerySo.setDateTimeRangeSo(so); return osmoticQuerySo; } catch (Exception e) { throw new IllegalArgumentException("日期格式错误: " + year, e); } } public List yearStat(OsmoticQuerySo osmoticQuerySo) { commonQueryHandle(osmoticQuerySo); return queryValue(osmoticQuerySo,Integer.valueOf(osmoticQuerySo.getYear())); } public List yearStatValue(OsmoticQuerySo osmoticQuerySo) { commonQueryHandle(osmoticQuerySo); return queryChart(osmoticQuerySo,Integer.valueOf(osmoticQuerySo.getYear())); } public void yearStatExport(OsmoticQuerySo osmoticQuerySo, HttpServletResponse response) { String headName = osmoticQuerySo.getProfileName() + "断面测压管水位(m)"; String fileName = "断面年度渗压统计"; String sheetName = "年度渗压统计"; if(osmoticQuerySo.getType() == 1){ fileName = osmoticQuerySo.getProfileName() + fileName; }else { headName = "渗流量(L/s)"; fileName = "年度渗流统计"; sheetName = "年度渗流统计"; } //上方表格数据 List resList = yearStat(osmoticQuerySo); //下方特征值数据 List chartList = queryChart(osmoticQuerySo,Integer.valueOf(osmoticQuerySo.getYear())); List stationCodes = osmoticQuerySo.getStationCodes(); //表头信息 List> headList = new ArrayList<>(); List heads1 = new ArrayList<>(); heads1.add("序号"); heads1.add("序号"); headList.add(heads1); List heads2 = new ArrayList<>(); heads2.add("监测日期"); heads2.add("监测日期"); headList.add(heads2); for(String code : stationCodes){ List heads = new ArrayList<>(); heads.add(headName); heads.add(code); headList.add(heads); } List heads3 = new ArrayList<>(); heads3.add("库水位(m)"); heads3.add("库水位(m)"); headList.add(heads3); List heads4 = new ArrayList<>(); heads4.add("降雨量(mm)"); heads4.add("降雨量(mm)"); headList.add(heads4); List> list = new ArrayList<>(); for (int j = 0;j < resList.size(); j++) { OsmoticStationVo2 vo = resList.get(j); Map test = new LinkedHashMap<>(); test.put("t0",j+1); test.put("t1", vo.getTm()); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); OsmoticValueVo2 valueVo = vo.getList().stream().filter(o->code.equals(o.getStationCode())).findFirst().orElse(null); test.put(code,valueVo != null ? valueVo.getValue() : ""); } test.put("t2", vo.getRz()); test.put("t3", vo.getDrp()); list.add(test); } Map max = new LinkedHashMap<>(); max.put("t0","全年度特征值统计"); max.put("t1", "最大值"); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); max.put(code,chartList.stream().filter(o->code.equals(o.getCd())).findFirst().get().getMaxValue()); } max.put("t2", chartList.stream().filter(o->"rz".equals(o.getCd())).findFirst().get().getMaxValue()); max.put("t3", chartList.stream().filter(o->"drp".equals(o.getCd())).findFirst().get().getMaxValue()); list.add(max); Map maxTm = new LinkedHashMap<>(); maxTm.put("t0","全年度特征值统计"); maxTm.put("t1", "日期"); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); maxTm.put(code,chartList.stream().filter(o->code.equals(o.getCd())).findFirst().get().getMaxTm()); } maxTm.put("t2", chartList.stream().filter(o->"rz".equals(o.getCd())).findFirst().get().getMaxTm()); maxTm.put("t3", chartList.stream().filter(o->"drp".equals(o.getCd())).findFirst().get().getMaxTm()); list.add(maxTm); Map min = new LinkedHashMap<>(); min.put("t0","全年度特征值统计"); min.put("t1", "最小值"); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); min.put(code,chartList.stream().filter(o->code.equals(o.getCd())).findFirst().get().getMinValue()); } min.put("t2", chartList.stream().filter(o->"rz".equals(o.getCd())).findFirst().get().getMinValue()); min.put("t3", chartList.stream().filter(o->"drp".equals(o.getCd())).findFirst().get().getMinValue()); list.add(min); Map minTm = new LinkedHashMap<>(); minTm.put("t0","全年度特征值统计"); minTm.put("t1", "日期"); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); minTm.put(code,chartList.stream().filter(o->code.equals(o.getCd())).findFirst().get().getMinTm()); } minTm.put("t2", chartList.stream().filter(o->"rz".equals(o.getCd())).findFirst().get().getMinTm()); minTm.put("t3", chartList.stream().filter(o->"drp".equals(o.getCd())).findFirst().get().getMinTm()); list.add(minTm); Map diff = new LinkedHashMap<>(); diff.put("t0","全年度特征值统计"); diff.put("t1", "年变幅"); for(int i = 0;i < stationCodes.size();i++){ String code = stationCodes.get(i); diff.put(code,chartList.stream().filter(o->code.equals(o.getCd())).findFirst().get().getDiff()); } diff.put("t2", chartList.stream().filter(o->"rz".equals(o.getCd())).findFirst().get().getDiff()); diff.put("t3", chartList.stream().filter(o->"drp".equals(o.getCd())).findFirst().get().getDiff()); list.add(diff); ExcelUtil.exportExcel(headList, DataHandleUtil.tableData(list),2,new int[]{0},fileName,response,sheetName); } public List listDvcd() { List dms = this.baseMapper.listDm();//查询断面 List res = new ArrayList<>(); for (String dm : dms) { DmDvcdVo vo = new DmDvcdVo(); vo.setDm(dm); vo.setDvcd(this.baseMapper.listDvcdByDm(dm)); res.add(vo); } return res; } public List listStcdMpcd() { List syBList = this.baseMapper.listStcdMpcd(); List syStcdMpcdVoList = new ArrayList<>(); Map> groupMapData = syBList.stream().collect( Collectors.groupingBy(JcskSyB::getStcd, Collectors.mapping(JcskSyB::getMpcd, Collectors.toList())) ); groupMapData.entrySet().stream().forEach(entry -> { SyStcdMpcdVo entity = new SyStcdMpcdVo(); entity.setStcd(entry.getKey()); entity.setMpcdList(entry.getValue()); syStcdMpcdVoList.add(entity); }); return syStcdMpcdVoList; } public Page historyPage(JcskSyRPageSo page) { return this.baseMapper.historyPage(page.getPageSo().toPage(),page); } public boolean saveData(JcskSyR dto) { List list = jcskSyBService.lambdaQuery().eq(JcskSyB::getDvcd, dto.getDvcd()).last("limit 1").list(); JcskSyB jcskSyB = list.get(0); dto.setStcd(jcskSyB.getStcd()); dto.setMpcd(jcskSyB.getMpcd()); dto.setIsArtificial(1); dto.setUpdateTm(LocalDateTime.now()); int insert = this.baseMapper.insert(dto); return insert > 0; } public boolean updateData(JcskSyR dto) { List list = jcskSyBService.lambdaQuery().eq(JcskSyB::getDvcd, dto.getDvcd()).last("limit 1").list(); JcskSyB jcskSyB = list.get(0); String stcd = jcskSyB.getStcd(); String mpcd = jcskSyB.getMpcd(); LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); wrapper.eq(JcskSyR::getMstm, dto.getMstm()) .eq(JcskSyR::getMpcd, dto.getMpcd()) .eq(JcskSyR::getStcd,dto.getStcd()) .set(JcskSyR::getHycncd, dto.getHycncd()) .set(JcskSyR::getRscd, dto.getRscd()) .set(JcskSyR::getSpprwl, dto.getSpprwl()) .set(JcskSyR::getTm, dto.getTm()) .set(JcskSyR::getUpdateTm, new Date()) .set(JcskSyR::getMpcd, mpcd) .set(JcskSyR::getStcd, stcd) .set(JcskSyR::getMstm,dto.getUpdateMstm()); int update = this.baseMapper.update(wrapper); return update > 0; } public Page artificialPage(JcskSyRPageSo page) { Page res = this.baseMapper.artificialPage(page.getPageSo().toPage(),page); return res; } public String transforDateToString(Date date) { // 将Date转换为LocalDateTime if(date == null){ return null; } LocalDateTime localDateTime = date.toInstant() .atZone(ZoneId.systemDefault()) .toLocalDateTime(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formattedDate = localDateTime.format(formatter); return formattedDate; } public void artificialExport(JcskSyRPageSo page, HttpServletResponse response) { Page res = this.baseMapper.artificialPage(page.getPageSo().toPage(), page); List records = res.getRecords(); // 创建导出数据列表 List> exportData = new ArrayList<>(); for (JcskSyR record : records) { Map row = new HashMap<>(); row.put("mstm", record.getMstm().toString()); row.put("tm", record.getTm()); row.put("spprwl", record.getSpprwl()); row.put("isArtificial", record.getIsArtificial() != null && record.getIsArtificial() == 1 ? "人工录入" : "自动采集"); row.put("updateTm", DateTransforUtil.transforLocalDateTimeToString(record.getUpdateTm(),"yyyy-MM-dd HH:mm:ss")); row.put("dm", record.getDm()); row.put("dmName", record.getDmName()); row.put("dvcd", record.getDvcd()); // 改为测点编号 exportData.add(row); } // 通过工具类创建writer ExcelWriter writer = cn.hutool.poi.excel.ExcelUtil.getWriter(); // 自定义标题(去掉水库代码、水工建筑物编号、stcd、mpcd) writer.addHeaderAlias("dvcd", "测点编号"); writer.addHeaderAlias("mstm", "测量时间"); writer.addHeaderAlias("tm", "温度(℃)"); writer.addHeaderAlias("spprwl", "渗流压力水位(m)"); writer.addHeaderAlias("isArtificial", "录入方式"); writer.addHeaderAlias("updateTm", "更新时间"); writer.addHeaderAlias("dm", "断面编码"); writer.addHeaderAlias("dmName", "断面名称"); // 只写出设置了别名的字段 writer.setOnlyAlias(true); // 一次性写出内容 writer.write(exportData, true); // 设置响应内容类型 response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"); try { // 设置响应头信息 String fileName = URLEncoder.encode("渗流压力人工录入数据", "UTF-8"); response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx"); // 将writer对象刷新到响应输出流中 writer.flush(response.getOutputStream(), true); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("导出Excel失败", e); } finally { // 关闭writer,释放内存 writer.close(); } } public boolean deleteData(ArtificialJcskSyDeleteDto dto) { if(StringUtils.isBlank(dto.getStcd())) { throw new IllegalArgumentException("stcd不能为空"); } if(StringUtils.isBlank(dto.getMpcd())){ throw new IllegalArgumentException("mpcd不能为空"); } if(dto.getMstm() == null){ throw new IllegalArgumentException("时间不能为空"); } LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(JcskSyR::getStcd, dto.getStcd()); queryWrapper.eq(JcskSyR::getMstm, dto.getMstm()); queryWrapper.eq(JcskSyR::getMpcd,dto.getMpcd()); queryWrapper.eq(JcskSyR::getIsArtificial,1); int delete = this.baseMapper.delete(queryWrapper); return delete > 0; } @Autowired private AttResBaseService attResBaseService; /** * 多项式方程计算 * @param dto * @return */ public ProjectSafeCalculateVo calculate(@NotNull ProjectSafeCalculateDto dto) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); ProjectSafeCalculateVo res = new ProjectSafeCalculateVo(); //根据dvcd查询stcd和mpcd queryWrapper.eq(JcskSyB::getDvcd, dto.getDvcd()); JcskSyB jcskSyB = jcskSyBService.getBaseMapper().selectOne(queryWrapper); String stcd = jcskSyB.getStcd(); String mpcd = jcskSyB.getMpcd(); //取得这个时间段得所有八点得数据 LambdaQueryWrapper eightAmLambdaQueryWrapper = new LambdaQueryWrapper<>(); eightAmLambdaQueryWrapper.eq(JcskSyREightAm::getStcd, stcd); eightAmLambdaQueryWrapper.eq(JcskSyREightAm::getMpcd, mpcd); eightAmLambdaQueryWrapper.ge(JcskSyREightAm::getMstm,dto.getDateTimeRangeSo().getStart()); eightAmLambdaQueryWrapper.le(JcskSyREightAm::getMstm,dto.getDateTimeRangeSo().getEnd()); eightAmLambdaQueryWrapper.orderByAsc(JcskSyREightAm::getMstm); List jcskSyREightAms = jcskSyREightAmMapper.selectList(eightAmLambdaQueryWrapper); AttResBase attResBase = attResBaseService.list().get(0); OsmoticQuerySo querySo = new OsmoticQuerySo(); querySo.setDateTimeRangeSo(dto.getDateTimeRangeSo()); List stRzVos = baseMapper.qeury8AmRz(querySo,attResBase.getStcd()); Map rzMap = stRzVos.stream() .collect(Collectors.toMap( StRzVo::getTm, // key: 时间 StRzVo::getRz, // value: 水位 (existing, replacement) -> existing // 如果key冲突,保留已存在的 )); //组合成为 时间 库水位 管道水位的数据 List data = new ArrayList<>(); Iterator iterator = jcskSyREightAms.iterator(); while (iterator.hasNext()) { JcskSyREightAm eightAm = iterator.next(); if(eightAm.getMstm() == null || eightAm.getSpprwl() == null){ iterator.remove(); } OsmoticPressDetailVo detailVo = new OsmoticPressDetailVo(); // 设置监测时间和监测值(管道水位) String mstmStr = eightAm.getMstm().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); detailVo.setTm(mstmStr); detailVo.setValue(eightAm.getSpprwl()); // 查找对应的库水位 BigDecimal rzValue = findClosestRzValue(rzMap, mstmStr); if(rzValue == null){ iterator.remove(); } detailVo.setRz(rzValue); //获取数据清洗规则 SyDataCheckRule rule = syDataCheckRuleService.getByDvcd(dto.getDvcd()); if(rule != null && rule.getIsAvailable() == 1){ //校验这条数据是否符合规则 if(rzValue.compareTo(rule.getRz()) >=0){ //如果当前库水位大于等于设置库水位,则跳过这条数据 iterator.remove(); } if(eightAm.getSpprwl().compareTo(rule.getSyValue()) <=0){ //如果当前监测值小于等于设置值,则跳过这套数据 iterator.remove(); } } data.add(detailVo); } if(data.isEmpty()){ return res; } List saves = new ArrayList<>(); RegressionEquation first = RegressionAnalysis.calculateLinear(data); LocalDateTime createTime = LocalDateTime.now(); if(first != null){ LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SyRegressionData::getDvcd, dto.getDvcd()); query.eq(SyRegressionData::getOrder,1); syRegressionDataService.remove(query); res.setOne(first.toString()); SyRegressionData syRegressionData = new SyRegressionData(); syRegressionData.setOrder(1); syRegressionData.setRegressionEquation(first.toString()); syRegressionData.setDvcd(dto.getDvcd()); syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart()); syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd()); syRegressionData.setCreateTime(createTime); saves.add(syRegressionData); } RegressionEquation second = RegressionAnalysis.calculateQuadratic(data); if(second != null){ LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SyRegressionData::getDvcd, dto.getDvcd()); query.eq(SyRegressionData::getOrder,2); syRegressionDataService.remove(query); res.setTwo(second.toString()); SyRegressionData syRegressionData = new SyRegressionData(); syRegressionData.setOrder(2); syRegressionData.setRegressionEquation(second.toString()); syRegressionData.setDvcd(dto.getDvcd()); syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart()); syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd()); syRegressionData.setCreateTime(createTime); saves.add(syRegressionData); } RegressionEquation three = RegressionAnalysis.calculateCubic(data); if(three != null){ LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SyRegressionData::getDvcd, dto.getDvcd()); query.eq(SyRegressionData::getOrder,3); syRegressionDataService.remove(query); res.setThree(three.toString()); SyRegressionData syRegressionData = new SyRegressionData(); syRegressionData.setOrder(3); syRegressionData.setRegressionEquation(three.toString()); syRegressionData.setDvcd(dto.getDvcd()); syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart()); syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd()); syRegressionData.setCreateTime(createTime); saves.add(syRegressionData); } RegressionEquation four = RegressionAnalysis.calculateQuartic(data); if(four != null){ LambdaQueryWrapper query = new LambdaQueryWrapper<>(); query.eq(SyRegressionData::getDvcd, dto.getDvcd()); query.eq(SyRegressionData::getOrder,4); syRegressionDataService.remove(query); res.setFour(four.toString()); SyRegressionData syRegressionData = new SyRegressionData(); syRegressionData.setOrder(4); syRegressionData.setRegressionEquation(four.toString()); syRegressionData.setDvcd(dto.getDvcd()); syRegressionData.setStartTime(dto.getDateTimeRangeSo().getStart()); syRegressionData.setEndTime(dto.getDateTimeRangeSo().getEnd()); syRegressionData.setCreateTime(createTime); saves.add(syRegressionData); } res.setDatas(data); syRegressionDataService.saveBatch(saves); return res; } /** * 查找最接近的库水位值 */ private BigDecimal findClosestRzValue(Map rzMap, String targetTimeStr) { // 如果直接匹配到,直接返回 if (rzMap.containsKey(targetTimeStr)) { return rzMap.get(targetTimeStr); } // 如果没有直接匹配,查找最接近的时间 LocalDateTime targetTime = LocalDateTime.parse(targetTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); String closestTime = null; long minDiff = Long.MAX_VALUE; for (String timeStr : rzMap.keySet()) { LocalDateTime time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); long diff = Math.abs(Duration.between(targetTime, time).toMinutes()); if (diff < minDiff) { minDiff = diff; closestTime = timeStr; } } return closestTime != null ? rzMap.get(closestTime) : BigDecimal.ZERO; } }