|
|
@@ -1,6 +1,5 @@
|
|
|
package com.fs.course.service.impl;
|
|
|
|
|
|
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
@@ -9,13 +8,13 @@ import com.fs.common.utils.DateUtils;
|
|
|
import com.fs.common.utils.PubFun;
|
|
|
import com.fs.common.utils.date.DateUtil;
|
|
|
import com.fs.common.utils.date.TimeTypeEnum;
|
|
|
-import com.fs.company.domain.CompanyDomain;
|
|
|
import com.fs.course.domain.FsUserCoursePeriod;
|
|
|
import com.fs.course.domain.FsUserCoursePeriodDays;
|
|
|
import com.fs.course.domain.FsUserCourseVideo;
|
|
|
import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
|
|
|
import com.fs.course.mapper.FsUserCoursePeriodMapper;
|
|
|
import com.fs.course.mapper.FsUserCourseVideoRedPackageMapper;
|
|
|
+import com.fs.course.param.BatchAddCourseSectionParam;
|
|
|
import com.fs.course.param.CompanyRedPacketParam;
|
|
|
import com.fs.course.param.CourseAnalysisParam;
|
|
|
import com.fs.course.param.PeriodCountParam;
|
|
|
@@ -27,7 +26,6 @@ import com.fs.course.vo.UpdateCourseTimeVo;
|
|
|
import com.fs.course.vo.newfs.FsCourseAnalysisCountVO;
|
|
|
import com.fs.his.mapper.FsUserMapper;
|
|
|
import com.fs.his.vo.OptionsVO;
|
|
|
-import com.fs.sop.domain.QwSopTempRules;
|
|
|
import com.fs.system.domain.SysConfig;
|
|
|
import com.fs.system.mapper.SysConfigMapper;
|
|
|
import lombok.AllArgsConstructor;
|
|
|
@@ -209,6 +207,154 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
|
|
|
return R.ok();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 批量添加课程小节
|
|
|
+ * @param param 批量添加参数
|
|
|
+ * @return 操作结果
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public R batchAddCourseSections(BatchAddCourseSectionParam param) {
|
|
|
+ try {
|
|
|
+ // 2. 获取营期信息
|
|
|
+ FsUserCoursePeriod period = fsUserCoursePeriodMapper.selectFsUserCoursePeriodById(param.getPeriodId());
|
|
|
+ if (period == null) {
|
|
|
+ return R.error("营期不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 获取已存在的课程小节
|
|
|
+ List<FsUserCoursePeriodDays> existingDays = list(new QueryWrapper<FsUserCoursePeriodDays>()
|
|
|
+ .eq("period_id", param.getPeriodId())
|
|
|
+ .eq("del_flag", "0")
|
|
|
+ .orderByAsc("lesson"));
|
|
|
+
|
|
|
+ // 4. 计算营期总天数
|
|
|
+ long totalDays;
|
|
|
+ if (period.getPeriodType() == 2) {
|
|
|
+ totalDays = 1;
|
|
|
+ } else {
|
|
|
+ totalDays = DateUtil.differenceTime(period.getPeriodStartingTime(), period.getPeriodEndTime(), TimeTypeEnum.DAY);
|
|
|
+ }
|
|
|
+ totalDays ++;
|
|
|
+ // 5. 验证是否超过营期范围
|
|
|
+ if (existingDays.size() + param.getVideoIds().size() > totalDays) {
|
|
|
+ return R.error("添加的课程数量超过营期范围,营期总天数:" + totalDays + ",当前已有:" + existingDays.size() + ",尝试添加:" + param.getVideoIds().size());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 6. 检查重复视频
|
|
|
+ Set<Long> existingVideoIds = existingDays.stream()
|
|
|
+ .map(FsUserCoursePeriodDays::getVideoId)
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+
|
|
|
+ List<Long> duplicateVideoIds = param.getVideoIds().stream()
|
|
|
+ .filter(existingVideoIds::contains)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (!duplicateVideoIds.isEmpty()) {
|
|
|
+ if (param.getSkipDuplicate() != null && param.getSkipDuplicate()) {
|
|
|
+ // 跳过重复的视频
|
|
|
+ param.getVideoIds().removeAll(duplicateVideoIds);
|
|
|
+ log.info("跳过重复的视频ID:{}", duplicateVideoIds);
|
|
|
+ if (param.getVideoIds().isEmpty()) {
|
|
|
+ return R.ok("所有视频都已存在,跳过添加");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return R.error("不能添加相同章节,重复的视频ID:" + duplicateVideoIds);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 7. 获取视频详情
|
|
|
+ FsUserCourseVideo queryVideo = new FsUserCourseVideo();
|
|
|
+ queryVideo.setCourseId(param.getCourseId());
|
|
|
+ List<FsUserCourseVideo> videoList = fsUserCourseVideoService.selectFsUserCourseVideoListByCourseId(queryVideo);
|
|
|
+ Map<Long, FsUserCourseVideo> videoMap = PubFun.listToMapByGroupObject(videoList, FsUserCourseVideo::getVideoId);
|
|
|
+
|
|
|
+ // 8. 验证视频是否都存在
|
|
|
+ for (Long videoId : param.getVideoIds()) {
|
|
|
+ if (!videoMap.containsKey(videoId)) {
|
|
|
+ return R.error("视频ID:" + videoId + " 不存在于课程中");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 9. 准备添加的小节数据
|
|
|
+ List<FsUserCoursePeriodDays> newDays = new ArrayList<>();
|
|
|
+ AtomicInteger lessonCounter = new AtomicInteger(existingDays.size());
|
|
|
+
|
|
|
+ // 确定开始课次
|
|
|
+ int startLesson = param.getStartLesson() != null ? param.getStartLesson() : existingDays.size();
|
|
|
+
|
|
|
+ for (int i = 0; i < param.getVideoIds().size(); i++) {
|
|
|
+ Long videoId = param.getVideoIds().get(i);
|
|
|
+ FsUserCourseVideo video = videoMap.get(videoId);
|
|
|
+
|
|
|
+ FsUserCoursePeriodDays newDay = new FsUserCoursePeriodDays();
|
|
|
+ newDay.setPeriodId(param.getPeriodId());
|
|
|
+ newDay.setCourseId(param.getCourseId());
|
|
|
+ newDay.setVideoId(videoId);
|
|
|
+
|
|
|
+ // 设置课次
|
|
|
+ if (param.getAutoSort() != null && param.getAutoSort()) {
|
|
|
+ newDay.setLesson(startLesson + i);
|
|
|
+ } else {
|
|
|
+ newDay.setLesson(lessonCounter.getAndIncrement());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算日期
|
|
|
+ newDay.setDayDate(period.getPeriodStartingTime().plusDays(newDay.getLesson()));
|
|
|
+
|
|
|
+ // 设置时间 - 优先使用参数中的时间,其次使用视频默认时间
|
|
|
+ if (param.getStartTime() != null) {
|
|
|
+ newDay.setStartDateTime(LocalDateTime.of(newDay.getDayDate(), param.getStartTime()));
|
|
|
+ } else if (video.getViewStartTime() != null) {
|
|
|
+ newDay.setStartDateTime(LocalDateTime.of(newDay.getDayDate(), video.getViewStartTime()));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (param.getEndDateTime() != null) {
|
|
|
+ newDay.setEndDateTime(LocalDateTime.of(newDay.getDayDate(), param.getEndDateTime()));
|
|
|
+ } else if (video.getViewEndTime() != null) {
|
|
|
+ newDay.setEndDateTime(LocalDateTime.of(newDay.getDayDate(), video.getViewEndTime()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置加入时间
|
|
|
+ SysConfig config = sysConfigMapper.selectConfigByConfigKey("joinTime.switch.config");
|
|
|
+ if (ObjectUtils.isNotEmpty(config) && config.getConfigValue().equals("1")) {
|
|
|
+ // 如果开启了配置,使用结束时间作为加入时间
|
|
|
+ newDay.setLastJoinTime(newDay.getEndDateTime());
|
|
|
+ } else {
|
|
|
+ if (param.getJoinTime() != null) {
|
|
|
+ newDay.setLastJoinTime(LocalDateTime.of(newDay.getDayDate(), param.getJoinTime()));
|
|
|
+ } else if (video.getLastJoinTime() != null) {
|
|
|
+ newDay.setLastJoinTime(LocalDateTime.of(newDay.getDayDate(), video.getLastJoinTime()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置状态 - 默认开启今天及以后的两天
|
|
|
+ LocalDate compareDay = LocalDate.now().plusDays(1);
|
|
|
+ if (newDay.getDayDate().isBefore(compareDay)) {
|
|
|
+ newDay.setStatus(1); // 已开始
|
|
|
+ } else {
|
|
|
+ newDay.setStatus(0); // 未开始
|
|
|
+ }
|
|
|
+
|
|
|
+ newDay.setCreateTime(new Date());
|
|
|
+ newDays.add(newDay);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 10. 批量保存
|
|
|
+ if (!newDays.isEmpty()) {
|
|
|
+ super.saveBatch(newDays);
|
|
|
+ log.info("批量添加课程小节成功,营期ID:{},添加数量:{}", param.getPeriodId(), newDays.size());
|
|
|
+ return R.ok("成功添加 " + newDays.size() + " 个课程小节");
|
|
|
+ } else {
|
|
|
+ return R.ok("没有需要添加的课程小节");
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("批量添加课程小节失败,营期ID:{},错误信息:{}", param.getPeriodId(), e.getMessage(), e);
|
|
|
+ throw new RuntimeException("批量添加课程小节失败:" + e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
@Override
|
|
|
public R updateListCourseData(List<FsUserCoursePeriodDays> entity) {
|
|
|
List<FsUserCoursePeriodDays> collect = entity.stream().map(e -> {
|