Browse Source

自动更新排序

xw 4 days ago
parent
commit
e14662eb9c

+ 23 - 0
fs-service/src/main/java/com/fs/course/mapper/FsUserCourseVideoMapper.java

@@ -155,6 +155,29 @@ public interface FsUserCourseVideoMapper
     @Select("select count(0) from fs_user_course_video where course_id = #{courseId} and course_sort = #{courseSort} and is_del = 0 ")
     Long selectFsUserCourseVideoByCourseSort(@Param("courseId")Long courseId, @Param("courseSort")Long courseSort);
 
+    /**
+     * 调整课程排序,将指定排序号及之后的视频排序号+1(用于修改排序时避免重复)
+     * @param courseId 课程ID
+     * @param targetSort 目标排序号
+     * @param excludeVideoId 排除的视频ID(当前正在修改的视频)
+     */
+    @Update("UPDATE fs_user_course_video SET course_sort = course_sort + 1 " +
+            "WHERE course_id = #{courseId} AND course_sort >= #{targetSort} " +
+            "AND video_id != #{excludeVideoId} AND is_del = 0")
+    void adjustCourseSortForUpdate(@Param("courseId") Long courseId,
+                                    @Param("targetSort") Long targetSort,
+                                    @Param("excludeVideoId") Long excludeVideoId);
+
+    /**
+     * 删除课程后调整排序,将指定排序号之后的视频排序号-1(保持排序连续)
+     * @param courseId 课程ID
+     * @param deletedSort 被删除课程的排序号
+     */
+    @Update("UPDATE fs_user_course_video SET course_sort = course_sort - 1 " +
+            "WHERE course_id = #{courseId} AND course_sort > #{deletedSort} AND is_del = 0")
+    void adjustCourseSortAfterDelete(@Param("courseId") Long courseId,
+                                      @Param("deletedSort") Long deletedSort);
+
 
     @Select("select video_id dict_value, title dict_label  from fs_user_course_video where course_id=#{id} and is_del = 0 order by course_sort")
     List<OptionsVO> selectFsUserCourseVodeAllList(Long id);

+ 56 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java

@@ -39,6 +39,7 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -590,6 +591,27 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
             //log.warn("营期日期记录数量或开始时间结束时间记录数量与选择修改的课程数量不匹配");
             return R.error("营期日期记录数量与选择修改的课程数量不匹配");
         }
+        
+        // 获取第一条记录的营期ID和课程ID,用于查询同营期的其他课程
+        Long periodId = list.get(0).getPeriodId();
+        Long firstId = list.get(0).getId();
+        LocalDate newStartDate = dateList.get(0);
+        
+        // 检查新的开始日期是否与其他课程冲突
+        FsUserCoursePeriodDays checkParam = new FsUserCoursePeriodDays();
+        checkParam.setPeriodId(periodId);
+        List<FsUserCoursePeriodDays> allCoursesInPeriod = fsUserCoursePeriodDaysMapper.selectFsUserCoursePeriodDaysList(checkParam);
+        
+        // 找出需要调整的后续课程(日期>=新开始日期 且 不在当前修改的列表中)
+        List<FsUserCoursePeriodDays> coursesToAdjust = allCoursesInPeriod.stream()
+            .filter(course -> !vo.getIds().contains(course.getId())) // 排除当前修改的课程
+            .filter(course -> course.getDayDate() != null && !course.getDayDate().isBefore(newStartDate)) // 日期 >= 新开始日期
+            .sorted(Comparator.comparing(FsUserCoursePeriodDays::getDayDate)) // 按日期排序
+            .collect(Collectors.toList());
+        
+        // 计算需要调整的天数
+        LocalDate lastDateInList = dateList.get(dateList.size() - 1);
+        
         // 遍历数据库记录列表,为每个记录设置对应的日期和其他字段
         for (int i = 0; i < list.size(); i++) {
             FsUserCoursePeriodDays day = list.get(i);
@@ -615,6 +637,40 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
                 day.setStatus(2);
             }
         }
+        
+        // 调整后续课程的日期,确保连续不跳跃
+        if (!coursesToAdjust.isEmpty()) {
+            // 从最后一个修改的课程日期的下一天开始安排后续课程
+            LocalDate nextAvailableDate = lastDateInList.plusDays(1);
+            for (FsUserCoursePeriodDays course : coursesToAdjust) {
+                // 获取原始时间(小时和分钟)
+                LocalTime originalStartTime = course.getStartDateTime().toLocalTime();
+                LocalTime originalEndTime = course.getEndDateTime().toLocalTime();
+                LocalTime originalJoinTime = course.getLastJoinTime() != null ? course.getLastJoinTime().toLocalTime() : originalEndTime;
+                
+                // 设置新的日期(保持原有的时间点)
+                course.setDayDate(nextAvailableDate);
+                course.setStartDateTime(LocalDateTime.of(nextAvailableDate, originalStartTime));
+                course.setEndDateTime(LocalDateTime.of(nextAvailableDate, originalEndTime));
+                course.setLastJoinTime(LocalDateTime.of(nextAvailableDate, originalJoinTime));
+                
+                // 重新计算状态
+                LocalDateTime now = LocalDateTime.now();
+                if (now.isAfter(course.getStartDateTime()) && now.isBefore(course.getEndDateTime())) {
+                    course.setStatus(1);
+                } else if (now.isBefore(course.getStartDateTime())) {
+                    course.setStatus(0);
+                } else {
+                    course.setStatus(2);
+                }
+                
+                list.add(course); // 添加到批量更新列表
+                
+                // 下一个课程的日期为当前日期+1天
+                nextAvailableDate = nextAvailableDate.plusDays(1);
+            }
+        }
+        
         // 批量更新到数据库
         fsUserCoursePeriodDaysMapper.batchUpdateCoursePeriodDays(list);
         return R.ok();

+ 23 - 16
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java

@@ -16,6 +16,7 @@ import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
 import com.fs.course.mapper.FsUserCoursePeriodMapper;
 import com.fs.course.mapper.FsUserCourseVideoMapper;
 import com.fs.course.mapper.FsUserCourseVideoRedPackageMapper;
+import com.fs.course.param.BatchAddCourseSectionParam;
 import com.fs.course.param.PeriodStatisticCountParam;
 import com.fs.course.service.IFsUserCoursePeriodDaysService;
 import com.fs.course.service.IFsUserCoursePeriodService;
@@ -355,23 +356,29 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
         queryVideo.setCourseId(fsUserCoursePeriod.getCourseId());
         List<FsUserCourseVideo> courseVideos = fsUserCourseVideoMapper.selectFsUserCourseVideoListByCourseId(queryVideo);
 
-        //  批量处理每日课程安排(提取重复常量,简化逻辑
+        // 4. 批量添加课程小节(修复:改用批量添加方法,避免课次号倒序问题
         if (!courseVideos.isEmpty()) {
-            // 定义重复使用的时间常量
-            LocalTime startTime = LocalTime.MIDNIGHT;
-            LocalTime endTime = LocalTime.of(23, 59, 59);
-            Long periodId = fsUserCoursePeriod.getPeriodId();
-
-            courseVideos.forEach(video -> {
-                FsUserCoursePeriodDays periodDaysEntity = new FsUserCoursePeriodDays();
-                periodDaysEntity.setPeriodId(periodId);
-                periodDaysEntity.setCourseId(video.getCourseId());
-                periodDaysEntity.setStartTime(startTime);
-                periodDaysEntity.setVideoIds(Collections.singletonList(video.getVideoId()));
-                periodDaysEntity.setEndTime1(endTime);
-                periodDaysEntity.setJoinTime(endTime);
-                fsUserCoursePeriodDaysService.addCourse(periodDaysEntity);
-            });
+            // 提取视频ID列表
+            List<Long> videoIds = courseVideos.stream()
+                    .map(FsUserCourseVideo::getVideoId)
+                    .collect(Collectors.toList());
+
+            // 构建批量添加参数
+            BatchAddCourseSectionParam param = new BatchAddCourseSectionParam();
+            param.setPeriodId(fsUserCoursePeriod.getPeriodId());
+            param.setCourseId(fsUserCoursePeriod.getCourseId());
+            param.setVideoIds(videoIds);
+            param.setStartTime(LocalTime.MIDNIGHT);
+            param.setEndDateTime(LocalTime.of(23, 59, 59));
+            param.setJoinTime(LocalTime.of(23, 59, 59));
+            param.setAutoSort(true); // 自动按courseSort排序
+            param.setSkipDuplicate(true); // 跳过重复视频
+
+            // 调用批量添加方法
+            R result = fsUserCoursePeriodDaysService.batchAddCourseSections(param);
+            if ((Integer)result.get("code") != 200) {
+                return R.error("课程安排创建失败:" + result.get("msg"));
+            }
         }
         return R.ok("营期及课程安排创建成功");
     }

+ 55 - 15
fs-service/src/main/java/com/fs/course/service/impl/FsUserCourseVideoServiceImpl.java

@@ -317,6 +317,27 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             fsUserCourseVideo.setListingStartTime(null);
             fsUserCourseVideo.setListingEndTime(null);
         }
+        
+        // 如果修改了排序号,需要处理排序冲突
+        if (fsUserCourseVideo.getCourseSort() != null) {
+            // 获取原视频信息
+            FsUserCourseVideo oldVideo = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(fsUserCourseVideo.getVideoId());
+            if (oldVideo != null && oldVideo.getCourseSort() != null) {
+                Long newSort = fsUserCourseVideo.getCourseSort();
+                Long oldSort = oldVideo.getCourseSort();
+                
+                // 如果排序号发生了变化
+                if (!newSort.equals(oldSort)) {
+                    // 检查新排序号是否已存在(排除当前视频)
+                    Long count = fsUserCourseVideoMapper.selectFsUserCourseVideoByCourseSort(oldVideo.getCourseId(), newSort);
+                    if (count > 0) {
+                        // 新排序号已存在,需要将该排序号及之后的所有视频排序号+1
+                        fsUserCourseVideoMapper.adjustCourseSortForUpdate(oldVideo.getCourseId(), newSort, fsUserCourseVideo.getVideoId());
+                    }
+                }
+            }
+        }
+        
         String videoRedisKey = "h5user:video:duration:" + fsUserCourseVideo.getVideoId();
         redisCache.setCacheObject(videoRedisKey, fsUserCourseVideo.getDuration());
         return fsUserCourseVideoMapper.updateFsUserCourseVideo(fsUserCourseVideo);
@@ -356,6 +377,17 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
     @Override
     public int deleteFsUserCourseVideoByVideoIds(String[] videoIds)
     {
+        // 先获取要删除的视频信息,用于后续调整排序
+        if (videoIds != null && videoIds.length > 0) {
+            for (String videoIdStr : videoIds) {
+                Long videoId = Long.valueOf(videoIdStr);
+                FsUserCourseVideo video = fsUserCourseVideoMapper.selectFsUserCourseVideoByVideoId(videoId);
+                if (video != null && video.getCourseId() != null && video.getCourseSort() != null) {
+                    // 删除视频后,将该排序号之后的所有视频排序号-1,保持排序连续
+                    fsUserCourseVideoMapper.adjustCourseSortAfterDelete(video.getCourseId(), video.getCourseSort());
+                }
+            }
+        }
         return fsUserCourseVideoMapper.deleteFsUserCourseVideoByVideoIds(videoIds);
     }
 
@@ -2575,9 +2607,9 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
         videoResourceList = videoResourceList.stream()
                 .sorted(Comparator.comparing(FsVideoResource::getSort).thenComparing(FsVideoResource::getId))
                 .collect(Collectors.toList());
-        FsUserCourseVideo param = new FsUserCourseVideo();
-        param.setCourseId(vo.getCourseId());
-        List<FsUserCourseVideo> videoList = selectFsUserCourseVideoList(param);
+        FsUserCourseVideo queryParam = new FsUserCourseVideo();
+        queryParam.setCourseId(vo.getCourseId());
+        List<FsUserCourseVideo> videoList = selectFsUserCourseVideoList(queryParam);
         AtomicLong i = new AtomicLong(videoList.size() + 1);
         String json = configService.selectConfigByKey("course.config");
         CourseConfig config = JSONUtil.toBean(json, CourseConfig.class);
@@ -2615,18 +2647,26 @@ public class FsUserCourseVideoServiceImpl implements IFsUserCourseVideoService
             LocalTime startTime = LocalTime.MIDNIGHT;
             LocalTime endTime = LocalTime.of(23, 59, 59);
             //获取营期数据
-            coursePeriodsList.stream().filter(e -> e.getPeriodStatus() != 3).forEach(video -> {
-                 //循环新增到对应营期中
-                collect.forEach(userCourseVideo->{
-                    FsUserCoursePeriodDays periodDaysEntity = new FsUserCoursePeriodDays();
-                    periodDaysEntity.setPeriodId(video.getPeriodId());//营期ID
-                    periodDaysEntity.setCourseId(video.getCourseId());//课程ID
-                    periodDaysEntity.setStartTime(startTime);
-                    periodDaysEntity.setVideoIds(Collections.singletonList(userCourseVideo.getVideoId()));
-                    periodDaysEntity.setEndTime1(endTime);
-                    periodDaysEntity.setJoinTime(endTime);
-                    fsUserCoursePeriodDaysService.addCourse(periodDaysEntity);
-                });
+            coursePeriodsList.stream().filter(e -> e.getPeriodStatus() != 3).forEach(period -> {
+                // 修复:改用批量添加方法,避免课次号倒序问题
+                // 提取新增视频的ID列表
+                List<Long> newVideoIds = collect.stream()
+                        .map(FsUserCourseVideo::getVideoId)
+                        .collect(Collectors.toList());
+
+                // 构建批量添加参数
+                BatchAddCourseSectionParam batchParam = new BatchAddCourseSectionParam();
+                batchParam.setPeriodId(period.getPeriodId());
+                batchParam.setCourseId(period.getCourseId());
+                batchParam.setVideoIds(newVideoIds);
+                batchParam.setStartTime(startTime);
+                batchParam.setEndDateTime(endTime);
+                batchParam.setJoinTime(endTime);
+                batchParam.setAutoSort(true); // 自动按courseSort排序
+                batchParam.setSkipDuplicate(true); // 跳过重复视频
+
+                // 调用批量添加方法
+                fsUserCoursePeriodDaysService.batchAddCourseSections(batchParam);
             });
         }
     }