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

334 lines
13 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.plugins.pagination.Page;
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.dto.SmsHolidayPageDto;
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 org.springframework.util.StringUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* 主题日短信服务实现类
*
* @author lyf
* @since 2025-09-23
*/
@Service
@Slf4j
public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoliday> implements ISmsHolidayService {
public Page<SmsHoliday> page(SmsHolidayPageDto dto) {
LambdaQueryWrapper<SmsHoliday> queryWrapper = new LambdaQueryWrapper<>();
// 添加查询条件
if (StringUtils.hasText(dto.getSubjectName())) {
queryWrapper.like(SmsHoliday::getSubjectName, dto.getSubjectName());
}
// 默认按创建时间降序排列
queryWrapper.orderByDesc(SmsHoliday::getCreateTm);
return page(dto.getPage(), queryWrapper);
}
@Autowired
private SmsSpecialistMapper specialistMapper;
@Autowired
private SmsLogMapper smsLogMapper;
@Autowired
private SmsHelper smsHelper;
// 记录任务发送状态 - 使用原子变量保证线程安全
private final AtomicBoolean sending = new AtomicBoolean(false);
@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) {
// 检查执行时间
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 = getValidSpecialistsForHoliday();
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());
// 去重
Set<String> distinct = new HashSet<>();
for (int i = 0; i < specialists.size(); i++) {
SmsSpecialist specialist = specialists.get(i);
if (distinct.contains(specialist.getPhone())) {
continue;
}
// 替换模板中的占位符
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);
// 更新专家的flagHolidaySentToday
specialist.setFlagHolidaySentToday(1);
specialistMapper.updateById(specialist);
distinct.add(specialist.getPhone());
log.info("向专家{}发送主题日短信[{}]结果: {}", specialist.getName(), smsTask.getSubjectName(), sendResult);
// 根据发送结果设置备注
if ("发送成功".equals(sendResult)) {
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送成功");
} else {
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送失败: " + sendResult);
}
// 应唐科要求,每次发送短讯要抄送给唐威,陈锋
carbonCopy(content);
// 保存短信日志记录
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());
}
@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 void carbonCopy(String content) {
// 检查当前日期是否超过10月5号
LocalDate today = LocalDate.now();
LocalDate limitDate = LocalDate.of(2025, 10, 5);
if (today.isAfter(limitDate)) {
log.info("当前日期{}已超过10月5日跳过抄送", today);
return;
}
List<String> phoneList = new ArrayList<>();
phoneList.add("18154318312"); //唐威
phoneList.add("13247155309"); //陈锋
phoneList.add("15671545233"); //李
smsHelper.send(phoneList, content);
}
/**
* 每天0点重置所有专家的flagHolidaySentToday为0
*/
@Scheduled(cron = "0 0 0 * * ?")
public void resetFlagHolidaySentToday() {
specialistMapper.resetFlagHolidaySentToday();
}
/**
* 获取所有有效专家(节日短信专用)
*/
private List<SmsSpecialist> getValidSpecialistsForHoliday() {
try {
LambdaQueryWrapper<SmsSpecialist> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(SmsSpecialist::getStatus, 1); // 1:有效
queryWrapper.eq(SmsSpecialist::getFlagHolidaySentToday, 0); // 未发送节日短信
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 {
// 如果其他线程正在执行,跳过
if (sending.get()) {
log.debug("其他线程正在执行主题日短信发送任务");
return;
}
// 查询今日需要执行的主题日任务
List<SmsHoliday> todayTasks = listTodayTasks();
if (todayTasks.isEmpty()) {
log.info("今日没有需要执行的主题日短信任务");
return;
}
log.info("检测到{}个主题日短信任务需要执行", todayTasks.size());
// 批量发送主题日短信
try {
sendBatchThemeSms(todayTasks);
} finally {
sending.set(false);
}
} catch (Exception e) {
log.error("定时检查主题日短信任务执行异常: {}", e.getMessage(), e);
sending.set(false);
}
}
}