|
@@ -1,38 +1,38 @@
|
|
|
package nju.seec.helper.service.impl;
|
|
package nju.seec.helper.service.impl;
|
|
|
|
|
|
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.google.common.collect.ImmutableSet;
|
|
|
-import lombok.Cleanup;
|
|
|
|
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
import lombok.SneakyThrows;
|
|
import lombok.SneakyThrows;
|
|
|
import nju.seec.helper.dao.ChooseDAO;
|
|
import nju.seec.helper.dao.ChooseDAO;
|
|
|
import nju.seec.helper.dao.CourseDAO;
|
|
import nju.seec.helper.dao.CourseDAO;
|
|
|
import nju.seec.helper.dao.SlideDAO;
|
|
import nju.seec.helper.dao.SlideDAO;
|
|
|
import nju.seec.helper.dto.LoginUser;
|
|
import nju.seec.helper.dto.LoginUser;
|
|
|
-import nju.seec.helper.dto.ModifySlideDTO;
|
|
|
|
|
import nju.seec.helper.dto.SlideDTO;
|
|
import nju.seec.helper.dto.SlideDTO;
|
|
|
|
|
+import nju.seec.helper.dto.SlideFileDTO;
|
|
|
import nju.seec.helper.dto.SlideStateDTO;
|
|
import nju.seec.helper.dto.SlideStateDTO;
|
|
|
import nju.seec.helper.entity.Course;
|
|
import nju.seec.helper.entity.Course;
|
|
|
import nju.seec.helper.entity.Slide;
|
|
import nju.seec.helper.entity.Slide;
|
|
|
-import nju.seec.helper.service.AuthUtil;
|
|
|
|
|
-import nju.seec.helper.service.QuizService;
|
|
|
|
|
|
|
+import nju.seec.helper.service.MessageService;
|
|
|
import nju.seec.helper.service.SlideService;
|
|
import nju.seec.helper.service.SlideService;
|
|
|
|
|
+import nju.seec.helper.service.util.AuthUtils;
|
|
|
import nju.seec.helper.util.CacheUtils;
|
|
import nju.seec.helper.util.CacheUtils;
|
|
|
import nju.seec.helper.util.Consts;
|
|
import nju.seec.helper.util.Consts;
|
|
|
import nju.seec.helper.util.FileUtils;
|
|
import nju.seec.helper.util.FileUtils;
|
|
|
import nju.seec.helper.util.enums.ExceptionType;
|
|
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.enums.SlideState;
|
|
|
import nju.seec.helper.util.exception.HelperException;
|
|
import nju.seec.helper.util.exception.HelperException;
|
|
|
import nju.seec.helper.vo.SlideVO;
|
|
import nju.seec.helper.vo.SlideVO;
|
|
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
import org.apache.pdfbox.pdmodel.PDDocument;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.data.domain.Page;
|
|
import org.springframework.data.domain.Page;
|
|
|
import org.springframework.data.domain.Pageable;
|
|
import org.springframework.data.domain.Pageable;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
|
|
-import java.io.InputStream;
|
|
|
|
|
-import java.time.LocalDateTime;
|
|
|
|
|
|
|
+import java.io.File;
|
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
|
|
|
+import java.util.Set;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
import java.util.concurrent.TimeUnit;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -40,6 +40,7 @@ import java.util.concurrent.TimeUnit;
|
|
|
*/
|
|
*/
|
|
|
@Service
|
|
@Service
|
|
|
public class SlideServiceImpl implements SlideService {
|
|
public class SlideServiceImpl implements SlideService {
|
|
|
|
|
+ private static final String SLIDE_STORE_DIR = "slide";
|
|
|
private static final long SLIDE_URL_LIVING_SECONDS = 20 * 60;
|
|
private static final long SLIDE_URL_LIVING_SECONDS = 20 * 60;
|
|
|
|
|
|
|
|
private final CourseDAO courseDAO;
|
|
private final CourseDAO courseDAO;
|
|
@@ -49,13 +50,16 @@ public class SlideServiceImpl implements SlideService {
|
|
|
private final FileUtils fileUtils;
|
|
private final FileUtils fileUtils;
|
|
|
private final CacheUtils cacheUtils;
|
|
private final CacheUtils cacheUtils;
|
|
|
|
|
|
|
|
- public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, QuizService quizService, FileUtils fileUtils, CacheUtils cacheUtils) {
|
|
|
|
|
|
|
+ private final MessageService messageService;
|
|
|
|
|
+
|
|
|
|
|
+ public SlideServiceImpl(CourseDAO courseDAO, SlideDAO slideDAO, ChooseDAO chooseDAO, FileUtils fileUtils, CacheUtils cacheUtils, MessageService messageService) {
|
|
|
this.courseDAO = courseDAO;
|
|
this.courseDAO = courseDAO;
|
|
|
this.slideDAO = slideDAO;
|
|
this.slideDAO = slideDAO;
|
|
|
this.chooseDAO = chooseDAO;
|
|
this.chooseDAO = chooseDAO;
|
|
|
this.quizService = quizService;
|
|
this.quizService = quizService;
|
|
|
this.fileUtils = fileUtils;
|
|
this.fileUtils = fileUtils;
|
|
|
this.cacheUtils = cacheUtils;
|
|
this.cacheUtils = cacheUtils;
|
|
|
|
|
+ this.messageService = messageService;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@@ -63,7 +67,9 @@ public class SlideServiceImpl implements SlideService {
|
|
|
@Override
|
|
@Override
|
|
|
public SlideVO createSlide(LoginUser teacher, SlideDTO slideDTO) {
|
|
public SlideVO createSlide(LoginUser teacher, SlideDTO slideDTO) {
|
|
|
Course course = courseDAO.findCourseById(slideDTO.getCourseId());
|
|
Course course = courseDAO.findCourseById(slideDTO.getCourseId());
|
|
|
- AuthUtil.checkDataAuth(teacher.getId(), course.getTeacherId(), "您无权创建该课程的幻灯片");
|
|
|
|
|
|
|
+ AuthUtils.checkDataAuth(teacher.getId(), course.getTeacherId(), "您无权创建该课程的课件");
|
|
|
|
|
+
|
|
|
|
|
+ checkSameName(0L, slideDTO.getCourseId(), slideDTO.getName());
|
|
|
|
|
|
|
|
Slide slide = new Slide()
|
|
Slide slide = new Slide()
|
|
|
.setCourseId(slideDTO.getCourseId())
|
|
.setCourseId(slideDTO.getCourseId())
|
|
@@ -71,39 +77,42 @@ public class SlideServiceImpl implements SlideService {
|
|
|
.setTeacherId(teacher.getId())
|
|
.setTeacherId(teacher.getId())
|
|
|
.setTeacherName(teacher.getName())
|
|
.setTeacherName(teacher.getName())
|
|
|
.setName(slideDTO.getName())
|
|
.setName(slideDTO.getName())
|
|
|
- .setState(SlideState.DRAFT);
|
|
|
|
|
|
|
+ .setState(slideDTO.getState());
|
|
|
|
|
|
|
|
- // 解析文件页数
|
|
|
|
|
MultipartFile file = slideDTO.getFile();
|
|
MultipartFile file = slideDTO.getFile();
|
|
|
- int pages;
|
|
|
|
|
- switch (Objects.requireNonNull(file.getContentType())) {
|
|
|
|
|
- // pdf
|
|
|
|
|
- case "application/pdf":
|
|
|
|
|
- @Cleanup InputStream fileInputStream = file.getInputStream();
|
|
|
|
|
- PDDocument doc = PDDocument.load(fileInputStream);
|
|
|
|
|
- pages = doc.getNumberOfPages();
|
|
|
|
|
- break;
|
|
|
|
|
- default:
|
|
|
|
|
- throw HelperException.of(ExceptionType.FORBIDDEN, "不支持的文件类型");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- slide.setPages(pages);
|
|
|
|
|
|
|
+ FileInfo fileInfo = getFileInfo(file);
|
|
|
|
|
+ slide.setPages(fileInfo.pages);
|
|
|
|
|
+ slide.setObjectName("temp");
|
|
|
|
|
+ slide = slideDAO.save(slide);
|
|
|
|
|
|
|
|
- // 上传文件
|
|
|
|
|
- String objectName = fileUtils.upload(LocalDateTime.now().toString() + "-" + file.getOriginalFilename(), file.getInputStream());
|
|
|
|
|
|
|
+ String objectName = getObjectName(slide.getId(), slide.getName(), fileInfo.suffix);
|
|
|
slide.setObjectName(objectName);
|
|
slide.setObjectName(objectName);
|
|
|
|
|
+ slide = slideDAO.save(slide);
|
|
|
|
|
|
|
|
- return new SlideVO(slideDAO.save(slide));
|
|
|
|
|
|
|
+ fileUtils.upload(objectName, file.getInputStream());
|
|
|
|
|
+
|
|
|
|
|
+ return new SlideVO(slide);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
@Override
|
|
@Override
|
|
|
- public SlideVO modifySlide(LoginUser user, ModifySlideDTO modifySlideDTO) {
|
|
|
|
|
- Slide slide = slideDAO.findSlideById(modifySlideDTO.getId());
|
|
|
|
|
- AuthUtil.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该幻灯片");
|
|
|
|
|
|
|
+ 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(modifySlideDTO.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);
|
|
slide = slideDAO.save(slide);
|
|
|
|
|
+
|
|
|
|
|
+ if (!oldObjectName.equals(newObjectName)) {
|
|
|
|
|
+ fileUtils.copy(oldObjectName, newObjectName);
|
|
|
|
|
+ fileUtils.delete(oldObjectName);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return new SlideVO(slide);
|
|
return new SlideVO(slide);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -111,22 +120,73 @@ public class SlideServiceImpl implements SlideService {
|
|
|
@Override
|
|
@Override
|
|
|
public void modifySlideState(LoginUser user, SlideStateDTO slideStateDTO) {
|
|
public void modifySlideState(LoginUser user, SlideStateDTO slideStateDTO) {
|
|
|
Slide slide = slideDAO.findSlideById(slideStateDTO.getId());
|
|
Slide slide = slideDAO.findSlideById(slideStateDTO.getId());
|
|
|
- AuthUtil.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该幻灯片状态");
|
|
|
|
|
|
|
+ AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权修改该课件状态");
|
|
|
|
|
|
|
|
slide.setState(slideStateDTO.getState());
|
|
slide.setState(slideStateDTO.getState());
|
|
|
|
|
+ slide = slideDAO.save(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);
|
|
slideDAO.save(slide);
|
|
|
- quizService.modifySlideState(slide);
|
|
|
|
|
|
|
+
|
|
|
|
|
+ fileUtils.upload(newObjectName, file.getInputStream());
|
|
|
|
|
+ if (!oldObjectName.equals(newObjectName)) {
|
|
|
|
|
+ fileUtils.delete(oldObjectName);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
@Override
|
|
@Override
|
|
|
- public void removeSlide(LoginUser user, Integer slideId) {
|
|
|
|
|
|
|
+ public void removeSlide(LoginUser user, Long slideId) {
|
|
|
Slide slide = slideDAO.findSlideById(slideId);
|
|
Slide slide = slideDAO.findSlideById(slideId);
|
|
|
- AuthUtil.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权删除该幻灯片");
|
|
|
|
|
|
|
+ AuthUtils.checkDataAuth(user.getId(), slide.getTeacherId(), "您无权删除该课件");
|
|
|
|
|
|
|
|
slide.setDeleteAt(System.currentTimeMillis());
|
|
slide.setDeleteAt(System.currentTimeMillis());
|
|
|
slideDAO.save(slide);
|
|
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)
|
|
@Transactional(readOnly = true)
|
|
|
@Override
|
|
@Override
|
|
|
public Page<SlideVO> teacherGetSlides(LoginUser teacher, String key, Pageable pageable) {
|
|
public Page<SlideVO> teacherGetSlides(LoginUser teacher, String key, Pageable pageable) {
|
|
@@ -135,15 +195,15 @@ public class SlideServiceImpl implements SlideService {
|
|
|
|
|
|
|
|
@Transactional(readOnly = true)
|
|
@Transactional(readOnly = true)
|
|
|
@Override
|
|
@Override
|
|
|
- public Page<SlideVO> teacherGetSlidesByCourse(LoginUser teacher, Integer courseId, String key, Pageable pageable) {
|
|
|
|
|
|
|
+ public Page<SlideVO> teacherGetSlidesByCourse(LoginUser teacher, Long courseId, String key, Pageable pageable) {
|
|
|
return slideDAO.findByCourseIdAndTeacherIdAndNameContains(courseId, teacher.getId(), key, pageable).map(SlideVO::new);
|
|
return slideDAO.findByCourseIdAndTeacherIdAndNameContains(courseId, teacher.getId(), key, pageable).map(SlideVO::new);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Transactional(readOnly = true)
|
|
@Transactional(readOnly = true)
|
|
|
@Override
|
|
@Override
|
|
|
- public Page<SlideVO> studentGetSlidesByCourse(LoginUser student, Integer courseId, String key, Pageable pageable) {
|
|
|
|
|
|
|
+ public Page<SlideVO> studentGetSlidesByCourse(LoginUser student, Long courseId, String key, Pageable pageable) {
|
|
|
if (!chooseDAO.existsByStudentIdAndCourseId(student.getId(), courseId)) {
|
|
if (!chooseDAO.existsByStudentIdAndCourseId(student.getId(), courseId)) {
|
|
|
- throw HelperException.of(ExceptionType.FORBIDDEN, "你无权查看该课程下的幻灯片");
|
|
|
|
|
|
|
+ throw HelperException.of(ExceptionType.FORBIDDEN, "你无权查看该课程下的课件");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return slideDAO.findByCourseIdAndStateNotInAndNameContains(courseId, ImmutableSet.of(SlideState.DRAFT), key, pageable).map(SlideVO::new);
|
|
return slideDAO.findByCourseIdAndStateNotInAndNameContains(courseId, ImmutableSet.of(SlideState.DRAFT), key, pageable).map(SlideVO::new);
|
|
@@ -151,8 +211,7 @@ public class SlideServiceImpl implements SlideService {
|
|
|
|
|
|
|
|
@Transactional(readOnly = true)
|
|
@Transactional(readOnly = true)
|
|
|
@Override
|
|
@Override
|
|
|
- public String getSlideUrl(LoginUser user, Integer slideId) {
|
|
|
|
|
-
|
|
|
|
|
|
|
+ public String getSlideUrl(LoginUser user, Long slideId) {
|
|
|
Slide slide = slideDAO.findSlideById(slideId);
|
|
Slide slide = slideDAO.findSlideById(slideId);
|
|
|
checkDataAccessAuth(user, slide);
|
|
checkDataAccessAuth(user, slide);
|
|
|
|
|
|
|
@@ -165,8 +224,25 @@ public class SlideServiceImpl implements SlideService {
|
|
|
return url;
|
|
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) {
|
|
private void checkDataAccessAuth(LoginUser user, Slide slide) {
|
|
|
- HelperException forbiddenEx = HelperException.of(ExceptionType.FORBIDDEN, "您无权访问该幻灯片");
|
|
|
|
|
|
|
+ HelperException forbiddenEx = HelperException.of(ExceptionType.FORBIDDEN, "您无权访问该课件");
|
|
|
|
|
|
|
|
switch (user.getType()) {
|
|
switch (user.getType()) {
|
|
|
case TEACHER:
|
|
case TEACHER:
|
|
@@ -175,7 +251,8 @@ public class SlideServiceImpl implements SlideService {
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|
|
|
case STUDENT:
|
|
case STUDENT:
|
|
|
- if (!chooseDAO.existsByStudentIdAndCourseId(user.getId(), slide.getCourseId())) {
|
|
|
|
|
|
|
+ if (!chooseDAO.existsByStudentIdAndCourseId(user.getId(), slide.getCourseId())
|
|
|
|
|
+ || slide.getState() == SlideState.DRAFT) {
|
|
|
throw forbiddenEx;
|
|
throw forbiddenEx;
|
|
|
}
|
|
}
|
|
|
break;
|
|
break;
|