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

271 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.SmsBirthdayMapper;
import com.whdc.mapper.SmsLogMapper;
import com.whdc.mapper.SmsSpecialistMapper;
import com.whdc.model.entity.SmsBirthday;
import com.whdc.model.entity.SmsLog;
import com.whdc.model.entity.SmsSpecialist;
import com.whdc.service.ISmsBirthdayService;
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.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 SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBirthday> implements ISmsBirthdayService {
@Autowired
private SmsSpecialistMapper specialistMapper;
@Autowired
private SmsLogMapper smsLogMapper;
@Autowired
private SmsHelper smsHelper;
// 记录今日是否已发送生日短信 - 使用原子变量保证线程安全
private final AtomicBoolean sending = new AtomicBoolean(false);
@Override
public List<SmsSpecialist> listBirthdayToday() {
try {
// 获取当前日期的月和日
LocalDate today = LocalDate.now();
String monthDay = today.format(DateTimeFormatter.ofPattern("MM-dd"));
// 查询今天过生日的专家(状态为有效的)
LambdaQueryWrapper<SmsSpecialist> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper
.apply("DATE_FORMAT(BIRTHDAY, '%m-%d') = {0}", monthDay)
.eq(SmsSpecialist::getFlagBirthdaySentToday, 0)
.eq(SmsSpecialist::getStatus, 1); // 1:有效
List<SmsSpecialist> specialists = specialistMapper.selectList(queryWrapper);
return specialists != null ? specialists : Collections.emptyList();
} catch (Exception e) {
// 记录异常并返回空列表
return Collections.emptyList();
}
}
@Override
public void sendBirthdaySms(List<SmsSpecialist> specialists) {
if (specialists == null || specialists.isEmpty()) {
log.info("没有需要发送生日短信的专家");
return;
}
// 获取生日短信模板
SmsBirthday smsBirthday = this.getById(1L); // 使用ID=1的记录
if (smsBirthday == null || smsBirthday.getStatus() != 1) {
log.warn("生日短信模板不存在或未启用");
return; // 模板不存在或未启用
}
String template = smsBirthday.getTemplate();
if (template == null || template.trim().isEmpty()) {
log.warn("生日短信模板内容为空");
return; // 模板内容为空
}
// 逐个发送个性化短信
int totalSpecialists = specialists.size();
log.info("开始向{}位专家发送生日短信", totalSpecialists);
//去重
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());
try {
log.info("正在发送第{}/{}位专家{}的生日短信", i + 1, totalSpecialists, specialist.getName());
// 创建短信日志记录
SmsLog smsLog = new SmsLog();
smsLog.setName(specialist.getName())
.setPhone(specialist.getPhone())
.setContent(content)
.setRemark("生日短信")
.setSendTm(new java.util.Date());
// 使用SmsHelper发送个性化短信
List<String> phoneList = Collections.singletonList(specialist.getPhone());
String sendResult = smsHelper.send(phoneList, content);
// 更新专家的flagBirthdaySentToday
specialist.setFlagBirthdaySentToday(1);
specialistMapper.updateById(specialist);
distinct.add(specialist.getPhone());
log.info("向专家{}发送生日短信结果: {}", specialist.getName(), sendResult);
// 根据发送结果设置备注
if ("发送成功".equals(sendResult)) {
smsLog.setRemark("生日短信-发送成功");
} else {
smsLog.setRemark("生日短信-发送失败: " + 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(), e.getMessage(), e);
// 即使发送失败,也保存短信记录
try {
SmsLog failedSmsLog = new SmsLog();
failedSmsLog.setName(specialist.getName())
.setPhone(specialist.getPhone())
.setContent(content)
.setRemark("生日短信-发送异常: " + e.getMessage())
.setSendTm(new java.util.Date());
smsLogMapper.insert(failedSmsLog);
} catch (Exception logException) {
log.error("保存发送失败的短信日志时发生异常: {}", logException.getMessage(), logException);
}
}
}
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点重置所有专家的flagBirthdaySentToday为0
*/
@Scheduled(cron = "0 0 0 * * ?")
public void resetFlagBirthdaySentToday() {
specialistMapper.resetFlagBirthdaySentToday();
}
/**
* 定时检查并发送生日短信
* 每分钟执行一次
*/
@Scheduled(cron = "0 * * * * ?")
public void checkAndSendBirthdaySms() {
try {
// 获取生日短信配置
SmsBirthday smsBirthday = this.getById(1L);
if (smsBirthday == null || smsBirthday.getStatus() != 1) {
log.info("生日短信功能未启用");
return;
}
// 检查执行时间
String executionTime = smsBirthday.getExecutionTmStr();
if (executionTime == null || executionTime.trim().isEmpty()) {
log.warn("生日短信执行时间未配置");
return;
}
// 如果已经发送过,不再重复发送
if (sending.get()) {
log.info("其他线程正在执行生日短信发送任务");
return;
}
// 获取当前时间
LocalDateTime now = LocalDateTime.now();
try {
// 将执行时间字符串与当前日期拼接
String todayWithExecutionTime = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " " + executionTime;
// 解析为完整的LocalDateTime
LocalDateTime scheduledTime = LocalDateTime.parse(
todayWithExecutionTime,
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
);
// 检查当前时间是否大于等于执行时间
if (now.isEqual(scheduledTime) || now.isAfter(scheduledTime)) {
// 原子性检查和设置发送状态
if (sending.compareAndSet(false, true)) {
try {
log.info("到达生日短信发送时间: {}, 开始执行发送任务", executionTime);
// 查询今天过生日的专家
List<SmsSpecialist> birthdaySpecialists = listBirthdayToday();
if (birthdaySpecialists.isEmpty()) {
log.info("今天没有专家过生日,无需发送生日短信");
} else {
log.info("今天有{}位专家过生日,开始发送生日短信", birthdaySpecialists.size());
// 发送生日短信
sendBirthdaySms(birthdaySpecialists);
log.info("生日短信发送任务完成");
}
} finally {
sending.set(false);
}
} else {
log.info("其他线程正在执行生日短信发送任务");
}
} else {
log.info("当前时间{}未到执行时间{}", now.format(DateTimeFormatter.ofPattern("HH:mm:ss")), executionTime);
}
} catch (Exception e) {
log.error("执行时间格式解析失败: {}", executionTime, e);
}
} catch (Exception e) {
log.error("定时检查生日短信任务执行异常: {}", e.getMessage(), e);
}
}
}