package com.ruoyi.system.service.impl;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.system.domain.*;
|
import com.ruoyi.system.mapper.NotifyChannelConfigMapper;
|
import com.ruoyi.system.mapper.SysMessageMapper;
|
import com.ruoyi.system.service.*;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.stereotype.Service;
|
|
import java.util.Collections;
|
import java.util.List;
|
|
/**
|
* 通知分发服务实现类
|
* 负责根据配置决定发送渠道并执行分发
|
*
|
* @author ruoyi
|
* @date 2025-12-07
|
*/
|
@Service
|
public class NotifyDispatchServiceImpl implements INotifyDispatchService {
|
|
private static final Logger log = LoggerFactory.getLogger(NotifyDispatchServiceImpl.class);
|
|
@Autowired
|
private NotifyChannelConfigMapper channelConfigMapper;
|
|
@Autowired
|
private INotifyTaskService notifyTaskService;
|
|
@Autowired
|
private INotifySendLogService notifySendLogService;
|
|
@Autowired
|
private SysMessageMapper sysMessageMapper;
|
|
@Autowired
|
private IWechatTaskNotifyService wechatTaskNotifyService;
|
|
@Autowired
|
private ISmsService smsService;
|
|
/**
|
* 获取指定通知类型启用的渠道列表
|
*/
|
@Override
|
public List<NotifyChannelConfig> getEnabledChannels(String notifyType) {
|
if (StringUtils.isEmpty(notifyType)) {
|
return Collections.emptyList();
|
}
|
return channelConfigMapper.selectEnabledChannelsByType(notifyType);
|
}
|
|
/**
|
* 检查指定渠道是否启用
|
*/
|
@Override
|
public boolean isChannelEnabled(String notifyType, String channel) {
|
NotifyChannelConfig config = channelConfigMapper.selectByTypeAndChannel(notifyType, channel);
|
return config != null && NotifyChannelConfig.ENABLED_YES.equals(config.getEnabled());
|
}
|
|
/**
|
* 分发通知任务
|
*/
|
@Override
|
public int dispatchNotify(NotifyTask notifyTask) {
|
if (notifyTask == null) {
|
return 0;
|
}
|
|
log.info("开始分发通知任务,id={}, taskId={}, userId={}, notifyType={}",
|
notifyTask.getId(), notifyTask.getTaskId(), notifyTask.getUserId(), notifyTask.getNotifyType());
|
|
// 更新状态为处理中
|
notifyTaskService.markProcessing(notifyTask.getId());
|
|
// 获取启用的渠道
|
List<NotifyChannelConfig> channels = getEnabledChannels(notifyTask.getNotifyType());
|
if (channels.isEmpty()) {
|
log.warn("没有启用的渠道,notifyType={}", notifyTask.getNotifyType());
|
notifyTaskService.markCompleted(notifyTask.getId());
|
return 0;
|
}
|
|
int successCount = 0;
|
StringBuilder errorMsgs = new StringBuilder();
|
|
// 按优先级依次发送各渠道
|
for (NotifyChannelConfig channelConfig : channels) {
|
String channel = channelConfig.getChannel();
|
boolean success = false;
|
String errorMsg = null;
|
|
try {
|
switch (channel) {
|
case NotifyChannelConfig.CHANNEL_SITE_MSG:
|
success = sendSiteMessage(notifyTask);
|
break;
|
case NotifyChannelConfig.CHANNEL_WECHAT:
|
success = sendWechatMessage(notifyTask);
|
break;
|
case NotifyChannelConfig.CHANNEL_SMS:
|
success = sendSmsMessage(notifyTask);
|
break;
|
default:
|
log.warn("不支持的渠道类型:{}", channel);
|
continue;
|
}
|
} catch (Exception e) {
|
errorMsg = e.getMessage();
|
log.error("发送{}消息失败,notifyTaskId={}", channel, notifyTask.getId(), e);
|
}
|
|
// 记录发送日志
|
recordSendLog(notifyTask, channel, success, errorMsg);
|
|
if (success) {
|
successCount++;
|
log.info("{}渠道发送成功,notifyTaskId={}", channel, notifyTask.getId());
|
} else {
|
if (errorMsgs.length() > 0) {
|
errorMsgs.append("; ");
|
}
|
errorMsgs.append(channel).append(":").append(errorMsg != null ? errorMsg : "发送失败");
|
}
|
}
|
|
// 更新任务状态
|
if (successCount > 0) {
|
notifyTaskService.markCompleted(notifyTask.getId());
|
} else {
|
notifyTaskService.incrementRetryCount(notifyTask.getId());
|
// 检查是否超过最大重试次数
|
NotifyTask updated = notifyTaskService.selectNotifyTaskById(notifyTask.getId());
|
if (updated.getRetryCount() >= updated.getMaxRetry()) {
|
notifyTaskService.markFailed(notifyTask.getId(), errorMsgs.toString());
|
} else {
|
// 重置为待处理状态,等待下次重试
|
notifyTaskService.updateNotifyTask(createStatusUpdate(notifyTask.getId(), NotifyTask.STATUS_PENDING));
|
}
|
}
|
|
log.info("通知任务分发完成,id={}, 成功渠道数={}", notifyTask.getId(), successCount);
|
return successCount;
|
}
|
|
/**
|
* 创建状态更新对象
|
*/
|
private NotifyTask createStatusUpdate(Long id, String status) {
|
NotifyTask update = new NotifyTask();
|
update.setId(id);
|
update.setStatus(status);
|
return update;
|
}
|
|
/**
|
* 记录发送日志
|
*/
|
private void recordSendLog(NotifyTask notifyTask, String channel, boolean success, String errorMsg) {
|
try {
|
NotifySendLog sendLog = new NotifySendLog();
|
sendLog.setNotifyTaskId(notifyTask.getId());
|
sendLog.setTaskId(notifyTask.getTaskId());
|
sendLog.setUserId(notifyTask.getUserId());
|
sendLog.setUserName(notifyTask.getUserName());
|
sendLog.setNotifyType(notifyTask.getNotifyType());
|
sendLog.setChannel(channel);
|
sendLog.setSendStatus(success ? NotifySendLog.SEND_STATUS_SUCCESS : NotifySendLog.SEND_STATUS_FAILED);
|
sendLog.setSendTime(DateUtils.getNowDate());
|
sendLog.setResponseMsg(errorMsg);
|
|
notifySendLogService.insertNotifySendLog(sendLog);
|
} catch (Exception e) {
|
log.error("记录发送日志失败", e);
|
}
|
}
|
|
/**
|
* 批量分发通知任务
|
*/
|
@Override
|
public int dispatchNotifies(List<NotifyTask> notifyTasks) {
|
if (notifyTasks == null || notifyTasks.isEmpty()) {
|
return 0;
|
}
|
|
int successCount = 0;
|
for (NotifyTask notifyTask : notifyTasks) {
|
int channelCount = dispatchNotify(notifyTask);
|
if (channelCount > 0) {
|
successCount++;
|
}
|
}
|
return successCount;
|
}
|
|
/**
|
* 处理待发送的通知任务
|
*/
|
@Override
|
public int processPendingNotifies(int limit) {
|
List<NotifyTask> pendingTasks = notifyTaskService.selectPendingNotifyTasks(limit);
|
if (pendingTasks.isEmpty()) {
|
return 0;
|
}
|
|
log.info("开始处理待发送通知任务,数量={}", pendingTasks.size());
|
return dispatchNotifies(pendingTasks);
|
}
|
|
/**
|
* 发送站内消息
|
*/
|
@Override
|
public boolean sendSiteMessage(NotifyTask notifyTask) {
|
try {
|
SysMessage message = new SysMessage();
|
message.setMessageType(getMessageType(notifyTask.getNotifyType()));
|
message.setMessageTitle(notifyTask.getTitle());
|
message.setMessageContent(notifyTask.getContent());
|
message.setTaskId(notifyTask.getTaskId());
|
message.setTaskCode(notifyTask.getTaskCode());
|
message.setReceiverId(notifyTask.getUserId());
|
message.setReceiverName(notifyTask.getUserName());
|
message.setSenderId(0L);
|
message.setSenderName("系统");
|
message.setIsRead("0");
|
message.setCreateTime(DateUtils.getNowDate());
|
message.setDelFlag("0");
|
|
sysMessageMapper.insertSysMessage(message);
|
log.info("站内消息发送成功,messageId={}, userId={}", message.getMessageId(), notifyTask.getUserId());
|
return true;
|
} catch (Exception e) {
|
log.error("站内消息发送失败,userId={}", notifyTask.getUserId(), e);
|
return false;
|
}
|
}
|
|
/**
|
* 根据通知类型获取消息类型
|
*/
|
private String getMessageType(String notifyType) {
|
switch (notifyType) {
|
case NotifyTask.NOTIFY_TYPE_TASK_ASSIGN:
|
return "PUSH";
|
case NotifyTask.NOTIFY_TYPE_STATUS_CHANGE:
|
return "STATUS";
|
case NotifyTask.NOTIFY_TYPE_TASK_CREATE:
|
return "CREATE";
|
default:
|
return "SYSTEM";
|
}
|
}
|
|
/**
|
* 发送微信订阅消息
|
*/
|
@Override
|
public boolean sendWechatMessage(NotifyTask notifyTask) {
|
try {
|
// 调用微信通知服务
|
int result = wechatTaskNotifyService.sendTaskNotifyMessage(
|
notifyTask.getTaskId(),
|
Collections.singletonList(notifyTask.getUserId()),
|
null // 不排除任何用户
|
);
|
|
if (result > 0) {
|
log.info("微信订阅消息发送成功,taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId());
|
return true;
|
} else {
|
log.warn("微信订阅消息发送失败,taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId());
|
return false;
|
}
|
} catch (Exception e) {
|
log.error("微信订阅消息发送异常,taskId={}, userId={}", notifyTask.getTaskId(), notifyTask.getUserId(), e);
|
return false;
|
}
|
}
|
|
/**
|
* 发送短信消息
|
*/
|
@Override
|
public boolean sendSmsMessage(NotifyTask notifyTask) {
|
try {
|
// 检查短信服务是否启用
|
if (!smsService.isEnabled()) {
|
log.info("短信服务已关闭,跳过发送");
|
return false;
|
}
|
|
String phone = notifyTask.getUserPhone();
|
if (StringUtils.isEmpty(phone)) {
|
log.warn("用户手机号为空,无法发送短信,userId={}", notifyTask.getUserId());
|
return false;
|
}
|
|
// 发送短信
|
boolean success = smsService.sendSms(phone, notifyTask.getContent());
|
if (success) {
|
log.info("短信发送成功,phone={}, userId={}", phone, notifyTask.getUserId());
|
} else {
|
log.warn("短信发送失败,phone={}, userId={}", phone, notifyTask.getUserId());
|
}
|
return success;
|
} catch (Exception e) {
|
log.error("短信发送异常,userId={}", notifyTask.getUserId(), e);
|
return false;
|
}
|
}
|
}
|