package com.tcm.training.admin.live.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.tcm.training.admin.app.notice.service.AppSystemNoticeDispatchCommand;
|
import com.tcm.training.admin.app.notice.service.AppSystemNoticeDispatchService;
|
import com.tcm.training.admin.app.notice.service.AppSystemNoticeType;
|
import com.tcm.training.admin.app.settings.entity.AppUserNotificationSetting;
|
import com.tcm.training.admin.app.settings.mapper.AppUserNotificationSettingMapper;
|
import com.tcm.training.admin.live.entity.LiveCourse;
|
import com.tcm.training.admin.live.entity.LiveReserve;
|
import com.tcm.training.admin.live.entity.LiveSession;
|
import com.tcm.training.admin.live.mapper.LiveCourseMapper;
|
import com.tcm.training.admin.live.mapper.LiveReserveMapper;
|
import com.tcm.training.admin.live.mapper.LiveSessionMapper;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Service;
|
|
import java.time.LocalDateTime;
|
import java.util.LinkedHashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 直播提醒通知分发服务。
|
*/
|
@Service
|
public class LiveRemindDispatchService {
|
|
private final LiveSessionMapper liveSessionMapper;
|
private final LiveReserveMapper liveReserveMapper;
|
private final LiveCourseMapper liveCourseMapper;
|
private final AppUserNotificationSettingMapper appUserNotificationSettingMapper;
|
private final AppSystemNoticeDispatchService appSystemNoticeDispatchService;
|
|
/**
|
* 注入直播提醒分发所需依赖。
|
*/
|
public LiveRemindDispatchService(LiveSessionMapper liveSessionMapper,
|
LiveReserveMapper liveReserveMapper,
|
LiveCourseMapper liveCourseMapper,
|
AppUserNotificationSettingMapper appUserNotificationSettingMapper,
|
AppSystemNoticeDispatchService appSystemNoticeDispatchService) {
|
this.liveSessionMapper = liveSessionMapper;
|
this.liveReserveMapper = liveReserveMapper;
|
this.liveCourseMapper = liveCourseMapper;
|
this.appUserNotificationSettingMapper = appUserNotificationSettingMapper;
|
this.appSystemNoticeDispatchService = appSystemNoticeDispatchService;
|
}
|
|
/**
|
* 定时扫描即将开播的预约用户,并按用户设置的提前提醒时间发放通知。
|
*/
|
@Scheduled(fixedDelayString = "${app.live.remind-dispatch-interval-ms:60000}")
|
public void dispatchScheduledReminds() {
|
LocalDateTime now = LocalDateTime.now();
|
List<LiveSession> sessions = liveSessionMapper.selectList(new LambdaQueryWrapper<LiveSession>()
|
.eq(LiveSession::getDeleted, 0)
|
.eq(LiveSession::getLiveStatus, 0)
|
.isNotNull(LiveSession::getStartTime)
|
.gt(LiveSession::getStartTime, now)
|
.orderByAsc(LiveSession::getStartTime)
|
.orderByAsc(LiveSession::getId));
|
for (LiveSession session : sessions) {
|
dispatchRemindsForSession(session, now, false);
|
}
|
}
|
|
/**
|
* 手动触发指定场次的直播提醒发放。
|
*/
|
public long dispatchManualRemind(LiveSession session) {
|
if (session == null) {
|
return 0L;
|
}
|
return dispatchRemindsForSession(session, LocalDateTime.now(), true);
|
}
|
|
/**
|
* 根据预约记录与提醒时间配置发放直播提醒。
|
*/
|
private long dispatchRemindsForSession(LiveSession session, LocalDateTime now, boolean ignoreReminderWindow) {
|
if (session == null || session.getId() == null || session.getStartTime() == null) {
|
return 0L;
|
}
|
List<LiveReserve> reserves = liveReserveMapper.selectList(new LambdaQueryWrapper<LiveReserve>()
|
.eq(LiveReserve::getSessionId, session.getId())
|
.eq(LiveReserve::getIsCancel, 0));
|
if (reserves.isEmpty()) {
|
return 0L;
|
}
|
LiveCourse liveCourse = liveCourseMapper.selectById(session.getLiveCourseId());
|
long dispatchedCount = 0L;
|
for (LiveReserve reserve : reserves) {
|
if (reserve.getUserId() == null) {
|
continue;
|
}
|
Integer advanceMinutes = resolveAdvanceMinutes(reserve.getUserId());
|
if (!ignoreReminderWindow && !isWithinReminderWindow(session.getStartTime(), now, advanceMinutes)) {
|
continue;
|
}
|
AppSystemNoticeDispatchCommand command = new AppSystemNoticeDispatchCommand();
|
command.setAppUserId(reserve.getUserId());
|
command.setNoticeTypeCode(AppSystemNoticeType.LIVE_REMIND);
|
command.setTitle("直播提醒");
|
command.setContent(defaultCourseTitle(liveCourse) + " 即将开播");
|
command.setReferenceType("LIVE_SESSION");
|
command.setReferenceId(session.getId());
|
command.setRequireUserSetting(Boolean.TRUE);
|
Map<String, String> payload = new LinkedHashMap<String, String>();
|
payload.put("courseId", session.getLiveCourseId() == null ? "" : String.valueOf(session.getLiveCourseId()));
|
payload.put("sessionId", String.valueOf(session.getId()));
|
payload.put("startTime", String.valueOf(session.getStartTime()));
|
payload.put("courseTitle", defaultCourseTitle(liveCourse));
|
command.setPayload(payload);
|
appSystemNoticeDispatchService.createAndPush(command);
|
dispatchedCount++;
|
}
|
return dispatchedCount;
|
}
|
|
/**
|
* 读取用户设置的提前提醒分钟数,未配置时默认按 60 分钟处理。
|
*/
|
private Integer resolveAdvanceMinutes(Long appUserId) {
|
AppUserNotificationSetting setting = appUserNotificationSettingMapper.selectOne(new LambdaQueryWrapper<AppUserNotificationSetting>()
|
.eq(AppUserNotificationSetting::getAppUserId, appUserId)
|
.eq(AppUserNotificationSetting::getDeleted, 0)
|
.last("limit 1"));
|
if (setting == null || setting.getAdvanceNoticeMinutes() == null || setting.getAdvanceNoticeMinutes().intValue() <= 0) {
|
return 60;
|
}
|
return setting.getAdvanceNoticeMinutes();
|
}
|
|
/**
|
* 判断当前时间是否已进入当前用户对应的提醒发送窗口。
|
*/
|
private boolean isWithinReminderWindow(LocalDateTime startTime, LocalDateTime now, Integer advanceMinutes) {
|
if (startTime == null || now == null) {
|
return false;
|
}
|
LocalDateTime remindTime = startTime.minusMinutes(advanceMinutes == null ? 60L : advanceMinutes.longValue());
|
return !now.isBefore(remindTime) && now.isBefore(startTime);
|
}
|
|
/**
|
* 返回安全的直播课程标题。
|
*/
|
private String defaultCourseTitle(LiveCourse liveCourse) {
|
if (liveCourse == null || liveCourse.getTitle() == null) {
|
return "您预约的直播";
|
}
|
return liveCourse.getTitle();
|
}
|
}
|