Compare commits

...

3 Commits

Author SHA1 Message Date
李一帆 da3b41b0b4 refactor(sms): 清理SMS相关代码并优化节日短信功能
用户提示词:给主题日短信功能也做相同逻辑的修改、cleanup code for sms series

- 为主题日短信添加与生日短信相同的优化逻辑
- 添加节日短信发送去重机制和数据库标记控制
- 新增节日短信抄送功能和定时重置任务
- 清理SmsHolidayServiceImpl和SmsBirthdayServiceImpl中的注释代码
- 优化导入语句,将通配符导入改为具体类导入
- 统一使用数据库标记控制发送状态,移除内存状态管理
- 增强线程安全控制,防止并发执行问题

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-28 16:52:49 +08:00
李一帆 21ac2c2756 feat(sms): 添加短信日志查询的时间范围筛选功能
- 在 SmsLogPageDto 中新增开始时间和结束时间字段
- 使用 @JsonFormat 注解格式化日期显示
- 在 SmsLogServiceImpl 中实现按时间范围查询逻辑
- 支持根据发送时间进行起止时间筛选
-保持默认按发送时间降序排列的查询规则
2025-09-28 16:02:27 +08:00
李一帆 0f94998144 fix(sms): 调整生日和主题日短信日志级别
- 将调试日志升级为信息日志以提高可见性-优化日志记录逻辑确保关键操作被正确跟踪- 统一异常处理中的日志输出格式
- 改进定时任务执行时的日志记录准确性
-修正线程安全状态检查时的日志描述
- 更新方法注释以符合实际实现逻辑
2025-09-28 10:16:24 +08:00
5 changed files with 98 additions and 72 deletions

View File

@ -13,4 +13,7 @@ import org.apache.ibatis.annotations.Update;
public interface SmsSpecialistMapper extends BaseMapper<SmsSpecialist> {
@Update("update specialist set flag_birthday_sent_today = 0")
void resetFlagBirthdaySentToday();
@Update("update specialist set flag_holiday_sent_today = 0")
void resetFlagHolidaySentToday();
}

View File

@ -1,9 +1,12 @@
package com.whdc.model.dto;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
* DTO
*
@ -19,6 +22,14 @@ public class SmsLogPageDto {
@ApiModelProperty(value = "每页条数", example = "10")
private Integer pageSize = 10;
@ApiModelProperty(value = "开始时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date stm;
@ApiModelProperty(value = "结束时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date etm;
@ApiModelProperty(value = "姓名")
private String name;

View File

@ -18,7 +18,11 @@ import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
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;
/**
@ -180,6 +184,7 @@ public class SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBi
public void resetFlagBirthdaySentToday() {
specialistMapper.resetFlagBirthdaySentToday();
}
/**
*
*
@ -190,7 +195,7 @@ public class SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBi
// 获取生日短信配置
SmsBirthday smsBirthday = this.getById(1L);
if (smsBirthday == null || smsBirthday.getStatus() != 1) {
log.debug("生日短信功能未启用");
log.info("生日短信功能未启用");
return;
}
@ -203,7 +208,7 @@ public class SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBi
// 如果已经发送过,不再重复发送
if (sending.get()) {
log.debug("其他线程正在执行生日短信发送任务");
log.info("其他线程正在执行生日短信发送任务");
return;
}
@ -224,29 +229,26 @@ public class SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBi
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());
try {
// 发送生日短信
sendBirthdaySms(birthdaySpecialists);
log.info("生日短信发送任务完成");
}
} finally {
sending.set(false);
}
log.info("生日短信发送任务完成");
} else {
log.info("其他线程正在执行生日短信发送任务");
}
} else {
log.debug("其他线程正在执行生日短信发送任务");
}
} else {
log.debug("当前时间{}未到执行时间{}", now.format(DateTimeFormatter.ofPattern("HH:mm:ss")), executionTime);
log.info("当前时间{}未到执行时间{}", now.format(DateTimeFormatter.ofPattern("HH:mm:ss")), executionTime);
}
} catch (Exception e) {
@ -257,19 +259,4 @@ public class SmsBirthdayServiceImpl extends ServiceImpl<SmsBirthdayMapper, SmsBi
log.error("定时检查生日短信任务执行异常: {}", e.getMessage(), e);
}
}
/**
*
* 00:00:01
*/
//todo delete this
// @Scheduled(cron = "1 0 0 * * ?")
// public void resetDailySendStatus() {
// try {
// sending.set(false);
// log.info("生日短信每日发送状态已重置");
// } catch (Exception e) {
// log.error("重置生日短信每日发送状态异常: {}", e.getMessage(), e);
// }
// }
}

View File

@ -21,10 +21,11 @@ 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.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@ -60,8 +61,8 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
@Autowired
private SmsHelper smsHelper;
// 记录每个任务今日是否已发送短信 - 使用并发Map保证线程安全
private final Map<Long, AtomicBoolean> taskSmsSentToday = new ConcurrentHashMap<>();
// 记录任务发送状态 - 使用原子变量保证线程安全
private final AtomicBoolean sending = new AtomicBoolean(false);
@Override
public List<SmsHoliday> listActiveTasks() {
@ -97,12 +98,6 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
// 筛选今天需要执行的任务
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()) {
@ -141,8 +136,8 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
return;
}
// 获取所有有效专家
List<SmsSpecialist> specialists = getValidSpecialists();
// 获取所有有效专家(节日短信专用)
List<SmsSpecialist> specialists = getValidSpecialistsForHoliday();
if (specialists.isEmpty()) {
log.info("没有有效专家,跳过主题日短信发送");
return;
@ -158,8 +153,14 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
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());
@ -177,6 +178,12 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
// 使用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);
// 根据发送结果设置备注
@ -186,6 +193,9 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
smsLog.setRemark("主题日短信-" + smsTask.getSubjectName() + "-发送失败: " + sendResult);
}
// 应唐科要求,每次发送短讯要抄送给唐威,陈锋
carbonCopy(content);
// 保存短信日志记录
smsLogMapper.insert(smsLog);
@ -220,11 +230,6 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
}
log.info("主题日短信任务[{}]发送完成", smsTask.getSubjectName());
// 标记任务今日已发送
AtomicBoolean sentFlag = taskSmsSentToday.computeIfAbsent(smsTask.getId(), k -> new AtomicBoolean(false));
sentFlag.set(true);
log.info("主题日短信任务[{}]发送完成", smsTask.getSubjectName());
}
@Override
@ -246,12 +251,32 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
}
/**
*
*
*/
private List<SmsSpecialist> getValidSpecialists() {
private void carbonCopy(String content) {
List<String> phoneList = new ArrayList<>();
phoneList.add("18154318312"); //唐威
phoneList.add("13247155309"); //陈锋
phoneList.add("15671545233"); //李
smsHelper.send(phoneList, content);
}
/**
* 0flagHolidaySentToday0
*/
@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);
@ -269,38 +294,32 @@ public class SmsHolidayServiceImpl extends ServiceImpl<SmsHolidayMapper, SmsHoli
@Scheduled(cron = "0 * * * * ?")
public void checkAndSendThemeSms() {
try {
// 如果其他线程正在执行,跳过
if (sending.get()) {
log.debug("其他线程正在执行主题日短信发送任务");
return;
}
// 查询今日需要执行的主题日任务
List<SmsHoliday> todayTasks = listTodayTasks();
if (todayTasks.isEmpty()) {
log.debug("今日没有需要执行的主题日短信任务");
log.info("今日没有需要执行的主题日短信任务");
return;
}
log.info("检测到{}个主题日短信任务需要执行", todayTasks.size());
// 批量发送主题日短信
try {
sendBatchThemeSms(todayTasks);
} finally {
sending.set(false);
}
} 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);
sending.set(false);
}
}
}

View File

@ -29,6 +29,12 @@ public class SmsLogServiceImpl extends ServiceImpl<SmsLogMapper, SmsLog> impleme
if (StringUtils.hasText(dto.getPhone())) {
queryWrapper.like(SmsLog::getPhone, dto.getPhone());
}
if (dto.getStm() != null) {
queryWrapper.ge(SmsLog::getSendTm, dto.getStm());
}
if (dto.getEtm() != null) {
queryWrapper.le(SmsLog::getSendTm, dto.getEtm());
}
// 默认按发送时间降序排列
queryWrapper.orderByDesc(SmsLog::getSendTm);