1.北京短信接口

This commit is contained in:
2025-10-20 16:24:36 +08:00
parent 0e1605d9b3
commit 2a0367f1ff
15 changed files with 658 additions and 7 deletions

View File

@@ -266,6 +266,8 @@ public class LineServiceImpl extends ServiceImpl<LineMapper, Line> implements Li
UserReportPO userReportPO = userReportPOMapper.selectById(lineDetail.getObjId()); UserReportPO userReportPO = userReportPOMapper.selectById(lineDetail.getObjId());
if(Objects.nonNull(userReportPO)){ if(Objects.nonNull(userReportPO)){
lineDetailDataVO.setObjName(userReportPO.getProjectName()); lineDetailDataVO.setObjName(userReportPO.getProjectName());
}else {
lineDetailDataVO.setObjName("/");
} }
lineDetailDataVO.setId(lineDetail.getNum()); lineDetailDataVO.setId(lineDetail.getNum());
lineDetailDataVO.setPtType(TerminalUtils.ptType(lineDetail.getPtType())); lineDetailDataVO.setPtType(TerminalUtils.ptType(lineDetail.getPtType()));

View File

@@ -0,0 +1,224 @@
package com.njcn.product.event.dataTransmit;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.product.event.transientes.mapper.PqsEventDetailStatusMapper;
import com.njcn.product.event.transientes.mapper.PqsEventdetailMapper;
import com.njcn.product.event.transientes.pojo.po.PqsEventDetailStatusPO;
import com.njcn.product.event.transientes.pojo.po.PqsEventdetail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author: cdf
* @CreateTime: 2025-10-20
* @Description: 暂降事件同步
*/
@Service
@EnableScheduling
@Slf4j
@RequiredArgsConstructor
public class dataSynchronization {
private final PqsEventdetailMapper pqsEventdetailMapper;
private final PqsEventDetailStatusMapper pqsEventDetailStatusMapper;
// 文件配置
@Value("${business.wavePath}")
private String sourceWaveDir;
@Value("${business.exportBaseDir}")
private String exportBaseDir;
// 定时任务配置
// 默认每2小时执行一次
private String cronExpression = "0 0 */2 * * ?";
private volatile boolean isRunning = false;
/**
* 定时执行的同步任务
*/
@Scheduled(cron = "${sag.sync.cronExpression}")
@Transactional
public void syncPqsEventdetails() {
// 防止任务并发执行
if (isRunning) {
log.warn("同步任务正在执行中,跳过本次调度");
return;
}
try {
isRunning = true;
log.info("=== 开始暂降事件波形文件同步任务 ===");
// 初始化
initialize();
// 同步最近N天的事件,因为存在事件补招,延迟的原因,采用大范围扫描
LocalDateTime end = LocalDateTime.now();
LocalDateTime start = end.minusHours(24);
syncEvents(start, end);
log.info("=== 同步任务完成 ===");
} catch (Exception e) {
log.error("同步任务执行失败", e);
} finally {
isRunning = false;
}
}
/**
* 初始化操作
*/
private void initialize() throws Exception {
// 检查目录
checkDirectories();
// 检查同步状态表
checkSyncStatusTable();
}
/**
* 同步指定时间范围内的事件
*/
public void syncEvents(LocalDateTime startTime, LocalDateTime endTime) throws Exception {
// 创建导出目录
String startStr = startTime.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String endStr = startTime.format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String exportDirName = String.format("%s_%s.json", startStr,endStr);
Path exportDir = Paths.get(exportBaseDir, exportDirName);
Files.createDirectories(exportDir);
log.info("创建导出目录: " + exportDir.toAbsolutePath());
// 查询未同步的事件
LambdaQueryWrapper<PqsEventdetail> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.between(PqsEventdetail::getTimeid,startTime,endTime);
List<PqsEventdetail> unsyncedEvents = pqsEventdetailMapper.selectList(lambdaQueryWrapper);
log.info("查询到 " + unsyncedEvents.size() + " 个暂降事件");
if(CollUtil.isEmpty(unsyncedEvents)){
return ;
}
// 查询已经存在记录的暂降事件
LambdaQueryWrapper<PqsEventDetailStatusPO> statusPOLambdaQueryWrapper = new LambdaQueryWrapper<>();
statusPOLambdaQueryWrapper.between(PqsEventDetailStatusPO::getEventTime,startTime,endTime);
List<PqsEventDetailStatusPO> hasList = pqsEventDetailStatusMapper.selectList(statusPOLambdaQueryWrapper);
log.info("查询到 " + hasList.size() + "条已存在记录事件");
//波形文件失败的事件id
List<String> waveFailEventDetailIds = hasList.stream().filter(it->it.getWaveFlag() == 0).map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
//排除已经成功的事件
if(CollUtil.isNotEmpty(hasList)){
List<String> hasIds = hasList.stream().map(PqsEventDetailStatusPO::getEventDetailId).collect(Collectors.toList());
unsyncedEvents = unsyncedEvents.stream().filter(it->!hasIds.contains(it.getEventdetailIndex())).collect(Collectors.toList());
}
//对为上传的事件进行上传操作
}
/**
* 检查必要的目录是否存在
*/
private void checkDirectories() throws IOException {
// 检查源目录
Path sourceDir = Paths.get(sourceWaveDir);
if (!Files.exists(sourceDir)) {
throw new IOException("源波形文件目录不存在: " + sourceDir);
}
// 检查导出基础目录
Path exportDir = Paths.get(exportBaseDir);
if (!Files.exists(exportDir)) {
Files.createDirectories(exportDir);
log.info("创建导出基础目录: " + exportDir);
}
}
/**
* 检查同步状态表是否存在
*/
private void checkSyncStatusTable() {
}
/**
* 导出单个事件
*/
private void exportSingleEvent(Path exportDir, PqsEventdetail event) throws Exception {
}
/**
* 生成事件信息文件
*/
private void generateEventInfoFile(Path eventDir, PqsEventdetail event) throws Exception {
}
/**
* 生成同步报告
*/
private void generateSyncReport(Path exportDir, int totalEvents, int successCount, int failureCount) throws Exception {
}
/**
* 更新事件同步状态
*/
private void updateSyncStatus(PqsEventdetail event, int status, String errorMessage) {
}
/**
* 获取波形类型描述
*/
private String getWaveTypeDesc(Integer waveType) {
if (waveType == null) return "未知";
switch (waveType) {
case 1: return "电压暂降";
case 2: return "电压暂升";
case 3: return "电压中断";
case 4: return "电压波动";
default: return "未知类型(" + waveType + ")";
}
}
/**
* 获取任务运行状态
*/
public boolean isRunning() {
return isRunning;
}
}

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.njcn.common.pojo.annotation.OperateInfo; import com.njcn.common.pojo.annotation.OperateInfo;
@@ -19,11 +20,15 @@ import com.njcn.product.event.devcie.pojo.po.PqsDeptsline;
import com.njcn.product.event.devcie.service.PqsDeptslineService; import com.njcn.product.event.devcie.service.PqsDeptslineService;
import com.njcn.product.event.transientes.mapper.PqUserLedgerMapper; import com.njcn.product.event.transientes.mapper.PqUserLedgerMapper;
import com.njcn.product.event.transientes.mapper.PqUserLineAssMapper; import com.njcn.product.event.transientes.mapper.PqUserLineAssMapper;
import com.njcn.product.event.transientes.pojo.dto.MsgDTO;
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.param.MonitorTerminalParam; import com.njcn.product.event.transientes.pojo.param.MonitorTerminalParam;
import com.njcn.product.event.transientes.pojo.param.SimulationMsgParam; import com.njcn.product.event.transientes.pojo.param.SimulationMsgParam;
import com.njcn.product.event.transientes.pojo.po.*; import com.njcn.product.event.transientes.pojo.po.*;
import com.njcn.product.event.transientes.service.*; import com.njcn.product.event.transientes.service.*;
import com.njcn.product.event.transientes.service.impl.MsgEventInfoServiceImpl; import com.njcn.product.event.transientes.service.impl.MsgEventInfoServiceImpl;
import com.njcn.product.event.transientes.utils.SmsUtils;
import com.njcn.product.event.transientes.websocket.WebSocketServer; import com.njcn.product.event.transientes.websocket.WebSocketServer;
import com.njcn.redis.utils.RedisUtil; import com.njcn.redis.utils.RedisUtil;
import com.njcn.web.controller.BaseController; import com.njcn.web.controller.BaseController;
@@ -34,12 +39,15 @@ import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -64,6 +72,7 @@ public class EventGateController extends BaseController {
@Value("${SYS_TYPE_ZT}") @Value("${SYS_TYPE_ZT}")
private String sysTypeZt; private String sysTypeZt;
private final WebSocketServer webSocketServer; private final WebSocketServer webSocketServer;
private final PqsDeptslineService pqsDeptslineService; private final PqsDeptslineService pqsDeptslineService;
@@ -84,6 +93,8 @@ public class EventGateController extends BaseController {
private final RedisUtil redisUtil; private final RedisUtil redisUtil;
private final SmsUtils smsUtils;
@OperateInfo @OperateInfo
@GetMapping("/eventMsg") @GetMapping("/eventMsg")
@@ -174,6 +185,7 @@ public class EventGateController extends BaseController {
try { try {
sendMessage(jsonObject); sendMessage(jsonObject);
}catch (Exception e){ }catch (Exception e){
e.printStackTrace();
log.error("短信组装发送失败!失败原因{}",e.getMessage()); log.error("短信组装发送失败!失败原因{}",e.getMessage());
} }
@@ -275,7 +287,7 @@ public class EventGateController extends BaseController {
} }
private void sendMessage(JSONObject jsonObject) throws Exception{ private void sendMessage(JSONObject jsonObject){
Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString()); Integer lineId = Integer.valueOf(jsonObject.get("lineid").toString());
List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list(); List<PqsDeptsline> pqLineDept = pqsDeptslineService.lambdaQuery().eq(PqsDeptsline::getLineIndex, lineId).eq(PqsDeptsline::getSystype, sysTypeZt).list();
Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet()); Set<String> deptIds = pqLineDept.stream().map(PqsDeptsline::getDeptsIndex).collect(Collectors.toSet());
@@ -300,19 +312,38 @@ public class EventGateController extends BaseController {
// System.out.println(stringBuilder); // System.out.println(stringBuilder);
List<MsgEventInfo> resultList = new ArrayList<>(); List<MsgEventInfo> resultList = new ArrayList<>();
List<MsgDTO> msgDTOList = new ArrayList<>();
for (PqsUser user : pqsUserList) { for (PqsUser user : pqsUserList) {
String msgId = IdUtil.simpleUUID();
MsgDTO dto = new MsgDTO();
dto.setMessage(stringBuilder.toString());
dto.setPhone(user.getPhone());
dto.setCustomMsgID(msgId);
msgDTOList.add(dto);
MsgEventInfo msgEventInfo = new MsgEventInfo(); MsgEventInfo msgEventInfo = new MsgEventInfo();
msgEventInfo.setEventIndex(jsonObject.get("eventdetail_index").toString()); msgEventInfo.setMsgIndex(msgId);
msgEventInfo.setMsgContent(stringBuilder.toString()); msgEventInfo.setMsgContent(stringBuilder.toString());
msgEventInfo.setMsgIndex(IdUtil.simpleUUID());
msgEventInfo.setPhone(user.getPhone()); msgEventInfo.setPhone(user.getPhone());
msgEventInfo.setSendResult(0);
msgEventInfo.setUserId(user.getUserIndex()); msgEventInfo.setUserId(user.getUserIndex());
msgEventInfo.setUserName(user.getName()); msgEventInfo.setUserName(user.getName());
msgEventInfo.setIsHandle(0); msgEventInfo.setIsHandle(0);
msgEventInfo.setSendResult(0);
msgEventInfo.setSendTime(LocalDateTime.now()); msgEventInfo.setSendTime(LocalDateTime.now());
msgEventInfo.setEventIndex(jsonObject.get("eventdetail_index").toString());
resultList.add(msgEventInfo); resultList.add(msgEventInfo);
} }
List<SmsResponseDTO.SmsItem> result = smsUtils.sendSmSToUser(msgDTOList);
Map<String,SmsResponseDTO.SmsItem> 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); msgEventInfoService.saveBatch(resultList);
} }
} }
@@ -326,6 +357,10 @@ public class EventGateController extends BaseController {
} }
private boolean apiSend(){ private boolean apiSend(){
return false; return false;
} }

View File

@@ -0,0 +1,112 @@
package com.njcn.product.event.transientes.job;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* @Author: cdf
* @CreateTime: 2025-10-16
* @Description: 定时同步暂降数据包
*/
@Component
@EnableScheduling
@RequiredArgsConstructor
public class ScheduledEvent implements SchedulingConfigurer {
@Value("${}")
private final String cronStr = "";
// 源文件夹路径
private final String sourceFolderPath = "D:\\";
// 压缩文件输出路径
private final String zipOutputPath = "./output_zips";
// 最终存放压缩文件的目录
private final String finalDestination = "./archive";
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
() -> dataToFile(),
triggerContext -> {
CronTrigger trigger = new CronTrigger(cronStr);
return trigger.nextExecutionTime(triggerContext);
}
);
}
public void dataToFile() {
try {
// 1. 创建临时文件夹并写入测试文件
String folderName = "data_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss"));
Path sourceDir = Paths.get(sourceFolderPath, folderName);
Files.createDirectories(sourceDir);
// 模拟生成文件例如log.txt
Path testFile = sourceDir.resolve("log.txt");
Files.write(testFile, "This is a test log file.".getBytes(), StandardOpenOption.CREATE);
// 2. 压缩文件夹
Path zipOutputDir = Paths.get(zipOutputPath);
Files.createDirectories(zipOutputDir);
Path zipFile = zipOutputDir.resolve(folderName + ".zip");
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile.toFile()))) {
Files.walk(sourceDir)
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
String zipEntryName = sourceDir.relativize(path).toString();
try {
zos.putNextEntry(new ZipEntry(zipEntryName));
Files.copy(path, zos);
zos.closeEntry();
} catch (IOException e) {
throw new RuntimeException("Failed to add file to zip: " + path, e);
}
});
}
// 3. 移动压缩文件到最终目录
Path finalDir = Paths.get(finalDestination);
Files.createDirectories(finalDir);
Path targetPath = finalDir.resolve(zipFile.getFileName());
Files.move(zipFile, targetPath, StandardCopyOption.REPLACE_EXISTING);
// 4. 删除临时文件夹(可选)
deleteDirectory(sourceDir.toFile());
System.out.println("Task completed: " + targetPath);
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 递归删除目录
*/
private void deleteDirectory(File directory) {
File[] allContents = directory.listFiles();
if (allContents != null) {
for (File file : allContents) {
deleteDirectory(file);
}
}
directory.delete();
}
}

View File

@@ -0,0 +1,13 @@
package com.njcn.product.event.transientes.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.njcn.product.event.transientes.pojo.po.PqsEventDetailStatusPO;
/**
* @Author: cdf
* @CreateTime: 2025-10-20
* @Description:
*/
public interface PqsEventDetailStatusMapper extends BaseMapper<PqsEventDetailStatusPO> {
}

View File

@@ -0,0 +1,20 @@
package com.njcn.product.event.transientes.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @Author: cdf
* @CreateTime: 2025-10-15
* @Description:
*/
@Data
public class MsgDTO {
private String message;
private String phone;
@JsonProperty(value = "customMsgID")
private String customMsgID;
}

View File

@@ -0,0 +1,31 @@
package com.njcn.product.event.transientes.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* @Author: cdf
* @CreateTime: 2025-10-15
* @Description:
*/
@Data
public class SmsResponseDTO {
private String code;
private String message;
private String batchId;
private List<SmsItem> items;
@Data
public static class SmsItem {
private String msg;
private String code;
@JsonProperty(value = "customMsgID")
private String customMsgID;
}
}

View File

@@ -0,0 +1,42 @@
package com.njcn.product.event.transientes.pojo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* @Author: cdf
* @CreateTime: 2025-10-15
* @Description:
*/
@Data
public class SmsSendDTO {
private String serviceCode;
private String account;
private String token;
private String ts;
private List<ItemInner> items;
@Data
public static class ItemInner{
private String content;
@JsonProperty(value = "customMsgID")
private String customMsgID;
private String to;
private String ext;
}
}

View File

@@ -0,0 +1,39 @@
package com.njcn.product.event.transientes.pojo.po;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.time.LocalDateTime;
import java.util.Date;
/**
* @Author: cdf
* @CreateTime: 2025-10-20
* @Description: 暂降事件同步记录
*/
@Data
public class PqsEventDetailStatusPO {
@TableId(value = "EVENT_DETAIL_ID")
private String eventDetailId;
@TableField(value = "EVENT_TIME")
private Date eventTime;
@TableField(value = "WAVE_FLAG")
private int waveFlag;
@TableField(value = "SYNC_STATUE")
private int syncStatus;
@TableField(value = "SYNC_TIME")
private LocalDateTime syncTime;
@TableField(value = "REMARK")
private String remark;
@TableField(value = "RETRY_COUNT")
private int retryCount;
}

View File

@@ -38,8 +38,15 @@ public class EventGateServiceImpl implements EventGateService {
private final WaveFileComponent waveFileComponent; private final WaveFileComponent waveFileComponent;
private final PqLineService pqLineService; private final PqLineService pqLineService;
private final PqLinedetailMapper pqLinedetailMapper; private final PqLinedetailMapper pqLinedetailMapper;
@Value("${WAVEPATH}") @Value("${business.wavePath}")
private String WAVEPATH; private String WAVEPATH;
/**
* 波形分析
* @param param
* @return
*/
@Override @Override
public WaveDataDTO getTransientAnalyseWave(MonitorTerminalParam param) { public WaveDataDTO getTransientAnalyseWave(MonitorTerminalParam param) {
WaveDataDTO waveDataDTO; WaveDataDTO waveDataDTO;

View File

@@ -502,7 +502,18 @@ public class LargeScreenCountServiceImpl implements LargeScreenCountService {
List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getLineIndex, ids)); List<PqUserLineAssPO> assList = pqUserLineAssMapper.selectList(new LambdaQueryWrapper<PqUserLineAssPO>().in(PqUserLineAssPO::getLineIndex, ids));
if (CollUtil.isNotEmpty(assList)) { if (CollUtil.isNotEmpty(assList)) {
List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList()); List<String> userIds = assList.stream().map(PqUserLineAssPO::getUserIndex).distinct().collect(Collectors.toList());
List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(new LambdaQueryWrapper<PqUserLedgerPO>().in(PqUserLedgerPO::getId, userIds)); LambdaQueryWrapper<PqUserLedgerPO> wrapper = new LambdaQueryWrapper<>();
if(userIds.size()>1000){
List<List<String>> userIdsList = CollUtil.split(userIds, 1000);
wrapper.and(w -> {
for (List<String> teIds : userIdsList) {
w.or(wIn -> wIn.in(PqUserLedgerPO::getId, teIds));
}
});
}else {
wrapper.in(PqUserLedgerPO::getId, userIds);
}
List<PqUserLedgerPO> poList = pqUserLedgerMapper.selectList(wrapper);
userMap = poList.stream().collect(Collectors.toMap(PqUserLedgerPO::getId, Function.identity())); userMap = poList.stream().collect(Collectors.toMap(PqUserLedgerPO::getId, Function.identity()));
assMap = assList.stream().collect(Collectors.groupingBy(PqUserLineAssPO::getLineIndex)); assMap = assList.stream().collect(Collectors.groupingBy(PqUserLineAssPO::getLineIndex));
} else { } else {

View File

@@ -0,0 +1,102 @@
package com.njcn.product.event.transientes.utils;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.SM3;
import cn.hutool.json.JSONObject;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.product.event.transientes.pojo.dto.MsgDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsResponseDTO;
import com.njcn.product.event.transientes.pojo.dto.SmsSendDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: cdf
* @CreateTime: 2025-10-15
* @Description: 短信工具
*/
@Component
@Slf4j
public class SmsUtils {
@Autowired
private RestTemplate restTemplate;
@Value("${smsServer.info}")
private String smsServer;
@Value("${smsServer.account}")
private String account;
@Value("${smsServer.password}")
private String password;
public List<SmsResponseDTO.SmsItem> sendSmSToUser(List<MsgDTO> msgDTOList) {
SmsSendDTO smsSendDTO = new SmsSendDTO();
smsSendDTO.setServiceCode("101001101");
smsSendDTO.setAccount(account);
String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DatePattern.PURE_DATETIME_PATTERN));
String sm3Hash = new SM3().digestHex(account + password + nowTime);
smsSendDTO.setToken(sm3Hash);
smsSendDTO.setTs(nowTime);
List<SmsSendDTO.ItemInner> temList = new ArrayList<>();
for (MsgDTO dto : msgDTOList) {
SmsSendDTO.ItemInner inner = new SmsSendDTO.ItemInner();
inner.setTo(dto.getPhone());
inner.setContent(dto.getMessage());
temList.add(inner);
}
smsSendDTO.setItems(temList);
String url = smsServer + "/sms/msg";
try {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> requestEntity = new HttpEntity<>(new JSONObject(smsSendDTO).toString(), headers);
ResponseEntity<SmsResponseDTO> response = restTemplate.exchange(
url,
HttpMethod.POST,
requestEntity,
SmsResponseDTO.class
);
// 处理响应
return handleSmsResponse(response);
} catch (RestClientException e) {
log.error("短信接口调用失败", e);
throw new RuntimeException("短信发送异常", e);
}
}
private List<SmsResponseDTO.SmsItem> handleSmsResponse(ResponseEntity<SmsResponseDTO> response) {
if (response.getStatusCode() == HttpStatus.OK) {
SmsResponseDTO smsResponse = response.getBody();
if (smsResponse != null && "0".equals(smsResponse.getCode())) {
log.info("短信发送成功batchId: {}", smsResponse.getBatchId());
return smsResponse.getItems();
} else {
log.error("短信发送失败: {}", (smsResponse != null ? smsResponse.getMessage() : "API 返回异常"));
throw new BusinessException("调用短信服务失败");
}
} else {
log.error("HTTP 请求失败,状态码: {}", response.getStatusCode());
throw new BusinessException("调用短信服务失败");
}
}
}

View File

@@ -51,3 +51,8 @@ spring:
min-idle: 0 min-idle: 0
smsServer:
info: http://22.33.194.50:18096
netInfo: http://22.33.191.206:18096
account: sms
password: aaa

View File

@@ -53,3 +53,8 @@ spring:
min-idle: 0 min-idle: 0
smsServer:
info: http://22.33.194.49:18095
netInfo: http://20.33.234.143:18095
account: sms
password: aaa

View File

@@ -38,6 +38,9 @@ db:
business: business:
#处理波形数据位置 #处理波形数据位置
wavePath: D://Comtrade wavePath: D://Comtrade
exportBaseDir: D://exportComtrade
cronExpression:
#wavePath: /usr/local/comtrade #wavePath: /usr/local/comtrade
#处理临时数据 #处理临时数据
tempPath: D://file tempPath: D://file
@@ -67,7 +70,7 @@ threadPool:
maxPoolSize: 20 maxPoolSize: 20
queueCapacity: 500 queueCapacity: 500
keepAliveSeconds: 60 keepAliveSeconds: 60
WAVEPATH: D:/Comtrade