|
|
@@ -0,0 +1,185 @@
|
|
|
+package cn.iocoder.byzs.module.aicourse.service.aiCourse;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import cn.hutool.extra.spring.SpringUtil;
|
|
|
+import cn.iocoder.byzs.framework.common.pojo.PageResult;
|
|
|
+import cn.iocoder.byzs.framework.common.util.object.BeanUtils;
|
|
|
+import cn.iocoder.byzs.framework.mybatis.core.query.LambdaQueryWrapperX;
|
|
|
+import cn.iocoder.byzs.module.aicourse.controller.admin.aiCourse.vo.AiCoursePageReqVO;
|
|
|
+import cn.iocoder.byzs.module.aicourse.controller.admin.aiCourse.vo.AiCourseRespVO;
|
|
|
+import cn.iocoder.byzs.module.aicourse.controller.admin.aiCourse.vo.AiCourseSaveReqVO;
|
|
|
+import cn.iocoder.byzs.module.aicourse.dal.dataobject.aiCourse.AiCourseDO;
|
|
|
+import cn.iocoder.byzs.module.aicourse.dal.dataobject.aiCourseProgress.AiCourseProgressDO;
|
|
|
+import cn.iocoder.byzs.module.aicourse.dal.dataobject.aiCourseType.AiCourseTypeDO;
|
|
|
+import cn.iocoder.byzs.module.aicourse.dal.mysql.aiCourse.AiCourseMapper;
|
|
|
+import cn.iocoder.byzs.module.aicourse.dal.mysql.aiCourseProgress.AiCourseProgressMapper;
|
|
|
+import cn.iocoder.byzs.module.aicourse.dal.mysql.aiCourseType.AiCourseTypeMapper;
|
|
|
+import cn.iocoder.byzs.module.infra.dal.dataobject.file.FileDO;
|
|
|
+import cn.iocoder.byzs.module.infra.framework.file.core.client.FileClient;
|
|
|
+import cn.iocoder.byzs.module.infra.service.file.FileConfigService;
|
|
|
+import cn.iocoder.byzs.module.infra.service.file.FileServiceImpl;
|
|
|
+import jakarta.annotation.Resource;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.validation.annotation.Validated;
|
|
|
+
|
|
|
+import java.util.List;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+import static cn.iocoder.byzs.framework.common.exception.util.ServiceExceptionUtil.exception;
|
|
|
+import static cn.iocoder.byzs.module.aicourse.enums.ErrorCodeConstants.*;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 课程 Service 实现类
|
|
|
+ *
|
|
|
+ * @author lyb
|
|
|
+ */
|
|
|
+@Service
|
|
|
+@Validated
|
|
|
+public class AiCourseServiceImpl implements AiCourseService {
|
|
|
+
|
|
|
+ @Resource
|
|
|
+ private AiCourseMapper aiCourseMapper;
|
|
|
+ @Resource
|
|
|
+ private AiCourseTypeMapper aiCourseTypeMapper;
|
|
|
+ @Resource
|
|
|
+ private FileServiceImpl fileService;
|
|
|
+ @Resource
|
|
|
+ private FileConfigService fileConfigService;
|
|
|
+ @Resource
|
|
|
+ private AiCourseProgressMapper aiCourseProgressMapper;
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Long createAiCourse(AiCourseSaveReqVO createReqVO) {
|
|
|
+ // 插入
|
|
|
+ AiCourseDO blockly = BeanUtils.toBean(createReqVO, AiCourseDO.class);
|
|
|
+ aiCourseMapper.insert(blockly);
|
|
|
+
|
|
|
+ if (blockly.getAcContentType().equals("video")) {
|
|
|
+ getSelf().asymcVideoFfmpeg(blockly);
|
|
|
+ }
|
|
|
+ // 返回
|
|
|
+ return blockly.getId();
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateAiCourse(AiCourseSaveReqVO updateReqVO) {
|
|
|
+ // 校验存在
|
|
|
+ AiCourseDO blocklyDO = validateAiCourseExists(updateReqVO.getId());
|
|
|
+ // 更新
|
|
|
+ AiCourseDO updateObj = BeanUtils.toBean(updateReqVO, AiCourseDO.class);
|
|
|
+ aiCourseMapper.updateById(updateObj);
|
|
|
+
|
|
|
+ //同步进度表中的课程类型
|
|
|
+ if (!blocklyDO.getAcType().equals(updateObj.getAcType())) {
|
|
|
+ AiCourseTypeDO blocklyTypeDO = aiCourseTypeMapper.selectById(updateObj.getAcType());
|
|
|
+ // 使用条件更新,将brpCtId等于旧课程类型ID的记录更新为新课程类型ID
|
|
|
+ aiCourseProgressMapper.update(new AiCourseProgressDO().setBrpCtId(updateObj.getAcType()).setBrpZtId(blocklyTypeDO.getCtParentId()),
|
|
|
+ new LambdaQueryWrapperX<AiCourseProgressDO>().eq(AiCourseProgressDO::getBrpCtId, blocklyDO.getAcType()));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (updateObj.getAcContentType().equals("video")) {
|
|
|
+ getSelf().asymcVideoFfmpeg(updateObj);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Async
|
|
|
+ public void asymcVideoFfmpeg(AiCourseDO blockly) {
|
|
|
+ //只对mp4文件进行处理
|
|
|
+ String blocklyVideoPath = blockly.getAcContent();
|
|
|
+ String ext = blocklyVideoPath.substring(blocklyVideoPath.lastIndexOf("."));
|
|
|
+ if (StrUtil.isBlank(ext) || ext.equals(".m3u8")) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取相对文件路径
|
|
|
+ FileDO fileDO= fileService.getFilePathByUrl(blockly.getAcContent());
|
|
|
+ if (fileDO == null || fileDO.getPath() == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ //切片
|
|
|
+ FileClient client = fileConfigService.getMasterFileClient();
|
|
|
+ String m3u8Path = client.ffmpegHts(fileDO.getPath());
|
|
|
+ if(StrUtil.isNotEmpty(m3u8Path)){
|
|
|
+ aiCourseMapper.updateById(new AiCourseDO().setId(blockly.getId()).setAcContent(m3u8Path));
|
|
|
+ fileDO.setUrl(m3u8Path);
|
|
|
+ fileService.updateFileById(fileDO);
|
|
|
+
|
|
|
+ // 从文件存储器中删除【暂时不删除mp4文件,删除时需要同步更改fileDo中path的相对路径更改成m3u8文件】
|
|
|
+// try {
|
|
|
+// client.delete(blocklyVideoPath);
|
|
|
+// } catch (Exception e) {
|
|
|
+// throw new RuntimeException(e);
|
|
|
+// }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteAiCourse(Long id) {
|
|
|
+ // 校验存在
|
|
|
+ validateAiCourseExists(id);
|
|
|
+ // 删除
|
|
|
+ aiCourseMapper.deleteById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void deleteAiCourseListByIds(List<Long> ids) {
|
|
|
+ // 校验存在
|
|
|
+ validateAiCourseExists(ids);
|
|
|
+ // 删除
|
|
|
+ aiCourseMapper.deleteByIds(ids);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateAiCourseExists(List<Long> ids) {
|
|
|
+ List<AiCourseDO> list = aiCourseMapper.selectByIds(ids);
|
|
|
+ if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
|
|
|
+ throw exception(BLOCKLY_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private AiCourseDO validateAiCourseExists(Long id) {
|
|
|
+ AiCourseDO blocklyDO = aiCourseMapper.selectById(id);
|
|
|
+ if (blocklyDO == null) {
|
|
|
+ throw exception(BLOCKLY_NOT_EXISTS);
|
|
|
+ }
|
|
|
+ return blocklyDO;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AiCourseDO getAiCourse(Long id) {
|
|
|
+ return aiCourseMapper.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PageResult<AiCourseRespVO> getAiCoursePage(AiCoursePageReqVO pageReqVO) {
|
|
|
+ pageReqVO.setPageNo((pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize());
|
|
|
+ List<AiCoursePageReqVO> blocklyPageReqVOS = aiCourseMapper.selectAiCoursePage(pageReqVO);
|
|
|
+
|
|
|
+ // 获取总记录数
|
|
|
+ int total = aiCourseMapper.selectAiCoursePageCount(pageReqVO);
|
|
|
+ // 调用服务层方法获取分页结果
|
|
|
+ return new PageResult<>(
|
|
|
+ blocklyPageReqVOS.stream()
|
|
|
+ .map(doItem -> BeanUtils.toBean(doItem, AiCourseRespVO.class))
|
|
|
+ .collect(Collectors.toList()),
|
|
|
+ (long) total
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<AiCoursePageReqVO> getAiCourseList(AiCoursePageReqVO pageReqVO) {
|
|
|
+ return aiCourseMapper.selectAiCourseList(pageReqVO);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获得自身的代理对象,解决 AOP 生效问题
|
|
|
+ *
|
|
|
+ * @return 自己
|
|
|
+ */
|
|
|
+ private AiCourseServiceImpl getSelf() {
|
|
|
+ return SpringUtil.getBean(getClass());
|
|
|
+ }
|
|
|
+
|
|
|
+}
|