SlideServiceImpl.java 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. package nju.seec.helper.service.impl;
  2. import com.google.common.collect.ImmutableSet;
  3. import lombok.SneakyThrows;
  4. import nju.seec.helper.dao.ChooseDAO;
  5. import nju.seec.helper.dao.CourseDAO;
  6. import nju.seec.helper.dao.SlideDAO;
  7. import nju.seec.helper.dto.*;
  8. import nju.seec.helper.entity.Course;
  9. import nju.seec.helper.entity.Slide;
  10. import nju.seec.helper.service.MessageService;
  11. import nju.seec.helper.service.SlideService;
  12. import nju.seec.helper.service.util.AuthUtils;
  13. import nju.seec.helper.util.CacheUtils;
  14. import nju.seec.helper.util.Consts;
  15. import nju.seec.helper.util.FileUtils;
  16. import nju.seec.helper.util.enums.ExceptionType;
  17. import nju.seec.helper.util.enums.MessageType;
  18. import nju.seec.helper.util.enums.SlideState;
  19. import nju.seec.helper.util.exception.HelperException;
  20. import nju.seec.helper.vo.SlideVO;
  21. import org.apache.pdfbox.pdmodel.PDDocument;
  22. import org.springframework.data.domain.Page;
  23. import org.springframework.data.domain.Pageable;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import org.springframework.web.multipart.MultipartFile;
  27. import java.io.File;
  28. import java.util.Objects;
  29. import java.util.Set;
  30. import java.util.concurrent.TimeUnit;
  31. /**
  32. * @author cst
  33. */
  34. @Service
  35. public class SlideServiceImpl implements SlideService {
  36. private static final long SLIDE_URL_LIVING_SECONDS = 20 * 60;
  37. private final CourseDAO courseDAO;
  38. private final SlideDAO slideDAO;
  39. private final ChooseDAO chooseDAO;
  40. private final FileUtils fileUtils;
  41. private final CacheUtils cacheUtils;
  42. private final MessageService messageService;
  43. public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, FileUtils fileUtils, CacheUtils cacheUtils, MessageService messageService) {
  44. this.courseDAO = courseDAO;
  45. this.slideDAO = slideDAO;
  46. this.chooseDAO = chooseDAO;
  47. this.fileUtils = fileUtils;
  48. this.cacheUtils = cacheUtils;
  49. this.messageService = messageService;
  50. }
  51. @Transactional(rollbackFor = Exception.class)
  52. @SneakyThrows
  53. @Override
  54. public SlideVO createSlide(LoginUser teacher, SlideDTO slideDTO) {
  55. Course course = courseDAO.findCourseById(slideDTO.getCourseId());
  56. AuthUtils.checkDataAuth(teacher.getId(), course.getTeacherId(), "您无权创建该课程的课件");
  57. checkSameName(0, slideDTO.getCourseId(), slideDTO.getName());
  58. Slide slide = new Slide()
  59. .setCourseId(slideDTO.getCourseId())
  60. .setCourseName(course.getName())
  61. .setTeacherId(teacher.getId())
  62. .setTeacherName(teacher.getName())
  63. .setName(slideDTO.getName())
  64. .setState(slideDTO.getState());
  65. handleFile(slide, slideDTO.getFile());
  66. return new SlideVO(slideDAO.save(slide));
  67. }
  68. @Transactional(rollbackFor = Exception.class)
  69. @Override
  70. public SlideVO modifySlide(LoginUser user, ModifySlideDTO modifySlideDTO) {
  71. Slide slide = slideDAO.findSlideById(modifySlideDTO.getId());
  72. AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件");
  73. checkSameName(slide.getId(), slide.getCourseId(), modifySlideDTO.getName());
  74. slide.setName(modifySlideDTO.getName());
  75. slide = slideDAO.save(slide);
  76. return new SlideVO(slide);
  77. }
  78. @Transactional(rollbackFor = Exception.class)
  79. @Override
  80. public void modifySlideState(LoginUser user, SlideStateDTO slideStateDTO) {
  81. Slide slide = slideDAO.findSlideById(slideStateDTO.getId());
  82. AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件状态");
  83. slide.setState(slideStateDTO.getState());
  84. slide = slideDAO.save(slide);
  85. // 增加通知
  86. if (slide.getState() == SlideState.IN_CLASS) {
  87. Set<Integer> studentIds = chooseDAO.findStudentIdsByCourseId(slide.getCourseId());
  88. messageService.createMessage(studentIds, MessageType.SLIDE_IN_CLASS, String.format("课程 [%s] 的课件 [%s] 已开课", slide.getCourseName(), slide.getName()), slide.getId());
  89. }
  90. }
  91. @Transactional(rollbackFor = Exception.class)
  92. @Override
  93. public void modifySlideFile(LoginUser user, SlideFileDTO slideFileDTO) {
  94. Slide slide = slideDAO.findSlideById(slideFileDTO.getId());
  95. AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件文件");
  96. if (slide.getState() != SlideState.DRAFT) {
  97. throw HelperException.of(ExceptionType.FORBIDDEN, "该课件非草稿状态,无法修改其文件");
  98. }
  99. handleFile(slide, slideFileDTO.getFile());
  100. slideDAO.save(slide);
  101. }
  102. @SneakyThrows
  103. private void handleFile(Slide slide, MultipartFile file) {
  104. switch (Objects.requireNonNull(file.getContentType())) {
  105. case "application/pdf":
  106. // 解析页数
  107. PDDocument doc = PDDocument.load(file.getInputStream());
  108. int pages = doc.getNumberOfPages();
  109. slide.setPages(pages);
  110. // 上传文件
  111. String objectName = slide.getCourseId() + File.separator + slide.getName() + ".pdf";
  112. fileUtils.upload(objectName, file.getInputStream());
  113. slide.setObjectName(objectName);
  114. break;
  115. default:
  116. throw HelperException.of(ExceptionType.PARAM_ERROR, "不支持的文件类型");
  117. }
  118. }
  119. @Transactional(rollbackFor = Exception.class)
  120. @Override
  121. public void removeSlide(LoginUser user, Integer slideId) {
  122. Slide slide = slideDAO.findSlideById(slideId);
  123. AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权删除该课件");
  124. slide.setDeleteAt(System.currentTimeMillis());
  125. slideDAO.save(slide);
  126. }
  127. @Transactional(readOnly = true)
  128. @Override
  129. public Page<SlideVO> teacherGetSlides(LoginUser teacher, String key, Pageable pageable) {
  130. return slideDAO.findByTeacherIdAndNameContains(teacher.getId(), key, pageable).map(SlideVO::new);
  131. }
  132. @Transactional(readOnly = true)
  133. @Override
  134. public Page<SlideVO> teacherGetSlidesByCourse(LoginUser teacher, Integer courseId, String key, Pageable pageable) {
  135. return slideDAO.findByCourseIdAndTeacherIdAndNameContains(courseId, teacher.getId(), key, pageable).map(SlideVO::new);
  136. }
  137. @Transactional(readOnly = true)
  138. @Override
  139. public Page<SlideVO> studentGetSlidesByCourse(LoginUser student, Integer courseId, String key, Pageable pageable) {
  140. if (!chooseDAO.existsByStudentIdAndCourseId(student.getId(), courseId)) {
  141. throw HelperException.of(ExceptionType.FORBIDDEN, "你无权查看该课程下的课件");
  142. }
  143. return slideDAO.findByCourseIdAndStateNotInAndNameContains(courseId, ImmutableSet.of(SlideState.DRAFT), key, pageable).map(SlideVO::new);
  144. }
  145. @Transactional(readOnly = true)
  146. @Override
  147. public String getSlideUrl(LoginUser user, Integer slideId) {
  148. Slide slide = slideDAO.findSlideById(slideId);
  149. checkDataAccessAuth(user, slide);
  150. String url = cacheUtils.get(Consts.SLIDE_URL_CACHE_NAME, slide.getObjectName());
  151. if (url != null) {
  152. return url;
  153. }
  154. url = fileUtils.getUrl(slide.getObjectName(), SLIDE_URL_LIVING_SECONDS);
  155. cacheUtils.set(Consts.SLIDE_URL_CACHE_NAME, slide.getObjectName(), url, SLIDE_URL_LIVING_SECONDS, TimeUnit.SECONDS);
  156. return url;
  157. }
  158. @Transactional(readOnly = true)
  159. @Override
  160. public SlideVO getOneSlide(LoginUser user, Integer slideId) {
  161. Slide slide = slideDAO.findSlideById(slideId);
  162. checkDataAccessAuth(user, slide);
  163. return new SlideVO(slide);
  164. }
  165. /**
  166. * 检查同名课件
  167. */
  168. private void checkSameName(Integer slideId, Integer courseId, String name) {
  169. if (slideDAO.existsByCourseIdAndName(slideId, courseId, name)) {
  170. throw HelperException.of(ExceptionType.CONFLICT, "该课件名已使用");
  171. }
  172. }
  173. private void checkDataAccessAuth(LoginUser user, Slide slide) {
  174. HelperException forbiddenEx = HelperException.of(ExceptionType.FORBIDDEN, "您无权访问该课件");
  175. switch (user.getType()) {
  176. case TEACHER:
  177. if (!slide.getTeacherId().equals(user.getId())) {
  178. throw forbiddenEx;
  179. }
  180. break;
  181. case STUDENT:
  182. if (!chooseDAO.existsByStudentIdAndCourseId(user.getId(), slide.getCourseId())
  183. || slide.getState() == SlideState.DRAFT) {
  184. throw forbiddenEx;
  185. }
  186. break;
  187. default:
  188. throw forbiddenEx;
  189. }
  190. }
  191. }