package com.ruoyi.system.service.impl; import com.alibaba.fastjson2.JSONObject; import com.ruoyi.common.config.SmsConfig; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.utils.SmsUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysTask; import com.ruoyi.system.domain.SysTaskEmergency; import com.ruoyi.system.mapper.SysTaskEmergencyMapper; import com.ruoyi.system.mapper.SysTaskMapper; import com.ruoyi.system.mapper.SysUserMapper; import com.ruoyi.system.service.ISmsService; import com.ruoyi.system.service.ISysConfigService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; /** * 短信发送服务实现类 * * @author ruoyi * @date 2025-12-07 */ @Service public class SmsServiceImpl implements ISmsService { private static final Logger log = LoggerFactory.getLogger(SmsServiceImpl.class); /** 系统配置键:短信开关 */ private static final String CONFIG_KEY_SMS_ENABLED = "sms.enabled"; @Autowired private SmsConfig smsConfig; @Autowired private ISysConfigService configService; @Autowired private SysUserMapper sysUserMapper; @Autowired private SysTaskMapper sysTaskMapper; @Autowired private SysTaskEmergencyMapper sysTaskEmergencyMapper; /** * 检查短信服务是否启用 * 优先从数据库配置读取,其次从配置文件读取 * * @return true=启用, false=禁用 */ @Override public boolean isEnabled() { try { // 优先从数据库配置读取 String enabled = configService.selectConfigByKey(CONFIG_KEY_SMS_ENABLED); if (StringUtils.isNotEmpty(enabled)) { return "true".equalsIgnoreCase(enabled); } } catch (Exception e) { log.warn("获取短信开关配置失败,使用配置文件配置", e); } // 从配置文件读取 return smsConfig.isEnabled(); } /** * 发送短信 * * @param phone 手机号 * @param content 短信内容 * @return 是否发送成功 */ @Override public boolean sendSms(String phone, String content) { if (!isEnabled()) { log.info("短信服务已关闭,跳过发送,phone={}", phone); return false; } if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(content)) { log.warn("短信发送参数不完整,phone={}, content={}", phone, content); return false; } try { // 添加签名 String fullContent = smsConfig.getSignName() + content; JSONObject result = SmsUtils.sendSms( smsConfig.getAddress(), smsConfig.getUserName(), smsConfig.getPassword(), phone, fullContent ); if (result != null) { int code = result.getIntValue("code", -1); if (code == 0) { log.info("短信发送成功,phone={}", phone); return true; } else { log.error("短信发送失败,phone={},code={},msg={}", phone, code, result.getString("msg")); } } } catch (Exception e) { log.error("短信发送异常,phone={}", phone, e); } return false; } /** * 批量发送短信 * * @param phones 手机号列表 * @param content 短信内容 * @return 成功发送的数量 */ @Override public int sendSmsBatch(List phones, String content) { if (!isEnabled()) { log.info("短信服务已关闭,跳过批量发送"); return 0; } if (phones == null || phones.isEmpty() || StringUtils.isEmpty(content)) { log.warn("批量短信发送参数不完整"); return 0; } int successCount = 0; for (String phone : phones) { if (sendSms(phone, content)) { successCount++; } } log.info("批量短信发送完成,总数={},成功={}", phones.size(), successCount); return successCount; } /** * 发送任务分配通知短信 * * @param taskId 任务ID * @param userIds 用户ID列表 * @param excludeUserId 排除的用户ID(可选,如创建人) * @return 成功发送的数量 */ @Override public int sendTaskAssignSms(Long taskId, List userIds, Long excludeUserId) { if (!isEnabled()) { log.info("短信服务已关闭,跳过任务分配短信发送,taskId={}", taskId); return 0; } if (taskId == null || userIds == null || userIds.isEmpty()) { log.warn("任务分配短信发送参数不完整,taskId={}, userIds={}", taskId, userIds); return 0; } // 查询任务信息 SysTask task = sysTaskMapper.selectSysTaskByTaskId(taskId); if (task == null) { log.warn("任务不存在,无法发送短信,taskId={}", taskId); return 0; } // 查询急救扩展信息 SysTaskEmergency emergency = sysTaskEmergencyMapper.selectSysTaskEmergencyByTaskId(taskId); // 构建短信内容 String content = buildTaskAssignSmsContent(task, emergency); int successCount = 0; for (Long userId : userIds) { // 排除指定用户 if (excludeUserId != null && excludeUserId.equals(userId)) { log.debug("跳过排除用户,userId={}", userId); continue; } // 查询用户信息 SysUser user = sysUserMapper.selectUserById(userId); if (user == null) { log.warn("用户不存在,跳过发送,userId={}", userId); continue; } String phone = user.getPhonenumber(); if (StringUtils.isEmpty(phone)) { log.warn("用户手机号为空,跳过发送,userId={}, userName={}", userId, user.getNickName()); continue; } // 发送短信 if (sendSms(phone, content)) { successCount++; log.info("任务分配短信发送成功,taskId={},userId={},phone={}", taskId, userId, phone); } } log.info("任务分配短信发送完成,taskId={},总数={},成功={}", taskId, userIds.size(), successCount); return successCount; } /** * 发送任务分配通知短信(不排除任何用户) * * @param taskId 任务ID * @param userIds 用户ID列表 * @return 成功发送的数量 */ @Override public int sendTaskAssignSms(Long taskId, List userIds) { return sendTaskAssignSms(taskId, userIds, null); } /** * 构建任务分配短信内容 * * @param task 任务信息 * @param emergency 急救扩展信息(可选) * @return 短信内容 */ private String buildTaskAssignSmsContent(SysTask task, SysTaskEmergency emergency) { String template = smsConfig.getTaskAssignTemplate(); // 任务编号 String taskCode = StringUtils.isNotEmpty(task.getTaskCode()) ? task.getTaskCode() : String.valueOf(task.getTaskId()); // 出发地 String departure; if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalOutName())) { departure = emergency.getHospitalOutName(); } else if (StringUtils.isNotEmpty(task.getDepartureAddress())) { departure = task.getDepartureAddress(); } else { departure = "待确认"; } // 目的地 String destination; if (emergency != null && StringUtils.isNotEmpty(emergency.getHospitalInName())) { destination = emergency.getHospitalInName(); } else if (StringUtils.isNotEmpty(task.getDestinationAddress())) { destination = task.getDestinationAddress(); } else { destination = "待确认"; } // 限制地址长度,避免短信过长 if (departure.length() > 20) { departure = departure.substring(0, 17) + "..."; } if (destination.length() > 20) { destination = destination.substring(0, 17) + "..."; } // 替换模板变量 return template .replace("{taskCode}", taskCode) .replace("{departure}", departure) .replace("{destination}", destination); } /** * 查询短信余额 * * @return 余额信息 */ @Override public String getBalance() { try { JSONObject result = SmsUtils.getBalance( smsConfig.getAddress(), smsConfig.getUserName(), smsConfig.getPassword() ); if (result != null) { return result.toJSONString(); } } catch (Exception e) { log.error("查询短信余额失败", e); } return "查询失败"; } }