| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- package nju.seec.helper.service.impl;
- import com.google.common.collect.ImmutableSet;
- import lombok.AllArgsConstructor;
- import lombok.SneakyThrows;
- import nju.seec.helper.dao.ChooseDAO;
- import nju.seec.helper.dao.CourseDAO;
- import nju.seec.helper.dao.SlideDAO;
- import nju.seec.helper.dto.LoginUser;
- import nju.seec.helper.dto.SlideDTO;
- import nju.seec.helper.dto.SlideFileDTO;
- import nju.seec.helper.dto.SlideStateDTO;
- import nju.seec.helper.entity.Course;
- import nju.seec.helper.entity.Slide;
- import nju.seec.helper.service.MessageService;
- import nju.seec.helper.service.QuizService;
- import nju.seec.helper.service.SlideService;
- import nju.seec.helper.service.util.AuthUtils;
- import nju.seec.helper.util.RedisCacheUtils;
- import nju.seec.helper.util.Consts;
- import nju.seec.helper.util.FileUtils;
- import nju.seec.helper.util.enums.ExceptionType;
- import nju.seec.helper.util.enums.MessageType;
- import nju.seec.helper.util.enums.SlideState;
- import nju.seec.helper.util.exception.HelperException;
- import nju.seec.helper.vo.SlideVO;
- import org.apache.pdfbox.pdmodel.PDDocument;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.domain.Page;
- import org.springframework.data.domain.Pageable;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import org.springframework.web.multipart.MultipartFile;
- import java.io.File;
- import java.util.Objects;
- import java.util.Set;
- import java.util.concurrent.TimeUnit;
- /**
- * @author cst
- */
- @Service
- public class SlideServiceImpl implements SlideService {
- private static final String SLIDE_STORE_DIR = "slide";
- private static final long SLIDE_URL_LIVING_SECONDS = 20 * 60;
- private final CourseDAO courseDAO;
- private final SlideDAO slideDAO;
- private final ChooseDAO chooseDAO;
- private final QuizService quizService;
- private final FileUtils fileUtils;
- private final RedisCacheUtils cacheUtils;
- private final MessageService messageService;
- @Autowired
- public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, FileUtils fileUtils, RedisCacheUtils cacheUtils, MessageService messageService, QuizService quizService) {
- this.courseDAO = courseDAO;
- this.slideDAO = slideDAO;
- this.chooseDAO = chooseDAO;
- this.fileUtils = fileUtils;
- this.cacheUtils = cacheUtils;
- this.messageService = messageService;
- this.quizService = quizService;
- }
- @Transactional(rollbackFor = Exception.class)
- @SneakyThrows
- @Override
- public SlideVO createSlide(LoginUser teacher, SlideDTO slideDTO) {
- Course course = courseDAO.findCourseById(slideDTO.getCourseId());
- AuthUtils.checkDataAuth(teacher.getId(), course.getTeacherId(), "您无权创建该课程的课件");
- checkSameName(0L, slideDTO.getCourseId(), slideDTO.getName());
- Slide slide = new Slide()
- .setCourseId(slideDTO.getCourseId())
- .setCourseName(course.getName())
- .setTeacherId(teacher.getId())
- .setTeacherName(teacher.getName())
- .setName(slideDTO.getName())
- .setState(slideDTO.getState());
- MultipartFile file = slideDTO.getFile();
- FileInfo fileInfo = getFileInfo(file);
- slide.setPages(fileInfo.pages);
- slide.setObjectName("temp");
- slide = slideDAO.save(slide);
- String objectName = getObjectName(slide.getId(), slide.getName(), fileInfo.suffix);
- slide.setObjectName(objectName);
- slide = slideDAO.save(slide);
- fileUtils.upload(objectName, file.getInputStream());
- return new SlideVO(slide);
- }
- @Transactional(rollbackFor = Exception.class)
- @Override
- public SlideVO modifySlide(LoginUser user, SlideDTO slideDTO) {
- Slide slide = slideDAO.findSlideById(slideDTO.getId());
- AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件");
- checkSameName(slide.getId(), slide.getCourseId(), slideDTO.getName());
- slide.setName(slideDTO.getName());
- String oldObjectName = slide.getObjectName();
- String newObjectName = getObjectName(slide.getId(), slide.getName(), oldObjectName.substring(oldObjectName.lastIndexOf('.') + 1));
- slide.setObjectName(newObjectName);
- slide = slideDAO.save(slide);
- if (!oldObjectName.equals(newObjectName)) {
- fileUtils.copy(oldObjectName, newObjectName);
- fileUtils.delete(oldObjectName);
- }
- return new SlideVO(slide);
- }
- @Transactional(rollbackFor = Exception.class)
- @Override
- public void modifySlideState(LoginUser user, SlideStateDTO slideStateDTO) {
- Slide slide = slideDAO.findSlideById(slideStateDTO.getId());
- AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件状态");
- slide.setState(slideStateDTO.getState());
- slide = slideDAO.save(slide);
- // 修改Slide状态同时推进quiz状态
- quizService.modifySlideState(slide);
- // 增加通知
- if (slide.getState() == SlideState.IN_CLASS) {
- Set<Long> studentIds = chooseDAO.findStudentIdsByCourseId(slide.getCourseId());
- messageService.createMessage(studentIds, MessageType.SLIDE_IN_CLASS, String.format("课程 [%s] 的课件 [%s] 已开课", slide.getCourseName(), slide.getName()), slide.getId());
- }
- }
- @Transactional(rollbackFor = Exception.class)
- @SneakyThrows
- @Override
- public void modifySlideFile(LoginUser user, SlideFileDTO slideFileDTO) {
- Slide slide = slideDAO.findSlideById(slideFileDTO.getId());
- AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件文件");
- MultipartFile file = slideFileDTO.getFile();
- FileInfo fileInfo = getFileInfo(file);
- slide.setPages(fileInfo.pages);
- String oldObjectName = slide.getObjectName();
- String newObjectName = getObjectName(slide.getId(), slide.getName(), fileInfo.suffix);
- slide.setObjectName(newObjectName);
- slideDAO.save(slide);
- fileUtils.upload(newObjectName, file.getInputStream());
- if (!oldObjectName.equals(newObjectName)) {
- fileUtils.delete(oldObjectName);
- }
- }
- @Transactional(rollbackFor = Exception.class)
- @Override
- public void removeSlide(LoginUser user, Long slideId) {
- Slide slide = slideDAO.findSlideById(slideId);
- AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权删除该课件");
- slide.setDeleteAt(System.currentTimeMillis());
- slideDAO.save(slide);
- }
- @SuppressWarnings("all")
- @SneakyThrows
- private FileInfo getFileInfo(MultipartFile file) {
- switch (Objects.requireNonNull(file.getContentType())) {
- case "application/pdf":
- // 解析页数
- PDDocument doc = PDDocument.load(file.getInputStream());
- return FileInfo.of(doc.getNumberOfPages(), "pdf");
- default:
- throw HelperException.of(ExceptionType.PARAM_ERROR, "不支持的文件类型");
- }
- }
- @AllArgsConstructor(staticName = "of")
- private static class FileInfo {
- private int pages;
- private String suffix;
- }
- private String getObjectName(Long slideId, String slideName, String suffix) {
- return SLIDE_STORE_DIR + File.separator + slideId + File.separator + slideName + "." + suffix;
- }
- @Transactional(readOnly = true)
- @Override
- public Page<SlideVO> teacherGetSlides(LoginUser teacher, String key, Pageable pageable) {
- return slideDAO.findByTeacherIdAndNameContains(teacher.getId(), key, pageable).map(SlideVO::new);
- }
- @Transactional(readOnly = true)
- @Override
- public Page<SlideVO> teacherGetSlidesByCourse(LoginUser teacher, Long courseId, String key, Pageable pageable) {
- return slideDAO.findByCourseIdAndTeacherIdAndNameContains(courseId, teacher.getId(), key, pageable).map(SlideVO::new);
- }
- @Transactional(readOnly = true)
- @Override
- public Page<SlideVO> studentGetSlidesByCourse(LoginUser student, Long courseId, String key, Pageable pageable) {
- if (!chooseDAO.existsByStudentIdAndCourseId(student.getId(), courseId)) {
- throw HelperException.of(ExceptionType.FORBIDDEN, "你无权查看该课程下的课件");
- }
- return slideDAO.findByCourseIdAndStateNotInAndNameContains(courseId, ImmutableSet.of(SlideState.DRAFT), key, pageable).map(SlideVO::new);
- }
- @Transactional(readOnly = true)
- @Override
- public String getSlideUrl(LoginUser user, Long slideId) {
- Slide slide = slideDAO.findSlideById(slideId);
- checkDataAccessAuth(user, slide);
- String url = cacheUtils.get(Consts.SLIDE_URL_CACHE_NAME, slide.getObjectName());
- if (url != null) {
- return url;
- }
- url = fileUtils.getUrl(slide.getObjectName(), SLIDE_URL_LIVING_SECONDS);
- cacheUtils.set(Consts.SLIDE_URL_CACHE_NAME, slide.getObjectName(), url, SLIDE_URL_LIVING_SECONDS, TimeUnit.SECONDS);
- return url;
- }
- @Transactional(readOnly = true)
- @Override
- public SlideVO getOneSlide(LoginUser user, Long slideId) {
- Slide slide = slideDAO.findSlideById(slideId);
- checkDataAccessAuth(user, slide);
- return new SlideVO(slide);
- }
- /**
- * 检查同名课件
- */
- private void checkSameName(Long slideId, Long courseId, String name) {
- if (slideDAO.existsByCourseIdAndName(slideId, courseId, name)) {
- throw HelperException.of(ExceptionType.CONFLICT, "该课件名已使用");
- }
- }
- private void checkDataAccessAuth(LoginUser user, Slide slide) {
- HelperException forbiddenEx = HelperException.of(ExceptionType.FORBIDDEN, "您无权访问该课件");
- switch (user.getType()) {
- case TEACHER:
- if (!slide.getTeacherId().equals(user.getId())) {
- throw forbiddenEx;
- }
- break;
- case STUDENT:
- if (!chooseDAO.existsByStudentIdAndCourseId(user.getId(), slide.getCourseId())
- || slide.getState() == SlideState.DRAFT) {
- throw forbiddenEx;
- }
- break;
- default:
- throw forbiddenEx;
- }
- }
- }
|