Procházet zdrojové kódy

新增营期复制功能

zyy před 1 týdnem
rodič
revize
af7fd494b9

+ 21 - 0
fs-admin/src/main/java/com/fs/course/controller/FsUserCoursePeriodController.java

@@ -151,6 +151,20 @@ public class FsUserCoursePeriodController extends BaseController {
         return fsUserCoursePeriodDaysService.addCourse(entity);
     }
 
+    @PreAuthorize("@ss.hasPermi('course:period:addCourse')")
+    @PostMapping("/batchAddCourseSections")
+    @ApiOperation("一键批量添加课程小节")
+    public R batchAddCourseSections(@Validated @RequestBody BatchAddCourseSectionParam param) {
+        try {
+            logger.info("开始批量添加课程小节,营期ID:{},课程ID:{},视频数量:{},视频ID列表:{}",
+                    param.getPeriodId(), param.getCourseId(), param.getVideoIds().size(), param.getVideoIds());
+            return fsUserCoursePeriodDaysService.batchAddCourseSections(param);
+        } catch (Exception e) {
+            logger.error("批量添加课程小节失败,营期ID:{},错误信息:{}", param.getPeriodId(), e.getMessage(), e);
+            return R.error("批量添加课程小节失败:" + e.getMessage());
+        }
+    }
+
     @PreAuthorize("@ss.hasPermi('course:period:dayRemove')")
     @Log(title = "会员营期课程删除", businessType = BusinessType.DELETE)
     @DeleteMapping("/day/{ids}")
@@ -288,4 +302,11 @@ public class FsUserCoursePeriodController extends BaseController {
         return R.ok();
     }
 
+    @ApiOperation("复制创建成功的营期和对应营期中的看课")
+    @PostMapping("/copyExistCampPeriod")
+    public R copyExistCampPeriod(@RequestBody PeriodStatisticCountParam param){
+        R result = fsUserCoursePeriodService.copyFsUserCoursePeriodAndCourse(param);
+        return result;
+    }
+
 }

+ 78 - 4
fs-admin/src/main/java/com/fs/course/controller/FsUserCourseTrainingCampController.java

@@ -9,11 +9,13 @@ import com.fs.common.core.domain.model.LoginUser;
 import com.fs.common.enums.BusinessType;
 import com.fs.common.utils.ServletUtils;
 import com.fs.common.utils.SortUtils;
+import com.fs.common.utils.StringUtils;
 import com.fs.course.config.CourseConfig;
 import com.fs.course.domain.FsUserCourseTrainingCamp;
 import com.fs.course.dto.FsUserCourseTrainingCampDTO;
 import com.fs.course.dto.FsUserCourseTrainingCampUpdateDTO;
 import com.fs.course.service.IFsUserCourseTrainingCampService;
+import com.fs.course.vo.FsUserCoursePeriodVO;
 import com.fs.course.vo.FsUserCourseTrainingCampVO;
 import com.fs.framework.web.service.TokenService;
 import com.fs.his.vo.OptionsVO;
@@ -25,10 +27,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
 
 import javax.validation.Valid;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
+import java.util.stream.Collectors;
 
 @RestController
 @RequestMapping("/course/trainingCamp")
@@ -109,6 +109,30 @@ public class FsUserCourseTrainingCampController {
         return AjaxResult.success();
     }
 
+
+    /**
+     * 更新训练营序号
+     * @param trainingCampId    训练营ID
+     * @param orderNumber       序号
+     * @return  AjaxResult
+     */
+    @Log(title = "训练营序号", businessType = BusinessType.UPDATE)
+    @PostMapping("/updateOrderNumber")
+    public AjaxResult updateOrderNumber(@RequestParam Long trainingCampId, @RequestParam Long orderNumber) {
+        if (trainingCampId == null) {
+            return AjaxResult.error("训练营ID不能为空");
+        }
+
+        FsUserCourseTrainingCamp trainingCamp = fsUserCourseTrainingCampService.getById(trainingCampId);
+        if (Objects.isNull(trainingCamp)) {
+            return AjaxResult.error("训练营不存在");
+        }
+
+        trainingCamp.setOrderNumber(orderNumber);
+        fsUserCourseTrainingCampService.updateById(trainingCamp);
+        return AjaxResult.success("序号更新成功");
+    }
+
     /**
      * 删除训练营
      * @param ids    参数
@@ -147,4 +171,54 @@ public class FsUserCourseTrainingCampController {
         return R.ok().put("data", new PageInfo<>(campList));
     }
 
+
+    /**
+     * 通过训练营来筛选营期-展示创建成功的营期
+     *
+     * @return
+     */
+    @GetMapping("/getScreeningCampPeriod")
+    public R getScreeningCampPeriod(@RequestParam String campPeriodType,
+                                    @RequestParam(required = false) Long periodId,
+                                    @RequestParam(required = false) String campPeriodName) {
+        try {
+            // 获取用户和配置信息
+            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+            Long userId = loginUser.getUser().getUserId();
+            CourseConfig config = getCourseConfig();
+            boolean needBindUser = config != null && config.getIsBound();
+            if ("2".equals(campPeriodType)) {
+                // 查询其他训练营
+                List<FsUserCoursePeriodVO> resultList = new ArrayList<>();
+                Map<String, Object> params = new HashMap<>();
+                params.put("scs", SortUtils.parseSort("order_number(desc),training_camp_id(desc)"));
+                if (needBindUser) params.put("userIds", userId);
+                List<FsUserCourseTrainingCampVO> fsUserCourseTrainingCampList= fsUserCourseTrainingCampService.selectFsUserCourseTrainingCampVOListByMap(params);
+                fsUserCourseTrainingCampList = fsUserCourseTrainingCampList.stream()
+                        .filter(camp -> !Objects.equals(camp.getTrainingCampId(), periodId))
+                        .collect(Collectors.toList());
+                return R.ok().put("resultList", fsUserCourseTrainingCampList);
+            } else if ("3".equals(campPeriodType)) {
+                // 新建训练营
+                if (StringUtils.isEmpty(campPeriodName)) {
+                    return R.error("训练营名称不能为空");
+                }
+                FsUserCourseTrainingCampDTO campDTO = new FsUserCourseTrainingCampDTO();
+                campDTO.setTrainingCampName(campPeriodName.trim());
+                return R.ok("训练营创建成功");
+            }
+            return R.error("不支持的训练营类型");
+        } catch (Exception e) {
+            return R.error("系统处理异常");
+        }
+    }
+    private CourseConfig getCourseConfig() {
+        try {
+            String json = configService.selectConfigByKey("course.config");
+            return JSONUtil.toBean(json, CourseConfig.class);
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
 }

+ 16 - 0
fs-service/src/main/java/com/fs/course/domain/FsUserCoursePeriod.java

@@ -118,4 +118,20 @@ public class FsUserCoursePeriod
      */
     private Date periodLine;
 
+    private Long courseId;
+
+    /**
+     * 自由学习模式,0-未开启,1-开启(开启后学员不受营期时间限制)
+     */
+    @Excel(name = "自由学习模式")
+    private Integer freeMode;
+
+    /** 是否需要单独注册会员,1-是,0-否(用于个微销售分享看课) */
+    private String isNeedRegisterMember;
+
+    // 控制休息提示是否打开要暂停  0-关闭 1-打开 null-默认打开
+    private Integer IsOpenRestReminder;
+    //  控制休息提示是否打开要暂停  0-关闭 1-打开 Json串 key值为companyId
+    private String isOpenRestFlag;
+
 }

+ 54 - 0
fs-service/src/main/java/com/fs/course/param/BatchAddCourseSectionParam.java

@@ -0,0 +1,54 @@
+package com.fs.course.param;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.time.LocalTime;
+import java.util.List;
+
+/**
+ * 批量添加课程小节参数
+ *
+ * @author fs
+ * @date 2024-12-31
+ */
+@Data
+@ApiModel(description = "批量添加课程小节参数")
+public class BatchAddCourseSectionParam {
+
+    @ApiModelProperty(value = "营期ID", required = true)
+    @NotNull(message = "营期ID不能为空")
+    private Long periodId;
+
+    @ApiModelProperty(value = "课程ID", required = true)
+    @NotNull(message = "课程ID不能为空")
+    private Long courseId;
+
+    @ApiModelProperty(value = "视频ID列表", required = true)
+    @NotEmpty(message = "视频ID列表不能为空")
+    private List<Long> videoIds;
+
+    @ApiModelProperty(value = "统一开始时间(如果设置则覆盖视频默认时间)")
+    private LocalTime startTime;
+
+    @ApiModelProperty(value = "统一结束时间(如果设置则覆盖视频默认时间)")
+    private LocalTime endDateTime;
+
+    @ApiModelProperty(value = "统一加入时间(如果设置则覆盖视频默认时间)")
+    private LocalTime joinTime;
+
+    @ApiModelProperty(value = "是否自动按视频顺序排序", example = "true")
+    private Boolean autoSort = true;
+
+    @ApiModelProperty(value = "起始课程序号(默认从现有课程数量+1开始)")
+    private Integer startLesson;
+
+    @ApiModelProperty(value = "是否跳过重复视频", example = "true")
+    private Boolean skipDuplicate = true;
+
+    @ApiModelProperty(value = "批量操作模式: 1-追加模式 2-覆盖模式", example = "1")
+    private Integer operationMode = 1;
+}

+ 8 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodDaysService.java

@@ -3,6 +3,7 @@ package com.fs.course.service;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsUserCoursePeriodDays;
+import com.fs.course.param.BatchAddCourseSectionParam;
 import com.fs.course.param.CompanyRedPacketParam;
 import com.fs.course.param.PeriodCountParam;
 import com.fs.course.vo.FsPeriodCountVO;
@@ -70,6 +71,13 @@ public interface IFsUserCoursePeriodDaysService extends IService<FsUserCoursePer
 
     R addCourse(FsUserCoursePeriodDays entity);
 
+    /**
+     * 批量添加课程小节
+     * @param param 批量添加参数
+     * @return 操作结果
+     */
+    R batchAddCourseSections(BatchAddCourseSectionParam param);
+
     R updateListCourseData(List<FsUserCoursePeriodDays> entity);
 
     /**

+ 3 - 0
fs-service/src/main/java/com/fs/course/service/IFsUserCoursePeriodService.java

@@ -1,5 +1,6 @@
 package com.fs.course.service;
 
+import com.fs.common.core.domain.R;
 import com.fs.course.domain.FsUserCoursePeriod;
 import com.fs.course.param.PeriodStatisticCountParam;
 import com.fs.course.vo.FsCourseStaticsCountVO;
@@ -101,4 +102,6 @@ public interface IFsUserCoursePeriodService
 
     List<Long> selectFsUserCoursePeriodListByPeriodId(List<Long> periodIds,Long companyId);
 
+    R copyFsUserCoursePeriodAndCourse(PeriodStatisticCountParam param);
+
 }

+ 218 - 4
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodDaysServiceImpl.java

@@ -16,10 +16,7 @@ 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.CompanyRedPacketParam;
-import com.fs.course.param.CourseAnalysisNoPageParam;
-import com.fs.course.param.CourseAnalysisParam;
-import com.fs.course.param.PeriodCountParam;
+import com.fs.course.param.*;
 import com.fs.course.service.IFsUserCoursePeriodDaysService;
 import com.fs.course.service.IFsUserCourseVideoService;
 import com.fs.course.vo.FsPeriodCountVO;
@@ -211,6 +208,223 @@ public class FsUserCoursePeriodDaysServiceImpl extends ServiceImpl<FsUserCourseP
         return R.ok();
     }
 
+    @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 (period.getFreeMode() == null || period.getFreeMode() != 1) {
+                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. 获取视频详情并按courseSort排序
+            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. 根据courseSort对要添加的视频进行排序(从小到大)
+            List<FsUserCourseVideo> sortedVideos = param.getVideoIds().stream()
+                    .map(videoMap::get)
+                    .sorted((v1, v2) -> {
+                        Long sort1 = v1.getCourseSort() != null ? v1.getCourseSort() : Long.MAX_VALUE;
+                        Long sort2 = v2.getCourseSort() != null ? v2.getCourseSort() : Long.MAX_VALUE;
+                        return sort1.compareTo(sort2);
+                    })
+                    .collect(Collectors.toList());
+
+            log.info("按courseSort排序后的视频顺序:");
+            for (int i = 0; i < sortedVideos.size(); i++) {
+                FsUserCourseVideo video = sortedVideos.get(i);
+                log.info("  序号: {}, 视频ID: {}, 标题: {}, courseSort: {}",
+                        i + 1, video.getVideoId(), video.getTitle(), video.getCourseSort());
+            }
+
+            // 10. 准备添加的小节数据,使用按courseSort排序后的视频列表
+            List<FsUserCoursePeriodDays> newDays = new ArrayList<>();
+
+            // 确定开始课次 - 从现有最大课次+1开始,确保连续性
+            int startLesson;
+            LocalDate startDate; // 新增:确定开始日期
+
+            if (param.getStartLesson() != null) {
+                startLesson = param.getStartLesson();
+                // 如果指定了起始课次,仍然基于营期开始时间计算日期
+                startDate = period.getPeriodStartingTime().plusDays(startLesson - 1);
+            } else {
+                // 获取现有最大课次,如果没有则从1开始
+                startLesson = existingDays.stream()
+                        .mapToInt(FsUserCoursePeriodDays::getLesson)
+                        .max()
+                        .orElse(0) + 1;
+
+                // 关键修复:获取已存在课程的最后日期,从该日期的下一天开始
+                if (!existingDays.isEmpty()) {
+                    // 按日期排序,获取最后一个课程的日期
+                    LocalDate lastDate = existingDays.stream()
+                            .map(FsUserCoursePeriodDays::getDayDate)
+                            .filter(date -> date != null)
+                            .max(LocalDate::compareTo)
+                            .orElse(period.getPeriodStartingTime().plusDays(startLesson - 2));
+
+                    startDate = lastDate.plusDays(1); // 从最后日期的下一天开始
+                    log.info("基于已存在课程的最后日期计算起始日期:最后日期={}, 新起始日期={}", lastDate, startDate);
+                } else {
+                    // 如果没有已存在的课程,从营期开始时间计算
+                    startDate = period.getPeriodStartingTime();
+                    log.info("营期暂无课程,从营期开始时间计算起始日期:{}", startDate);
+                }
+            }
+
+            // 使用排序后的视频列表进行处理,确保按courseSort顺序添加
+            for (int i = 0; i < sortedVideos.size(); i++) {
+                FsUserCourseVideo video = sortedVideos.get(i);
+                Long videoId = video.getVideoId();
+
+                FsUserCoursePeriodDays newDay = new FsUserCoursePeriodDays();
+                newDay.setPeriodId(param.getPeriodId());
+                newDay.setCourseId(param.getCourseId());
+                newDay.setVideoId(videoId);
+
+                // 设置课次 - 严格按排序后的顺序递增,确保有序
+                newDay.setLesson(startLesson + i);
+
+                // 计算日期 - 修复:基于起始日期递增,而不是基于课次计算
+                // 这样可以避免当已存在课程的日期与课次不对应时出现重复日期
+                LocalDate courseDate = startDate.plusDays(i);
+                newDay.setDayDate(courseDate);
+
+                // 设置时间 - 优先使用参数中的时间,其次使用视频默认时间
+                if (param.getStartTime() != null) {
+                    newDay.setStartDateTime(LocalDateTime.of(courseDate, param.getStartTime()));
+                } else if (video.getViewStartTime() != null) {
+                    newDay.setStartDateTime(LocalDateTime.of(courseDate, video.getViewStartTime()));
+                }
+
+                if (param.getEndDateTime() != null) {
+                    newDay.setEndDateTime(LocalDateTime.of(courseDate, param.getEndDateTime()));
+                } else if (video.getViewEndTime() != null) {
+                    newDay.setEndDateTime(LocalDateTime.of(courseDate, 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(courseDate, param.getJoinTime()));
+                    } else if (video.getLastJoinTime() != null) {
+                        newDay.setLastJoinTime(LocalDateTime.of(courseDate, video.getLastJoinTime()));
+                    }
+                }
+
+                // 设置状态:如果开启自由模式,默认为进行中(status=1)
+                if (period.getFreeMode() != null && period.getFreeMode() == 1) {
+                    // 自由模式:直接设置为进行中
+                    newDay.setStatus(1);
+                } else {
+                    // 固定模式:默认开启今天及以后的两天
+                    LocalDate compareDay = LocalDate.now().plusDays(1);
+                    if (courseDate.isBefore(compareDay)) {
+                        newDay.setStatus(1); // 已开始
+                    } else {
+                        newDay.setStatus(0); // 未开始
+                    }
+                }
+
+                newDay.setCreateTime(new Date());
+                newDays.add(newDay);
+
+                log.debug("准备添加课程:课次={}, 日期={}, 视频ID={}, 标题={}, courseSort={}",
+                        newDay.getLesson(), newDay.getDayDate(), videoId, video.getTitle(), video.getCourseSort());
+            }
+
+            // 11. 批量保存,确保按courseSort排序的结果保存
+            if (!newDays.isEmpty()) {
+                // 再次按课次排序,确保数据库中的顺序正确(按照批量操作排序保障规范)
+                newDays.sort(Comparator.comparing(FsUserCoursePeriodDays::getLesson));
+
+                log.info("即将批量添加课程小节(按courseSort排序):");
+                for (int i = 0; i < newDays.size(); i++) {
+                    FsUserCoursePeriodDays day = newDays.get(i);
+                    FsUserCourseVideo video = videoMap.get(day.getVideoId());
+                    log.info("  序号: {}, 课次: {}, 日期: {}, 视频ID: {}, 标题: {}, courseSort: {}",
+                            i + 1, day.getLesson(), day.getDayDate(), day.getVideoId(),
+                            video != null ? video.getTitle() : "Unknown",
+                            video != null ? video.getCourseSort() : "null");
+                }
+
+                super.saveBatch(newDays);
+                log.info("批量添加课程小节成功(按courseSort排序),营期ID:{},添加数量:{},课次范围:{}-{}",
+                        param.getPeriodId(), newDays.size(),
+                        newDays.get(0).getLesson(),
+                        newDays.get(newDays.size() - 1).getLesson());
+                return R.ok("成功按courseSort排序添加 " + newDays.size() + " 个课程小节,课次范围:" +
+                        newDays.get(0).getLesson() + "-" + newDays.get(newDays.size() - 1).getLesson());
+            } 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 -> {

+ 40 - 0
fs-service/src/main/java/com/fs/course/service/impl/FsUserCoursePeriodServiceImpl.java

@@ -3,6 +3,7 @@ package com.fs.course.service.impl;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.fs.common.core.domain.R;
 import com.fs.common.core.redis.RedisCache;
 import com.fs.common.exception.CustomException;
 import com.fs.common.exception.ServiceException;
@@ -12,6 +13,7 @@ import com.fs.course.mapper.FsUserCoursePeriodDaysMapper;
 import com.fs.course.mapper.FsUserCoursePeriodMapper;
 import com.fs.course.mapper.FsUserCourseVideoRedPackageMapper;
 import com.fs.course.param.PeriodStatisticCountParam;
+import com.fs.course.service.IFsUserCoursePeriodDaysService;
 import com.fs.course.service.IFsUserCoursePeriodService;
 import com.fs.course.vo.FsCourseStaticsCountVO;
 import com.fs.course.vo.FsUserCoursePeriodVO;
@@ -24,6 +26,7 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
+import java.time.LocalTime;
 import java.time.temporal.ChronoUnit;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -46,6 +49,8 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     private FsUserCoursePeriodDaysMapper fsUserCoursePeriodDaysMapper;
     @Resource
     private FsUserCourseVideoRedPackageMapper fsUserCourseVideoRedPackageMapper;
+    @Autowired
+    private IFsUserCoursePeriodDaysService fsUserCoursePeriodDaysService;
 
     /**
      * 查询会员营期
@@ -310,4 +315,39 @@ public class FsUserCoursePeriodServiceImpl implements IFsUserCoursePeriodService
     public List<Long> selectFsUserCoursePeriodListByPeriodId(List<Long> periodIds, Long companyId) {
         return fsUserCoursePeriodMapper.selectFsUserCoursePeriodListByPeriodId(periodIds,companyId);
     }
+
+    @Override
+    public R copyFsUserCoursePeriodAndCourse(PeriodStatisticCountParam param) {
+        if (param == null || param.getPeriodId() == null || param.getTrainingCampId() == null) {
+            return R.error("营期信息不完整");
+        }
+        //通过现有的营期Id查询,并查询到对应的营期看课
+        FsUserCoursePeriod fsUserCoursePeriod = selectFsUserCoursePeriodById(param.getPeriodId());
+        if (fsUserCoursePeriod == null) {
+            return R.error("未查询到当前营期");
+        }
+        //查询并复制当前营期所有的视频
+        FsUserCoursePeriodDays fsUserCoursePeriodDays = new FsUserCoursePeriodDays();
+        fsUserCoursePeriodDays.setPeriodId(param.getPeriodId());
+        List<FsUserCoursePeriodDays> fsUserCoursePeriodDayslist = fsUserCoursePeriodDaysService.selectFsUserCoursePeriodDaysList(fsUserCoursePeriodDays);
+        fsUserCoursePeriod.setTrainingCampId(param.getTrainingCampId());
+        fsUserCoursePeriod.setPeriodId(null);
+        if (insertFsUserCoursePeriod(fsUserCoursePeriod) <= 0) {
+            return R.error("营期创建失败");
+        }
+        // 定义重复使用的时间常量
+        LocalTime startTime = LocalTime.MIDNIGHT;
+        LocalTime endTime = LocalTime.of(23, 59, 59);
+        fsUserCoursePeriodDayslist.forEach(userCoursePeriodDays -> {
+            userCoursePeriodDays.setPeriodId(fsUserCoursePeriod.getPeriodId());
+            userCoursePeriodDays.setId(null);
+            userCoursePeriodDays.setStartTime(startTime);
+            userCoursePeriodDays.setEndTime1(endTime);
+            userCoursePeriodDays.setJoinTime(endTime);
+            userCoursePeriodDays.setVideoIds(Collections.singletonList(userCoursePeriodDays.getVideoId()));
+            fsUserCoursePeriodDaysService.addCourse(userCoursePeriodDays);
+        });
+        return R.ok();
+
+    }
 }