ChenSiTong 6 лет назад
Родитель
Сommit
4c1bd05c72
22 измененных файлов с 214 добавлено и 119 удалено
  1. 1 1
      pom.xml
  2. 51 0
      src/main/java/nju/seec/helper/api/bok/BokKnowledgeApi.java
  3. 47 49
      src/main/java/nju/seec/helper/api/bok/BokQuestionApi.java
  4. 27 0
      src/main/java/nju/seec/helper/controller/KnowledgeController.java
  5. 3 4
      src/main/java/nju/seec/helper/dto/question/BaseQuestionDTO.java
  6. 1 1
      src/main/java/nju/seec/helper/service/impl/CodeServiceImpl.java
  7. 2 2
      src/main/java/nju/seec/helper/service/impl/CourseFileServiceImpl.java
  8. 16 16
      src/main/java/nju/seec/helper/service/impl/QuestionServiceImpl.java
  9. 2 2
      src/main/java/nju/seec/helper/service/impl/SlideServiceImpl.java
  10. 1 1
      src/main/java/nju/seec/helper/service/impl/UserServiceImpl.java
  11. 5 5
      src/main/java/nju/seec/helper/util/cache/GuavaCacheUtils.java
  12. 1 1
      src/main/java/nju/seec/helper/util/cache/RedisCacheUtils.java
  13. 6 6
      src/main/java/nju/seec/helper/util/oss/OssObjectUrlUtils.java
  14. 1 1
      src/main/java/nju/seec/helper/util/oss/OssUtils.java
  15. 16 0
      src/main/java/nju/seec/helper/vo/knowledge/BokKnowledgeNodeVO.java
  16. 14 14
      src/main/java/nju/seec/helper/vo/question/BaseQuestionVO.java
  17. 4 4
      src/main/java/nju/seec/helper/vo/question/BokQuestionVO.java
  18. 5 5
      src/main/java/nju/seec/helper/vo/question/ChoiceQuestionVO.java
  19. 4 4
      src/main/java/nju/seec/helper/vo/question/TrueOrFalseQuestionVO.java
  20. 2 0
      src/main/resources/application-deploy.yml
  21. 2 0
      src/main/resources/application-dev.yml
  22. 3 3
      src/main/resources/application.yml

+ 1 - 1
pom.xml

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

+ 51 - 0
src/main/java/nju/seec/helper/api/bok/BokKnowledgeApi.java

@@ -0,0 +1,51 @@
+package nju.seec.helper.api.bok;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import nju.seec.helper.util.RestRequestUtil;
+import nju.seec.helper.util.cache.GuavaCacheUtils;
+import nju.seec.helper.vo.knowledge.BokKnowledgeNodeVO;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @author cst
+ */
+@Component
+public class BokKnowledgeApi {
+    private final RestRequestUtil restRequestUtil;
+    private final GuavaCacheUtils cacheUtils;
+
+    @Value("${bok.knowledgeUrl}")
+    private String knowledgeUrl;
+
+    @Value("${bok.knowledgeGetAllUrl}")
+    private String knowledgeGetAllUrl;
+
+    private static final String BOK_KNOWLEDGE_CACHE_NAME = "helper_bok_knowledge";
+
+    public BokKnowledgeApi(RestRequestUtil restRequestUtil, GuavaCacheUtils cacheUtils) {
+        this.restRequestUtil = restRequestUtil;
+        this.cacheUtils = cacheUtils;
+    }
+
+    @SuppressWarnings("unchecked")
+    public List<BokKnowledgeNodeVO> getKnowledgeNodes() {
+        Object cache = cacheUtils.get(BOK_KNOWLEDGE_CACHE_NAME, "all");
+        if (cache instanceof List) {
+            return (List<BokKnowledgeNodeVO>) cache;
+        }
+        List<BokKnowledgeNodeVO> bokKnowledgeNodeVOList = restRequestUtil.sendPostRequest(knowledgeGetAllUrl, KnowledgeGetDTO.of("", "part of"), List.class);
+        cacheUtils.set(BOK_KNOWLEDGE_CACHE_NAME, "all", bokKnowledgeNodeVOList);
+        return bokKnowledgeNodeVOList;
+    }
+
+    @AllArgsConstructor(staticName = "of")
+    @Data
+    private static class KnowledgeGetDTO {
+        private String name;
+        private String relation;
+    }
+}

+ 47 - 49
src/main/java/nju/seec/helper/api/BokApi.java → src/main/java/nju/seec/helper/api/bok/BokQuestionApi.java

@@ -1,20 +1,19 @@
-package nju.seec.helper.api;
+package nju.seec.helper.api.bok;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import lombok.Data;
-import lombok.extern.slf4j.Slf4j;
 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.GuavaCacheUtil;
+import nju.seec.helper.util.cache.GuavaCacheUtils;
 import nju.seec.helper.util.RestRequestUtil;
-import nju.seec.helper.vo.question.BokQuestion;
+import nju.seec.helper.vo.question.BokQuestionVO;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
@@ -32,11 +31,10 @@ import java.util.stream.Collectors;
  * <p>
  * updated by cst
  */
-@Slf4j
 @Component
-public class BokApi {
+public class BokQuestionApi {
     private final RestRequestUtil restRequestUtil;
-    private final GuavaCacheUtil cacheUtils;
+    private final GuavaCacheUtils cacheUtils;
     @Value("${bok.tqUrl}")
     private String tqUrl;
     @Value("${bok.tqStemSearchUrl}")
@@ -44,12 +42,12 @@ public class BokApi {
     @Value("${bok.tqIdSearchUrl}")
     private String tqIdSearchUrl;
 
-    public BokApi(RestRequestUtil restRequestUtil, GuavaCacheUtil cacheUtils) {
+    public BokQuestionApi(RestRequestUtil restRequestUtil, GuavaCacheUtils cacheUtils) {
         this.restRequestUtil = restRequestUtil;
         this.cacheUtils = cacheUtils;
     }
 
-    public Page<BokQuestion> bokFindByStemLike(String stem, Pageable pageable) {
+    public Page<BokQuestionVO> bokFindByStemLike(String stem, Pageable pageable) {
         Map<String, String> urlParams = ImmutableMap.of(
                 "content", stem,
                 "page", String.valueOf(1 + pageable.getPageNumber()),
@@ -57,18 +55,18 @@ public class BokApi {
         );
         BokSearchResult result = restRequestUtil.sendGetRequest(tqStemSearchUrl, BokSearchResult.class, urlParams);
 
-        List<BokQuestion> bokQuestions = result.getEmbedded().getQuestions();
-        cacheUtils.setAll(BOK_CACHE_NAME, bokQuestions.parallelStream().collect(Collectors.toMap(BokQuestion::getId, bokQuestion -> bokQuestion)));
-        return new PageImpl<>(bokQuestions, pageable, result.getPage().getTotalElements());
+        List<BokQuestionVO> bokQuestionVOS = result.getEmbedded().getQuestions();
+        cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, bokQuestionVOS.parallelStream().collect(Collectors.toMap(BokQuestionVO::getId, bokQuestion -> bokQuestion)));
+        return new PageImpl<>(bokQuestionVOS, pageable, result.getPage().getTotalElements());
     }
 
-    private static String BOK_CACHE_NAME = "BOK";
+    private static final String BOK_QUESTION_CACHE_NAME = "helper_bok_question";
 
     @SuppressWarnings({"unchecked", "rawtypes"})
-    public List<BokQuestion> bokFindByIdIn(final List<String> ids) {
-        Map<String, BokQuestion> bokQuestionsMap = Maps.newHashMapWithExpectedSize(ids.size());
+    public List<BokQuestionVO> bokFindByIdIn(final List<String> ids) {
+        Map<String, BokQuestionVO> bokQuestionsMap = Maps.newHashMapWithExpectedSize(ids.size());
 
-        final Map<String, BokQuestion> cacheBokQuestionsMap = (Map) cacheUtils.multiGet(BOK_CACHE_NAME, ids);
+        final Map<String, BokQuestionVO> cacheBokQuestionsMap = (Map) cacheUtils.multiGet(BOK_QUESTION_CACHE_NAME, ids);
         bokQuestionsMap.putAll(cacheBokQuestionsMap);
 
         List<String> requestIds = Lists.newArrayList(ids);
@@ -78,12 +76,12 @@ public class BokApi {
             Map<String, String> urlParams = ImmutableMap.of("id", requestIds.stream().reduce((a, b) -> a + "," + b).orElse(""));
 
             BokSearchResult result = restRequestUtil.sendGetRequest(tqIdSearchUrl, BokSearchResult.class, urlParams);
-            List<BokQuestion> bokQuestions = result.getEmbedded().getQuestions();
+            List<BokQuestionVO> bokQuestionVOList = result.getEmbedded().getQuestions();
 
-            Map<String, BokQuestion> remoteBokQuestionsMap = bokQuestions.parallelStream().collect(Collectors.toMap(BokQuestion::getId, bokQuestion -> bokQuestion));
+            Map<String, BokQuestionVO> remoteBokQuestionsMap = bokQuestionVOList.parallelStream().collect(Collectors.toMap(BokQuestionVO::getId, bokQuestion -> bokQuestion));
 
             bokQuestionsMap.putAll(remoteBokQuestionsMap);
-            cacheUtils.setAll(BOK_CACHE_NAME, (Map) remoteBokQuestionsMap);
+            cacheUtils.setAll(BOK_QUESTION_CACHE_NAME, (Map) remoteBokQuestionsMap);
         }
 
         return ids.stream()
@@ -91,27 +89,27 @@ public class BokApi {
                 .collect(Collectors.toList());
     }
 
-    public BokQuestion bokFindById(String questionId) {
-        Object cachedBokQuestion = cacheUtils.get(BOK_CACHE_NAME, questionId);
-        if (cachedBokQuestion instanceof BokQuestion) {
-            return (BokQuestion) cachedBokQuestion;
+    public BokQuestionVO bokFindById(String questionId) {
+        Object cachedBokQuestion = cacheUtils.get(BOK_QUESTION_CACHE_NAME, questionId);
+        if (cachedBokQuestion instanceof BokQuestionVO) {
+            return (BokQuestionVO) cachedBokQuestion;
         }
-        BokQuestion bokQuestion = restRequestUtil.sendGetRequest(tqUrl + "/" + questionId, BokQuestion.class, Collections.emptyMap());
-        cacheUtils.set(BOK_CACHE_NAME, bokQuestion.getId(), bokQuestion);
-        return bokQuestion;
+        BokQuestionVO bokQuestionVO = restRequestUtil.sendGetRequest(tqUrl + "/" + questionId, BokQuestionVO.class, Collections.emptyMap());
+        cacheUtils.set(BOK_QUESTION_CACHE_NAME, bokQuestionVO.getId(), bokQuestionVO);
+        return bokQuestionVO;
     }
 
-    public BokQuestion createQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
-        BokQuestion bokQuestion = getQuestion(baseQuestionDTO);
-        bokQuestion.setId(questionId);
-        bokQuestion = restRequestUtil.sendPostRequest(tqUrl, bokQuestion, BokQuestion.class);
-        return bokQuestion;
+    public BokQuestionVO createQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
+        BokQuestionVO bokQuestionVO = getQuestion(baseQuestionDTO);
+        bokQuestionVO.setId(questionId);
+        bokQuestionVO = restRequestUtil.sendPostRequest(tqUrl, bokQuestionVO, BokQuestionVO.class);
+        return bokQuestionVO;
     }
 
-    public BokQuestion modifyQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
-        BokQuestion bokQuestion = getQuestion(baseQuestionDTO);
-        bokQuestion.setId(questionId);
-        restRequestUtil.sendPutRequest(tqUrl + "/" + questionId, bokQuestion);
+    public BokQuestionVO modifyQuestion(String questionId, BaseQuestionDTO baseQuestionDTO) {
+        BokQuestionVO bokQuestionVO = getQuestion(baseQuestionDTO);
+        bokQuestionVO.setId(questionId);
+        restRequestUtil.sendPutRequest(tqUrl + "/" + questionId, bokQuestionVO);
         return bokFindById(questionId);
     }
 
@@ -119,31 +117,31 @@ public class BokApi {
         restRequestUtil.sendDeleteRequest(tqUrl + "/" + questionId);
     }
 
-    private BokQuestion getQuestion(BaseQuestionDTO baseQuestionDTO) {
-        BokQuestion bokQuestion = new BokQuestion();
-        bokQuestion.setType(baseQuestionDTO.getType());
-        bokQuestion.setStem(baseQuestionDTO.getStem());
-        bokQuestion.setKeyPoints(baseQuestionDTO.getKeyPoints());
-        bokQuestion.setTags(baseQuestionDTO.getTags());
-        bokQuestion.setKnowledgeId(baseQuestionDTO.getKnowledgeId());
+    private BokQuestionVO getQuestion(BaseQuestionDTO baseQuestionDTO) {
+        BokQuestionVO bokQuestionVO = new BokQuestionVO();
+        bokQuestionVO.setType(baseQuestionDTO.getType());
+        bokQuestionVO.setStem(baseQuestionDTO.getStem());
+        bokQuestionVO.setKeyPoints(baseQuestionDTO.getKeyPoints());
+        bokQuestionVO.setTags(baseQuestionDTO.getTags());
+        bokQuestionVO.setKnowledgeId(baseQuestionDTO.getKnowledgeId());
 
         final QuestionType questionType = QuestionType.getQuestionType(baseQuestionDTO.getType());
         switch (Objects.requireNonNull(questionType)) {
             case CHOICE:
                 ChoiceQuestionDTO choiceQuestionDTO = (ChoiceQuestionDTO) baseQuestionDTO;
-                bokQuestion.setOptions(choiceQuestionDTO.getOptions());
-                bokQuestion.setAnswer(choiceQuestionDTO.getAnswer());
-                bokQuestion.setAnalysis(choiceQuestionDTO.getAnalysis());
+                bokQuestionVO.setOptions(choiceQuestionDTO.getOptions());
+                bokQuestionVO.setAnswer(choiceQuestionDTO.getAnswer());
+                bokQuestionVO.setAnalysis(choiceQuestionDTO.getAnalysis());
                 break;
             case TRUE_FALSE:
                 TrueOrFalseQuestionDTO trueOrFalseQuestionDTO = (TrueOrFalseQuestionDTO) baseQuestionDTO;
-                bokQuestion.setAnswer(String.valueOf(trueOrFalseQuestionDTO.getAnswer()));
-                bokQuestion.setAnalysis(trueOrFalseQuestionDTO.getAnalysis());
+                bokQuestionVO.setAnswer(String.valueOf(trueOrFalseQuestionDTO.getAnswer()));
+                bokQuestionVO.setAnalysis(trueOrFalseQuestionDTO.getAnalysis());
                 break;
             default:
                 throw HelperException.of(ExceptionType.ERROR, "不支持的题目类型");
         }
-        return bokQuestion;
+        return bokQuestionVO;
     }
 
     @Data
@@ -154,7 +152,7 @@ public class BokApi {
 
         @Data
         private static class Embedded {
-            private List<BokQuestion> questions = Collections.emptyList();
+            private List<BokQuestionVO> questions = Collections.emptyList();
         }
 
         @Data

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

@@ -0,0 +1,27 @@
+package nju.seec.helper.controller;
+
+import nju.seec.helper.api.bok.BokKnowledgeApi;
+import nju.seec.helper.vo.knowledge.BokKnowledgeNodeVO;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * @author cst
+ */
+@RestController
+@RequestMapping("/api/knowledge")
+public class KnowledgeController {
+    private final BokKnowledgeApi bokKnowledgeApi;
+
+    public KnowledgeController(BokKnowledgeApi bokKnowledgeApi) {
+        this.bokKnowledgeApi = bokKnowledgeApi;
+    }
+
+    @GetMapping
+    public List<BokKnowledgeNodeVO> getKnowledgeNodes() {
+        return bokKnowledgeApi.getKnowledgeNodes();
+    }
+}

+ 3 - 4
src/main/java/nju/seec/helper/dto/question/BaseQuestionDTO.java

@@ -8,7 +8,7 @@ import org.hibernate.validator.constraints.Length;
 
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
-import java.util.Set;
+import java.util.List;
 
 /**
  * @author cst
@@ -37,7 +37,6 @@ public abstract class BaseQuestionDTO {
     protected String type;
 
     protected String keyPoints;
-    protected Set<String> tags;
-    protected Set<String> knowledgeId;
-
+    protected List<String> tags;
+    protected List<String> knowledgeId;
 }

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

@@ -3,7 +3,7 @@ package nju.seec.helper.service.impl;
 import nju.seec.helper.service.CodeService;
 import nju.seec.helper.util.Consts;
 import nju.seec.helper.util.MailUtils;
-import nju.seec.helper.util.RedisCacheUtils;
+import nju.seec.helper.util.cache.RedisCacheUtils;
 import nju.seec.helper.util.SmsUtils;
 import org.springframework.stereotype.Service;
 

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

@@ -11,8 +11,8 @@ 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.util.OssObjectUrlUtils;
-import nju.seec.helper.util.OssUtils;
+import nju.seec.helper.util.oss.OssObjectUrlUtils;
+import nju.seec.helper.util.oss.OssUtils;
 import nju.seec.helper.vo.CourseFileVO;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;

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

@@ -1,6 +1,6 @@
 package nju.seec.helper.service.impl;
 
-import nju.seec.helper.api.BokApi;
+import nju.seec.helper.api.bok.BokQuestionApi;
 import nju.seec.helper.aspect.auth.LoginUser;
 import nju.seec.helper.dao.QuestionRecordDAO;
 import nju.seec.helper.dao.QuizDAO;
@@ -14,7 +14,7 @@ import nju.seec.helper.enums.UserType;
 import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.service.QuestionService;
 import nju.seec.helper.vo.question.BaseQuestionVO;
-import nju.seec.helper.vo.question.BokQuestion;
+import nju.seec.helper.vo.question.BokQuestionVO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageImpl;
@@ -38,21 +38,21 @@ public class QuestionServiceImpl implements QuestionService {
     private final UserDAO userDAO;
     private final QuestionRecordDAO questionRecordDAO;
 
-    private final BokApi bokApi;
+    private final BokQuestionApi bokQuestionApi;
 
     @Autowired
     public QuestionServiceImpl(QuizDAO quizDAO
             , UserDAO userDAO
-            , QuestionRecordDAO questionRecordDAO, BokApi bokApi) {
+            , QuestionRecordDAO questionRecordDAO, BokQuestionApi bokQuestionApi) {
         this.quizDAO = quizDAO;
         this.userDAO = userDAO;
         this.questionRecordDAO = questionRecordDAO;
-        this.bokApi = bokApi;
+        this.bokQuestionApi = bokQuestionApi;
     }
 
     @Override
     public Page<BaseQuestionVO> getQuestions(LoginUser user, String stem, Pageable pageable) {
-        return bokApi.bokFindByStemLike(stem, pageable).map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true));
+        return bokQuestionApi.bokFindByStemLike(stem, pageable).map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true));
     }
 
     @Transactional(readOnly = true)
@@ -60,7 +60,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 bokApi.bokFindByIdIn(questionIds)
+        return bokQuestionApi.bokFindByIdIn(questionIds)
                 .stream()
                 .map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, quiz.getState() == QuizState.CLOSED || user.getType() == UserType.TEACHER))
                 .collect(Collectors.toList());
@@ -70,7 +70,7 @@ public class QuestionServiceImpl implements QuestionService {
     @Override
     public List<BaseQuestionVO> getQuestionsByQuiz(Quiz quiz) {
         List<String> questionIds = quiz.getQuestions();
-        return bokApi.bokFindByIdIn(questionIds)
+        return bokQuestionApi.bokFindByIdIn(questionIds)
                 .stream()
                 .map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true))
                 .collect(Collectors.toList());
@@ -78,7 +78,7 @@ public class QuestionServiceImpl implements QuestionService {
 
     @Override
     public BaseQuestionVO getOneQuestion(LoginUser user, String questionId) {
-        return BaseQuestionVO.convertBokQuestionToVO(bokApi.bokFindById(questionId), true);
+        return BaseQuestionVO.convertBokQuestionToVO(bokQuestionApi.bokFindById(questionId), true);
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -90,11 +90,11 @@ public class QuestionServiceImpl implements QuestionService {
             questionId = UUID.randomUUID().toString().replaceAll("-", "");
         } while (questionRecordDAO.existsByQuestionId(questionId));
 
-        BokQuestion bokQuestion = bokApi.createQuestion(questionId, baseQuestionDTO);
+        BokQuestionVO bokQuestionVO = bokQuestionApi.createQuestion(questionId, baseQuestionDTO);
         questionRecordDAO.save(new QuestionRecord()
                 .setTeacher(userDAO.findUserById(user.getId()))
-                .setQuestionId(bokQuestion.getId()));
-        return BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true);
+                .setQuestionId(bokQuestionVO.getId()));
+        return BaseQuestionVO.convertBokQuestionToVO(bokQuestionVO, true);
     }
 
     @Transactional(readOnly = true)
@@ -102,9 +102,9 @@ public class QuestionServiceImpl implements QuestionService {
     public BaseQuestionVO modifyQuestion(LoginUser user, String questionId, BaseQuestionDTO baseQuestionDTO) {
         QuestionRecord questionRecord = questionRecordDAO.findByTeacherAndQuestionId(userDAO.findUserById(user.getId()), questionId)
                 .orElseThrow(() -> HelperException.of(ExceptionType.FORBIDDEN, "您无权修改该问题"));
-        BokQuestion bokQuestion = bokApi.modifyQuestion(questionId, baseQuestionDTO);
+        BokQuestionVO bokQuestionVO = bokQuestionApi.modifyQuestion(questionId, baseQuestionDTO);
         questionRecordDAO.save(questionRecord);
-        return BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true);
+        return BaseQuestionVO.convertBokQuestionToVO(bokQuestionVO, true);
     }
 
     @Transactional(rollbackFor = Exception.class)
@@ -112,7 +112,7 @@ public class QuestionServiceImpl implements QuestionService {
     public void deleteQuestion(LoginUser user, String questionId) {
         QuestionRecord questionRecord = questionRecordDAO.findByTeacherAndQuestionId(userDAO.findUserById(user.getId()), questionId)
                 .orElseThrow(() -> HelperException.of(ExceptionType.FORBIDDEN, "您无权删除该问题"));
-        bokApi.deleteQuestion(questionId);
+        bokQuestionApi.deleteQuestion(questionId);
         questionRecordDAO.delete(questionRecord);
     }
 
@@ -122,7 +122,7 @@ public class QuestionServiceImpl implements QuestionService {
         Page<String> questionIdPage = questionRecordDAO.findQuestionIdsByTeacher(userDAO.findUserById(user.getId()), pageable);
 
         return new PageImpl<>(
-                bokApi.bokFindByIdIn(questionIdPage.getContent())
+                bokQuestionApi.bokFindByIdIn(questionIdPage.getContent())
                         .stream()
                         .map(bokQuestion -> BaseQuestionVO.convertBokQuestionToVO(bokQuestion, true))
                         .collect(Collectors.toList())

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

@@ -21,8 +21,8 @@ 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.util.OssObjectUrlUtils;
-import nju.seec.helper.util.OssUtils;
+import nju.seec.helper.util.oss.OssObjectUrlUtils;
+import nju.seec.helper.util.oss.OssUtils;
 import nju.seec.helper.util.file.FileInfo;
 import nju.seec.helper.util.file.FileUtils;
 import nju.seec.helper.vo.SlideVO;

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

@@ -12,7 +12,7 @@ import nju.seec.helper.exception.HelperException;
 import nju.seec.helper.service.UserService;
 import nju.seec.helper.util.Consts;
 import nju.seec.helper.util.EncryptUtils;
-import nju.seec.helper.util.RedisCacheUtils;
+import nju.seec.helper.util.cache.RedisCacheUtils;
 import nju.seec.helper.vo.UserVO;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;

+ 5 - 5
src/main/java/nju/seec/helper/util/GuavaCacheUtil.java → src/main/java/nju/seec/helper/util/cache/GuavaCacheUtils.java

@@ -1,4 +1,4 @@
-package nju.seec.helper.util;
+package nju.seec.helper.util.cache;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
@@ -17,12 +17,12 @@ import java.util.stream.Collectors;
  * updated by cst
  */
 @Component
-public class GuavaCacheUtil {
+public class GuavaCacheUtils {
     private Cache<Object, Object> cache;
 
-    public GuavaCacheUtil(@Value("${guavaCache.maximumSize}") Long maximumSize,
-                          @Value("${guavaCache.expireAfterAccessInSeconds}") Long expireAfterAccessInSeconds,
-                          @Value("${guavaCache.expireAfterWriteInSeconds}") Long expireAfterWriteInSeconds) {
+    public GuavaCacheUtils(@Value("${guavaCache.maximumSize}") Long maximumSize,
+                           @Value("${guavaCache.expireAfterAccessInSeconds}") Long expireAfterAccessInSeconds,
+                           @Value("${guavaCache.expireAfterWriteInSeconds}") Long expireAfterWriteInSeconds) {
         CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
         builder.maximumSize(maximumSize);
         builder.expireAfterAccess(expireAfterAccessInSeconds, TimeUnit.SECONDS);

+ 1 - 1
src/main/java/nju/seec/helper/util/RedisCacheUtils.java → src/main/java/nju/seec/helper/util/cache/RedisCacheUtils.java

@@ -1,4 +1,4 @@
-package nju.seec.helper.util;
+package nju.seec.helper.util.cache;
 
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Component;

+ 6 - 6
src/main/java/nju/seec/helper/util/OssObjectUrlUtils.java → src/main/java/nju/seec/helper/util/oss/OssObjectUrlUtils.java

@@ -1,8 +1,7 @@
-package nju.seec.helper.util;
+package nju.seec.helper.util.oss;
 
 import nju.seec.helper.util.Consts;
-import nju.seec.helper.util.OssUtils;
-import nju.seec.helper.util.RedisCacheUtils;
+import nju.seec.helper.util.cache.RedisCacheUtils;
 import org.springframework.stereotype.Component;
 
 import java.util.concurrent.TimeUnit;
@@ -24,10 +23,11 @@ public class OssObjectUrlUtils {
 
     public String getUrl(String objectName) {
         String url = cacheUtils.get(OSS_OBJECT_URL_NAME, objectName);
-        if (url == null) {
-            url = ossUtils.getUrl(objectName, OSS_OBJECT_URL_LIVING_SECONDS);
-            cacheUtils.set(OSS_OBJECT_URL_NAME, objectName, url, OSS_OBJECT_URL_LIVING_SECONDS, TimeUnit.SECONDS);
+        if (url != null) {
+            return url;
         }
+        url = ossUtils.getUrl(objectName, OSS_OBJECT_URL_LIVING_SECONDS);
+        cacheUtils.set(OSS_OBJECT_URL_NAME, objectName, url, OSS_OBJECT_URL_LIVING_SECONDS, TimeUnit.SECONDS);
         return url;
     }
 }

+ 1 - 1
src/main/java/nju/seec/helper/util/OssUtils.java → src/main/java/nju/seec/helper/util/oss/OssUtils.java

@@ -1,4 +1,4 @@
-package nju.seec.helper.util;
+package nju.seec.helper.util.oss;
 
 import com.aliyun.oss.ClientException;
 import com.aliyun.oss.OSS;

+ 16 - 0
src/main/java/nju/seec/helper/vo/knowledge/BokKnowledgeNodeVO.java

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

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

@@ -5,7 +5,7 @@ import lombok.NonNull;
 import nju.seec.helper.enums.QuestionType;
 
 import java.util.Date;
-import java.util.Set;
+import java.util.List;
 
 /**
  * @author XuShengTao
@@ -19,28 +19,28 @@ public abstract class BaseQuestionVO {
     protected String stem;
     protected String analysis;
     protected String keyPoints;
-    protected Set<String> tags;
-    protected Set<String> knowledgeId;
+    protected List<String> tags;
+    protected List<String> knowledgeId;
     private Date lastModified;
 
-    public static BaseQuestionVO convertBokQuestionToVO(@NonNull BokQuestion bokQuestion, boolean withAnswer) {
-        switch (bokQuestion.getType()) {
+    public static BaseQuestionVO convertBokQuestionToVO(@NonNull BokQuestionVO bokQuestionVO, boolean withAnswer) {
+        switch (bokQuestionVO.getType()) {
             case "choice":
-                return new ChoiceQuestionVO(bokQuestion, withAnswer);
+                return new ChoiceQuestionVO(bokQuestionVO, withAnswer);
             case "true_false":
-                return new TrueOrFalseQuestionVO(bokQuestion, withAnswer);
+                return new TrueOrFalseQuestionVO(bokQuestionVO, withAnswer);
             default:
                 return null;
         }
     }
 
-    protected BaseQuestionVO(BokQuestion bokQuestion) {
-        this.id = bokQuestion.getId();
-        this.stem = bokQuestion.getStem();
-        this.keyPoints = bokQuestion.getKeyPoints();
-        this.tags = bokQuestion.getTags();
-        this.knowledgeId = bokQuestion.getKnowledgeId();
-        this.lastModified = bokQuestion.getLastModified();
+    protected BaseQuestionVO(BokQuestionVO bokQuestionVO) {
+        this.id = bokQuestionVO.getId();
+        this.stem = bokQuestionVO.getStem();
+        this.keyPoints = bokQuestionVO.getKeyPoints();
+        this.tags = bokQuestionVO.getTags();
+        this.knowledgeId = bokQuestionVO.getKnowledgeId();
+        this.lastModified = bokQuestionVO.getLastModified();
     }
 
     /**

+ 4 - 4
src/main/java/nju/seec/helper/vo/question/BokQuestion.java → src/main/java/nju/seec/helper/vo/question/BokQuestionVO.java

@@ -5,8 +5,8 @@ import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 
 import java.util.Date;
+import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * @author sheen
@@ -14,7 +14,7 @@ import java.util.Set;
  * updated by cst
  */
 @Data
-public class BokQuestion {
+public class BokQuestionVO {
     private String id;
     private String type;
     private String stem;
@@ -23,8 +23,8 @@ public class BokQuestion {
     @JsonProperty(value = "key_points")
     private String keyPoints;
     private String analysis;
-    private Set<String> tags;
-    private Set<String> knowledgeId;
+    private List<String> tags;
+    private List<String> knowledgeId;
     @JsonFormat(pattern = "yyyy-MM-dd hh:mm:ss")
     private Date lastModified;
 }

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

@@ -18,14 +18,14 @@ public class ChoiceQuestionVO extends BaseQuestionVO {
     private Map<String, String> options;
     private String answer;
 
-    public ChoiceQuestionVO(@NonNull BokQuestion bokQuestion, boolean withAnswer) {
-        super(bokQuestion);
+    public ChoiceQuestionVO(@NonNull BokQuestionVO bokQuestionVO, boolean withAnswer) {
+        super(bokQuestionVO);
         this.type = QuestionType.CHOICE;
-        this.options = bokQuestion.getOptions();
+        this.options = bokQuestionVO.getOptions();
 
         if (withAnswer) {
-            this.answer = bokQuestion.getAnswer();
-            this.analysis = bokQuestion.getAnalysis();
+            this.answer = bokQuestionVO.getAnswer();
+            this.analysis = bokQuestionVO.getAnalysis();
         }
     }
 

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

@@ -21,13 +21,13 @@ public class TrueOrFalseQuestionVO extends BaseQuestionVO {
         return this.answer.equals(Boolean.valueOf(String.valueOf(answer)));
     }
 
-    public TrueOrFalseQuestionVO(@NonNull BokQuestion bokQuestion, boolean withAnswer) {
-        super(bokQuestion);
+    public TrueOrFalseQuestionVO(@NonNull BokQuestionVO bokQuestionVO, boolean withAnswer) {
+        super(bokQuestionVO);
         this.type = QuestionType.TRUE_FALSE;
 
         if (withAnswer) {
-            this.answer = Boolean.valueOf(bokQuestion.getAnswer());
-            this.analysis = bokQuestion.getAnalysis();
+            this.answer = Boolean.valueOf(bokQuestionVO.getAnswer());
+            this.analysis = bokQuestionVO.getAnalysis();
         }
     }
 }

+ 2 - 0
src/main/resources/application-deploy.yml

@@ -56,6 +56,8 @@ bok:
   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
 guavaCache:
   maximumSize: 1000
   expireAfterAccessInSeconds: 0

+ 2 - 0
src/main/resources/application-dev.yml

@@ -56,6 +56,8 @@ bok:
   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
 guavaCache:
   maximumSize: 1000
   expireAfterAccessInSeconds: 0

+ 3 - 3
src/main/resources/application.yml

@@ -1,3 +1,3 @@
-#spring:
-#  profiles:
-#    active: dev
+spring:
+  profiles:
+    active: dev