Selaa lähdekoodia

refactor: 对接新的BOK接口

ChenSiTong 6 vuotta sitten
vanhempi
commit
49effb3d4e
32 muutettua tiedostoa jossa 501 lisäystä ja 363 poistoa
  1. 12 14
      src/main/java/nju/seec/helper/api/bok/KnowledgeApi.java
  2. 42 95
      src/main/java/nju/seec/helper/api/bok/QuestionApi.java
  3. 70 0
      src/main/java/nju/seec/helper/api/bok/QuestionQueryApi.java
  4. 41 0
      src/main/java/nju/seec/helper/api/bok/UserInteractiveApi.java
  5. 28 0
      src/main/java/nju/seec/helper/api/bok/constant/QuestionType.java
  6. 16 0
      src/main/java/nju/seec/helper/api/bok/dto/CollectDTO.java
  7. 23 0
      src/main/java/nju/seec/helper/api/bok/dto/RateDTO.java
  8. 16 0
      src/main/java/nju/seec/helper/api/bok/vo/KnowledgeNodeVO.java
  9. 14 0
      src/main/java/nju/seec/helper/api/bok/vo/PageVO.java
  10. 14 0
      src/main/java/nju/seec/helper/api/bok/vo/PageableQuestionListVO.java
  11. 31 0
      src/main/java/nju/seec/helper/api/bok/vo/QuestionVO.java
  12. 1 5
      src/main/java/nju/seec/helper/api/dataanalysis/EventApi.java
  13. 2 6
      src/main/java/nju/seec/helper/api/dataanalysis/ExerciseApi.java
  14. 2 7
      src/main/java/nju/seec/helper/aspect/auth/AuthAspect.java
  15. 2 2
      src/main/java/nju/seec/helper/controller/KnowledgeController.java
  16. 14 9
      src/main/java/nju/seec/helper/controller/QuestionController.java
  17. 1 1
      src/main/java/nju/seec/helper/entity/User.java
  18. 1 1
      src/main/java/nju/seec/helper/enums/ExceptionType.java
  19. 0 39
      src/main/java/nju/seec/helper/enums/QuestionType.java
  20. 4 9
      src/main/java/nju/seec/helper/enums/QuizState.java
  21. 4 5
      src/main/java/nju/seec/helper/enums/SlideState.java
  22. 9 4
      src/main/java/nju/seec/helper/service/QuestionService.java
  23. 23 13
      src/main/java/nju/seec/helper/service/impl/QuestionServiceImpl.java
  24. 2 0
      src/main/java/nju/seec/helper/util/Consts.java
  25. 22 2
      src/main/java/nju/seec/helper/util/RestRequestUtil.java
  26. 3 3
      src/main/java/nju/seec/helper/util/cache/CaffeineCacheUtils.java
  27. 0 59
      src/main/java/nju/seec/helper/util/cache/GuavaCacheUtils.java
  28. 10 6
      src/main/java/nju/seec/helper/vo/question/BaseQuestionVO.java
  29. 1 7
      src/main/java/nju/seec/helper/vo/question/ChoiceQuestionVO.java
  30. 1 4
      src/main/java/nju/seec/helper/vo/question/TrueOrFalseQuestionVO.java
  31. 43 32
      src/main/resources/application-deploy.yml
  32. 49 40
      src/main/resources/application-dev.yml

+ 12 - 14
src/main/java/nju/seec/helper/api/bok/KnowledgeApi.java

@@ -5,8 +5,8 @@ import lombok.Data;
 import nju.seec.helper.util.Consts;
 import nju.seec.helper.util.RestRequestUtil;
 import nju.seec.helper.util.cache.CaffeineCacheUtils;
-import nju.seec.helper.vo.knowledge.BokKnowledgeNodeVO;
-import org.springframework.beans.factory.annotation.Value;
+import nju.seec.helper.api.bok.vo.KnowledgeNodeVO;
+import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
 
 import java.util.List;
@@ -15,17 +15,15 @@ import java.util.List;
  * @author cst
  */
 @Component
+@ConfigurationProperties("bok.knowledge")
+@Data
 public class KnowledgeApi {
+    private static final String BOK_KNOWLEDGE_CACHE_NAME = Consts.BOK_KNOWLEDGE_CACHE_NAME;
+
     private final RestRequestUtil restRequestUtil;
     private final CaffeineCacheUtils cacheUtils;
 
-    @Value("${bok.knowledgeUrl}")
-    private String knowledgeUrl;
-
-    @Value("${bok.knowledgeGetAllUrl}")
-    private String knowledgeGetAllUrl;
-
-    private static final String BOK_KNOWLEDGE_CACHE_NAME = Consts.SYS_NAME + "_bok_knowledge";
+    private String url;
 
     public KnowledgeApi(RestRequestUtil restRequestUtil, CaffeineCacheUtils cacheUtils) {
         this.restRequestUtil = restRequestUtil;
@@ -33,14 +31,14 @@ public class KnowledgeApi {
     }
 
     @SuppressWarnings("unchecked")
-    public List<BokKnowledgeNodeVO> getAllKnowledgeNodes() {
+    public List<KnowledgeNodeVO> getAllKnowledgeNodes() {
         Object cache = cacheUtils.get(BOK_KNOWLEDGE_CACHE_NAME, "all");
         if (cache instanceof List) {
-            return (List<BokKnowledgeNodeVO>) cache;
+            return (List<KnowledgeNodeVO>) cache;
         }
-        List<BokKnowledgeNodeVO> bokKnowledgeNodeVOList = restRequestUtil.sendPostRequest(knowledgeGetAllUrl, KnowledgeGetDTO.of("", "part of"), List.class);
-        cacheUtils.set(BOK_KNOWLEDGE_CACHE_NAME, "all", bokKnowledgeNodeVOList);
-        return bokKnowledgeNodeVOList;
+        List<KnowledgeNodeVO> knowledgeNodeVOList = restRequestUtil.sendGetRequest(url, List.class);
+        cacheUtils.set(BOK_KNOWLEDGE_CACHE_NAME, "all", knowledgeNodeVOList);
+        return knowledgeNodeVOList;
     }
 
     @AllArgsConstructor(staticName = "of")

+ 42 - 95
src/main/java/nju/seec/helper/api/bok/QuestionApi.java

@@ -1,29 +1,27 @@
 package nju.seec.helper.api.bok;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
+import cn.hutool.core.util.StrUtil;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 import lombok.Data;
+import nju.seec.helper.api.bok.constant.QuestionType;
+import nju.seec.helper.api.bok.vo.PageableQuestionListVO;
+import nju.seec.helper.api.bok.vo.QuestionVO;
 import nju.seec.helper.dto.question.BaseQuestionDTO;
 import nju.seec.helper.dto.question.ChoiceQuestionDTO;
 import nju.seec.helper.dto.question.TrueOrFalseQuestionDTO;
 import nju.seec.helper.enums.ExceptionType;
-import nju.seec.helper.enums.QuestionType;
 import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.util.Consts;
 import nju.seec.helper.util.RestRequestUtil;
 import nju.seec.helper.util.cache.CaffeineCacheUtils;
-import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Component;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
-import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
@@ -32,143 +30,92 @@ import java.util.stream.Collectors;
  * updated by cst
  */
 @Component
+@ConfigurationProperties("bok.question")
+@Data
 public class QuestionApi {
+    private static final String BOK_QUESTION_CACHE_NAME = Consts.BOK_QUESTION_CACHE_NAME;
+
     private final RestRequestUtil restRequestUtil;
     private final CaffeineCacheUtils cacheUtils;
-    @Value("${bok.tqUrl}")
-    private String tqUrl;
-    @Value("${bok.tqStemSearchUrl}")
-    private String tqStemSearchUrl;
-    @Value("${bok.tqIdSearchUrl}")
-    private String tqIdSearchUrl;
+    private String url;
+    private String searchUrl;
 
     public QuestionApi(RestRequestUtil restRequestUtil, CaffeineCacheUtils cacheUtils) {
         this.restRequestUtil = restRequestUtil;
         this.cacheUtils = cacheUtils;
     }
 
-    public Page<QuestionVO> bokFindByStemLike(String stem, Pageable pageable) {
-        Map<String, String> urlParams = ImmutableMap.of(
-                "content", stem,
-                "page", String.valueOf(1 + pageable.getPageNumber()),
-                "size", String.valueOf(pageable.getPageSize())
-        );
-        BokSearchResult result = restRequestUtil.sendGetRequest(tqStemSearchUrl, BokSearchResult.class, urlParams);
-
-        List<QuestionVO> questionVOList = result.getEmbedded().getQuestions();
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public Page<QuestionVO> searchQuestions(String stem, String tag, String knowledgeId, Pageable pageable) {
+        Map<String, ?> urlParams = (Map) ImmutableMap.builder()
+                .put("stem", stem)
+                .put("tag", tag)
+                .put("knowledgeId", knowledgeId)
+                .put("page", String.valueOf(1 + pageable.getPageNumber()))
+                .put("size", String.valueOf(pageable.getPageSize()))
+                .put("sort", pageable.getSort().stream()
+                        .map(order -> StrUtil.concat(true, "sort=", order.getProperty(), ",", order.getDirection().toString()))
+                        .reduce((o1, o2) -> StrUtil.join("&", o1, o2))
+                        .orElse("")
+                )
+                .build();
+        PageableQuestionListVO result = restRequestUtil.sendGetRequest(searchUrl, PageableQuestionListVO.class, urlParams);
+
+        List<QuestionVO> questionVOList = result.getQuestions();
         cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, questionVOList.parallelStream().collect(Collectors.toMap(QuestionVO::getId, bokQuestion -> bokQuestion)));
         return new PageImpl<>(questionVOList, pageable, result.getPage().getTotalElements());
     }
 
-    private static final String BOK_QUESTION_CACHE_NAME = Consts.SYS_NAME + "_bok_question";
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public List<QuestionVO> bokFindByIdIn(final List<String> ids) {
-        Map<String, QuestionVO> bokQuestionsMap = Maps.newHashMapWithExpectedSize(ids.size());
-
-        final Map<String, QuestionVO> cacheBokQuestionsMap = (Map) cacheUtils.multiGet(BOK_QUESTION_CACHE_NAME, ids);
-        bokQuestionsMap.putAll(cacheBokQuestionsMap);
-
-        List<String> requestIds = Lists.newArrayList(ids);
-        requestIds.removeAll(cacheBokQuestionsMap.keySet());
-        //未缓存的去这里拿
-        if (!requestIds.isEmpty()) {
-            Map<String, String> urlParams = ImmutableMap.of("id", requestIds.stream().reduce((a, b) -> a + "," + b).orElse(""));
-
-            BokSearchResult result = restRequestUtil.sendGetRequest(tqIdSearchUrl, BokSearchResult.class, urlParams);
-            List<QuestionVO> questionVOList = result.getEmbedded().getQuestions();
-
-            Map<String, QuestionVO> remoteBokQuestionsMap = questionVOList.parallelStream().collect(Collectors.toMap(QuestionVO::getId, bokQuestion -> bokQuestion));
-
-            bokQuestionsMap.putAll(remoteBokQuestionsMap);
-            cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, (Map) remoteBokQuestionsMap);
-        }
-
-        return ids.stream()
-                .map(bokQuestionsMap::get)
-                .collect(Collectors.toList());
-    }
-
-    public QuestionVO bokFindById(String questionId) {
+    public QuestionVO findQuestionsById(String questionId) {
         Object cachedBokQuestion = cacheUtils.get(BOK_QUESTION_CACHE_NAME, questionId);
         if (cachedBokQuestion instanceof QuestionVO) {
             return (QuestionVO) cachedBokQuestion;
         }
-        QuestionVO questionVO = restRequestUtil.sendGetRequest(tqUrl + "/" + questionId, QuestionVO.class, Collections.emptyMap());
+        QuestionVO questionVO = restRequestUtil.sendGetRequest(url + "/" + questionId, QuestionVO.class);
         cacheUtils.set(BOK_QUESTION_CACHE_NAME, questionVO.getId(), questionVO);
         return questionVO;
     }
 
     public QuestionVO createQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
-        QuestionVO questionVO = getQuestion(baseQuestionDTO);
+        QuestionVO questionVO = createQuestionVO(baseQuestionDTO);
         questionVO.setId(questionId);
-        questionVO = restRequestUtil.sendPostRequest(tqUrl, questionVO, QuestionVO.class);
+        questionVO = restRequestUtil.sendPostRequest(url, questionVO, QuestionVO.class);
         return questionVO;
     }
 
     public QuestionVO modifyQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
-        QuestionVO questionVO = getQuestion(baseQuestionDTO);
+        QuestionVO questionVO = createQuestionVO(baseQuestionDTO);
         questionVO.setId(questionId);
-        restRequestUtil.sendPutRequest(tqUrl + "/" + questionId, questionVO);
-        return bokFindById(questionId);
+        restRequestUtil.sendPutRequest(url + "/" + questionId, questionVO);
+        return findQuestionsById(questionId);
     }
 
     public void deleteQuestion(String questionId) {
-        restRequestUtil.sendDeleteRequest(tqUrl + "/" + questionId);
+        restRequestUtil.sendDeleteRequest(url + "/" + questionId);
     }
 
-    private QuestionVO getQuestion(BaseQuestionDTO baseQuestionDTO) {
+    private QuestionVO createQuestionVO(BaseQuestionDTO baseQuestionDTO) {
         QuestionVO questionVO = new QuestionVO();
-        questionVO.setType(baseQuestionDTO.getType());
+        questionVO.setType(QuestionType.valueOf(baseQuestionDTO.getType()));
         questionVO.setStem(baseQuestionDTO.getStem());
         questionVO.setKeyPoints(baseQuestionDTO.getKeyPoints());
         questionVO.setTags(baseQuestionDTO.getTags());
         questionVO.setKnowledgeId(baseQuestionDTO.getKnowledgeId());
+        questionVO.setAnalysis(baseQuestionDTO.getAnalysis());
 
-        final QuestionType questionType = QuestionType.getQuestionType(baseQuestionDTO.getType());
-        switch (Objects.requireNonNull(questionType)) {
-            case CHOICE:
+        switch (questionVO.getType()) {
+            case choice:
                 ChoiceQuestionDTO choiceQuestionDTO = (ChoiceQuestionDTO) baseQuestionDTO;
                 questionVO.setOptions(choiceQuestionDTO.getOptions());
                 questionVO.setAnswer(choiceQuestionDTO.getAnswer());
-                questionVO.setAnalysis(choiceQuestionDTO.getAnalysis());
                 break;
-            case TRUE_FALSE:
+            case true_false:
                 TrueOrFalseQuestionDTO trueOrFalseQuestionDTO = (TrueOrFalseQuestionDTO) baseQuestionDTO;
                 questionVO.setAnswer(String.valueOf(trueOrFalseQuestionDTO.getAnswer()));
-                questionVO.setAnalysis(trueOrFalseQuestionDTO.getAnalysis());
                 break;
             default:
                 throw HelperException.of(ExceptionType.ERROR, "不支持的题目类型");
         }
         return questionVO;
     }
-
-    public void starQuestion(String userId, String questionId) {
-
-    }
-
-    public void likeQuestion(String userId, String questionId) {
-
-    }
-
-    @Data
-    private static class BokSearchResult {
-        @JsonProperty("_embedded")
-        private Embedded embedded = new Embedded();
-        private Page page;
-
-        @Data
-        private static class Embedded {
-            private List<QuestionVO> questions = Collections.emptyList();
-        }
-
-        @Data
-        private static class Page {
-            private int size;
-            private int number;
-            private int totalPages;
-            private long totalElements;
-        }
-    }
 }

+ 70 - 0
src/main/java/nju/seec/helper/api/bok/QuestionQueryApi.java

@@ -0,0 +1,70 @@
+package nju.seec.helper.api.bok;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.gson.reflect.TypeToken;
+import lombok.Data;
+import nju.seec.helper.api.bok.vo.QuestionVO;
+import nju.seec.helper.util.Consts;
+import nju.seec.helper.util.JsonUtils;
+import nju.seec.helper.util.RestRequestUtil;
+import nju.seec.helper.util.cache.CaffeineCacheUtils;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @author cst
+ */
+@Component
+@ConfigurationProperties("bok.question-query")
+@Data
+public class QuestionQueryApi {
+    private static final String BOK_QUESTION_CACHE_NAME = Consts.BOK_QUESTION_CACHE_NAME;
+
+    private final RestRequestUtil restRequestUtil;
+    private final CaffeineCacheUtils cacheUtils;
+
+    private String byIdUrl;
+
+    public QuestionQueryApi(RestRequestUtil restRequestUtil, CaffeineCacheUtils cacheUtils) {
+        this.restRequestUtil = restRequestUtil;
+        this.cacheUtils = cacheUtils;
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public List<QuestionVO> queryQuestionById(final List<String> ids) {
+        Map<String, QuestionVO> bokQuestionsMap = Maps.newHashMapWithExpectedSize(ids.size());
+
+        final Map<String, QuestionVO> cacheBokQuestionsMap = (Map) cacheUtils.multiGet(BOK_QUESTION_CACHE_NAME, ids);
+        bokQuestionsMap.putAll(cacheBokQuestionsMap);
+
+        List<String> requestIds = Lists.newArrayList(ids);
+        requestIds.removeAll(cacheBokQuestionsMap.keySet());
+        //未缓存的去这里拿
+        if (!requestIds.isEmpty()) {
+            Map<String, String> urlParams = ImmutableMap.of("id", requestIds.stream().reduce((a, b) -> a + "," + b).orElse(""));
+
+            String json = restRequestUtil.sendGetRequest(byIdUrl, String.class, urlParams);
+
+            List<QuestionVO> questionVOList = JsonUtils.fromJson(json, new TypeToken<List<QuestionVO>>() {
+            });
+
+            Map<String, QuestionVO> remoteBokQuestionsMap =
+                    questionVOList
+                            .parallelStream()
+                            .collect(Collectors.toMap(QuestionVO::getId, bokQuestion -> bokQuestion));
+
+            bokQuestionsMap.putAll(remoteBokQuestionsMap);
+            cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, (Map) remoteBokQuestionsMap);
+        }
+
+        return ids.stream()
+                .map(bokQuestionsMap::get)
+                .collect(Collectors.toList());
+    }
+}

+ 41 - 0
src/main/java/nju/seec/helper/api/bok/UserInteractiveApi.java

@@ -0,0 +1,41 @@
+package nju.seec.helper.api.bok;
+
+import com.google.common.collect.ImmutableMap;
+import lombok.Data;
+import nju.seec.helper.api.bok.dto.CollectDTO;
+import nju.seec.helper.api.bok.dto.RateDTO;
+import nju.seec.helper.util.Consts;
+import nju.seec.helper.util.RestRequestUtil;
+import nju.seec.helper.util.cache.CaffeineCacheUtils;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author cst
+ */
+@Component
+@ConfigurationProperties("bok.user")
+@Data
+public class UserInteractiveApi {
+    private static final String BOK_QUESTION_CACHE_NAME = Consts.BOK_QUESTION_CACHE_NAME;
+
+    private final RestRequestUtil restRequestUtil;
+    private final CaffeineCacheUtils cacheUtils;
+
+    private String rateUrl;
+    private String collectionUrl;
+    private String questionUrl;
+
+    public UserInteractiveApi(RestRequestUtil restRequestUtil, CaffeineCacheUtils cacheUtils) {
+        this.restRequestUtil = restRequestUtil;
+        this.cacheUtils = cacheUtils;
+    }
+
+    public void collectQuestion(String userId, String questionId, CollectDTO collectDTO) {
+        restRequestUtil.sendPostRequest(collectionUrl, collectDTO, Object.class, ImmutableMap.of("userId", userId, "questionId", questionId));
+    }
+
+    public void rateQuestion(String userId, String questionId, RateDTO rateDTO) {
+        restRequestUtil.sendPostRequest(rateUrl, rateDTO, Object.class, ImmutableMap.of("userId", userId, "questionId", questionId));
+    }
+}

+ 28 - 0
src/main/java/nju/seec/helper/api/bok/constant/QuestionType.java

@@ -0,0 +1,28 @@
+package nju.seec.helper.api.bok.constant;
+
+
+/**
+ * @author bok
+ */
+public enum QuestionType {
+    /**
+     * 选择题
+     */
+    choice,
+    /**
+     * 判断题
+     */
+    true_false,
+    /**
+     * 多选题
+     */
+    multiple_choice,
+    /**
+     * 填空题
+     */
+    blank,
+    /**
+     * 简答题
+     */
+    short_answer
+}

+ 16 - 0
src/main/java/nju/seec/helper/api/bok/dto/CollectDTO.java

@@ -0,0 +1,16 @@
+package nju.seec.helper.api.bok.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author bok
+ * <p>
+ * updated by cst
+ */
+@Data
+public class CollectDTO {
+    @NotNull(message = "缺少是否收藏")
+    Boolean collect;
+}

+ 23 - 0
src/main/java/nju/seec/helper/api/bok/dto/RateDTO.java

@@ -0,0 +1,23 @@
+package nju.seec.helper.api.bok.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+
+/**
+ * @author bok
+ * <p>
+ * updated by cst
+ */
+@Data
+public class RateDTO {
+    /**
+     * 取值 1-5
+     */
+    @Max(value = 5, message = "最大评分为5")
+    @Min(value = 1, message = "最小评分为1")
+    @NotNull(message = "缺少评分")
+    Integer rate;
+}

+ 16 - 0
src/main/java/nju/seec/helper/api/bok/vo/KnowledgeNodeVO.java

@@ -0,0 +1,16 @@
+package nju.seec.helper.api.bok.vo;
+
+import lombok.Data;
+
+/**
+ * @author cst
+ */
+@Data
+public class KnowledgeNodeVO {
+    private String id;
+    private String abbreviation;
+    private String name;
+    private String englishName;
+    private String parentId;
+    private String parentName;
+}

+ 14 - 0
src/main/java/nju/seec/helper/api/bok/vo/PageVO.java

@@ -0,0 +1,14 @@
+package nju.seec.helper.api.bok.vo;
+
+import lombok.Data;
+
+/**
+ * @author Kunduin
+ */
+@Data
+public class PageVO {
+    Integer size;
+    Long totalElements;
+    Integer totalPages;
+    Integer number;
+}

+ 14 - 0
src/main/java/nju/seec/helper/api/bok/vo/PageableQuestionListVO.java

@@ -0,0 +1,14 @@
+package nju.seec.helper.api.bok.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author Kunduin
+ */
+@Data
+public class PageableQuestionListVO {
+    List<QuestionVO> questions;
+    PageVO page;
+}

+ 31 - 0
src/main/java/nju/seec/helper/api/bok/vo/QuestionVO.java

@@ -0,0 +1,31 @@
+package nju.seec.helper.api.bok.vo;
+
+import lombok.Data;
+import nju.seec.helper.api.bok.constant.QuestionType;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Kunduin
+ */
+@Data
+public class QuestionVO {
+    String id;
+    QuestionType type;
+    String stem;
+    Map<String, String> options;
+
+    /**
+     * 填空题 __1__ __2__
+     */
+    Map<String, String> blanks;
+
+    String answer;
+    String keyPoints;
+    String analysis;
+    List<String> tags;
+    List<String> knowledgeId;
+    Date lastModifiedTime;
+}

+ 1 - 5
src/main/java/nju/seec/helper/api/dataanalysis/EventApi.java

@@ -25,12 +25,8 @@ public class EventApi {
 
     @Async
     public void reportEvent(Event event) {
-        try {
-            System.out.println(event);
+        System.out.println(event);
 //            restRequestUtil.sendPostRequest(eventReportUrl, event, Boolean.class);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
     }
 
     /**

+ 2 - 6
src/main/java/nju/seec/helper/api/dataanalysis/ExerciseApi.java

@@ -24,12 +24,8 @@ public class ExerciseApi {
 
     @Async
     public void reportExercise(List<ExerciseRecord> exerciseRecords) {
-        try {
-            System.out.println(exerciseRecords);
-//            restRequestUtil.sendPostRequest(exerciseReportUrl, exerciseRecord, Boolean.class);
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        System.out.println(exerciseRecords);
+//        restRequestUtil.sendPostRequest(exerciseReportUrl, exerciseRecords, Boolean.class);
     }
 
     public ExerciseRecord createExerciseRecord(String userId, String questionId, LocalDateTime startAt, LocalDateTime endAt, Boolean pass) {

+ 2 - 7
src/main/java/nju/seec/helper/aspect/auth/AuthAspect.java

@@ -21,11 +21,9 @@ import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.Arrays;
 import java.util.Date;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.stream.Collectors;
 
 /**
  * @author cst
@@ -46,10 +44,7 @@ public class AuthAspect {
     public void authCheck(JoinPoint joinPoint, Auth auth) {
         LoginUser user = getLoginUser();
 
-        if (!Arrays
-                .stream(auth.roles())
-                .collect(Collectors.toSet())
-                .contains(user.getRole())) {
+        if (user.getRole() == null) {
             throw HelperException.of(ExceptionType.FORBIDDEN, String.format("您暂时无法%s,请重新登录", auth.message()));
         }
 
@@ -95,7 +90,7 @@ public class AuthAspect {
 
         user.setName(userInfo.name)
                 .setEmail(userInfo.email)
-                .setRole(userInfo.role)
+//                .setRole(userInfo.role)
                 .setPhone(userInfo.phone)
                 .setPid(userInfo.id);
 

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

@@ -1,7 +1,7 @@
 package nju.seec.helper.controller;
 
 import nju.seec.helper.api.bok.KnowledgeApi;
-import nju.seec.helper.vo.knowledge.BokKnowledgeNodeVO;
+import nju.seec.helper.api.bok.vo.KnowledgeNodeVO;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -28,7 +28,7 @@ public class KnowledgeController {
      * @return
      */
     @GetMapping
-    public List<BokKnowledgeNodeVO> getAllKnowledgeNodes() {
+    public List<KnowledgeNodeVO> getAllKnowledgeNodes() {
         return knowledgeApi.getAllKnowledgeNodes();
     }
 }

+ 14 - 9
src/main/java/nju/seec/helper/controller/QuestionController.java

@@ -1,5 +1,7 @@
 package nju.seec.helper.controller;
 
+import nju.seec.helper.api.bok.dto.CollectDTO;
+import nju.seec.helper.api.bok.dto.RateDTO;
 import nju.seec.helper.aspect.auth.Auth;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.controller.response.PageResponse;
@@ -23,7 +25,6 @@ import java.util.Set;
  * @author xst
  * <p>
  * updated by cst
- * @doc http://47.100.18.120:3000/SEEC-BOK/API-DOC/src/master/helper/api/Quiz-%e6%b5%8b%e8%af%95.md
  */
 @RestController
 @RequestMapping("/api/question")
@@ -39,8 +40,12 @@ public class QuestionController {
      */
     @Auth(roles = {UserRole.TEACHER}, message = "获得题目列表")
     @GetMapping
-    public PageResponse<BaseQuestionVO> getQuestionList(LoginUser user, @RequestParam(required = false, defaultValue = "") String key, @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
-        return PageResponse.of(questionService.getQuestions(user, key, pageable));
+    public PageResponse<BaseQuestionVO> getQuestionList(LoginUser user,
+                                                        @RequestParam(required = false, defaultValue = "") String stem,
+                                                        @RequestParam(required = false, defaultValue = "") String tag,
+                                                        @RequestParam(required = false, defaultValue = "") String knowledgeId,
+                                                        @PageableDefault(Integer.MAX_VALUE) Pageable pageable) {
+        return PageResponse.of(questionService.getQuestions(user, stem, tag, knowledgeId, pageable));
     }
 
     /**
@@ -111,17 +116,17 @@ public class QuestionController {
      * 收藏题目
      */
     @Auth(roles = UserRole.STUDENT, message = "收藏题目")
-    @PostMapping("/{questionId}/star")
-    public void starQuestion(LoginUser user, @PathVariable String questionId) {
-        questionService.starQuestion(user, questionId);
+    @PostMapping("/{questionId}/collect")
+    public void starQuestion(LoginUser user, @PathVariable String questionId, @Validated @RequestBody CollectDTO collectDTO) {
+        questionService.collectQuestion(user, questionId, collectDTO);
     }
 
     /**
      * 评价题目
      */
     @Auth(roles = UserRole.STUDENT, message = "评价题目")
-    @PostMapping("/{questionId}/like")
-    public void likeQuestion(LoginUser user, @PathVariable String questionId) {
-        questionService.likeQuestion(user, questionId);
+    @PostMapping("/{questionId}/rate")
+    public void rateQuestion(LoginUser user, @PathVariable String questionId, @Validated @RequestBody RateDTO rateDTO) {
+        questionService.rateQuestion(user, questionId, rateDTO);
     }
 }

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

@@ -37,7 +37,7 @@ public class User {
     private String email;
 
     @Enumerated(EnumType.STRING)
-    @Column(nullable = false, updatable = false)
+    @Column(nullable = false)
     private UserRole role;
 
     @Column(nullable = false)

+ 1 - 1
src/main/java/nju/seec/helper/enums/ExceptionType.java

@@ -12,7 +12,7 @@ public enum ExceptionType {
     // http code
     PARAM_ERROR(HttpStatus.BAD_REQUEST), UNAUTHORIZED(HttpStatus.UNAUTHORIZED), FORBIDDEN(HttpStatus.FORBIDDEN), NOT_FOUND(HttpStatus.NOT_FOUND), CONFLICT(HttpStatus.CONFLICT), ERROR(HttpStatus.INTERNAL_SERVER_ERROR);
 
-    private HttpStatus status;
+    private final HttpStatus status;
 
     ExceptionType(HttpStatus status) {
         this.status = status;

+ 0 - 39
src/main/java/nju/seec/helper/enums/QuestionType.java

@@ -1,39 +0,0 @@
-package nju.seec.helper.enums;
-
-import com.fasterxml.jackson.annotation.JsonValue;
-
-import java.util.Map;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * @author cst
- */
-public enum QuestionType {
-    /**
-     * 单选
-     */
-    CHOICE("choice"),
-    /**
-     * 判断
-     */
-    TRUE_FALSE("true_false");
-
-    private String value;
-
-    private final static Map<String, QuestionType> VALUE_TYPE_MAP =
-            Stream.of(QuestionType.values()).collect(Collectors.toMap(QuestionType::getValue, questionType -> questionType));
-
-    QuestionType(String value) {
-        this.value = value;
-    }
-
-    @JsonValue
-    public String getValue() {
-        return value;
-    }
-
-    public static QuestionType getQuestionType(String value) {
-        return VALUE_TYPE_MAP.get(value);
-    }
-}

+ 4 - 9
src/main/java/nju/seec/helper/enums/QuizState.java

@@ -1,10 +1,13 @@
 package nju.seec.helper.enums;
 
+import lombok.Getter;
+
 /**
  * @author xst
  * <p>
  * updated by cst
  */
+@Getter
 public enum QuizState {
     /**
      * 未开始
@@ -18,17 +21,9 @@ public enum QuizState {
      * 已结束
      */
     CLOSED("已结束");
-    private String name;
+    private final String name;
 
     QuizState(String name) {
         this.name = name;
     }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setName(String name) {
-        this.name = name;
-    }
 }

+ 4 - 5
src/main/java/nju/seec/helper/enums/SlideState.java

@@ -1,8 +1,11 @@
 package nju.seec.helper.enums;
 
+import lombok.Getter;
+
 /**
  * @author cst
  */
+@Getter
 public enum SlideState {
     /**
      * 草稿
@@ -24,13 +27,9 @@ public enum SlideState {
      * 结束
      */
     FINISH(5);
-    private Integer num;
+    private final Integer num;
 
     SlideState(Integer num) {
         this.num = num;
     }
-
-    public Integer getNum() {
-        return num;
-    }
 }

+ 9 - 4
src/main/java/nju/seec/helper/service/QuestionService.java

@@ -1,5 +1,7 @@
 package nju.seec.helper.service;
 
+import nju.seec.helper.api.bok.dto.CollectDTO;
+import nju.seec.helper.api.bok.dto.RateDTO;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.dto.question.BaseQuestionDTO;
 import nju.seec.helper.entity.Quiz;
@@ -21,10 +23,11 @@ public interface QuestionService {
      *
      * @param user
      * @param stem
-     * @param pageable
+     * @param tag
+     * @param knowledgeId * @param pageable
      * @return
      */
-    Page<BaseQuestionVO> getQuestions(LoginUser user, String stem, Pageable pageable);
+    Page<BaseQuestionVO> getQuestions(LoginUser user, String stem, String tag, String knowledgeId, Pageable pageable);
 
     /**
      * 根据测试获取题目
@@ -101,14 +104,16 @@ public interface QuestionService {
      *
      * @param user
      * @param questionId
+     * @param collectDTO
      */
-    void starQuestion(LoginUser user, String questionId);
+    void collectQuestion(LoginUser user, String questionId, CollectDTO collectDTO);
 
     /**
      * 评价题目
      *
      * @param user
      * @param questionId
+     * @param rateDTO
      */
-    void likeQuestion(LoginUser user, String questionId);
+    void rateQuestion(LoginUser user, String questionId, RateDTO rateDTO);
 }

+ 23 - 13
src/main/java/nju/seec/helper/service/impl/QuestionServiceImpl.java

@@ -1,8 +1,10 @@
 package nju.seec.helper.service.impl;
 
 import cn.hutool.core.util.IdUtil;
-import nju.seec.helper.api.bok.QuestionApi;
-import nju.seec.helper.api.bok.QuestionVO;
+import nju.seec.helper.api.bok.*;
+import nju.seec.helper.api.bok.dto.CollectDTO;
+import nju.seec.helper.api.bok.dto.RateDTO;
+import nju.seec.helper.api.bok.vo.QuestionVO;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.dao.QuestionRecordDAO;
 import nju.seec.helper.dao.QuizDAO;
@@ -39,20 +41,28 @@ public class QuestionServiceImpl implements QuestionService {
     private final QuestionRecordDAO questionRecordDAO;
 
     private final QuestionApi questionApi;
+    private final QuestionQueryApi questionQueryApi;
+    private final UserInteractiveApi userInteractiveApi;
 
     @Autowired
     public QuestionServiceImpl(QuizDAO quizDAO
             , UserDAO userDAO
-            , QuestionRecordDAO questionRecordDAO, QuestionApi questionApi) {
+            , QuestionRecordDAO questionRecordDAO
+            , QuestionApi questionApi
+            , QuestionQueryApi questionQueryApi
+            , UserInteractiveApi userInteractiveApi
+    ) {
         this.quizDAO = quizDAO;
         this.userDAO = userDAO;
         this.questionRecordDAO = questionRecordDAO;
         this.questionApi = questionApi;
+        this.questionQueryApi = questionQueryApi;
+        this.userInteractiveApi = userInteractiveApi;
     }
 
     @Override
-    public Page<BaseQuestionVO> getQuestions(LoginUser user, String stem, Pageable pageable) {
-        return questionApi.bokFindByStemLike(stem, pageable).map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true));
+    public Page<BaseQuestionVO> getQuestions(LoginUser user, String stem, String tag, String knowledgeId, Pageable pageable) {
+        return questionApi.searchQuestions(stem, tag, knowledgeId, pageable).map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true));
     }
 
     @Transactional(readOnly = true)
@@ -60,7 +70,7 @@ public class QuestionServiceImpl implements QuestionService {
     public List<BaseQuestionVO> getQuestionsByQuiz(LoginUser user, Long quizId) {
         Quiz quiz = quizDAO.findQuizById(quizId);
         List<String> questionIds = quiz.getQuestions();
-        return questionApi.bokFindByIdIn(questionIds)
+        return questionQueryApi.queryQuestionById(questionIds)
                 .stream()
                 .map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, quiz.getState() == QuizState.CLOSED || user.getRole() == UserRole.TEACHER))
                 .collect(Collectors.toList());
@@ -70,7 +80,7 @@ public class QuestionServiceImpl implements QuestionService {
     @Override
     public List<BaseQuestionVO> getQuestionsByQuiz(Quiz quiz) {
         List<String> questionIds = quiz.getQuestions();
-        return questionApi.bokFindByIdIn(questionIds)
+        return questionQueryApi.queryQuestionById(questionIds)
                 .stream()
                 .map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true))
                 .collect(Collectors.toList());
@@ -78,7 +88,7 @@ public class QuestionServiceImpl implements QuestionService {
 
     @Override
     public BaseQuestionVO getOneQuestion(LoginUser user, String questionId) {
-        return BaseQuestionVO.convertBokQuestionToVO(questionApi.bokFindById(questionId), true);
+        return BaseQuestionVO.convertBokQuestionToVO(questionApi.findQuestionsById(questionId), true);
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -122,7 +132,7 @@ public class QuestionServiceImpl implements QuestionService {
         Page<String> questionIdPage = questionRecordDAO.findQuestionIdsByTeacher(userDAO.findUserById(user.getId()), pageable);
 
         return new PageImpl<>(
-                questionApi.bokFindByIdIn(questionIdPage.getContent())
+                questionQueryApi.queryQuestionById(questionIdPage.getContent())
                         .stream()
                         .map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true))
                         .collect(Collectors.toList())
@@ -138,12 +148,12 @@ public class QuestionServiceImpl implements QuestionService {
     }
 
     @Override
-    public void starQuestion(LoginUser user, String questionId) {
-        questionApi.starQuestion(String.valueOf(user.getPid()), questionId);
+    public void collectQuestion(LoginUser user, String questionId, CollectDTO collectDTO) {
+        userInteractiveApi.collectQuestion(String.valueOf(user.getPid()), questionId, collectDTO);
     }
 
     @Override
-    public void likeQuestion(LoginUser user, String questionId) {
-        questionApi.likeQuestion(String.valueOf(user.getPid()), questionId);
+    public void rateQuestion(LoginUser user, String questionId, RateDTO rateDTO) {
+        userInteractiveApi.rateQuestion(String.valueOf(user.getPid()), questionId, rateDTO);
     }
 }

+ 2 - 0
src/main/java/nju/seec/helper/util/Consts.java

@@ -5,6 +5,8 @@ package nju.seec.helper.util;
  */
 public class Consts {
     public static final String SYS_NAME = "helper";
+    public static final String BOK_QUESTION_CACHE_NAME = Consts.SYS_NAME + "_bok_question";
+    public static final String BOK_KNOWLEDGE_CACHE_NAME = Consts.SYS_NAME + "_bok_knowledge";
 
 //    public static final String SESSION_USER_NAME = SYS_NAME + "_user";
 //    public static final String EMAIL_CACHE_NAME = SYS_NAME + "_email";

+ 22 - 2
src/main/java/nju/seec/helper/util/RestRequestUtil.java

@@ -12,6 +12,26 @@ import java.util.Map;
  */
 @Component
 public class RestRequestUtil {
+    public <T> T sendPostRequest(String url, Object request, Class<T> responseType, Map<String, ?> uriVariables) {
+        RestTemplate client = new RestTemplate();
+        return client.postForObject(url, request, responseType, uriVariables);
+    }
+
+    public void sendPutRequest(String url, Object request, Map<String, ?> uriVariables) {
+        RestTemplate client = new RestTemplate();
+        client.put(url, request, uriVariables);
+    }
+
+    public void sendDeleteRequest(String url, Map<String, ?> uriVariables) {
+        RestTemplate client = new RestTemplate();
+        client.delete(url, uriVariables);
+    }
+
+    public <T> T sendGetRequest(String url, Class<T> responseType, Map<String, ?> uriVariables) {
+        RestTemplate client = new RestTemplate();
+        return client.getForObject(url, responseType, uriVariables);
+    }
+
     public <T> T sendPostRequest(String url, Object request, Class<T> responseType) {
         RestTemplate client = new RestTemplate();
         return client.postForObject(url, request, responseType);
@@ -27,8 +47,8 @@ public class RestRequestUtil {
         client.delete(url);
     }
 
-    public <T> T sendGetRequest(String url, Class<T> responseType, Map<String, ?> uriVariables) {
+    public <T> T sendGetRequest(String url, Class<T> responseType) {
         RestTemplate client = new RestTemplate();
-        return client.getForObject(url, responseType, uriVariables);
+        return client.getForObject(url, responseType);
     }
 }

+ 3 - 3
src/main/java/nju/seec/helper/util/cache/CaffeineCacheUtils.java

@@ -19,9 +19,9 @@ import java.util.stream.Collectors;
 public class CaffeineCacheUtils {
     private final Cache<String, Object> cache;
 
-    public CaffeineCacheUtils(@Value("${guavaCache.maximumSize}") Long maximumSize,
-                              @Value("${guavaCache.expireAfterAccessInSeconds}") Long expireAfterAccessInSeconds,
-                              @Value("${guavaCache.expireAfterWriteInSeconds}") Long expireAfterWriteInSeconds) {
+    public CaffeineCacheUtils(@Value("${helper.cache.maximumSize}") Long maximumSize,
+                              @Value("${helper.cache.expireAfterAccessInSeconds}") Long expireAfterAccessInSeconds,
+                              @Value("${helper.cache.expireAfterWriteInSeconds}") Long expireAfterWriteInSeconds) {
         cache = Caffeine
                 .newBuilder()
                 .maximumSize(maximumSize)

+ 0 - 59
src/main/java/nju/seec/helper/util/cache/GuavaCacheUtils.java

@@ -1,59 +0,0 @@
-package nju.seec.helper.util.cache;
-
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.ImmutableMap;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.util.Collection;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-
-/**
- * @author xst
- * <p>
- * updated by cst
- */
-@Component
-public class GuavaCacheUtils {
-    private final Cache<String, Object> cache;
-
-    public GuavaCacheUtils(@Value("${guavaCache.maximumSize}") Long maximumSize,
-                           @Value("${guavaCache.expireAfterAccessInSeconds}") Long expireAfterAccessInSeconds,
-                           @Value("${guavaCache.expireAfterWriteInSeconds}") Long expireAfterWriteInSeconds) {
-        cache = CacheBuilder
-                .newBuilder()
-                .maximumSize(maximumSize)
-                .expireAfterAccess(expireAfterAccessInSeconds, TimeUnit.SECONDS)
-                .expireAfterWrite(expireAfterWriteInSeconds, TimeUnit.SECONDS)
-                .build();
-    }
-
-    public void set(String cacheName, String key, Object value) {
-        cache.put(combineKey(cacheName, key), value);
-    }
-
-    public void setAll(String cacheName, Map<String, Object> putAll) {
-        final Map<String, Object> all = putAll.entrySet().stream().collect(Collectors.toMap(entry -> combineKey(cacheName, entry.getKey()), Map.Entry::getValue));
-        cache.putAll(all);
-    }
-
-    public Object get(String cacheName, String key) {
-        return cache.getIfPresent(combineKey(cacheName, key));
-    }
-
-    public ImmutableMap<String, Object> multiGet(String cacheName, Collection<String> keys) {
-        Collection<String> body = keys.stream().map(s -> combineKey(cacheName, s)).collect(Collectors.toList());
-        return cache.getAllPresent(body);
-    }
-
-    public void remove(String cacheName, String key) {
-        cache.invalidate(combineKey(cacheName, key));
-    }
-
-    private String combineKey(String cacheName, String key) {
-        return cacheName + ":" + key;
-    }
-}

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

@@ -2,11 +2,12 @@ package nju.seec.helper.vo.question;
 
 import lombok.Data;
 import lombok.NonNull;
-import nju.seec.helper.api.bok.QuestionVO;
-import nju.seec.helper.enums.QuestionType;
+import nju.seec.helper.api.bok.vo.QuestionVO;
+import nju.seec.helper.api.bok.constant.QuestionType;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author XuShengTao
@@ -17,18 +18,19 @@ import java.util.List;
 public abstract class BaseQuestionVO {
     protected String id;
     protected QuestionType type;
+    protected Map<String, String> options;
     protected String stem;
     protected String analysis;
     protected String keyPoints;
     protected List<String> tags;
     protected List<String> knowledgeId;
-    private Date lastModified;
+    protected Date lastModified;
 
     public static BaseQuestionVO convertBokQuestionToVO(@NonNull QuestionVO questionVO, boolean withAnswer) {
         switch (questionVO.getType()) {
-            case "choice":
+            case choice:
                 return new ChoiceQuestionVO(questionVO, withAnswer);
-            case "true_false":
+            case true_false:
                 return new TrueOrFalseQuestionVO(questionVO, withAnswer);
             default:
                 return null;
@@ -37,11 +39,13 @@ public abstract class BaseQuestionVO {
 
     protected BaseQuestionVO(QuestionVO questionVO) {
         this.id = questionVO.getId();
+        this.type = questionVO.getType();
+        this.options = questionVO.getOptions();
         this.stem = questionVO.getStem();
         this.keyPoints = questionVO.getKeyPoints();
         this.tags = questionVO.getTags();
         this.knowledgeId = questionVO.getKnowledgeId();
-        this.lastModified = questionVO.getLastModified();
+        this.lastModified = questionVO.getLastModifiedTime();
     }
 
     /**

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

@@ -3,10 +3,7 @@ package nju.seec.helper.vo.question;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NonNull;
-import nju.seec.helper.api.bok.QuestionVO;
-import nju.seec.helper.enums.QuestionType;
-
-import java.util.Map;
+import nju.seec.helper.api.bok.vo.QuestionVO;
 
 /**
  * @author xst
@@ -16,13 +13,10 @@ import java.util.Map;
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class ChoiceQuestionVO extends BaseQuestionVO {
-    private Map<String, String> options;
     private String answer;
 
     public ChoiceQuestionVO(@NonNull QuestionVO questionVO, boolean withAnswer) {
         super(questionVO);
-        this.type = QuestionType.CHOICE;
-        this.options = questionVO.getOptions();
 
         if (withAnswer) {
             this.answer = questionVO.getAnswer();

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

@@ -4,8 +4,7 @@ import cn.hutool.core.convert.Convert;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.NonNull;
-import nju.seec.helper.api.bok.QuestionVO;
-import nju.seec.helper.enums.QuestionType;
+import nju.seec.helper.api.bok.vo.QuestionVO;
 
 /**
  * @author xst
@@ -16,7 +15,6 @@ import nju.seec.helper.enums.QuestionType;
 @Data
 public class TrueOrFalseQuestionVO extends BaseQuestionVO {
     private Boolean answer;
-    private String analysis;
 
     @Override
     public boolean pass(Object answer) {
@@ -25,7 +23,6 @@ public class TrueOrFalseQuestionVO extends BaseQuestionVO {
 
     public TrueOrFalseQuestionVO(@NonNull QuestionVO questionVO, boolean withAnswer) {
         super(questionVO);
-        this.type = QuestionType.TRUE_FALSE;
 
         if (withAnswer) {
             this.answer = Boolean.valueOf(questionVO.getAnswer());

+ 43 - 32
src/main/resources/application-deploy.yml

@@ -16,31 +16,31 @@ spring:
   http:
     encoding:
       force: true
-#  redis:
-#    host: localhost
-#    port: 6379
+  #  redis:
+  #    host: localhost
+  #    port: 6379
   data:
-#    redis:
-#      repositories:
-#        enabled: false
+    #    redis:
+    #      repositories:
+    #        enabled: false
     web:
       pageable:
         max-page-size: 1000
         one-indexed-parameters: true
-#  mail:
-#    host: smtp.exmail.qq.com
-#    username: noreply@seecoder.cn
-#    password: eNrZcqucgcFtLC29
-#    properties:
-#      mail:
-#        smtp:
-#          auth: true
-#          socketFactory:
-#            class: javax.net.ssl.SSLSocketFactory
-#            port: 465
-#          starttls:
-#            enable: true
-#            required: true
+  #  mail:
+  #    host: smtp.exmail.qq.com
+  #    username: noreply@seecoder.cn
+  #    password: eNrZcqucgcFtLC29
+  #    properties:
+  #      mail:
+  #        smtp:
+  #          auth: true
+  #          socketFactory:
+  #            class: javax.net.ssl.SSLSocketFactory
+  #            port: 465
+  #          starttls:
+  #            enable: true
+  #            required: true
   servlet:
     multipart:
       max-file-size: 50MB
@@ -57,13 +57,20 @@ aliyun:
 #    signName: seeccoder
 #    templateCode: SMS_181555598
 bok:
-  url: http://bok.seecoder.cn
-  tqUrl: ${bok.url}/api/question
-  tqSearchUrl: ${bok.tqUrl}/search
-  tqStemSearchUrl: ${bok.tqSearchUrl}/findByStemLike?content={content}&size={size}&page={page}
-  tqIdSearchUrl: ${bok.tqSearchUrl}/findByIdIn?id={id}
-  knowledgeUrl: ${bok.url}/api/neo
-  knowledgeGetAllUrl: ${bok.knowledgeUrl}/getAll
+  url: http://120.78.159.171:6060
+  question:
+    url: ${bok.url}/api/question
+    search-url: ${bok.question.url}?stem={stem}&tag={tag}&knowledgeId={knowledgeId}&page={page}&size={size}&{sort}
+  question-query:
+    url: ${bok.url}/api/question-query
+    by-id-url: ${bok.question-query.url}/id?id={id}
+  knowledge:
+    url: ${bok.url}/api/knowledge
+  user:
+    url: ${bok.url}/api/user
+    rate-url: ${bok.user.url}/{userId}/question/{questionId}/rate
+    collection-url: ${bok.user.url}/{userId}/question/{questionId}/collection
+    question-url: ${bok.user.url}/{userId}/question?collection={collection}&rate={rate}
 #data-analysis:
 #  url: http://dataanalysis.seecoder.cn
 #  eventUrl: ${data-analysis.url}/api/event
@@ -75,8 +82,12 @@ guavaCache:
 jwt:
   secret: SEEC-1919810-OIDC-114514
 # 自定义数据
-#helper:
-#  mail:
-#    from: ${spring.mail.username}
-#    subject: seecoder
-#  user-timeout-seconds: 43200
+helper:
+  #  mail:
+  #    from: ${spring.mail.username}
+  #    subject: seecoder
+  #  user-timeout-seconds: 43200
+  cache:
+    maximumSize: 1000
+    expireAfterAccessInSeconds: 0
+    expireAfterWriteInSeconds: 900

+ 49 - 40
src/main/resources/application-dev.yml

@@ -14,31 +14,31 @@ spring:
   http:
     encoding:
       force: true
-#  redis:
-#    host: localhost
-#    port: 6379
+  #  redis:
+  #    host: localhost
+  #    port: 6379
   data:
-#    redis:
-#      repositories:
-#        enabled: false
+    #    redis:
+    #      repositories:
+    #        enabled: false
     web:
       pageable:
         max-page-size: 1000
         one-indexed-parameters: true
-#  mail:
-#    host: smtp.exmail.qq.com
-#    username: noreply@seecoder.cn
-#    password: eNrZcqucgcFtLC29
-#    properties:
-#      mail:
-#        smtp:
-#          auth: true
-#          socketFactory:
-#            class: javax.net.ssl.SSLSocketFactory
-#            port: 465
-#          starttls:
-#            enable: true
-#            required: true
+  #  mail:
+  #    host: smtp.exmail.qq.com
+  #    username: noreply@seecoder.cn
+  #    password: eNrZcqucgcFtLC29
+  #    properties:
+  #      mail:
+  #        smtp:
+  #          auth: true
+  #          socketFactory:
+  #            class: javax.net.ssl.SSLSocketFactory
+  #            port: 465
+  #          starttls:
+  #            enable: true
+  #            required: true
   servlet:
     multipart:
       max-file-size: 50MB
@@ -55,32 +55,41 @@ aliyun:
 #    signName: seeccoder
 #    templateCode: SMS_181555598
 bok:
-  url: http://bok.seecoder.cn
-  tqUrl: ${bok.url}/api/question
-  tqSearchUrl: ${bok.tqUrl}/search
-  tqStemSearchUrl: ${bok.tqSearchUrl}/findByStemLike?content={content}&size={size}&page={page}
-  tqIdSearchUrl: ${bok.tqSearchUrl}/findByIdIn?id={id}
-  knowledgeUrl: ${bok.url}/api/neo
-  knowledgeGetAllUrl: ${bok.knowledgeUrl}/getAll
+  url: http://120.78.159.171:6060
+  question:
+    url: ${bok.url}/api/question
+    search-url: ${bok.question.url}?stem={stem}&tag={tag}&knowledgeId={knowledgeId}&page={page}&size={size}&{sort}
+  question-query:
+    url: ${bok.url}/api/question-query
+    by-id-url: ${bok.question-query.url}/id?id={id}
+  knowledge:
+    url: ${bok.url}/api/knowledge
+  user:
+    url: ${bok.url}/api/user
+    rate-url: ${bok.user.url}/{userId}/question/{questionId}/rate
+    collection-url: ${bok.user.url}/{userId}/question/{questionId}/collection
+    question-url: ${bok.user.url}/{userId}/question?collection={collection}&rate={rate}
+#  tqUrl: ${bok.url}/api/question
+#  tqSearchUrl: ${bok.tqUrl}
+#  tqStemSearchUrl: ${bok.tqSearchUrl}/findByStemLike?content={content}&size={size}&page={page}
+#  tqIdSearchUrl: ${bok.tqSearchUrl}/findByIdIn?id={id}
+#  knowledgeUrl: ${bok.url}/api/neo
+#  knowledgeGetAllUrl: ${bok.knowledgeUrl}/getAll
 data-analysis:
   url: http://dataanalysis.seecoder.cn
   eventUrl: ${data-analysis.url}/api/event
   eventReportUrl: ${data-analysis.eventUrl}/report
   exerciseUrl: ${data-analysis.url}/api/exercise
   exerciseReportUrl: ${data-analysis.exerciseUrl}/report
-guavaCache:
-  maximumSize: 1000
-  expireAfterAccessInSeconds: 0
-  expireAfterWriteInSeconds: 900
 jwt:
   secret: SEEC-1919810-OIDC-114514
 # 自定义数据
-#helper:
-#  mail:
-#    from: ${spring.mail.username}
-#    subject: seecoder
-#  user-timeout-seconds: 43200
-management:
-  endpoint:
-    health:
-      show-details: always
+helper:
+  #  mail:
+  #    from: ${spring.mail.username}
+  #    subject: seecoder
+  #  user-timeout-seconds: 43200
+  cache:
+    maximumSize: 1000
+    expireAfterAccessInSeconds: 0
+    expireAfterWriteInSeconds: 900