From 828630e424d3885ec22815c9d2b2fa16eaddb640 Mon Sep 17 00:00:00 2001 From: hzj <826100833@qq.com> Date: Wed, 3 Jun 2026 13:28:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=8C=97=E4=BA=AC=E5=85=AC?= =?UTF-8?q?=E5=8F=B8=E8=A6=81=E6=B1=82=E4=BF=AE=E6=94=B9=E6=9A=82=E9=99=8D?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=89=8B=E6=9C=BA=E7=9F=AD=E4=BF=A1=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E7=9B=B8=E5=85=B3=E7=AD=96=E7=95=A5=E5=8F=8A=E5=86=85?= =?UTF-8?q?=E5=AE=B9=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/EventGateController.java | 25 +- .../event/transientes/job/SendMessageJob.java | 35 ++ .../transientes/security/SecurityConfig.java | 2 +- .../service/SendMessageService.java | 14 + .../impl/LargeScreenCountServiceImpl.java | 11 +- .../service/impl/SendMessageServiceImpl.java | 409 ++++++++++++++++++ 6 files changed, 486 insertions(+), 10 deletions(-) create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/job/SendMessageJob.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/service/SendMessageService.java create mode 100644 event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/SendMessageServiceImpl.java diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java index 53ad8d6..0743e02 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/controller/EventGateController.java @@ -72,6 +72,8 @@ public class EventGateController extends BaseController { @Value("${SYS_TYPE_ZT}") private String sysTypeZt; + @Value("${business.RealTimeSMSSwitch:false}") + private boolean realTimeSMSSwitch; private final WebSocketServer webSocketServer; @@ -98,6 +100,17 @@ public class EventGateController extends BaseController { private final ThreadPoolTaskExecutor smsTaskExecutor; private final PqlineCache pqlineCache; + private final SendMessageService messageService; + + @GetMapping("/testSendMessage") + @ApiOperation("接收远程推送的暂态事件") + public HttpResult SendMessage(@RequestParam("startTime") String startTime,@RequestParam("endtTime") String endtTime) { + String methodDescribe = getMethodDescribe("SendMessage"); + messageService.sendMessage(LocalDateTimeUtil.parse(startTime,DatePattern.NORM_DATETIME_PATTERN),LocalDateTimeUtil.parse(endtTime,DatePattern.NORM_DATETIME_PATTERN)); + return HttpResultUtil.assembleCommonResponseResult(CommonResponseEnum.SUCCESS, null, methodDescribe); + + } + @OperateInfo @GetMapping("/eventMsg") @ApiOperation("接收远程推送的暂态事件") @@ -161,9 +174,13 @@ public class EventGateController extends BaseController { webSocketServer.sendMessageToAll(jsonObject.toString()); //针对前置推送的暂降事件进行短信发送功能 - smsTaskExecutor.execute(() -> { - sendMessage(jsonObject, str); - }); + //开启实时短信功能默认关闭走批量 + if(realTimeSMSSwitch){ + smsTaskExecutor.execute(() -> { + sendMessage(jsonObject, str); + }); + } + } @@ -417,7 +434,7 @@ public class EventGateController extends BaseController { BigDecimal bigDecimal = new BigDecimal(jsonObject.get("eventvalue").toString()).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP); stringBuilder.append(".").append(jsonObject.get("ms").toString()).append(",").append(jsonObject.get("bdname").toString()).append(busName) // .append("_").append(jsonObject.get("pointname").toString()) - .append("发生电压暂降事件,事件残余电压").append(bigDecimal).append("%,持续时间:").append(jsonObject.get("persisttime").toString()).append("S;"); + .append("发生电压暂降事件,事件残余电压").append(bigDecimal).append("%,持续时间:").append(String.format("%.3f", Double.parseDouble(jsonObject.get("persisttime").toString()))).append("S;"); stringBuilder.append(objStr); String message; diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/job/SendMessageJob.java b/event_smart/src/main/java/com/njcn/product/event/transientes/job/SendMessageJob.java new file mode 100644 index 0000000..064c75b --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/job/SendMessageJob.java @@ -0,0 +1,35 @@ +package com.njcn.product.event.transientes.job; + +import com.njcn.product.event.transientes.service.SendMessageService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * Description: + * Date: 2026/05/29 上午 10:45【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Component +@EnableScheduling +@RequiredArgsConstructor +@Slf4j +public class SendMessageJob { + private final SendMessageService messageService; + + @Scheduled(cron = "${business.sendMessageCronExpression}") + public void executeJob() { + // 获取当前时间 + LocalDateTime now = LocalDateTime.now(); + // 减去一个小时 + LocalDateTime threeHourAgo = now.minusHours(3); + + messageService.sendMessage(threeHourAgo,now); + } +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/security/SecurityConfig.java b/event_smart/src/main/java/com/njcn/product/event/transientes/security/SecurityConfig.java index d106015..304e15c 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/security/SecurityConfig.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/security/SecurityConfig.java @@ -34,7 +34,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() - .antMatchers("/cn_authenticate","/ws/**","/accept/testEvent","/accept/eventMsg","/accept/simpleTest","/accept/phoneSend","/accept/refreshIdCache","/largescreen/sycnUser").permitAll() // 允许访问认证接口 + .antMatchers("/cn_authenticate","/ws/**","/accept/testEvent","/accept/eventMsg","/accept/simpleTest","/accept/phoneSend","/accept/refreshIdCache","/accept/testSendMessage","/largescreen/sycnUser").permitAll() // 允许访问认证接口 // .antMatchers("/**").permitAll() // 允许访问认证接口 .anyRequest().authenticated() .and() diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/SendMessageService.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/SendMessageService.java new file mode 100644 index 0000000..6dc768b --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/SendMessageService.java @@ -0,0 +1,14 @@ +package com.njcn.product.event.transientes.service; + +import java.time.LocalDateTime; + +/** + * Description: + * Date: 2026/05/29 上午 11:30【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +public interface SendMessageService { + void sendMessage(LocalDateTime threeHourAgo, LocalDateTime now); +} diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java index b0c58ad..773def9 100644 --- a/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/LargeScreenCountServiceImpl.java @@ -697,13 +697,14 @@ public class LargeScreenCountServiceImpl implements LargeScreenCountService { DateTime start = DateUtil.beginOfDay(DateUtil.parse(largeScreenCountParam.getSearchBeginTime())); DateTime end = DateUtil.endOfDay(DateUtil.parse(largeScreenCountParam.getSearchEndTime())); - LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); - lambdaQueryWrapper.eq(!StringUtils.isEmpty(largeScreenCountParam.getSendResult()), MsgEventInfo::getSendResult, largeScreenCountParam.getSendResult()); - lambdaQueryWrapper.orderByDesc(MsgEventInfo::getSendTime).between(MsgEventInfo::getSendTime, start, end); + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.select("DISTINCT msg_index,user_id, user_name,send_time,msg_content,phone,send_result,is_handle "); + queryWrapper.lambda().eq(!StringUtils.isEmpty(largeScreenCountParam.getSendResult()), MsgEventInfo::getSendResult, largeScreenCountParam.getSendResult()); + queryWrapper.lambda().orderByDesc(MsgEventInfo::getSendTime).between(MsgEventInfo::getSendTime, start, end); if(StrUtil.isNotBlank(largeScreenCountParam.getSearchValue())){ - lambdaQueryWrapper.and(w->w.like(MsgEventInfo::getUserName,largeScreenCountParam.getSearchValue()).or().like(MsgEventInfo::getPhone,largeScreenCountParam.getSearchValue())); + queryWrapper.lambda().and(w->w.like(MsgEventInfo::getUserName,largeScreenCountParam.getSearchValue()).or().like(MsgEventInfo::getPhone,largeScreenCountParam.getSearchValue())); } - return msgEventInfoService.page(new Page<>(PageFactory.getPageNum(largeScreenCountParam), PageFactory.getPageSize(largeScreenCountParam)), lambdaQueryWrapper); + return msgEventInfoService.page(new Page<>(PageFactory.getPageNum(largeScreenCountParam), PageFactory.getPageSize(largeScreenCountParam)), queryWrapper); } @Override diff --git a/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/SendMessageServiceImpl.java b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/SendMessageServiceImpl.java new file mode 100644 index 0000000..e020891 --- /dev/null +++ b/event_smart/src/main/java/com/njcn/product/event/transientes/service/impl/SendMessageServiceImpl.java @@ -0,0 +1,409 @@ +package com.njcn.product.event.transientes.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.njcn.product.event.config.RedisUtil; +import com.njcn.product.event.devcie.pojo.dto.LedgerBaseInfoDTO; +import com.njcn.product.event.devcie.pojo.po.PqsDeptsline; +import com.njcn.product.event.devcie.service.PqsDeptslineService; +import com.njcn.product.event.transientes.mapper.PqUserLedgerMapper; +import com.njcn.product.event.transientes.mapper.PqUserLineAssMapper; +import com.njcn.product.event.transientes.mapper.PqsEventdetailMapper; +import com.njcn.product.event.transientes.pojo.dto.SmsResponseDTO; +import com.njcn.product.event.transientes.pojo.dto.SmsSendDTO; +import com.njcn.product.event.transientes.pojo.po.*; +import com.njcn.product.event.transientes.service.*; +import com.njcn.product.event.transientes.utils.SmsUtils; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Description: + * Date: 2026/05/29 上午 11:30【需求编号】 + * + * @author clam + * @version V1.0.0 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class SendMessageServiceImpl implements SendMessageService { + private final PqUserLineAssMapper pqUserLineAssMapper; + private final PqUserLedgerMapper pqUserLedgerMapper; + private final PqsEventdetailMapper pqsEventdetailMapper; + private final MsgEventInfoService msgEventInfoService; + private final static String NAME_KEY = "LineCache:"; + private final RedisUtil redisUtil; + private final ThreadPoolTaskExecutor smsTaskExecutor; + private final PqsUsersetService pqsUsersetService; + private final SmsUtils smsUtils; + + private final PqsDeptslineService pqsDeptslineService; + @Value("${SYS_TYPE_ZT}") + private String sysTypeZt; + + private final PqsDeptsService pqsDeptsService; + + private final PqsUserService pqsUserService; + @Override + public void sendMessage(LocalDateTime threeHourAgo, LocalDateTime now) { + log.info("开始扫描暂态事件时间段:"+threeHourAgo+"-"+now); + //查询重要敏感客户 + List poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper().select(PqUserLedgerPO::getId, PqUserLedgerPO::getCustomerName,PqUserLedgerPO::getIsShow).eq(PqUserLedgerPO::getIsShow, 1)); + List userIds = poList.stream().map(PqUserLedgerPO::getId).collect(Collectors.toList()); + List pqUserLineAssPOS = pqUserLineAssMapper.selectList(new LambdaQueryWrapper().in(PqUserLineAssPO::getUserIndex, userIds)); + List lineIds = pqUserLineAssPOS.stream().map(PqUserLineAssPO::getLineIndex).distinct().collect(Collectors.toList()); + LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); + lambdaQueryWrapper.in(PqsEventdetail::getLineid,lineIds).between(PqsEventdetail::getCreateTime,threeHourAgo,now); + List pqsEventdetails = pqsEventdetailMapper.selectList(lambdaQueryWrapper); + log.info("扫描到敏感客户暂态事件:"+pqsEventdetails.size()+"条"); + + if(!CollectionUtils.isEmpty(pqsEventdetails)){ + List ledgerBaseInfoDTOS = (List)redisUtil.getObjectByKey(NAME_KEY + StrUtil.DASHED+"LedgerBaseInfoDTO"); + Map LedgerBaseInfoDTOMap = ledgerBaseInfoDTOS.stream().collect(Collectors.toMap(LedgerBaseInfoDTO::getLineId, Function.identity())); + + List msgEventInfos = msgEventInfoService.lambdaQuery().between(MsgEventInfo::getSendTime, threeHourAgo, now).eq(MsgEventInfo::getSendResult, 1).list(); + List successSendEventIds = msgEventInfos.stream().map(MsgEventInfo::getEventIndex).distinct().collect(Collectors.toList()); + + pqsEventdetails = pqsEventdetails.stream() + .filter(temp -> shouldSendSMS(temp.getEventvalue(), temp.getPersisttime()) && (!successSendEventIds.contains(temp.getEventdetailIndex()))) + .collect(Collectors.toList()); + log.info("扫描到敏感客户暂态事件过滤后事件:"+pqsEventdetails.size()+"条"); + + if(!CollectionUtils.isEmpty(pqsEventdetails)){ + log.info("过滤后事件数:"+pqsEventdetails.size()); + + List finalPqsEventdetails = pqsEventdetails; + poList.forEach(temp->{ + List tempLineIds = pqUserLineAssPOS.stream() + .filter(pqUserLineAssPO -> Objects.equals(pqUserLineAssPO.getUserIndex(), temp.getId())) + .map(PqUserLineAssPO::getLineIndex).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(tempLineIds)){ + return; + } + + List result = finalPqsEventdetails.stream().filter(pqsEventdetail -> tempLineIds.contains(pqsEventdetail.getLineid())).collect(Collectors.toList()); + if(CollectionUtils.isEmpty(result)){ + return; + } + //组装台账信息 + List tempLedger = ledgerBaseInfoDTOS.stream().filter(line -> tempLineIds.contains(line.getLineId())).collect(Collectors.toList()); + + Map> busNameMap = tempLedger.stream().map(LedgerBaseInfoDTO::getBusBarName).collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage)); + String allBus = busNameMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map( + entry -> { + return entry.getKey() + "母线" + entry.getValue().size() + "条"; + } + ).collect(Collectors.joining("、")); + Map> subStaionMap = tempLedger.stream().map(LedgerBaseInfoDTO::getStationName).distinct().collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage)); + + String allsubStation = subStaionMap.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) // 按电压等级排序(110,220,500) + .map(entry -> { + String voltage = entry.getKey(); // 例如 "110kV" + List stations = entry.getValue(); + // 构建组内字符串:第一个保留全名,后续的去掉电压前缀 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < stations.size(); i++) { + String fullName = stations.get(i); + if (i == 0) { + sb.append(fullName); // 第一个保留完整名称(含电压) + } else { + // 去掉电压前缀(例如 "110kV标厂变" -> "标厂变") + String pureName = fullName.startsWith(voltage) + ? fullName.substring(voltage.length()) + : fullName; + sb.append("、").append(pureName); + } + } + return sb.toString(); + }) + .collect(Collectors.joining(",")); + result.forEach(event->{ + event.setBusBarName(LedgerBaseInfoDTOMap.get(event.getLineid()).getBusBarName()); + event.setStationName(LedgerBaseInfoDTOMap.get(event.getLineid()).getStationName()); + }); + + + Map> groupFilterNull = result.stream() + .filter(e -> e.getStationName() != null) + .collect(Collectors.groupingBy(PqsEventdetail::getStationName)); + //组装暂降信息 + StringBuilder stringBuilder = new StringBuilder(temp.getCustomerName()); + stringBuilder.append("上级直供变电站共有相关"+allBus+","); + stringBuilder.append("涉及"+allsubStation+"。"); + AtomicInteger index = new AtomicInteger(); + + String eventString = groupFilterNull.entrySet().stream().map(entry -> { + String substationnName = entry.getKey(); // 例如 "110kV智芯变" + List value = entry.getValue(); + StringBuilder sb = new StringBuilder(); + if (index.getAndIncrement() == 0) { + sb.append(LocalDateTimeUtil.format(value.get(0).getTimeid(),DatePattern.NORM_DATETIME_MINUTE_PATTERN)).append(","); + }else { + sb.append(LocalDateTimeUtil.format(value.get(0).getTimeid(),"HH:mm")).append(","); + + } + if (value.size() == 1) { + + BigDecimal eventvalue = new BigDecimal(value.get(0).getEventvalue()).multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP); + BigDecimal persisttime = new BigDecimal(value.get(0).getPersisttime()).divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP); + + sb.append(substationnName).append(value.get(0).getBusBarName()).append("发生电压暂降,电压跌落至").append(eventvalue).append("%,持续时间:").append(persisttime).append("S"); + } else { +// String minTime = LocalDateTimeUtil.format(value.stream() +// .map(PqsEventdetail::getTimeid) +// .min(LocalDateTime::compareTo).get(), DatePattern.NORM_DATETIME_MINUTE_PATTERN); +// String maxTime = LocalDateTimeUtil.format(value.stream() +// .map(eventdetail -> { +// return eventdetail.getTimeid().plus(Duration.ofMillis(eventdetail.getMs().longValue())); +// }) +// .max(LocalDateTime::compareTo).get(), DatePattern.NORM_DATETIME_MS_FORMATTER); +// String BusNameList = value.stream().map(PqsEventdetail::getBusBarName).collect(Collectors.joining("、")); + Map> BusNameMap = value.stream().map(PqsEventdetail::getBusBarName).distinct().collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage)); + String allBusName = BusNameMap.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) // 按电压等级排序(110,220,500) + .map(tempEntry -> { + String voltage = tempEntry.getKey(); // 例如 "110kV" + List busNameList = tempEntry.getValue(); + // 构建组内字符串:第一个保留全名,后续的去掉电压前缀 + StringBuilder busName = new StringBuilder(); + for (int i = 0; i < busNameList.size(); i++) { + String fullName = busNameList.get(i).replace("母线",""); + if (i == 0) { + busName.append(fullName); // 第一个保留完整名称(含电压) + } else { + // 去掉电压前缀(例如 "10kV3B#母线" -> "3B#") + String pureName = fullName.startsWith(voltage) + ? fullName.substring(voltage.length()) + : fullName; + busName.append("、").append(pureName.replace("母线","")); + } + } + return busName.toString(); + }) + .collect(Collectors.joining(",")); + BigDecimal eventvalueMin = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getEventvalue).min().getAsDouble()) + .multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP); + BigDecimal eventvalueMax = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getEventvalue).max().getAsDouble()) + .multiply(new BigDecimal(100)).setScale(2, RoundingMode.HALF_UP); + + BigDecimal persisttimeMin = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getPersisttime).min().getAsDouble()) + .divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP); + BigDecimal persisttimeMax = new BigDecimal(value.stream().mapToDouble(PqsEventdetail::getPersisttime).max().getAsDouble()) + .divide(new BigDecimal(1000)).setScale(3, RoundingMode.HALF_UP); + sb.append(substationnName).append(allBusName) + .append("母线发生电压暂降,电压跌落至").append(eventvalueMin).append("%—").append(eventvalueMax).append("%,持续时间:") + .append(persisttimeMin).append("S—").append(persisttimeMax).append("S"); + } + + return sb.toString(); + }).collect(Collectors.joining(";")); + + stringBuilder.append(eventString).append("。"); + List eventLineIds = result.stream().map(PqsEventdetail::getLineid).collect(Collectors.toList()); + List eventdetailIndexs = result.stream().map(PqsEventdetail::getEventdetailIndex).collect(Collectors.toList()); + + List pqLineDept = pqsDeptslineService.lambdaQuery().in(PqsDeptsline::getLineIndex, eventLineIds).eq(PqsDeptsline::getSystype, sysTypeZt).list(); + if(CollectionUtils.isEmpty(pqLineDept)){ + return; + } + Set deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet()); + Set resultIds = getAllParentDeptIds(deptIds); + + List pqsUserSetList = pqsUsersetService.lambdaQuery().eq(PqsUserSet::getIsNotice, 1).in(PqsUserSet::getDeptsIndex, resultIds).list(); + if (CollUtil.isEmpty(pqsUserSetList)) { + //当前事件未找到用户信息,判断为不需要发送短信用户 + return; + } + List pqsUserList = pqsUserService.lambdaQuery().select(PqsUser::getUserIndex, PqsUser::getPhone, PqsUser::getName).in(PqsUser::getUserIndex, pqsUserSetList.stream().map(PqsUserSet::getUserIndex).collect(Collectors.toList())).list(); + if(!CollectionUtils.isEmpty(pqsUserList)){ + //开始发送短信 + smsTaskExecutor.execute(() -> { + sendMessageforUser(stringBuilder.toString(), pqsUserList,eventdetailIndexs); + }); + } + + + }); + + + } + + } + + + } + + private void sendMessageforUser(String content, List pqsUserList, List eventdetailIndexs) { + + //发送短信 + List resultList = new ArrayList<>(); + List msgDTOList = new ArrayList<>(); + String message; + if (content.length() > 500) { + message = content.substring(0, 490).concat(";详情请登录电压暂降监测平台查看。"); + } else { + message = content.toString(); + } + for (PqsUser user : pqsUserList) { + String msgId = IdUtil.simpleUUID(); + + SmsSendDTO.ItemInner dto = new SmsSendDTO.ItemInner(); + dto.setContent(message); + dto.setTo(user.getPhone()); + dto.setCustomMsgID(msgId); + msgDTOList.add(dto); + for (String eventdetailIndex : eventdetailIndexs) { + MsgEventInfo msgEventInfo = new MsgEventInfo(); + msgEventInfo.setMsgIndex(msgId); + msgEventInfo.setMsgContent(message); + msgEventInfo.setPhone(user.getPhone()); + msgEventInfo.setUserId(user.getUserIndex()); + msgEventInfo.setUserName(user.getName()); + msgEventInfo.setIsHandle(0); + msgEventInfo.setSendResult(0); + msgEventInfo.setSendTime(LocalDateTime.now()); + msgEventInfo.setEventIndex(eventdetailIndex); + resultList.add(msgEventInfo); + } + + } + + List result = smsUtils.sendSmSToUser(msgDTOList); + Map stringSmsItemMap = result.stream().collect(Collectors.toMap(SmsResponseDTO.SmsItem::getCustomMsgID, Function.identity())); + + resultList.forEach(item -> { + if (stringSmsItemMap.containsKey(item.getMsgIndex())) { + SmsResponseDTO.SmsItem smsItem = stringSmsItemMap.get(item.getMsgIndex()); + item.setSendResult(Objects.equals(smsItem.getCode(), "0") ? 1 : 0); + } + }); + msgEventInfoService.saveBatch(resultList); + } + + public Set getAllParentDeptIds(Set deptIds) { + // 首次获取直接父级 + List allDeptList = pqsDeptsService.lambdaQuery().list(); + // 递归获取所有父级 + Set result = recursivelyGetParentIds(deptIds, allDeptList); + return result; + } + /** + * 递归获取所有父级ID + * + * @param currentParentIds 当前层级的父级ID集合 + * @return 所有层级的父级ID集合 + */ + private Set recursivelyGetParentIds(Set currentParentIds, List allDeptList) { + Set result = new HashSet<>(currentParentIds); + Set nextLevelParentIds = new HashSet<>(); + List parentDeptList = allDeptList.stream().filter(it -> currentParentIds.contains(it.getDeptsIndex())).collect(Collectors.toList()); + for (PqsDepts pqsDepts : parentDeptList) { + if (!pqsDepts.getParentnodeid().equals("0")) { + nextLevelParentIds.add(pqsDepts.getParentnodeid()); + } + } + // 如果有更高层级的父级,继续递归 + if (!nextLevelParentIds.isEmpty()) { + Set deeperParentIds = recursivelyGetParentIds(nextLevelParentIds, allDeptList); + result.addAll(deeperParentIds); + } + return result; + } + + + private boolean shouldSendSMS( Double value , Double time ) { + + + // 条件1: 电压降至50%以下,持续时间超过20ms + if (value < 0.5 && time >= 20) { + return true; + } + + // 条件2: 电压降至50%—70%,持续时间超过200ms + if (value >= 50 && value < 70 && time >= 200) { + return true; + } + + // 条件3: 电压降至70%—80%,持续时间超过500ms + if (value >= 70 && value < 80 && time >= 500) { + return true; + } + + return false; + } + + private static String extractVoltage(String name) { + int kVIndex = name.indexOf("kV"); + if (kVIndex == -1) { + log.info("存在台账"+name+"不符合命名规范"); + throw new IllegalArgumentException("无法解析电压等级: " + name); + } + // 返回从开头到 "kV" 结束的部分(包含 "kV") + return name.substring(0, kVIndex + 2); + } + + public static void main(String[] args) { +// Stream.of(1,2,3).collect(Collectors.toList()).forEach( +// temp->{ +// if(temp==2){ +// return; +// } +// System.out.println(temp); +// } +// ); + List substations = Arrays.asList( + "110kV智芯变", + "110kV标厂变", + "110kV科创变", + "220kV开发区变", + "220kV高新变", + "500kV枢纽换流站" + ); + + // 按电压等级字符串(含kV)分组 + Map> grouped = substations.stream() + .collect(Collectors.groupingBy(SendMessageServiceImpl::extractVoltage)); + String collect = grouped.entrySet().stream() + .sorted(Map.Entry.comparingByKey()) // 按电压等级排序(110,220,500) + .map(entry -> { + String voltage = entry.getKey(); // 例如 "110kV" + List stations = entry.getValue(); + // 构建组内字符串:第一个保留全名,后续的去掉电压前缀 + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < stations.size(); i++) { + String fullName = stations.get(i); + if (i == 0) { + sb.append(fullName); // 第一个保留完整名称(含电压) + } else { + // 去掉电压前缀(例如 "110kV标厂变" -> "标厂变") + String pureName = fullName.startsWith(voltage) + ? fullName.substring(voltage.length()) + : fullName; + sb.append("、").append(pureName); + } + } + return sb.toString(); + }) + .collect(Collectors.joining(";")); + System.out.println(collect); + } +}