From ed527bae283588de0a9848390348e93c3820fef9 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期一, 20 四月 2026 17:07:49 +0800
Subject: [PATCH] feat:通知功能完善
---
tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/HealthCourseAppService.java | 66 ++++++++++++++++++++++++++++++++
1 files changed, 65 insertions(+), 1 deletions(-)
diff --git a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/HealthCourseAppService.java b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/HealthCourseAppService.java
index a878260..743ff41 100644
--- a/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/HealthCourseAppService.java
+++ b/tcm-training-admin-backend/src/main/java/com/tcm/training/admin/live/service/HealthCourseAppService.java
@@ -4,19 +4,26 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+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.common.Jsons;
import com.tcm.training.admin.common.PageResponse;
import com.tcm.training.admin.live.dto.HealthCourseSaveRequest;
import com.tcm.training.admin.live.dto.HealthCourseStatusRequest;
import com.tcm.training.admin.live.dto.HealthCourseVideoSaveRequest;
import com.tcm.training.admin.live.entity.Expert;
+import com.tcm.training.admin.live.entity.CoursePurchaseOrder;
import com.tcm.training.admin.live.entity.HealthCourse;
+import com.tcm.training.admin.live.entity.HealthCourseMemberJoinRecord;
import com.tcm.training.admin.live.entity.HealthCourseVideo;
import com.tcm.training.admin.live.entity.LiveCourseCategory;
import com.tcm.training.admin.live.excel.HealthCourseExportRow;
import com.tcm.training.admin.live.excel.HealthCourseVideoImportRow;
import com.tcm.training.admin.live.mapper.ExpertMapper;
import com.tcm.training.admin.live.mapper.HealthCourseMapper;
+import com.tcm.training.admin.live.mapper.CoursePurchaseOrderMapper;
+import com.tcm.training.admin.live.mapper.HealthCourseMemberJoinRecordMapper;
import com.tcm.training.admin.live.mapper.HealthCourseVideoMapper;
import com.tcm.training.admin.live.mapper.LiveCourseCategoryMapper;
import com.tcm.training.admin.live.vo.ExpertVO;
@@ -53,15 +60,24 @@
private final HealthCourseVideoMapper healthCourseVideoMapper;
private final LiveCourseCategoryMapper liveCourseCategoryMapper;
private final ExpertMapper expertMapper;
+ private final CoursePurchaseOrderMapper coursePurchaseOrderMapper;
+ private final HealthCourseMemberJoinRecordMapper healthCourseMemberJoinRecordMapper;
+ private final AppSystemNoticeDispatchService appSystemNoticeDispatchService;
public HealthCourseAppService(HealthCourseMapper healthCourseMapper,
HealthCourseVideoMapper healthCourseVideoMapper,
LiveCourseCategoryMapper liveCourseCategoryMapper,
- ExpertMapper expertMapper) {
+ ExpertMapper expertMapper,
+ CoursePurchaseOrderMapper coursePurchaseOrderMapper,
+ HealthCourseMemberJoinRecordMapper healthCourseMemberJoinRecordMapper,
+ AppSystemNoticeDispatchService appSystemNoticeDispatchService) {
this.healthCourseMapper = healthCourseMapper;
this.healthCourseVideoMapper = healthCourseVideoMapper;
this.liveCourseCategoryMapper = liveCourseCategoryMapper;
this.expertMapper = expertMapper;
+ this.coursePurchaseOrderMapper = coursePurchaseOrderMapper;
+ this.healthCourseMemberJoinRecordMapper = healthCourseMemberJoinRecordMapper;
+ this.appSystemNoticeDispatchService = appSystemNoticeDispatchService;
}
public PageResponse<HealthCourseListItemVO> page(int page,
@@ -297,6 +313,7 @@
next.setDeleted(0);
healthCourseVideoMapper.insert(next);
refreshCourseStats(courseId);
+ dispatchCourseUpdateNotice(courseId, next);
return detailVideoResource(next.getId());
}
@@ -380,6 +397,7 @@
video.setDeleted(0);
healthCourseVideoMapper.insert(video);
touchedCourseIds.add(course.getId());
+ dispatchCourseUpdateNotice(course.getId(), video);
}
if (touchedCourseIds.isEmpty()) {
throw new IllegalArgumentException("导入文件没有可用数据");
@@ -500,6 +518,52 @@
healthCourseMapper.updateById(course);
}
+ /**
+ * 在课程新增章节后通知已购课或已加入学习的用户。
+ */
+ private void dispatchCourseUpdateNotice(Long courseId, HealthCourseVideo video) {
+ if (courseId == null || video == null || video.getId() == null) {
+ return;
+ }
+ HealthCourse course = requireCourse(courseId);
+ Set<Long> appUserIds = new LinkedHashSet<Long>();
+ List<CoursePurchaseOrder> orders = coursePurchaseOrderMapper.selectList(new LambdaQueryWrapper<CoursePurchaseOrder>()
+ .eq(CoursePurchaseOrder::getDeleted, 0)
+ .eq(CoursePurchaseOrder::getStatus, "PAID")
+ .eq(CoursePurchaseOrder::getCourseId, courseId));
+ for (CoursePurchaseOrder order : orders) {
+ if (order.getAppUserId() != null) {
+ appUserIds.add(order.getAppUserId());
+ }
+ }
+ List<HealthCourseMemberJoinRecord> joinRecords = healthCourseMemberJoinRecordMapper.selectList(new LambdaQueryWrapper<HealthCourseMemberJoinRecord>()
+ .eq(HealthCourseMemberJoinRecord::getDeleted, 0)
+ .eq(HealthCourseMemberJoinRecord::getCourseId, courseId));
+ for (HealthCourseMemberJoinRecord joinRecord : joinRecords) {
+ if (joinRecord.getAppUserId() != null) {
+ appUserIds.add(joinRecord.getAppUserId());
+ }
+ }
+ for (Long appUserId : appUserIds) {
+ AppSystemNoticeDispatchCommand command = new AppSystemNoticeDispatchCommand();
+ command.setAppUserId(appUserId);
+ command.setNoticeTypeCode(AppSystemNoticeType.COURSE_UPDATE_NOTICE);
+ command.setTitle("课程更新通知");
+ command.setContent(course.getTitle() + " 已更新新章节");
+ // 使用章节主键作为引用,保证同一章节对同一用户只发一次。
+ command.setReferenceType("HEALTH_COURSE_VIDEO");
+ command.setReferenceId(video.getId());
+ command.setRequireUserSetting(Boolean.TRUE);
+ Map<String, String> payload = new LinkedHashMap<String, String>();
+ payload.put("courseId", String.valueOf(courseId));
+ payload.put("courseTitle", course.getTitle());
+ payload.put("videoId", String.valueOf(video.getId()));
+ payload.put("chapterName", defaultText(video.getChapterName()));
+ command.setPayload(payload);
+ appSystemNoticeDispatchService.createAndPush(command);
+ }
+ }
+
private HealthCourse requireCourse(Long id) {
HealthCourse course = healthCourseMapper.selectById(id);
if (course == null) {
--
Gitblit v1.7.1