fxkh-txl-service/src/main/java/com/whdc/service/impl/SmsHolidayServiceImpl.java

289 lines
11 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.whdc.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whdc.mapper.SmsLogMapper;
import com.whdc.mapper.SmsHolidayMapper;
import com.whdc.mapper.SmsSpecialistMapper;
import com.whdc.model.entity.SmsLog;
import com.whdc.model.entity.SmsHoliday;
import com.whdc.model.entity.SmsSpecialist;
import com.whdc.service.ISmsHolidayService;
import com.whdc.utils.SmsHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 主题日短信服务实现类
*
* @author lyf
* @since 2025-09-23
*/
@Service
@Slf4j
public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoliday> implements ISmsHolidayService {
@Autowired
private SmsSpecialistMapper specialistMapper;
@Autowired
private SmsLogMapper smsLogMapper;
@Autowired
private SmsHelper smsHelper;
// 记录每个任务今日是否已发送短信 - 使用并发Map保证线程安全
private final Map<Long, AtomicBoolean> taskSmsSentToday = new ConcurrentHashMap<>();
@Override
public List<SmsHoliday> listActiveTasks() {
try {
LocalDate today = LocalDate.now();
// 查询当前活动中的主题日短信任务
LambdaQueryWrapper<SmsHoliday> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.eq(SmsHoliday::getStatus, 1) // 1:有效
.le(SmsHoliday::getStartDate, today) // 开始日期小于等于今天
.ge(SmsHoliday::getEndDate, today); // 结束日期大于等于今天
List<SmsHoliday> tasks = this.list(queryWrapper);
return tasks != null ? tasks : Collections.emptyList();
} catch (Exception e) {
log.error("查询活动中的主题日短信任务失败: {}", e.getMessage(), e);
return Collections.emptyList();
}
}
@Override
public List<SmsHoliday> listTodayTasks() {
try {
// 获取当前活动中的任务
List<SmsHoliday> activeTasks = listActiveTasks();
if (activeTasks.isEmpty()) {
return Collections.emptyList();
}
LocalDate today = LocalDate.now();
List<SmsHoliday> todayTasks = new java.util.ArrayList<>();
// 筛选今天需要执行的任务
for (SmsHoliday task : activeTasks) {
// 检查是否已经发送过
AtomicBoolean sentFlag = taskSmsSentToday.computeIfAbsent(task.getId(), k -> new AtomicBoolean(false));
if (sentFlag.get()) {
continue; // 今日已发送,跳过
}
// 检查执行时间
String executionTime = task.getExecutionTmStr();
if (executionTime == null || executionTime.trim().isEmpty()) {
log.warn("主题日任务{}执行时间未配置", task.getSubjectName());
continue;
}
// 检查当前时间是否达到执行时间
LocalDateTime now = LocalDateTime.now();
try {
String todayWithExecutionTime = today.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + executionTime;
LocalDateTime scheduledTime = LocalDateTime.parse(
todayWithExecutionTime,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
);
if (now.isEqual(scheduledTime) || now.isAfter(scheduledTime)) {
todayTasks.add(task);
}
} catch (Exception e) {
log.error("主题日任务{}执行时间格式解析失败: {}", task.getSubjectName(), executionTime, e);
}
}
return todayTasks;
} catch (Exception e) {
log.error("查询今日主题日任务失败: {}", e.getMessage(), e);
return Collections.emptyList();
}
}
@Override
public void sendThemeSms(SmsHoliday smsTask) {
if (smsTask == null) {
log.warn("主题日短信任务为空");
return;
}
// 获取所有有效专家
List<SmsSpecialist> specialists = getValidSpecialists();
if (specialists.isEmpty()) {
log.info("没有有效专家,跳过主题日短信发送");
return;
}
String template = smsTask.getTemplate();
if (template == null || template.trim().isEmpty()) {
log.warn("主题日任务{}模板内容为空", smsTask.getSubjectName());
return;
}
// 逐个发送个性化短信
int totalSpecialists = specialists.size();
log.info("开始向{}位专家发送主题日短信[{}]", totalSpecialists, smsTask.getSubjectName());
for (int i = 0; i < specialists.size(); i++) {
SmsSpecialist specialist = specialists.get(i);
// 替换模板中的占位符
String content = template.replace("{姓名}", specialist.getName())
.replace("{主题}", smsTask.getSubjectName());
try {
log.info("正在发送第{}/{}位专家{}的主题日短信", i + 1, totalSpecialists, specialist.getName());
// 创建短信日志记录
SmsLog smsLog = new SmsLog();
smsLog.setName(specialist.getName())
.setPhone(specialist.getPhone())
.setContent(content)
.setRemark("主题日短信-" + smsTask.getSubjectName())
.setSendTm(new java.util.Date());
// 使用SmsHelper发送个性化短信
List<String> phoneList = Collections.singletonList(specialist.getPhone());
String sendResult = smsHelper.send(phoneList, content);
log.info("向专家{}发送主题日短信[{}]结果: {}", specialist.getName(), smsTask.getSubjectName(), sendResult);
// 根据发送结果设置备注
if ("发送成功".equals(sendResult)) {
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送成功");
} else {
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送失败: " + sendResult);
}
// 保存短信日志记录
smsLogMapper.insert(smsLog);
// 如果不是最后一位专家等待3秒再发送下一条
if (i < specialists.size() - 1) {
try {
log.info("等待3秒后发送下一条短信...");
Thread.sleep(3000); // 3秒间隔
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
log.warn("短信发送间隔被中断");
break;
}
}
} catch (Exception e) {
log.error("向专家{}发送主题日短信[{}]时发生异常: {}", specialist.getName(), smsTask.getSubjectName(), e.getMessage(), e);
// 即使发送失败,也保存短信记录
try {
SmsLog failedSmsLog = new SmsLog();
failedSmsLog.setName(specialist.getName())
.setPhone(specialist.getPhone())
.setContent(content)
.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送异常: " + e.getMessage())
.setSendTm(new java.util.Date());
smsLogMapper.insert(failedSmsLog);
} catch (Exception logException) {
log.error("保存发送失败的短信日志时发生异常: {}", logException.getMessage(), logException);
}
}
}
log.info("主题日短信任务[{}]发送完成", smsTask.getSubjectName());
// 标记任务今日已发送
AtomicBoolean sentFlag = taskSmsSentToday.computeIfAbsent(smsTask.getId(), k -> new AtomicBoolean(false));
sentFlag.set(true);
log.info("主题日短信任务[{}]发送完成", smsTask.getSubjectName());
}
@Override
public void sendBatchThemeSms(List<SmsHoliday> smsTasks) {
if (smsTasks == null || smsTasks.isEmpty()) {
log.info("没有需要发送的主题日短信任务");
return;
}
log.info("开始批量发送{}个主题日短信任务", smsTasks.size());
for (SmsHoliday task : smsTasks) {
try {
sendThemeSms(task);
} catch (Exception e) {
log.error("发送主题日短信任务[{}]失败: {}", task.getSubjectName(), e.getMessage(), e);
}
}
log.info("批量主题日短信任务发送完成");
}
/**
* 获取所有有效专家
*/
private List<SmsSpecialist> getValidSpecialists() {
try {
LambdaQueryWrapper<SmsSpecialist> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SmsSpecialist::getStatus, 1); // 1:有效
queryWrapper.isNotNull(SmsSpecialist::getPhone); // 手机号不为空
List<SmsSpecialist> specialists = specialistMapper.selectList(queryWrapper);
return specialists != null ? specialists : Collections.emptyList();
} catch (Exception e) {
log.error("查询有效专家失败: {}", e.getMessage(), e);
return Collections.emptyList();
}
}
/**
* 定时检查并发送主题日短信
* 每分钟执行一次
*/
@Scheduled(cron = "0 * * * * ?")
public void checkAndSendThemeSms() {
try {
// 查询今日需要执行的主题日任务
List<SmsHoliday> todayTasks = listTodayTasks();
if (todayTasks.isEmpty()) {
log.debug("今日没有需要执行的主题日短信任务");
return;
}
log.info("检测到{}个主题日短信任务需要执行", todayTasks.size());
// 批量发送主题日短信
sendBatchThemeSms(todayTasks);
} catch (Exception e) {
log.error("定时检查主题日短信任务执行异常: {}", e.getMessage(), e);
}
}
/**
* 重置每日发送状态
* 每天凌晨00:00:01执行
*/
@Scheduled(cron = "1 0 0 * * ?")
public void resetDailySendStatus() {
try {
// 重置所有任务的发送状态
for (AtomicBoolean sentFlag : taskSmsSentToday.values()) {
sentFlag.set(false);
}
log.info("主题日短信每日发送状态已重置");
} catch (Exception e) {
log.error("重置主题日短信每日发送状态异常: {}", e.getMessage(), e);
}
}
}