فهرست منبع

Merge branch 'iterator4'

ChenSiTong 6 سال پیش
والد
کامیت
96e1d0c243
33فایلهای تغییر یافته به همراه241 افزوده شده و 92 حذف شده
  1. 13 1
      pom.xml
  2. 2 2
      src/main/java/nju/seec/helper/HelperApplication.java
  3. 24 0
      src/main/java/nju/seec/helper/controller/CommentController.java
  4. 9 4
      src/main/java/nju/seec/helper/controller/QuizController.java
  5. 22 1
      src/main/java/nju/seec/helper/dao/CommentDAO.java
  6. 12 0
      src/main/java/nju/seec/helper/dao/QuizDAO.java
  7. 16 3
      src/main/java/nju/seec/helper/dao/QuizStudentAnswerDAO.java
  8. 1 1
      src/main/java/nju/seec/helper/dto/user/UserDTO.java
  9. 2 0
      src/main/java/nju/seec/helper/entity/Course.java
  10. 2 0
      src/main/java/nju/seec/helper/entity/Quiz.java
  11. 2 0
      src/main/java/nju/seec/helper/entity/Slide.java
  12. 5 4
      src/main/java/nju/seec/helper/entity/User.java
  13. 21 0
      src/main/java/nju/seec/helper/service/CommentService.java
  14. 0 8
      src/main/java/nju/seec/helper/service/MessageService.java
  15. 11 0
      src/main/java/nju/seec/helper/service/QuizService.java
  16. 3 2
      src/main/java/nju/seec/helper/service/QuizStudentAnswerService.java
  17. 31 3
      src/main/java/nju/seec/helper/service/impl/CommentServiceImpl.java
  18. 1 3
      src/main/java/nju/seec/helper/service/impl/CourseFileServiceImpl.java
  19. 4 6
      src/main/java/nju/seec/helper/service/impl/CourseServiceImpl.java
  20. 0 6
      src/main/java/nju/seec/helper/service/impl/MessageServiceImpl.java
  21. 0 1
      src/main/java/nju/seec/helper/service/impl/NoticeServiceImpl.java
  22. 10 6
      src/main/java/nju/seec/helper/service/impl/QuizServiceImpl.java
  23. 3 3
      src/main/java/nju/seec/helper/service/impl/QuizStudentAnswerServiceImpl.java
  24. 1 2
      src/main/java/nju/seec/helper/service/impl/ReplyServiceImpl.java
  25. 1 2
      src/main/java/nju/seec/helper/service/impl/SlideServiceImpl.java
  26. 0 5
      src/main/java/nju/seec/helper/service/impl/UserServiceImpl.java
  27. 9 9
      src/main/java/nju/seec/helper/util/EncryptUtils.java
  28. 1 1
      src/main/java/nju/seec/helper/util/OssObjectUrlUtils.java
  29. 1 1
      src/main/java/nju/seec/helper/vo/question/BaseQuestionVO.java
  30. 1 1
      src/main/java/nju/seec/helper/vo/quiz/QuizStudentAnswerStatisticVO.java
  31. 15 0
      src/main/resources/ehcache.xml
  32. 9 0
      src/main/resources/hibernate.properties
  33. 9 17
      src/main/resources/update.sql

+ 13 - 1
pom.xml

@@ -10,7 +10,7 @@
     </parent>
     <groupId>cn.seecoder</groupId>
     <artifactId>helper-backend</artifactId>
-    <version>4.0.0</version>
+    <version>4.1.2</version>
     <packaging>jar</packaging>
     <name>helper</name>
     <description>backend</description>
@@ -64,6 +64,10 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-websocket</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-cache</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>
@@ -117,6 +121,14 @@
             <artifactId>hibernate-types-52</artifactId>
             <version>2.9.5</version>
         </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-jcache</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.ehcache</groupId>
+            <artifactId>ehcache</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 2 - 2
src/main/java/nju/seec/helper/HelperApplication.java

@@ -2,7 +2,7 @@ package nju.seec.helper;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
+import org.springframework.cache.annotation.EnableCaching;
 import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
 import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
@@ -10,7 +10,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
 /**
  * @author cst
  */
-@ConfigurationPropertiesScan("nju.seec.helper.config.properties")
+@EnableCaching
 @EnableTransactionManagement
 @EnableAsync
 @EnableJpaAuditing

+ 24 - 0
src/main/java/nju/seec/helper/controller/CommentController.java

@@ -13,11 +13,14 @@ import org.springframework.data.web.PageableDefault;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.validation.constraints.NotNull;
+
 /**
  * 评论
  *
  * @author cst
  */
+@Validated
 @RestController
 @RequestMapping("/api/comment")
 public class CommentController {
@@ -88,4 +91,25 @@ public class CommentController {
     public CommentVO getOneComment(LoginUser user, @PathVariable Long commentId) {
         return commentService.getOneComment(user, commentId);
     }
+
+    /**
+     * 取得自己某一页的评论
+     */
+    @Auth(roles = {UserType.TEACHER, UserType.STUDENT}, message = "获取自己的评论")
+    @GetMapping("/slide/{slideId}/self")
+    public PageResponse<CommentVO> getSelfComments(LoginUser user,
+                                                   @PathVariable Long slideId,
+                                                   @RequestParam(required = false, defaultValue = "1") Integer pageNumber,
+                                                   @RequestParam(required = false, defaultValue = "true") Boolean show,
+                                                   @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        return PageResponse.of(commentService.getSelfCommentsBySlideAndPageNumber(user, slideId, pageNumber, show, pageable));
+    }
+
+    @Auth(roles = {UserType.TEACHER, UserType.STUDENT}, message = "修改评论展示状态")
+    @PutMapping("/{commentId}/show")
+    public void modifyCommentShow(LoginUser user,
+                                  @PathVariable Long commentId,
+                                  @NotNull(message = "缺少展示状态") Boolean show) {
+        commentService.modifyCommentShow(user, commentId, show);
+    }
 }

+ 9 - 4
src/main/java/nju/seec/helper/controller/QuizController.java

@@ -11,7 +11,7 @@ import nju.seec.helper.enums.QuizState;
 import nju.seec.helper.enums.UserType;
 import nju.seec.helper.service.QuizService;
 import nju.seec.helper.service.QuizStudentAnswerService;
-import nju.seec.helper.vo.QuizStudentAnswerStatisticVO;
+import nju.seec.helper.vo.quiz.QuizStudentAnswerStatisticVO;
 import nju.seec.helper.vo.quiz.QuizStudentAnswerVO;
 import nju.seec.helper.vo.quiz.QuizVO;
 import org.springframework.data.domain.Pageable;
@@ -60,13 +60,15 @@ public class QuizController {
     /**
      * 基于状态获取测试列表
      */
-    @Auth(roles = UserType.STUDENT, message = "获取测试列表")
+    @Auth(roles = {UserType.TEACHER, UserType.STUDENT}, message = "获取测试列表")
     @GetMapping("/state")
     public PageResponse<QuizVO> getQuizzesByState(LoginUser user,
                                                   QuizState state,
                                                   @RequestParam(required = false, defaultValue = "") String key,
                                                   @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
         switch (user.getType()) {
+            case TEACHER:
+                return PageResponse.of(quizService.teacherGetQuizzesByState(user, state, key, pageable));
             case STUDENT:
                 return PageResponse.of(quizService.studentGetQuizzesByState(user, state, key, pageable));
             default:
@@ -124,8 +126,11 @@ public class QuizController {
      */
     @Auth(roles = {UserType.TEACHER}, message = "获取学生作答")
     @GetMapping("/{quizId}/student-answers")
-    public PageResponse<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, @PathVariable Long quizId, @PageableDefault(size = Integer.MAX_VALUE) Pageable pageable) {
-        return PageResponse.of(quizStudentAnswerService.getQuizStudentAnswers(user, quizId, pageable));
+    public PageResponse<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user,
+                                                                   @PathVariable Long quizId,
+                                                                   @RequestParam(required = false, defaultValue = "") String key,
+                                                                   @PageableDefault(size = Integer.MAX_VALUE) Pageable pageable) {
+        return PageResponse.of(quizStudentAnswerService.getQuizStudentAnswers(user, quizId, key, pageable));
     }
 
     /**

+ 22 - 1
src/main/java/nju/seec/helper/dao/CommentDAO.java

@@ -1,6 +1,7 @@
 package nju.seec.helper.dao;
 
 import nju.seec.helper.entity.Comment;
+import nju.seec.helper.entity.User;
 import nju.seec.helper.enums.ExceptionType;
 import nju.seec.helper.exception.HelperException;
 import org.springframework.data.domain.Page;
@@ -37,10 +38,18 @@ public interface CommentDAO extends JpaRepository<Comment, Long>, JpaSpecificati
      */
     long countBySlideIdAndPageNumberAndTopNumberNot(Long slideId, Integer pageNumber, Integer topNumber);
 
+    /**
+     * 根据课件ID、页码、置顶指数检索
+     *
+     * @param slideId
+     * @param pageNumber
+     * @param topNumber
+     * @return
+     */
     List<Comment> findBySlideIdAndPageNumberAndTopNumberGreaterThan(Long slideId, Integer pageNumber, Integer topNumber);
 
     /**
-     * 根据课件ID、页码、是否展示获取
+     * 根据课件ID、页码、是否展示检索
      *
      * @param slideId
      * @param pageNumber
@@ -49,4 +58,16 @@ public interface CommentDAO extends JpaRepository<Comment, Long>, JpaSpecificati
      * @return
      */
     Page<Comment> findBySlideIdAndPageNumberAndShow(Long slideId, Integer pageNumber, Boolean show, Pageable pageable);
+
+    /**
+     * 根据课件ID、页码、用户ID、是否展示检索
+     *
+     * @param slideId
+     * @param pageNumber
+     * @param user
+     * @param show
+     * @param pageable
+     * @return
+     */
+    Page<Comment> findBySlideIdAndPageNumberAndUserAndShow(Long slideId, Integer pageNumber, User user, Boolean show, Pageable pageable);
 }

+ 12 - 0
src/main/java/nju/seec/helper/dao/QuizDAO.java

@@ -2,6 +2,7 @@ package nju.seec.helper.dao;
 
 import nju.seec.helper.entity.Quiz;
 import nju.seec.helper.entity.Slide;
+import nju.seec.helper.entity.User;
 import nju.seec.helper.enums.ExceptionType;
 import nju.seec.helper.enums.QuizState;
 import nju.seec.helper.exception.HelperException;
@@ -82,4 +83,15 @@ public interface QuizDAO extends JpaRepository<Quiz, Long>, JpaSpecificationExec
      * @return
      */
     Page<Quiz> findBySlideAndNameContains(Slide slide, String name, Pageable pageable);
+
+    /**
+     * 根据教师、状态、测试名称检索
+     *
+     * @param teacher
+     * @param quizState
+     * @param name
+     * @param pageable
+     * @return
+     */
+    Page<Quiz> findByTeacherAndStateAndNameContains(User teacher, QuizState quizState, String name, Pageable pageable);
 }

+ 16 - 3
src/main/java/nju/seec/helper/dao/QuizStudentAnswerDAO.java

@@ -5,9 +5,13 @@ import nju.seec.helper.entity.QuizStudentAnswer;
 import nju.seec.helper.entity.User;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.stereotype.Repository;
+import org.springframework.util.StringUtils;
 
+import javax.persistence.criteria.JoinType;
 import java.util.List;
 import java.util.Optional;
 
@@ -17,7 +21,7 @@ import java.util.Optional;
  * updated by cst
  */
 @Repository
-public interface QuizStudentAnswerDAO extends JpaRepository<QuizStudentAnswer, Long> {
+public interface QuizStudentAnswerDAO extends JpaRepository<QuizStudentAnswer, Long>, JpaSpecificationExecutor<QuizStudentAnswer> {
     /**
      * 检查测试是否已有提交
      *
@@ -38,11 +42,20 @@ public interface QuizStudentAnswerDAO extends JpaRepository<QuizStudentAnswer, L
     /**
      * 根据测试分页检索
      *
-     * @param quiz
+     * @param quizId
+     * @param key
      * @param pageable
      * @return
      */
-    Page<QuizStudentAnswer> findByQuiz(Quiz quiz, Pageable pageable);
+    default Page<QuizStudentAnswer> findByQuizIdAndKey(Long quizId, String key, Pageable pageable) {
+        return this.findAll(
+                (Specification<QuizStudentAnswer>) (root, criteriaQuery, criteriaBuilder) ->
+                        StringUtils.hasText(key) ?
+                                criteriaBuilder.and(criteriaBuilder.equal(root.get("quiz").get("id"), quizId), criteriaBuilder.like(root.join("student", JoinType.LEFT).get("name"), nju.seec.helper.util.StringUtils.keyPattern(key))) :
+                                criteriaBuilder.equal(root.get("quiz").get("id"), quizId)
+                , pageable
+        );
+    }
 
     /**
      * 根据测试检索

+ 1 - 1
src/main/java/nju/seec/helper/dto/user/UserDTO.java

@@ -34,6 +34,6 @@ public class UserDTO implements Serializable {
     @Length(max = 50, message = "密码长度不能超过50位", groups = Create.class)
     private String password;
 
-    @NotNull(message = "缺少用户类型")
+    @NotNull(message = "缺少用户类型", groups = Create.class)
     private UserType type;
 }

+ 2 - 0
src/main/java/nju/seec/helper/entity/Course.java

@@ -21,6 +21,8 @@ import java.time.LocalDateTime;
 @DynamicUpdate
 @DynamicInsert
 @Where(clause = "delete_at = 0")
+@Cacheable
+@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 public class Course {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)

+ 2 - 0
src/main/java/nju/seec/helper/entity/Quiz.java

@@ -26,6 +26,8 @@ import java.util.List;
 @DynamicInsert
 @DynamicUpdate
 @Where(clause = "delete_at = 0 and slide_id in (select s.id from slide s where s.delete_at = 0) and course_id in (select c.id from course c where c.delete_at = 0)")
+@Cacheable
+@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 public class Quiz {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)

+ 2 - 0
src/main/java/nju/seec/helper/entity/Slide.java

@@ -22,6 +22,8 @@ import java.time.LocalDateTime;
 @DynamicUpdate
 @DynamicInsert
 @Where(clause = "delete_at = 0 and course_id in (select c.id from course c where c.delete_at = 0)")
+@Cacheable
+@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 public class Slide {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)

+ 5 - 4
src/main/java/nju/seec/helper/entity/User.java

@@ -4,11 +4,10 @@ import lombok.Data;
 import lombok.experimental.Accessors;
 import nju.seec.helper.enums.UserState;
 import nju.seec.helper.enums.UserType;
-import org.hibernate.annotations.ColumnDefault;
-import org.hibernate.annotations.CreationTimestamp;
-import org.hibernate.annotations.DynamicInsert;
-import org.hibernate.annotations.DynamicUpdate;
+import org.hibernate.annotations.*;
 
+import javax.persistence.Entity;
+import javax.persistence.Table;
 import javax.persistence.*;
 import java.time.LocalDateTime;
 
@@ -22,6 +21,8 @@ import java.time.LocalDateTime;
         @UniqueConstraint(name = "user_email_unique", columnNames = "email")})
 @DynamicUpdate
 @DynamicInsert
+@Cacheable
+@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 public class User {
     @Id
     @GeneratedValue(strategy = GenerationType.IDENTITY)

+ 21 - 0
src/main/java/nju/seec/helper/service/CommentService.java

@@ -62,4 +62,25 @@ public interface CommentService extends AuthService<Comment> {
      * @return
      */
     CommentVO getOneComment(LoginUser user, Long commentId);
+
+    /**
+     * 取得自己的评论
+     *
+     * @param user
+     * @param slideId
+     * @param pageNumber
+     * @param show
+     * @param pageable
+     * @return
+     */
+    Page<CommentVO> getSelfCommentsBySlideAndPageNumber(LoginUser user, Long slideId, Integer pageNumber, Boolean show, Pageable pageable);
+
+    /**
+     * 修改评论展示状态
+     *
+     * @param user
+     * @param commentId
+     * @param show
+     */
+    void modifyCommentShow(LoginUser user, Long commentId, Boolean show);
 }

+ 0 - 8
src/main/java/nju/seec/helper/service/MessageService.java

@@ -31,14 +31,6 @@ public interface MessageService {
      */
     void deleteMessages(LoginUser user, MessageDTO messageDTO);
 
-    /**
-     * 删除关联消息
-     *
-     * @param refId
-     * @param messageType
-     */
-    void deleteMessages(Long refId, MessageType messageType);
-
     /**
      * 设置消息已阅
      *

+ 11 - 0
src/main/java/nju/seec/helper/service/QuizService.java

@@ -92,4 +92,15 @@ public interface QuizService extends AuthService<Quiz> {
      * @param slide
      */
     void modifyQuizState(Slide slide);
+
+    /**
+     * 教师基于状态获取测试
+     *
+     * @param user
+     * @param state
+     * @param key
+     * @param pageable
+     * @return
+     */
+    Page<QuizVO> teacherGetQuizzesByState(LoginUser user, QuizState state, String key, Pageable pageable);
 }

+ 3 - 2
src/main/java/nju/seec/helper/service/QuizStudentAnswerService.java

@@ -2,7 +2,7 @@ package nju.seec.helper.service;
 
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.dto.quiz.QuizStudentAnswerDTO;
-import nju.seec.helper.vo.QuizStudentAnswerStatisticVO;
+import nju.seec.helper.vo.quiz.QuizStudentAnswerStatisticVO;
 import nju.seec.helper.vo.quiz.QuizStudentAnswerVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
@@ -26,10 +26,11 @@ public interface QuizStudentAnswerService {
      *
      * @param user
      * @param quizId
+     * @param key
      * @param pageable
      * @return
      */
-    Page<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, Long quizId, Pageable pageable);
+    Page<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, Long quizId, String key, Pageable pageable);
 
     /**
      * 学生查看自己的答案

+ 31 - 3
src/main/java/nju/seec/helper/service/impl/CommentServiceImpl.java

@@ -79,6 +79,10 @@ public class CommentServiceImpl implements CommentService {
     public void topComment(LoginUser user, Long commentId) {
         Comment comment = commentDAO.findCommentById(commentId);
 
+        if (!comment.getShow()) {
+            throw HelperException.of(ExceptionType.FORBIDDEN, "私密评论,无法置顶");
+        }
+
         if (!existsUpdateAuth(user, comment)) {
             throw HelperException.of(ExceptionType.FORBIDDEN, "您无权在该评论区置顶评论");
         }
@@ -117,12 +121,35 @@ public class CommentServiceImpl implements CommentService {
         Comment comment = commentDAO.findCommentById(commentId);
 
         if (!existsGetAuth(user, comment)) {
-            throw HelperException.of(ExceptionType.FORBIDDEN, "您无权参考该评论");
+            throw HelperException.of(ExceptionType.FORBIDDEN, "您无权获取该评论");
         }
 
         return new CommentVO(comment);
     }
 
+    @Transactional(readOnly = true)
+    @Override
+    public Page<CommentVO> getSelfCommentsBySlideAndPageNumber(LoginUser user, Long slideId, Integer pageNumber, Boolean show, Pageable pageable) {
+        return commentDAO.findBySlideIdAndPageNumberAndUserAndShow(slideId, pageNumber, userDAO.findUserById(user.getId()), show, pageable).map(CommentVO::new);
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void modifyCommentShow(LoginUser user, Long commentId, Boolean show) {
+        Comment comment = commentDAO.findCommentById(commentId);
+
+        if (comment.getShow().equals(show)) {
+            return;
+        }
+
+        if (!existsUpdateAuth(user, comment)) {
+            throw HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该评论的展示状态");
+        }
+
+        unTopComment(comment);
+        commentDAO.save(comment.setShow(show));
+    }
+
     private void unTopComment(Comment comment) {
         Integer topNumber = comment.getTopNumber();
         comment.setTopNumber(0);
@@ -130,7 +157,7 @@ public class CommentServiceImpl implements CommentService {
             commentDAO.saveAll(
                     commentDAO.findBySlideIdAndPageNumberAndTopNumberGreaterThan(comment.getSlideId(), comment.getPageNumber(), topNumber)
                             .parallelStream()
-                            .peek(topComment -> topComment.setTopNumber(comment.getTopNumber() - 1))
+                            .peek(topComment -> topComment.setTopNumber(topComment.getTopNumber() - 1))
                             .collect(Collectors.toList())
             );
         }
@@ -148,7 +175,8 @@ public class CommentServiceImpl implements CommentService {
 
     @Override
     public boolean existsUpdateAuth(LoginUser user, Comment comment) {
-        return slideDAO.findSlideById(comment.getSlideId()).getTeacher().getId().equals(user.getId());
+        return comment.getUser().getId().equals(user.getId())
+                || slideDAO.findSlideById(comment.getSlideId()).getTeacher().getId().equals(user.getId());
     }
 
     @Override

+ 1 - 3
src/main/java/nju/seec/helper/service/impl/CourseFileServiceImpl.java

@@ -11,7 +11,7 @@ import nju.seec.helper.enums.ExceptionType;
 import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.service.CourseFileService;
 import nju.seec.helper.service.CourseService;
-import nju.seec.helper.service.util.OssObjectUrlUtils;
+import nju.seec.helper.util.OssObjectUrlUtils;
 import nju.seec.helper.util.OssUtils;
 import nju.seec.helper.vo.CourseFileVO;
 import org.springframework.data.domain.Page;
@@ -102,8 +102,6 @@ public class CourseFileServiceImpl implements CourseFileService {
     public String getCourseFileUrl(LoginUser user, Long courseFileId) {
         CourseFile courseFile = courseFileDAO.findCourseFileById(courseFileId);
 
-        System.currentTimeMillis();
-
         if (!existsGetAuth(user, courseFile)) {
             throw HelperException.of(ExceptionType.FORBIDDEN, "您无权获取该附件的链接");
         }

+ 4 - 6
src/main/java/nju/seec/helper/service/impl/CourseServiceImpl.java

@@ -12,7 +12,6 @@ import nju.seec.helper.enums.ExceptionType;
 import nju.seec.helper.enums.UserType;
 import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.service.CourseService;
-import nju.seec.helper.util.EncryptUtils;
 import nju.seec.helper.vo.CourseVO;
 import nju.seec.helper.vo.UserVO;
 import org.springframework.dao.DataIntegrityViolationException;
@@ -46,8 +45,7 @@ public class CourseServiceImpl implements CourseService {
                                     .setTeacher(userDAO.findUserById(teacher.getId()))
                                     .setName(courseDTO.getName())
                                     .setBio(courseDTO.getBio())
-                                    .setCode(EncryptUtils.encode(courseDTO.getCode()))
-                    )
+                                    .setCode(courseDTO.getCode()))
             );
         } catch (DataIntegrityViolationException e) {
             throw HelperException.of(ExceptionType.CONFLICT, "创建失败,请检查课程信息是否正确且不与已有课程冲突");
@@ -68,7 +66,7 @@ public class CourseServiceImpl implements CourseService {
                     courseDAO.save(
                             course.setName(courseDTO.getName())
                                     .setBio(courseDTO.getBio())
-                                    .setCode(EncryptUtils.encode(courseDTO.getCode()))
+                                    .setCode(courseDTO.getCode())
                     )
             );
         } catch (DataIntegrityViolationException e) {
@@ -98,7 +96,7 @@ public class CourseServiceImpl implements CourseService {
             throw HelperException.of(ExceptionType.CONFLICT, "您已选课");
         }
 
-        if (!courseDAO.existsByIdAndCode(courseId, EncryptUtils.encode(chooseDTO.getCode()))) {
+        if (!courseDAO.existsByIdAndCode(courseId, chooseDTO.getCode())) {
             throw HelperException.of(ExceptionType.NOT_FOUND, "选课码错误");
         }
 
@@ -142,7 +140,7 @@ public class CourseServiceImpl implements CourseService {
             throw HelperException.of(ExceptionType.FORBIDDEN, "您无权获取该课程选课码");
         }
 
-        return EncryptUtils.decode(course.getCode());
+        return course.getCode();
     }
 
     @Transactional(readOnly = true)

+ 0 - 6
src/main/java/nju/seec/helper/service/impl/MessageServiceImpl.java

@@ -45,12 +45,6 @@ public class MessageServiceImpl implements MessageService {
         messageDAO.deleteByToUserIdAndIdIn(user.getId(), messageDTO.getIds());
     }
 
-    @Async
-    @Override
-    public void deleteMessages(Long refId, MessageType messageType) {
-        messageDAO.deleteByRefIdAndType(refId, messageType);
-    }
-
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void readMessages(LoginUser user, MessageDTO messageDTO) {

+ 0 - 1
src/main/java/nju/seec/helper/service/impl/NoticeServiceImpl.java

@@ -89,7 +89,6 @@ public class NoticeServiceImpl implements NoticeService {
             throw HelperException.of(ExceptionType.FORBIDDEN, "您无权删除该公告");
         }
         noticeDAO.delete(notice);
-        messageService.deleteMessages(noticeId, MessageType.NOTICE_NEW);
     }
 
     @Transactional(readOnly = true)

+ 10 - 6
src/main/java/nju/seec/helper/service/impl/QuizServiceImpl.java

@@ -3,10 +3,7 @@ package nju.seec.helper.service.impl;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import nju.seec.helper.aspect.auth.LoginUser;
-import nju.seec.helper.dao.ChooseDAO;
-import nju.seec.helper.dao.QuizDAO;
-import nju.seec.helper.dao.QuizStudentAnswerDAO;
-import nju.seec.helper.dao.SlideDAO;
+import nju.seec.helper.dao.*;
 import nju.seec.helper.dto.quiz.QuizDTO;
 import nju.seec.helper.entity.Course;
 import nju.seec.helper.entity.Quiz;
@@ -39,15 +36,17 @@ public class QuizServiceImpl implements QuizService {
     private final QuizDAO quizDAO;
     private final QuizStudentAnswerDAO quizStudentAnswerDAO;
     private final ChooseDAO chooseDAO;
+    private final UserDAO userDAO;
 
     private final MessageService messageService;
 
     @Autowired
-    public QuizServiceImpl(SlideDAO slideDAO, QuizDAO quizDAO, QuizStudentAnswerDAO quizStudentAnswerDAO, ChooseDAO chooseDAO, MessageService messageService) {
+    public QuizServiceImpl(SlideDAO slideDAO, QuizDAO quizDAO, QuizStudentAnswerDAO quizStudentAnswerDAO, ChooseDAO chooseDAO, UserDAO userDAO, MessageService messageService) {
         this.slideDAO = slideDAO;
         this.quizDAO = quizDAO;
         this.quizStudentAnswerDAO = quizStudentAnswerDAO;
         this.chooseDAO = chooseDAO;
+        this.userDAO = userDAO;
         this.messageService = messageService;
     }
 
@@ -143,7 +142,6 @@ public class QuizServiceImpl implements QuizService {
         }
         quiz.setDeleteAt(System.currentTimeMillis());
         quizDAO.save(quiz);
-        messageService.deleteMessages(quizId, MessageType.QUIZ_NEW);
     }
 
     private static final Set<QuizState> STATES_NOT_GET_BY_STUDENT_SET = ImmutableSet.of(QuizState.NOT_STARTED);
@@ -160,6 +158,12 @@ public class QuizServiceImpl implements QuizService {
         return quizDAO.findBySlideAndStateNotInAndNameContains(slideDAO.findSlideById(slideId), STATES_NOT_GET_BY_STUDENT_SET, key, pageable).map(QuizVO::new);
     }
 
+    @Transactional(readOnly = true)
+    @Override
+    public Page<QuizVO> teacherGetQuizzesByState(LoginUser user, QuizState state, String key, Pageable pageable) {
+        return quizDAO.findByTeacherAndStateAndNameContains(userDAO.findUserById(user.getId()), state, key, pageable).map(QuizVO::new);
+    }
+
     @Transactional(readOnly = true)
     @Override
     public Page<QuizVO> studentGetQuizzesByState(LoginUser user, QuizState state, String key, Pageable pageable) {

+ 3 - 3
src/main/java/nju/seec/helper/service/impl/QuizStudentAnswerServiceImpl.java

@@ -13,8 +13,8 @@ import nju.seec.helper.enums.ExceptionType;
 import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.service.QuestionService;
 import nju.seec.helper.service.QuizStudentAnswerService;
-import nju.seec.helper.vo.QuizStudentAnswerStatisticVO;
 import nju.seec.helper.vo.question.BaseQuestionVO;
+import nju.seec.helper.vo.quiz.QuizStudentAnswerStatisticVO;
 import nju.seec.helper.vo.quiz.QuizStudentAnswerVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
@@ -95,8 +95,8 @@ public class QuizStudentAnswerServiceImpl implements QuizStudentAnswerService {
 
     @Transactional(readOnly = true)
     @Override
-    public Page<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, Long quizId, Pageable pageable) {
-        return quizStudentAnswerDAO.findByQuiz(quizDAO.findQuizById(quizId), pageable).map(quizStudentAnswer -> new QuizStudentAnswerVO(quizStudentAnswer, questionService.getQuestionsByQuiz(quizDAO.findQuizById(quizId))));
+    public Page<QuizStudentAnswerVO> getQuizStudentAnswers(LoginUser user, Long quizId, String key, Pageable pageable) {
+        return quizStudentAnswerDAO.findByQuizIdAndKey(quizId, key, pageable).map(quizStudentAnswer -> new QuizStudentAnswerVO(quizStudentAnswer, questionService.getQuestionsByQuiz(quizDAO.findQuizById(quizId))));
     }
 
     @Transactional(readOnly = true)

+ 1 - 2
src/main/java/nju/seec/helper/service/impl/ReplyServiceImpl.java

@@ -12,7 +12,6 @@ import nju.seec.helper.entity.Reply;
 import nju.seec.helper.entity.Slide;
 import nju.seec.helper.enums.ExceptionType;
 import nju.seec.helper.enums.MessageType;
-import nju.seec.helper.enums.UserType;
 import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.service.MessageService;
 import nju.seec.helper.service.ReplyService;
@@ -87,7 +86,7 @@ public class ReplyServiceImpl implements ReplyService {
 
     @Override
     public boolean existsAddAuth(LoginUser user, Reply reply) {
-        return user.getType() == UserType.TEACHER;
+        return slideDAO.findSlideById(reply.getComment().getSlideId()).getTeacher().getId().equals(user.getId());
     }
 
     @Override

+ 1 - 2
src/main/java/nju/seec/helper/service/impl/SlideServiceImpl.java

@@ -21,7 +21,7 @@ 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.OssObjectUrlUtils;
 import nju.seec.helper.util.OssUtils;
 import nju.seec.helper.util.file.FileInfo;
 import nju.seec.helper.util.file.FileUtils;
@@ -188,7 +188,6 @@ public class SlideServiceImpl implements SlideService {
 
         slide.setDeleteAt(System.currentTimeMillis());
         slideDAO.save(slide);
-        messageService.deleteMessages(slideId, MessageType.SLIDE_IN_CLASS);
     }
 
     @SneakyThrows

+ 0 - 5
src/main/java/nju/seec/helper/service/impl/UserServiceImpl.java

@@ -24,11 +24,6 @@ import org.springframework.transaction.annotation.Transactional;
 public class UserServiceImpl implements UserService {
     private final RedisCacheUtils cacheUtils;
     private final UserDAO userDAO;
-//    private final static Map<String, UserType> EMAIL_SUFFIX_AND_USER_TYPE_MAP =
-//            ImmutableMap.of(
-//                    "smail.nju.edu.cn", UserType.STUDENT,
-//                    "nju.edu.cn", UserType.TEACHER
-//            );
 
     public UserServiceImpl(UserDAO userDAO, RedisCacheUtils cacheUtils) {
         this.userDAO = userDAO;

+ 9 - 9
src/main/java/nju/seec/helper/util/EncryptUtils.java

@@ -1,25 +1,25 @@
 package nju.seec.helper.util;
 
+import lombok.SneakyThrows;
 import lombok.experimental.UtilityClass;
+import org.apache.commons.codec.binary.Hex;
 
-import java.util.Base64;
+import java.security.MessageDigest;
 
 /**
  * @author cst
  */
 @UtilityClass
 public class EncryptUtils {
+    private static final String ALGORITHM = "SHA-256";
+
     /**
      * 加密
      */
+    @SneakyThrows
     public String encode(String string) {
-        return Base64.getEncoder().encodeToString(string.getBytes());
-    }
-
-    /**
-     * 解密
-     */
-    public String decode(String string) {
-        return new String(Base64.getDecoder().decode(string));
+        MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
+        byte[] hash = messageDigest.digest(string.getBytes());
+        return Hex.encodeHexString(hash);
     }
 }

+ 1 - 1
src/main/java/nju/seec/helper/service/util/OssObjectUrlUtils.java → src/main/java/nju/seec/helper/util/OssObjectUrlUtils.java

@@ -1,4 +1,4 @@
-package nju.seec.helper.service.util;
+package nju.seec.helper.util;
 
 import nju.seec.helper.util.Consts;
 import nju.seec.helper.util.OssUtils;

+ 1 - 1
src/main/java/nju/seec/helper/vo/question/BaseQuestionVO.java

@@ -34,7 +34,7 @@ public abstract class BaseQuestionVO {
         }
     }
 
-    public BaseQuestionVO(BokQuestion bokQuestion) {
+    protected BaseQuestionVO(BokQuestion bokQuestion) {
         this.id = bokQuestion.getId();
         this.stem = bokQuestion.getStem();
         this.keyPoints = bokQuestion.getKeyPoints();

+ 1 - 1
src/main/java/nju/seec/helper/vo/QuizStudentAnswerStatisticVO.java → src/main/java/nju/seec/helper/vo/quiz/QuizStudentAnswerStatisticVO.java

@@ -1,4 +1,4 @@
-package nju.seec.helper.vo;
+package nju.seec.helper.vo.quiz;
 
 import lombok.AllArgsConstructor;
 import lombok.Data;

+ 15 - 0
src/main/resources/ehcache.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<eh:config xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:eh='http://www.ehcache.org/v3'
+           xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.3.xsd">
+    <eh:persistence directory="${java.io.tmpdir}/helper-cache-data"/>
+    <eh:cache-template name="default">
+        <eh:expiry>
+            <eh:ttl unit="seconds">600</eh:ttl>
+        </eh:expiry>
+        <eh:resources>            <!--堆内内存可以放2000个条目,超出部分堆外100MB-->
+            <eh:heap unit="entries">2000</eh:heap>
+            <eh:offheap unit="MB">100</eh:offheap>
+        </eh:resources>
+    </eh:cache-template>
+</eh:config>
+

+ 9 - 0
src/main/resources/hibernate.properties

@@ -0,0 +1,9 @@
+hibernate.format_sql=true
+hibernate.cache.use_second_level_cache=true
+hibernate.cache.use_query_cache=true
+hibernate.cache.region_prefix=helper
+hibernate.cache.region.factory_class=org.hibernate.cache.jcache.internal.JCacheRegionFactory
+hibernate.cache.provider_configuration_file_resource_path=ehcache.xml
+hibernate.cache.use_structured_entries=true
+hibernate.generate_statistics=false
+hibernate.javax.cache.missing_cache_strategy=create

+ 9 - 17
src/main/resources/update.sql

@@ -1,21 +1,13 @@
-drop index choose_student on choose;
+update user
+set password = sha2(from_base64(password), 256);
 
-alter table choose
-    drop constraint course_student_unique;
+update course
+set code = from_base64(code);
 
-alter table course add index course_teacher (teacher_id);
+update admin
+set password = sha2(from_base64(password), 256);
 
-alter table course
-    drop constraint course_name_unique;
+alter table comment
+    add index comment_slide_page_user (slide_id, page_number, user_id);
 
-alter table quiz
-    add index quiz_slide (slide_id);
-
-alter table quiz
-    drop constraint quiz_name_unique;
-
-alter table slide
-    add index slide_course (course_id);
-
-alter table slide
-    drop constraint slide_name_unique;
+drop index slide_page_top on comment;