Explorar o código

feat: 根据课程推荐题目

ChenSiTong %!s(int64=6) %!d(string=hai) anos
pai
achega
c780e85630

+ 1 - 1
pom.xml

@@ -10,7 +10,7 @@
     </parent>
     <groupId>cn.seecoder</groupId>
     <artifactId>helper-backend</artifactId>
-    <version>5.3.0</version>
+    <version>5.4.0</version>
     <packaging>jar</packaging>
     <name>helper</name>
     <description>backend</description>

+ 9 - 2
src/main/java/nju/seec/helper/controller/CourseController.java

@@ -1,17 +1,18 @@
 package nju.seec.helper.controller;
 
-import nju.seec.helper.sys.dataanalysis.constant.EventAction;
-import nju.seec.helper.sys.dataanalysis.constant.EventType;
 import nju.seec.helper.aspect.auth.Auth;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.aspect.event.Event;
 import nju.seec.helper.controller.response.PageResponse;
 import nju.seec.helper.dto.course.ChooseDTO;
 import nju.seec.helper.dto.course.CourseDTO;
+import nju.seec.helper.dto.course.CourseKnowledgeDTO;
 import nju.seec.helper.dto.groups.Create;
 import nju.seec.helper.dto.groups.Modify;
 import nju.seec.helper.enums.UserRole;
 import nju.seec.helper.service.CourseService;
+import nju.seec.helper.sys.dataanalysis.constant.EventAction;
+import nju.seec.helper.sys.dataanalysis.constant.EventType;
 import nju.seec.helper.vo.CourseVO;
 import nju.seec.helper.vo.UserVO;
 import org.springframework.data.domain.Pageable;
@@ -64,6 +65,12 @@ public class CourseController {
         return courseService.modifyCourse(user, courseId, courseDTO);
     }
 
+    @Auth(roles = UserRole.TEACHER, message = "修改课程知识点")
+    @PutMapping("/{courseId}/knowledge")
+    public void modifyCourseKnowledgeId(LoginUser user, @PathVariable Long courseId, @Validated @RequestBody CourseKnowledgeDTO courseKnowledgeDTO) {
+        courseService.modifyCourseKnowledgeId(user, courseId, courseKnowledgeDTO);
+    }
+
     /**
      * 学生选课
      */

+ 1 - 1
src/main/java/nju/seec/helper/controller/CourseFileController.java

@@ -3,7 +3,7 @@ package nju.seec.helper.controller;
 import nju.seec.helper.aspect.auth.Auth;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.controller.response.PageResponse;
-import nju.seec.helper.dto.course.CourseFileDTO;
+import nju.seec.helper.dto.coursefile.CourseFileDTO;
 import nju.seec.helper.enums.UserRole;
 import nju.seec.helper.service.CourseFileService;
 import nju.seec.helper.vo.CourseFileVO;

+ 7 - 1
src/main/java/nju/seec/helper/controller/QuestionController.java

@@ -166,10 +166,16 @@ public class QuestionController {
 
     @Auth(roles = UserRole.STUDENT, message = "取得推荐题目")
     @GetMapping("/recommendation")
-    public List<BaseQuestionVO> getRecommendationQuestions(LoginUser user, @RequestParam(required = false) List<String> knowledgeId, Integer questionNum) {
+    public List<BaseQuestionVO> getRecommendationQuestions(LoginUser user, @RequestParam(required = false) List<String> knowledgeId, @RequestParam(required = false, defaultValue = "5") Integer questionNum) {
         return questionService.getRecommendationQuestions(user, knowledgeId, questionNum);
     }
 
+    @Auth(roles = UserRole.STUDENT, message = "根据课程取得推荐题目")
+    @GetMapping("/course/{courseId}/recommendation")
+    public List<BaseQuestionVO> getRecommendationQuestionsByCourse(LoginUser user, @PathVariable Long courseId, @RequestParam(required = false, defaultValue = "5") Integer questionNum) {
+        return questionService.getRecommendationQuestionsByCourse(user, courseId, questionNum);
+    }
+
     @Auth(roles = UserRole.STUDENT, message = "提交做题情况")
     @PostMapping("/record")
     public void submitAnswerRecord(LoginUser user, @Validated @RequestBody StudentAnswerDTO studentAnswerDTO) {

+ 3 - 0
src/main/java/nju/seec/helper/dto/course/CourseDTO.java

@@ -6,6 +6,7 @@ import org.hibernate.validator.constraints.Length;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 import java.io.Serializable;
+import java.util.List;
 
 /**
  * @author cst
@@ -22,4 +23,6 @@ public class CourseDTO implements Serializable {
     @NotBlank
     @Length(max = 50, message = "选课码长度不能超过50")
     private String code;
+
+    private List<String> knowledgeId;
 }

+ 15 - 0
src/main/java/nju/seec/helper/dto/course/CourseKnowledgeDTO.java

@@ -0,0 +1,15 @@
+package nju.seec.helper.dto.course;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+/**
+ * @author cst
+ */
+@Data
+public class CourseKnowledgeDTO {
+    @NotEmpty(message = "知识点列表不能为空")
+    private List<String> knowledgeId;
+}

+ 19 - 0
src/main/java/nju/seec/helper/dto/coursefile/CourseFileDTO.java

@@ -0,0 +1,19 @@
+package nju.seec.helper.dto.coursefile;
+
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author cst
+ */
+@Data
+public class CourseFileDTO implements Serializable {
+    private static final long serialVersionUID = -3754505745869667461L;
+    @NotNull(message = "缺少课程ID")
+    private Long courseId;
+    @NotNull(message = "缺少文件")
+    private MultipartFile file;
+}

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

@@ -10,6 +10,7 @@ import javax.persistence.ForeignKey;
 import javax.persistence.Table;
 import javax.persistence.*;
 import java.time.LocalDateTime;
+import java.util.List;
 
 /**
  * @author cst
@@ -48,4 +49,8 @@ public class Course {
     @ColumnDefault("0")
     @Column(name = "delete_at", nullable = false)
     private Long deleteAt = 0L;
+
+    @Type(type = "json")
+    @Column(columnDefinition = "json", name = "knowledge_id")
+    private List<String> knowledgeId;
 }

+ 1 - 1
src/main/java/nju/seec/helper/service/CourseFileService.java

@@ -1,7 +1,7 @@
 package nju.seec.helper.service;
 
 import nju.seec.helper.aspect.auth.LoginUser;
-import nju.seec.helper.dto.course.CourseFileDTO;
+import nju.seec.helper.dto.coursefile.CourseFileDTO;
 import nju.seec.helper.entity.CourseFile;
 import nju.seec.helper.vo.CourseFileVO;
 import org.springframework.data.domain.Page;

+ 10 - 0
src/main/java/nju/seec/helper/service/CourseService.java

@@ -3,6 +3,7 @@ package nju.seec.helper.service;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.dto.course.ChooseDTO;
 import nju.seec.helper.dto.course.CourseDTO;
+import nju.seec.helper.dto.course.CourseKnowledgeDTO;
 import nju.seec.helper.entity.Course;
 import nju.seec.helper.vo.CourseVO;
 import nju.seec.helper.vo.UserVO;
@@ -32,6 +33,15 @@ public interface CourseService extends AuthService<Course> {
      */
     CourseVO modifyCourse(LoginUser user, Long courseId, CourseDTO courseDTO);
 
+    /**
+     * 修改课程知识点
+     *
+     * @param user
+     * @param courseId
+     * @param courseKnowledgeDTO
+     */
+    void modifyCourseKnowledgeId(LoginUser user, Long courseId, CourseKnowledgeDTO courseKnowledgeDTO);
+
     /**
      * 删除课程(伪删除)
      *

+ 10 - 1
src/main/java/nju/seec/helper/service/QuestionService.java

@@ -42,7 +42,6 @@ public interface QuestionService {
     /**
      * 根据测试获取题目(无需权限检验)
      *
-     *
      * @param questionIds@return
      */
     List<BaseQuestionVO> getQuestionsByIds(List<String> questionIds);
@@ -164,4 +163,14 @@ public interface QuestionService {
      * @param studentAnswerDTO
      */
     void record(LoginUser user, StudentAnswerDTO studentAnswerDTO);
+
+    /**
+     * 感觉课程取得推荐题目
+     *
+     * @param user
+     * @param courseId
+     * @param questionNum
+     * @return
+     */
+    List<BaseQuestionVO> getRecommendationQuestionsByCourse(LoginUser user, Long courseId, Integer questionNum);
 }

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

@@ -5,7 +5,7 @@ import lombok.SneakyThrows;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.dao.CourseDAO;
 import nju.seec.helper.dao.CourseFileDAO;
-import nju.seec.helper.dto.course.CourseFileDTO;
+import nju.seec.helper.dto.coursefile.CourseFileDTO;
 import nju.seec.helper.entity.Course;
 import nju.seec.helper.entity.CourseFile;
 import nju.seec.helper.enums.ExceptionType;

+ 33 - 20
src/main/java/nju/seec/helper/service/impl/CourseServiceImpl.java

@@ -6,6 +6,7 @@ import nju.seec.helper.dao.CourseDAO;
 import nju.seec.helper.dao.UserDAO;
 import nju.seec.helper.dto.course.ChooseDTO;
 import nju.seec.helper.dto.course.CourseDTO;
+import nju.seec.helper.dto.course.CourseKnowledgeDTO;
 import nju.seec.helper.entity.Choose;
 import nju.seec.helper.entity.Course;
 import nju.seec.helper.enums.ExceptionType;
@@ -39,14 +40,14 @@ public class CourseServiceImpl implements CourseService {
     @Override
     public CourseVO createCourse(LoginUser teacher, CourseDTO courseDTO) {
         try {
-            return new CourseVO(
-                    courseDAO.save(
-                            new Course()
-                                    .setTeacher(userDAO.findUserById(teacher.getId()))
-                                    .setName(courseDTO.getName())
-                                    .setBio(courseDTO.getBio())
-                                    .setCode(courseDTO.getCode()))
-            );
+            Course course = new Course()
+                    .setTeacher(userDAO.findUserById(teacher.getId()))
+                    .setName(courseDTO.getName())
+                    .setBio(courseDTO.getBio())
+                    .setCode(courseDTO.getCode())
+                    .setKnowledgeId(courseDTO.getKnowledgeId());
+
+            return new CourseVO(courseDAO.save(course));
         } catch (DataIntegrityViolationException e) {
             throw HelperException.of(ExceptionType.CONFLICT, "创建失败,请检查课程信息是否正确且不与已有课程冲突");
         }
@@ -61,19 +62,31 @@ public class CourseServiceImpl implements CourseService {
             throw HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该课程");
         }
 
+        course.setName(courseDTO.getName())
+                .setBio(courseDTO.getBio())
+                .setCode(courseDTO.getCode());
+
         try {
-            return new CourseVO(
-                    courseDAO.save(
-                            course.setName(courseDTO.getName())
-                                    .setBio(courseDTO.getBio())
-                                    .setCode(courseDTO.getCode())
-                    )
-            );
+            return new CourseVO(courseDAO.save(course));
         } catch (DataIntegrityViolationException e) {
             throw HelperException.of(ExceptionType.CONFLICT, "修改失败,请检查课程信息是否正确且不与已有课程冲突");
         }
     }
 
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public void modifyCourseKnowledgeId(LoginUser user, Long courseId, CourseKnowledgeDTO courseKnowledgeDTO) {
+        Course course = courseDAO.findCourseById(courseId);
+
+        if (!existsUpdateAuth(user, course)) {
+            throw HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该课程知识点");
+        }
+
+        course.setKnowledgeId(courseKnowledgeDTO.getKnowledgeId());
+
+        courseDAO.save(course);
+    }
+
     @Transactional(rollbackFor = Exception.class)
     @Override
     public void deleteCourse(LoginUser user, Long courseId) {
@@ -100,11 +113,11 @@ public class CourseServiceImpl implements CourseService {
             throw HelperException.of(ExceptionType.NOT_FOUND, "选课码错误");
         }
 
-        chooseDAO.save(
-                new Choose()
-                        .setCourseId(courseId)
-                        .setStudentId(studentId)
-        );
+        Choose choose = new Choose()
+                .setCourseId(courseId)
+                .setStudentId(studentId);
+
+        chooseDAO.save(choose);
     }
 
     @Transactional(rollbackFor = Exception.class)

+ 19 - 36
src/main/java/nju/seec/helper/service/impl/EventServiceImpl.java

@@ -1,18 +1,15 @@
 package nju.seec.helper.service.impl;
 
-import com.google.common.collect.Lists;
-import nju.seec.helper.sys.dataanalysis.api.EventApi;
-import nju.seec.helper.sys.dataanalysis.model.Event;
 import nju.seec.helper.dao.*;
-import nju.seec.helper.entity.*;
-import nju.seec.helper.enums.UserRole;
 import nju.seec.helper.service.EventService;
+import nju.seec.helper.sys.dataanalysis.api.EventApi;
+import nju.seec.helper.sys.dataanalysis.model.Event;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.time.LocalDateTime;
 import java.util.List;
-import java.util.Objects;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @author cst
@@ -39,34 +36,20 @@ public class EventServiceImpl implements EventService {
     @Transactional(readOnly = true)
     @Override
     public List<Event> getAllEvents() {
-        List<Event> events = Lists.newArrayList();
-        List<Course> courses = courseDAO.findAll();
-        courses.forEach(course -> {
-            List<Choose> chooses = chooseDAO.findByCourseId(course.getId());
-            chooses.forEach(
-                    choose -> {
-                        User student = userDAO.findUserById(choose.getStudentId());
-                        if (student.getPid() != null) {
-                            events.add(eventApi.createParticipateClassEventDTO(String.valueOf(Objects.requireNonNull(student).getPid()), LocalDateTime.now(), course));
-                        }
-                    }
-            );
-        });
-        List<Comment> comments = commentDAO.findAll();
-        comments.forEach(comment -> {
-            User user = comment.getUser();
-            if (user.getPid() != null && user.getRole() == UserRole.STUDENT) {
-                events.add(eventApi.createInitPostEventDTO(String.valueOf(user.getPid()), comment.getCreateAt(), comment.getTitle()));
-            }
-        });
-        List<QuizStudentAnswer> quizStudentAnswers = quizStudentAnswerDAO.findAll();
-        quizStudentAnswers.forEach(quizStudentAnswer -> {
-            User student = quizStudentAnswer.getStudent();
-            if (student.getPid() != null) {
-                Quiz quiz = quizStudentAnswer.getQuiz();
-                events.add(eventApi.createCompleteQuizEventDTO(String.valueOf(student.getPid()), quizStudentAnswer.getSubmitAt(), quiz));
-            }
-        });
-        return events;
+        return Stream.of(
+                courseDAO.findAll()
+                        .stream()
+                        .flatMap(course -> chooseDAO.findByCourseId(course.getId())
+                                .stream()
+                                .map(choose -> eventApi.createParticipateClassEventDTO(String.valueOf(userDAO.findUserById(choose.getStudentId()).getPid()), choose.getChooseAt(), course)))
+                , commentDAO.findAll()
+                        .stream()
+                        .map(comment -> eventApi.createInitPostEventDTO(String.valueOf(comment.getUser().getPid()), comment.getCreateAt(), comment.getTitle()))
+                , quizStudentAnswerDAO.findAll()
+                        .stream()
+                        .map(quizStudentAnswer -> eventApi.createCompleteQuizEventDTO(String.valueOf(quizStudentAnswer.getStudent().getPid()), quizStudentAnswer.getSubmitAt(), quizStudentAnswer.getQuiz()))
+        )
+                .flatMap(eventStream -> eventStream)
+                .collect(Collectors.toList());
     }
 }

+ 10 - 4
src/main/java/nju/seec/helper/service/impl/QuestionServiceImpl.java

@@ -3,10 +3,7 @@ package nju.seec.helper.service.impl;
 import cn.hutool.core.util.IdUtil;
 import com.google.common.collect.Lists;
 import nju.seec.helper.aspect.auth.LoginUser;
-import nju.seec.helper.dao.ChooseDAO;
-import nju.seec.helper.dao.QuestionRecordDAO;
-import nju.seec.helper.dao.QuizDAO;
-import nju.seec.helper.dao.UserDAO;
+import nju.seec.helper.dao.*;
 import nju.seec.helper.dto.question.BaseQuestionDTO;
 import nju.seec.helper.dto.question.StudentAnswerDTO;
 import nju.seec.helper.entity.QuestionRecord;
@@ -54,6 +51,7 @@ public class QuestionServiceImpl implements QuestionService {
     private final UserDAO userDAO;
     private final QuestionRecordDAO questionRecordDAO;
     private final ChooseDAO chooseDAO;
+    private final CourseDAO courseDAO;
 
     private final QuestionApi questionApi;
     private final QuestionQueryApi questionQueryApi;
@@ -67,6 +65,7 @@ public class QuestionServiceImpl implements QuestionService {
             , UserDAO userDAO
             , QuestionRecordDAO questionRecordDAO
             , ChooseDAO chooseDAO
+            , CourseDAO courseDAO
             , QuestionApi questionApi
             , QuestionQueryApi questionQueryApi
             , UserInteractiveApi userInteractiveApi
@@ -78,6 +77,7 @@ public class QuestionServiceImpl implements QuestionService {
         this.userDAO = userDAO;
         this.questionRecordDAO = questionRecordDAO;
         this.chooseDAO = chooseDAO;
+        this.courseDAO = courseDAO;
         this.questionApi = questionApi;
         this.questionQueryApi = questionQueryApi;
         this.userInteractiveApi = userInteractiveApi;
@@ -206,6 +206,12 @@ public class QuestionServiceImpl implements QuestionService {
                 .collect(Collectors.toList());
     }
 
+    @Transactional(readOnly = true)
+    @Override
+    public List<BaseQuestionVO> getRecommendationQuestionsByCourse(LoginUser user, Long courseId, Integer questionNum) {
+        return this.getRecommendationQuestions(user, courseDAO.findCourseById(courseId).getKnowledgeId(), questionNum);
+    }
+
     @Override
     public void record(LoginUser user, StudentAnswerDTO studentAnswerDTO) {
         if (studentAnswerDTO.getRecords() == null || studentAnswerDTO.getRecords().isEmpty()) {