瀏覽代碼

会员营期一键同步

xw 1 周之前
父節點
當前提交
6ea957a06a

+ 22 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseVideoController.java

@@ -16,6 +16,7 @@ import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsUserCourse;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.domain.FsUserCoursePeriodDays;
+import com.fs.course.dto.CoursePeriodSyncResultDTO;
 import com.fs.course.domain.FsUserCourseVideo;
 import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
@@ -235,6 +236,27 @@ public class FsUserCourseVideoController extends BaseController
         return getDataTable(list);
     }
 
+    /**
+     * 同步会员营期
+     * 将课程的视频排序同步到绑定的营期中(更新lesson和dayDate)
+     */
+    @Log(title = "同步会员营期", businessType = BusinessType.UPDATE)
+    @PostMapping("/syncCoursePeriod/{courseId}")
+    public AjaxResult syncCoursePeriod(@PathVariable Long courseId)
+    {
+        CoursePeriodSyncResultDTO result = fsUserCourseVideoService.syncCoursePeriod(courseId);
+
+        // 如果没有更新任何记录,返回友好提示
+        if (result.getTotalUpdated() == 0) {
+            return AjaxResult.error("暂无需要同步的营期数据");
+        }
+
+        StringBuilder message = new StringBuilder();
+        message.append("同步完成,共更新").append(result.getTotalUpdated()).append("条数据");
+
+        return AjaxResult.success(message.toString(), result);
+    }
+
     @GetMapping("/getVideoListByCourseIdAll")
     public TableDataInfo getVideoListByCourseIdAll(Long courseId)
     {

+ 74 - 0
fs-service/src/main/java/com/fs/course/dto/CoursePeriodSyncResultDTO.java

@@ -0,0 +1,74 @@
+package com.fs.course.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 课程营期同步结果DTO
+ *
+ * @author fs
+ */
+@Data
+public class CoursePeriodSyncResultDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 同步的营期列表
+     */
+    private List<PeriodSyncDetail> periodDetails;
+
+    /**
+     * 总更新记录数
+     */
+    private Integer totalUpdated;
+
+    /**
+     * 同步的营期数量
+     */
+    private Integer periodCount;
+
+    /**
+     * 营期同步明细
+     */
+    @Data
+    public static class PeriodSyncDetail implements Serializable {
+        private static final long serialVersionUID = 1L;
+
+        /**
+         * 营期ID
+         */
+        private Long periodId;
+
+        /**
+         * 营期名称
+         */
+        private String periodName;
+
+        /**
+         * 更新的记录数
+         */
+        private Integer updatedCount;
+    }
+
+    public CoursePeriodSyncResultDTO() {
+        this.periodDetails = new ArrayList<>();
+        this.totalUpdated = 0;
+        this.periodCount = 0;
+    }
+
+    /**
+     * 添加营期同步明细
+     */
+    public void addPeriodDetail(Long periodId, String periodName, Integer updatedCount) {
+        PeriodSyncDetail detail = new PeriodSyncDetail();
+        detail.setPeriodId(periodId);
+        detail.setPeriodName(periodName);
+        detail.setUpdatedCount(updatedCount);
+        this.periodDetails.add(detail);
+        this.totalUpdated += updatedCount;
+        this.periodCount++;
+    }
+}

+ 10 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCourseVideoService.java

@@ -5,6 +5,7 @@ import com.fs.common.core.domain.AjaxResult;
 import com.fs.common.core.domain.R;
 import com.fs.common.core.domain.ResponseResult;
 import com.fs.course.domain.FsUserCourseVideo;
+import com.fs.course.dto.CoursePeriodSyncResultDTO;
 import com.fs.course.param.*;
 import com.fs.course.param.newfs.FsUserCourseAddCompanyUserParam;
 import com.fs.course.param.newfs.FsUserCourseVideoLinkParam;
@@ -248,4 +249,13 @@ public interface IFsUserCourseVideoService extends IService<FsUserCourseVideo> {
     R createRoomMiniLinkByCourse(FsCourseLinkRoomNewParam param);
 
     void updateMediaPublishStatus(String vid);
+
+    /**
+     * 同步会员营期
+     * 将课程的视频排序同步到绑定的营期中(更新lesson和dayDate)
+     *
+     * @param courseId 课程ID
+     * @return 同步结果
+     */
+    CoursePeriodSyncResultDTO syncCoursePeriod(Long courseId);
 }

+ 116 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -36,6 +36,7 @@ import com.fs.course.config.CourseConfig;
 import com.fs.course.config.RandomRedPacketConfig;
 import com.fs.course.config.RandomRedPacketRule;
 import com.fs.course.domain.*;
+import com.fs.course.dto.CoursePeriodSyncResultDTO;
 import com.fs.course.dto.CoursePackageDTO;
 import com.fs.course.mapper.*;
 import com.fs.course.param.*;
@@ -4357,5 +4358,120 @@ public class FsUserCourseVideoServiceImpl extends ServiceImpl<FsUserCourseVideoM
             }
         }
     }
+
+    /**
+     * 同步会员营期
+     * 将课程的视频排序同步到绑定的营期中(更新lesson和dayDate)
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public CoursePeriodSyncResultDTO syncCoursePeriod(Long courseId) {
+        log.info("开始同步课程 {} 的会员营期", courseId);
+
+        CoursePeriodSyncResultDTO result = new CoursePeriodSyncResultDTO();
+
+        // 1. 查询课程视频,按courseSort排序
+        FsUserCourseVideo queryVideo = new FsUserCourseVideo();
+        queryVideo.setCourseId(courseId);
+        List<FsUserCourseVideo> courseVideos = fsUserCourseVideoMapper.selectFsUserCourseVideoListByCourseId(queryVideo);
+
+        if (courseVideos == null || courseVideos.isEmpty()) {
+            log.warn("课程 {} 没有视频", courseId);
+            return result;
+        }
+
+        // 按courseSort排序
+        courseVideos.sort(Comparator.comparing(v -> v.getCourseSort() != null ? v.getCourseSort() : Long.MAX_VALUE));
+        log.info("课程 {} 共有 {} 个视频", courseId, courseVideos.size());
+
+        // 2. 查询该课程绑定的营期
+        FsUserCoursePeriod queryPeriod = new FsUserCoursePeriod();
+        queryPeriod.setCourseId(courseId);
+        List<FsUserCoursePeriod> periods = fsUserCoursePeriodMapper.selectFsUserCoursePeriodList(queryPeriod);
+
+        if (periods == null || periods.isEmpty()) {
+            log.warn("课程 {} 没有绑定营期", courseId);
+            return result;
+        }
+
+        // 过滤已结束的营期
+        List<FsUserCoursePeriod> activePeriods = periods.stream()
+                .filter(p -> p.getPeriodStatus() != null && p.getPeriodStatus() != 3)
+                .collect(Collectors.toList());
+
+        if (activePeriods.isEmpty()) {
+            log.warn("课程 {} 的所有营期已结束", courseId);
+            return result;
+        }
+
+        log.info("课程 {} 有 {} 个未结束营期", courseId, activePeriods.size());
+
+        // 3. 遍历营期进行同步
+        for (FsUserCoursePeriod period : activePeriods) {
+            try {
+                // 查询营期中的课程
+                FsUserCoursePeriodDays queryDays = new FsUserCoursePeriodDays();
+                queryDays.setPeriodId(period.getPeriodId());
+                queryDays.setCourseId(courseId);
+                List<FsUserCoursePeriodDays> existingDays = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(queryDays);
+
+                if (existingDays.isEmpty()) {
+                    continue;
+                }
+
+                // 构建 videoId -> day 的映射
+                Map<Long, FsUserCoursePeriodDays> videoToDayMap = existingDays.stream()
+                        .collect(Collectors.toMap(FsUserCoursePeriodDays::getVideoId, d -> d, (a, b) -> a));
+
+                // 获取营期开始日期
+                LocalDate periodStartDate = period.getPeriodStartingTime();
+                if (periodStartDate == null) {
+                    periodStartDate = LocalDate.now();
+                }
+
+                // 更新lesson和dayDate
+                List<FsUserCoursePeriodDays> daysToUpdate = new ArrayList<>();
+                for (int i = 0; i < courseVideos.size(); i++) {
+                    FsUserCourseVideo video = courseVideos.get(i);
+                    if (videoToDayMap.containsKey(video.getVideoId())) {
+                        FsUserCoursePeriodDays day = videoToDayMap.get(video.getVideoId());
+                        int newLesson = i;
+                        LocalDate newDayDate = periodStartDate.plusDays(newLesson);
+
+                        // 判断是否需要更新
+                        if (day.getLesson() == null || day.getLesson() != newLesson || !newDayDate.equals(day.getDayDate())) {
+                            day.setLesson(newLesson);
+                            day.setDayDate(newDayDate);
+
+                            // 更新时间字段
+                            if (day.getStartDateTime() != null) {
+                                day.setStartDateTime(LocalDateTime.of(newDayDate, day.getStartDateTime().toLocalTime()));
+                            }
+                            if (day.getEndDateTime() != null) {
+                                day.setEndDateTime(LocalDateTime.of(newDayDate, day.getEndDateTime().toLocalTime()));
+                            }
+                            if (day.getLastJoinTime() != null) {
+                                day.setLastJoinTime(LocalDateTime.of(newDayDate, day.getLastJoinTime().toLocalTime()));
+                            }
+
+                            daysToUpdate.add(day);
+                        }
+                    }
+                }
+
+                // 批量更新
+                if (!daysToUpdate.isEmpty()) {
+                    fsUserCoursePeriodDaysMapper.batchUpdateCoursePeriodDays(daysToUpdate);
+                    result.addPeriodDetail(period.getPeriodId(), period.getPeriodName(), daysToUpdate.size());
+                    log.info("营期 {} ({}) 同步完成,更新 {} 条", period.getPeriodId(), period.getPeriodName(), daysToUpdate.size());
+                }
+            } catch (Exception e) {
+                log.error("同步营期 {} 失败", period.getPeriodId(), e);
+            }
+        }
+
+        log.info("课程 {} 同步完成,共更新 {} 条记录", courseId, result.getTotalUpdated());
+        return result;
+    }
 }
 

+ 1 - 1
fs-service/src/main/resources/mapper/course/FsUserCoursePeriodDaysMapper.xml

@@ -43,7 +43,7 @@
                 </foreach>
             </if>
         </where>
-        order by a.day_date
+        order by a.lesson, a.day_date
     </select>
     <select id="selectFsUserCoursePeriodDaysCount" parameterType="FsUserCoursePeriodDays" resultType="java.lang.Long">
         select count(a.id) from fs_user_course_period_days a