SlideServiceImpl.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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.LoginUser;
  8. import nju.seec.helper.dto.SlideDTO;
  9. import nju.seec.helper.entity.Course;
  10. import nju.seec.helper.entity.Page;
  11. import nju.seec.helper.entity.Slide;
  12. import nju.seec.helper.service.SlideService;
  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.SlideState;
  17. import nju.seec.helper.util.exception.HelperException;
  18. import nju.seec.helper.vo.SlideVO;
  19. import org.apache.pdfbox.pdmodel.PDDocument;
  20. import org.springframework.data.domain.Pageable;
  21. import org.springframework.stereotype.Service;
  22. import org.springframework.transaction.annotation.Transactional;
  23. import org.springframework.web.multipart.MultipartFile;
  24. import java.time.LocalDateTime;
  25. import java.util.List;
  26. import java.util.Objects;
  27. import java.util.concurrent.TimeUnit;
  28. import java.util.stream.Collectors;
  29. import java.util.stream.IntStream;
  30. /**
  31. * @author cst
  32. */
  33. @Service
  34. public class SlideServiceImpl implements SlideService {
  35. private static final long SLIDE_URL_LIVING_SECONDS = 20 * 60;
  36. private final CourseDAO courseDAO;
  37. private final SlideDAO slideDAO;
  38. private final ChooseDAO chooseDAO;
  39. private final FileUtils fileUtils;
  40. private final CacheUtils cacheUtils;
  41. public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, FileUtils fileUtils, CacheUtils cacheUtils) {
  42. this.courseDAO = courseDAO;
  43. this.slideDAO = slideDAO;
  44. this.chooseDAO = chooseDAO;
  45. this.fileUtils = fileUtils;
  46. this.cacheUtils = cacheUtils;
  47. }
  48. @Transactional(rollbackFor = Exception.class)
  49. @SneakyThrows
  50. @Override
  51. public SlideVO createSlide(LoginUser teacher, SlideDTO slideDTO) {
  52. Course course = courseDAO.findCourseById(slideDTO.getCourseId());
  53. if (!course.getTeacherId().equals(teacher.getId())) {
  54. throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "您无权创建该课程的幻灯片");
  55. }
  56. Slide slide = new Slide();
  57. slide.setCourseId(slideDTO.getCourseId())
  58. .setTeacherId(teacher.getId())
  59. .setName(slideDTO.getName())
  60. .setState(SlideState.DRAFT);
  61. // 解析文件页数
  62. MultipartFile file = slideDTO.getFile();
  63. int pageNum;
  64. switch (Objects.requireNonNull(file.getContentType())) {
  65. // pdf
  66. case "application/pdf":
  67. PDDocument doc = PDDocument.load(file.getInputStream());
  68. pageNum = doc.getNumberOfPages();
  69. break;
  70. default:
  71. throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "不支持的文件类型");
  72. }
  73. slide.setPages(IntStream.rangeClosed(1, pageNum)
  74. .mapToObj(number -> {
  75. Page page = new Page();
  76. page.setTeacherId(teacher.getId());
  77. page.setNumber(number);
  78. return page;
  79. })
  80. .collect(Collectors.toList())
  81. );
  82. // 上传文件
  83. String objectName = fileUtils.upload(LocalDateTime.now().toString() + "-" + file.getOriginalFilename(), file.getInputStream());
  84. slide.setObjectName(objectName);
  85. return new SlideVO(slideDAO.save(slide));
  86. }
  87. @Transactional(readOnly = true)
  88. @Override
  89. public List<SlideVO> teacherGetSlides(LoginUser teacher, String key, Pageable pageable) {
  90. return slideDAO
  91. .findByTeacherIdAndNameContains(teacher.getId(), key, pageable)
  92. .stream()
  93. .map(SlideVO::new)
  94. .collect(Collectors.toList());
  95. }
  96. @Transactional(readOnly = true)
  97. @Override
  98. public List<SlideVO> studentGetSlides(LoginUser student, Integer courseId, String key, Pageable pageable) {
  99. if (!chooseDAO.existsByStudentIdAndCourseId(student.getId(), courseId)) {
  100. throw HelperException.of(HelperException.ExceptionType.FORBIDDEN, "你无权查看该课程下的幻灯片");
  101. }
  102. return slideDAO
  103. .findByCourseIdAndStateNotInAndNameContains(courseId, ImmutableSet.of(SlideState.DRAFT), key, pageable)
  104. .stream()
  105. .map(SlideVO::new)
  106. .collect(Collectors.toList());
  107. }
  108. @Transactional(readOnly = true)
  109. @Override
  110. public String getSlideUrl(LoginUser user, Integer slideId) {
  111. checkDataAccessAuth(user, slideId);
  112. Slide slide = slideDAO.findSlideById(slideId);
  113. String url = cacheUtils.get(Consts.SLIDE_URL_CACHE_NAME, slide.getObjectName());
  114. if (url != null) {
  115. return url;
  116. }
  117. url = fileUtils.getUrl(slide.getObjectName(), SLIDE_URL_LIVING_SECONDS);
  118. cacheUtils.set(Consts.SLIDE_URL_CACHE_NAME, slide.getObjectName(), url, SLIDE_URL_LIVING_SECONDS, TimeUnit.SECONDS);
  119. return url;
  120. }
  121. private void checkDataAccessAuth(LoginUser user, Integer slideId) {
  122. HelperException forbiddenEx = HelperException.of(HelperException.ExceptionType.FORBIDDEN, "您无权访问该幻灯片");
  123. Slide slide = slideDAO.findSlideById(slideId);
  124. switch (user.getType()) {
  125. case TEACHER:
  126. if (!slide.getTeacherId().equals(user.getId())) {
  127. throw forbiddenEx;
  128. }
  129. break;
  130. case STUDENT:
  131. if (!chooseDAO.existsByStudentIdAndCourseId(user.getId(), slide.getCourseId())) {
  132. throw forbiddenEx;
  133. }
  134. break;
  135. default:
  136. throw forbiddenEx;
  137. }
  138. }
  139. }