package nju.seec.helper.service.impl; import com.google.common.collect.ImmutableSet; import com.google.common.io.Files; import lombok.SneakyThrows; import nju.seec.helper.aspect.auth.LoginUser; import nju.seec.helper.dao.ChooseDAO; import nju.seec.helper.dao.CourseDAO; import nju.seec.helper.dao.SlideDAO; import nju.seec.helper.dao.UserDAO; import nju.seec.helper.dto.slide.SlideDTO; import nju.seec.helper.dto.slide.SlideFileDTO; import nju.seec.helper.dto.slide.SlideStateDTO; import nju.seec.helper.entity.Course; import nju.seec.helper.entity.Slide; import nju.seec.helper.enums.ExceptionType; import nju.seec.helper.enums.MessageType; import nju.seec.helper.enums.SlideState; import nju.seec.helper.exception.HelperException; import nju.seec.helper.service.CourseService; import nju.seec.helper.service.MessageService; import nju.seec.helper.service.QuizService; import nju.seec.helper.service.SlideService; import nju.seec.helper.service.util.OssObjectUrlUtils; import nju.seec.helper.util.OssUtils; import nju.seec.helper.util.file.FileInfo; import nju.seec.helper.util.file.FileUtils; import nju.seec.helper.vo.SlideVO; import org.springframework.dao.DataIntegrityViolationException; 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.Set; /** * @author cst */ @Service public class SlideServiceImpl implements SlideService { private static final String SLIDE_STORE_DIR = "slide"; private final CourseDAO courseDAO; private final SlideDAO slideDAO; private final ChooseDAO chooseDAO; private final UserDAO userDAO; private final OssUtils ossUtils; private final OssObjectUrlUtils ossObjectUrlUtils; private final QuizService quizService; private final MessageService messageService; private final CourseService courseService; public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, UserDAO userDAO, OssUtils ossUtils, OssObjectUrlUtils ossObjectUrlUtils, QuizService quizService, MessageService messageService, CourseService courseService) { this.courseDAO = courseDAO; this.slideDAO = slideDAO; this.chooseDAO = chooseDAO; this.userDAO = userDAO; this.ossUtils = ossUtils; this.ossObjectUrlUtils = ossObjectUrlUtils; this.quizService = quizService; this.messageService = messageService; this.courseService = courseService; } @Transactional(rollbackFor = Exception.class) @SneakyThrows @Override public SlideVO createSlide(LoginUser teacher, SlideDTO slideDTO) { Course course = courseDAO.findCourseById(slideDTO.getCourseId()); Slide slide = new Slide() .setCourse(course) .setTeacher(userDAO.findUserById(teacher.getId())) .setName(slideDTO.getName()) .setState(slideDTO.getState()); if (!existsAddAuth(teacher, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权创建该课件"); } try { MultipartFile file = slideDTO.getFile(); FileInfo fileInfo = getFileInfo(file); slide.setPages(fileInfo.getPages()); slide.setObjectName("temp"); slide = slideDAO.save(slide); String objectName = getObjectName(slide.getId(), slide.getName(), fileInfo.getExtension()); slide.setObjectName(objectName); slide = slideDAO.save(slide); ossUtils.upload(objectName, file.getInputStream()); return new SlideVO(slide); } catch (DataIntegrityViolationException e) { throw HelperException.of(ExceptionType.CONFLICT, "创建失败,请检查课件信息是否正确且不与已有课件冲突"); } } @Transactional(rollbackFor = Exception.class) @Override public SlideVO modifySlide(LoginUser user, Long slideId, SlideDTO slideDTO) { Slide slide = slideDAO.findSlideById(slideId); if (!existsUpdateAuth(user, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该课件"); } try { slide.setName(slideDTO.getName()); String oldObjectName = slide.getObjectName(); String newObjectName = getObjectName(slide.getId(), slide.getName(), Files.getFileExtension(oldObjectName)); slide.setObjectName(newObjectName); slide = slideDAO.save(slide); if (!oldObjectName.equals(newObjectName)) { ossUtils.copy(oldObjectName, newObjectName); ossUtils.delete(oldObjectName); } return new SlideVO(slide); } catch (DataIntegrityViolationException e) { throw HelperException.of(ExceptionType.CONFLICT, "修改失败,请检查课件信息是否正确且不与已有课件冲突"); } } @Transactional(rollbackFor = Exception.class) @Override public void modifySlideState(LoginUser user, Long slideId, SlideStateDTO slideStateDTO) { Slide slide = slideDAO.findSlideById(slideId); if (!existsUpdateAuth(user, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该课件状态"); } slide.setState(slideStateDTO.getState()); slide = slideDAO.save(slide); // 增加通知 if (slide.getState() == SlideState.IN_CLASS) { Set studentIds = chooseDAO.findStudentIdsByCourseId(slide.getCourse().getId()); messageService.createMessage(studentIds, MessageType.SLIDE_IN_CLASS, String.format("[%s] - [%s] 已开课", slide.getCourse().getName(), slide.getName()), slide.getId()); } // 修改Slide状态同时推进quiz状态 quizService.modifyQuizState(slide); } @Transactional(rollbackFor = Exception.class) @SneakyThrows @Override public void modifySlideFile(LoginUser user, Long slideId, SlideFileDTO slideFileDTO) { Slide slide = slideDAO.findSlideById(slideId); if (!existsUpdateAuth(user, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该课件文件"); } MultipartFile file = slideFileDTO.getFile(); FileInfo fileInfo = getFileInfo(file); slide.setPages(fileInfo.getPages()); String oldObjectName = slide.getObjectName(); String newObjectName = getObjectName(slide.getId(), slide.getName(), fileInfo.getExtension()); slide.setObjectName(newObjectName); slideDAO.save(slide); ossUtils.upload(newObjectName, file.getInputStream()); if (!oldObjectName.equals(newObjectName)) { ossUtils.delete(oldObjectName); } } @Transactional(rollbackFor = Exception.class) @Override public void deleteSlide(LoginUser user, Long slideId) { Slide slide = slideDAO.findSlideById(slideId); if (!existsDelAuth(user, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权删除该课件"); } slide.setDeleteAt(System.currentTimeMillis()); slideDAO.save(slide); } @SneakyThrows private FileInfo getFileInfo(MultipartFile file) { return FileUtils.getFileInfo(file); } private String getObjectName(Long slideId, String slideName, String extension) { return SLIDE_STORE_DIR + File.separator + slideId + File.separator + slideName + "." + extension; } @Transactional(readOnly = true) @Override public Page teacherGetSlides(LoginUser teacher, String key, Pageable pageable) { return slideDAO.findByTeacherAndNameContains(userDAO.findUserById(teacher.getId()), key, pageable).map(SlideVO::new); } private static final Set STATES_NOT_GET_BY_STUDENT_SET = ImmutableSet.of(SlideState.DRAFT); @Transactional(readOnly = true) @Override public Page getSlidesByCourse(LoginUser user, Long courseId, String key, Pageable pageable) { Course course = courseDAO.findCourseById(courseId); if (!courseService.existsGetAuth(user, course)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权访问该课程的课件"); } switch (user.getType()) { case TEACHER: return slideDAO.findByCourseAndNameContains(course, key, pageable).map(SlideVO::new); case STUDENT: return slideDAO.findByCourseAndStateNotInAndNameContains(course, STATES_NOT_GET_BY_STUDENT_SET, key, pageable).map(SlideVO::new); default: return Page.empty(); } } @Transactional(readOnly = true) @Override public String getSlideUrl(LoginUser user, Long slideId) { Slide slide = slideDAO.findSlideById(slideId); if (!existsGetAuth(user, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权获取该课件的链接"); } return ossObjectUrlUtils.getUrl(slide.getObjectName()); } @Transactional(readOnly = true) @Override public SlideVO getOneSlide(LoginUser user, Long slideId) { Slide slide = slideDAO.findSlideById(slideId); if (!existsGetAuth(user, slide)) { throw HelperException.of(ExceptionType.FORBIDDEN, "您无权访问该课件"); } return new SlideVO(slide); } @Override public boolean existsAddAuth(LoginUser user, Slide slide) { return slide.getCourse().getTeacher().getId().equals(user.getId()); } @Override public boolean existsDelAuth(LoginUser user, Slide slide) { return slide.getTeacher().getId().equals(user.getId()); } @Override public boolean existsUpdateAuth(LoginUser user, Slide slide) { return slide.getTeacher().getId().equals(user.getId()); } @Override public boolean existsGetAuth(LoginUser user, Slide slide) { return courseService.existsGetAuth(user, courseDAO.findCourseById(slide.getCourse().getId())); } }