qilikuacha il y a 3 ans
Parent
commit
39b37db381
28 fichiers modifiés avec 193 ajouts et 53 suppressions
  1. BIN
      APITest/__pycache__/category_test.cpython-35.pyc
  2. BIN
      APITest/__pycache__/category_test.cpython-38.pyc
  3. BIN
      APITest/__pycache__/constants.cpython-35.pyc
  4. BIN
      APITest/__pycache__/constants.cpython-38.pyc
  5. BIN
      APITest/__pycache__/exam_test.cpython-35.pyc
  6. BIN
      APITest/__pycache__/exam_test.cpython-38.pyc
  7. BIN
      APITest/__pycache__/group_test.cpython-35.pyc
  8. BIN
      APITest/__pycache__/group_test.cpython-38.pyc
  9. BIN
      APITest/__pycache__/learningmaterial_test.cpython-35.pyc
  10. BIN
      APITest/__pycache__/learningmaterial_test.cpython-38.pyc
  11. BIN
      APITest/__pycache__/user_test.cpython-35.pyc
  12. BIN
      APITest/__pycache__/user_test.cpython-38.pyc
  13. 1 1
      APITest/constants.py
  14. 75 9
      APITest/setup_db.py
  15. 7 5
      APITest/user_test.py
  16. 2 16
      jtxt.iml
  17. 1 1
      src/main/java/com/jtxt/demo/config/MongoConfig.java
  18. 13 0
      src/main/java/com/jtxt/demo/controller/CategoryController.java
  19. 27 4
      src/main/java/com/jtxt/demo/controller/ExamController.java
  20. 21 3
      src/main/java/com/jtxt/demo/controller/LearningMaterialController.java
  21. 9 0
      src/main/java/com/jtxt/demo/controller/TagController.java
  22. 4 0
      src/main/java/com/jtxt/demo/controller/UserController.java
  23. 4 0
      src/main/java/com/jtxt/demo/model/LearningMaterial.java
  24. 1 1
      src/main/java/com/jtxt/demo/repository/ReadHistoryRepository.java
  25. 20 5
      src/main/java/com/jtxt/demo/service/ExamServiceImpl.java
  26. 1 1
      src/main/java/com/jtxt/demo/service/LearningMaterialService.java
  27. 7 6
      src/main/java/com/jtxt/demo/service/LearningMaterialServiceImpl.java
  28. 0 1
      src/main/resources/application.properties

BIN
APITest/__pycache__/category_test.cpython-35.pyc


BIN
APITest/__pycache__/category_test.cpython-38.pyc


BIN
APITest/__pycache__/constants.cpython-35.pyc


BIN
APITest/__pycache__/constants.cpython-38.pyc


BIN
APITest/__pycache__/exam_test.cpython-35.pyc


BIN
APITest/__pycache__/exam_test.cpython-38.pyc


BIN
APITest/__pycache__/group_test.cpython-35.pyc


BIN
APITest/__pycache__/group_test.cpython-38.pyc


BIN
APITest/__pycache__/learningmaterial_test.cpython-35.pyc


BIN
APITest/__pycache__/learningmaterial_test.cpython-38.pyc


BIN
APITest/__pycache__/user_test.cpython-35.pyc


BIN
APITest/__pycache__/user_test.cpython-38.pyc


+ 1 - 1
APITest/constants.py

@@ -1,2 +1,2 @@
-HOST_IP = 'localhost'
+HOST_IP = '8.141.68.219'
 WEBSITE_PREFIX = 'http://%s:8080' % (HOST_IP)

+ 75 - 9
APITest/setup_db.py

@@ -43,7 +43,7 @@ def _text(resp):
 def add_dummy_users(namePrefix = 'testuser-', password = 'test', number = 10):
     groups = add_groups()
     users = []
-    nicknames = ['小强', '小张', '小李', '大王']
+    nicknames = ['小强', '小张', '小李', '大王']
     firstNames = ['一', '二', '三', '四', '五']
     lastNames = ['张', '王', '李', '杜', '靳']
     for i in range(number):
@@ -107,7 +107,8 @@ def create_exams(namePrefix='测试考试-', number=2, tags=[]):
             'name': namePrefix + _random_string(3),
             'description': '可以回家做',
             'duration': random.randint(0, 863) * 100, # seconds
-            'tags': tags
+            'tags': tags,
+            'startTime': '2021-05-01T10:00:00'
         }
         resp = create_exam(new_exam)
         exams.append(_text(resp)['id'])
@@ -123,7 +124,7 @@ def create_questions(namePrefix='qtest-', number=10, from_file=False):
     if from_file:
         files = os.listdir('./demo-questions/')
         for file_name in files:
-            with open('./demo-questions/' + file_name, 'r') as read_obj:
+            with open('./demo-questions/' + file_name, encoding="UTF-8") as read_obj:
                 print('loading ' + file_name + ' to db')
                 exam_tag = file_name.split('-')[1]
                 exam_prefix = file_name.split('-')[0]
@@ -150,7 +151,14 @@ def create_questions(namePrefix='qtest-', number=10, from_file=False):
                     level = row[10];
                     tags = []
                     if len(row[11]) > 0:
-                        tags.append(row[11])
+                        if row[11] == '线路工':
+                            tags.append('XianLuGong')
+                        elif row[11] == '桥隧工':
+                            tags.append('QiaoSuiGong')
+                        elif row[11] == '大型线路机械司机':
+                            tags.append('DaXingXianLuJiXieSiJi')
+                        elif row[11] == '测量工':
+                            tags.append('CeLiangGong')
                     if len(content) == 0 or len(qType) == 0 or len(answers) == 0 or len(finalAnswer) == 0:
                         print('Skip due to required info missing')
                         continue
@@ -164,6 +172,7 @@ def create_questions(namePrefix='qtest-', number=10, from_file=False):
                         'questionLevel': level,
                         'tags': tags,
                         'answerAnalysis': answerAnalysis,
+                        
                     }
                     resp = create_question(question)
                     random_exam_id = exams[random.randint(0, len(exams)-1)]
@@ -171,7 +180,7 @@ def create_questions(namePrefix='qtest-', number=10, from_file=False):
                         'questionId': _text(resp)['id']
                     }
                     # if random number equals to magic number, then add tag 今日必练
-                    if random.randint(0, 10) == 3:
+                    if random.randint(0, 100) == 3:
                         add_tag(datetime.today().strftime('%Y%m%d'), questionId=_text(resp)['id'])
                     # add newly created question to a random exam
                     add_question_to_exam(random_exam_id, [exam_to_question])
@@ -235,13 +244,34 @@ def create_categories(namePrefix= 'testCategory-', number=3):
     print ('created ' + str(len(categories)) + ' categories: ' + ','.join(categories))
     return categories
 
+def create_2_levels_categories(root_level, second_levels):
+    resp = create_category(root_level)
+    parent_id = _text(resp)['id']
+    children = []
+    for category_name in second_levels:
+        child = create_category(category_name)
+        child_id = _text(child)['id']
+        update_category(child_id, {
+            'parentId': parent_id
+        })
+        children.append(child_id)
+    return children
+
+
+
+
 def create_specific_categories():
     categories = []
     resp = show_root_categories()
     if len(_text(resp)) == 0:
-        for name in ['历史', '科普', '知识']: #所有类别
-            resp = create_category(name)
-            categories.append(_text(resp)['id'])
+        categories.extend(create_2_levels_categories('思政', ['党规党纪', '思想理论', '党史故事']))
+        categories.extend(create_2_levels_categories('安全', ['劳动安全', '作业安全', '事故案例']))
+        categories.extend(create_2_levels_categories('理论', ['基础理论', '专业理论']))
+        categories.extend(create_2_levels_categories('实作', ['作业指导书', '作业技巧', '应急处置']))
+        categories.extend(create_2_levels_categories('教材', ['文字', '音像', '课件']))
+        categories.extend(create_2_levels_categories('法纪', ['国家法律', '法纪法规', '交通规则']))
+        categories.extend(create_2_levels_categories('健康', ['健康知识', '健康养生', '心理辅导']))
+        categories.extend(create_2_levels_categories('集萃', ['旅游', '摄影','诗词', '名篇']))
     else:
         print('Skip creating specific categories')
         root_categories = _text(resp)
@@ -250,7 +280,7 @@ def create_specific_categories():
     return categories
 
 def read_material_from_file(file_name):
-    file = open('./demo-materials/' + file_name, 'r')
+    file = open('./demo-materials/' + file_name, encoding="UTF-8")
     file_lines = file.readlines()
     count = 0
     content = ''
@@ -347,11 +377,47 @@ def get_tag(tag):
     url = WEBSITE_PREFIX + '/tags/' + tag
     return requests.get(url)
 
+def delete_all_exams():
+    url = WEBSITE_PREFIX + '/admin/exams'
+    return requests.delete(url)
+
+def delete_all_questions():
+    url = WEBSITE_PREFIX + '/admin/questions'
+    return requests.delete(url)
+
+def delete_all_categories():
+    url = WEBSITE_PREFIX + '/admin/categories'
+    return requests.delete(url)
+
+def delete_all_tags():
+    url = WEBSITE_PREFIX + '/admin/tags'
+    return requests.delete(url)
+
+def delete_all_materials():
+    url = WEBSITE_PREFIX + '/admin/materials'
+    return requests.delete(url)
+
+def delete_all_comments():
+    url = WEBSITE_PREFIX + '/admin/comments'
+    return requests.delete(url)
+
 if override:
     all_users = json.loads(get_all_users().text)
     for user in all_users:
         delete_user(user['userName'])
     print('deleted all users')
+    delete_all_exams()
+    print('deleted all exams')
+    delete_all_questions()
+    print('deleted all questions')
+    delete_all_categories()
+    print('deleted all categories')
+    delete_all_tags()
+    print('deleted all tags')
+    delete_all_materials()
+    print('deleted all materials')
+    delete_all_comments()
+    print('deleted all comments')
 if want_user:
     add_dummy_users()
 else:

+ 7 - 5
APITest/user_test.py

@@ -6,6 +6,8 @@ OK = 200
 CREATED = 201
 CONFLICT = 409
 
+from constants import WEBSITE_PREFIX
+
 def test_multiple_user_apis():
     prev_count = len(json.loads(get_all_users().text))
     resp = register_user('pytest-user', 'fake-password')
@@ -38,11 +40,11 @@ def test_multiple_user_apis():
     delete_user(resp['userName'])
 
 def get_user(userName):
-    url = 'http://localhost:8080/user/' + userName
+    url = WEBSITE_PREFIX + '/user/' + userName
     return requests.get(url)
 
 def register_user(userName, password):
-    url = 'http://localhost:8080/user/register'
+    url = WEBSITE_PREFIX + '/user/register'
     data = {
         'userName': userName,
         'password': password
@@ -50,19 +52,19 @@ def register_user(userName, password):
     return requests.post(url, json=data)
 
 def get_all_users():
-    url = 'http://localhost:8080/admin/users'
+    url = WEBSITE_PREFIX + '/admin/users'
     resp = requests.get(url)
     return resp
 
 def delete_user(userName):
-    url = 'http://localhost:8080/admin/users'
+    url = WEBSITE_PREFIX + '/admin/users'
     data = {
         'userName': userName
     }
     return requests.delete(url, json=data)
 
 def update_user(userName, updatedData):
-    url = 'http://localhost:8080/user/' + userName
+    url = WEBSITE_PREFIX + '/user/' + userName
     return requests.put(url, json=updatedData)
 
 

+ 2 - 16
jtxt.iml

@@ -1,20 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" version="4">
-  <component name="FacetManager">
-    <facet type="Spring" name="Spring">
-      <configuration />
-    </facet>
-    <facet type="web" name="Web">
-      <configuration>
-        <webroots />
-        <sourceRoots>
-          <root url="file://$MODULE_DIR$/src/main/java" />
-          <root url="file://$MODULE_DIR$/src/main/resources" />
-        </sourceRoots>
-      </configuration>
-    </facet>
-  </component>
-  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_11">
+<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
     <output url="file://$MODULE_DIR$/target/classes" />
     <output-test url="file://$MODULE_DIR$/target/test-classes" />
     <content url="file://$MODULE_DIR$">

+ 1 - 1
src/main/java/com/jtxt/demo/config/MongoConfig.java

@@ -22,7 +22,7 @@ public class MongoConfig extends AbstractMongoClientConfiguration {
 
     @Override
     public MongoClient mongoClient() {
-        ConnectionString connectionString = new ConnectionString("mongodb://jtxt-admin:jtxt-admin@120.77.221.199:27017/?authSource=jtxt-dev");
+        ConnectionString connectionString = new ConnectionString("mongodb://jtxt-admin:jtxt-admin@localhost:27017/?authSource=jtxt-dev");
         MongoClientSettings mongoClientSettings = MongoClientSettings.builder()
                 .applyConnectionString(connectionString)
                 .build();

+ 13 - 0
src/main/java/com/jtxt/demo/controller/CategoryController.java

@@ -4,6 +4,8 @@ import com.jtxt.demo.model.LearningMaterial;
 import com.jtxt.demo.model.MaterialCategory;
 import com.jtxt.demo.model.Question;
 import com.jtxt.demo.model.QuestionCategory;
+import com.jtxt.demo.repository.CategoryRepository;
+import com.jtxt.demo.repository.CategoryToMaterialRepository;
 import com.jtxt.demo.service.CategoryService;
 import com.jtxt.demo.service.QuestionCategoryService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -19,6 +21,10 @@ public class CategoryController {
     private CategoryService categoryService;
     @Autowired
     private QuestionCategoryService questionCategoryService;
+    @Autowired
+    private CategoryToMaterialRepository categoryToMaterialRepository;
+    @Autowired
+    private CategoryRepository categoryRepository;
 
     @GetMapping("/categories")
     public ResponseEntity<?> showCategoryRootLevel() {
@@ -92,6 +98,13 @@ public class CategoryController {
         boolean rst = categoryService.deleteCategory(categoryInDb);
         return new ResponseEntity<>(rst ? HttpStatus.OK : HttpStatus.NOT_ACCEPTABLE);
     }
+    // Note this is dangerous
+    @DeleteMapping("/admin/categories")
+    public ResponseEntity<?> deleteAllCategories() {
+        categoryToMaterialRepository.deleteAll();
+        categoryRepository.deleteAll();
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
 
     @DeleteMapping("/admin/q-categories/{categoryId}")
     public ResponseEntity<?> deleteQuestionCategory(@PathVariable String categoryId) {

+ 27 - 4
src/main/java/com/jtxt/demo/controller/ExamController.java

@@ -1,6 +1,9 @@
 package com.jtxt.demo.controller;
 
 import com.jtxt.demo.model.*;
+import com.jtxt.demo.repository.ExamRepository;
+import com.jtxt.demo.repository.ExamToQuestionRepository;
+import com.jtxt.demo.repository.QuestionRepository;
 import com.jtxt.demo.service.EventService;
 import com.jtxt.demo.service.ExamService;
 import com.jtxt.demo.service.PointsHistoryService;
@@ -11,6 +14,7 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
 
+import java.io.UnsupportedEncodingException;
 import java.time.LocalDateTime;
 import java.time.temporal.WeekFields;
 import java.util.List;
@@ -27,7 +31,14 @@ public class ExamController {
     @Autowired
     private PointsHistoryService pointsHistoryService;
     @Autowired
+    private ExamRepository examRepository;
+    @Autowired
+    private QuestionRepository questionRepository;
+    @Autowired
     private EventService eventService;
+    @Autowired
+    private ExamToQuestionRepository examToQuestionRepository;
+
     private static final String DAILY_QUESTIONS = "daily-questions";
     private static final String WEEKLY_QUESTIONS = "weekly-questions";
     private static final int DAILY_QUESTIONS_NUM = 5;
@@ -57,6 +68,19 @@ public class ExamController {
         updatedExam.setId(examId);
         return new ResponseEntity<>(examService.editExam(updatedExam), HttpStatus.OK);
     }
+    // Note this is dangerous
+    @DeleteMapping("/admin/questions")
+    public ResponseEntity<?> deleteAllQuestions() {
+        questionRepository.deleteAll();
+        examToQuestionRepository.deleteAll();
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
+    // Note this is dangerous
+    @DeleteMapping("/admin/exams")
+    public ResponseEntity<?> deleteAllExams() {
+        examRepository.deleteAll();
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
     @DeleteMapping("/exams/{examId}")
     public ResponseEntity<?> deleteExam(@PathVariable String examId) {
         Exam exam = examService.getExamById(examId);
@@ -67,7 +91,7 @@ public class ExamController {
     }
     // 根据工种不同,只返回该工种的问题
     @PostMapping("/exams/{examId}/start")
-    public ResponseEntity<?> startExam(@PathVariable String examId, @RequestBody User user, @RequestParam(value = "type", required = false) String engineerType) {
+    public ResponseEntity<?> startExam(@PathVariable String examId, @RequestBody User user, @RequestParam(value = "type", required = true) String engineerType) {
         if (examId.equals(DAILY_QUESTIONS)) {
             return new ResponseEntity<>(examService.randomlyPickQuestionsByEngineerType(DAILY_QUESTIONS_NUM, engineerType, false), HttpStatus.OK);
         }
@@ -79,7 +103,7 @@ public class ExamController {
             return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
         // 早于考试时间
-        if (LocalDateTime.now(CHINA_ZONE).isBefore(exam.getStartTime())) {
+        if (exam.getStartTime() != null && LocalDateTime.now(CHINA_ZONE).isBefore(exam.getStartTime())) {
             return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
         }
         List<String> questionList = examService.startExam(exam, user);
@@ -126,7 +150,7 @@ public class ExamController {
             return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
         examHistory.setExamId(examId);
-        return new ResponseEntity<>(examService.endExam(examHistory), HttpStatus.OK);
+        return new ResponseEntity<>(examService.endExam(examHistory) == null ? HttpStatus.CONFLICT : HttpStatus.OK);
     }
     @GetMapping("/exams")
     public ResponseEntity<?> showAllExams(@RequestBody(required = false) User user) {
@@ -191,5 +215,4 @@ public class ExamController {
             return new ResponseEntity<>(HttpStatus.NOT_ACCEPTABLE);
         }
     }
-
 }

+ 21 - 3
src/main/java/com/jtxt/demo/controller/LearningMaterialController.java

@@ -1,6 +1,8 @@
 package com.jtxt.demo.controller;
 
 import com.jtxt.demo.model.*;
+import com.jtxt.demo.repository.CommentRepository;
+import com.jtxt.demo.repository.LearningMaterialRepository;
 import com.jtxt.demo.service.TagToResourcesService;
 import com.jtxt.demo.service.LearningMaterialService;
 import com.jtxt.demo.service.QuestionService;
@@ -12,7 +14,11 @@ import org.springframework.web.bind.annotation.*;
 @RestController
 public class LearningMaterialController {
     @Autowired
-    LearningMaterialService materialService;
+    private LearningMaterialService materialService;
+    @Autowired
+    private LearningMaterialRepository learningMaterialRepository;
+    @Autowired
+    private CommentRepository commentRepository;
 
 
     @GetMapping("/materials/{materialId}")
@@ -43,8 +49,8 @@ public class LearningMaterialController {
         if (material == null) {
             return new ResponseEntity<>(HttpStatus.NOT_FOUND);
         }
-        materialService.readMaterial(material, user);
-        return new ResponseEntity<>(HttpStatus.OK);
+        boolean status = materialService.readMaterial(material, user);
+        return new ResponseEntity<>(status ? HttpStatus.OK : HttpStatus.NOT_ACCEPTABLE);
     }
     @GetMapping("/materials/{materialId}/read")
     public ResponseEntity<?> isMaterialReable(@PathVariable String materialId, @RequestParam("user") String userName) {
@@ -111,4 +117,16 @@ public class LearningMaterialController {
         return new ResponseEntity<>(rst ? HttpStatus.OK : HttpStatus.NOT_ACCEPTABLE);
     }
 
+    @DeleteMapping("/admin/materials")
+    public ResponseEntity<?> deleteAllMaterials() {
+        learningMaterialRepository.deleteAll();
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
+
+    @DeleteMapping("/admin/comments")
+    public ResponseEntity<?> deleteAllComments() {
+        commentRepository.deleteAll();
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
+
 }

+ 9 - 0
src/main/java/com/jtxt/demo/controller/TagController.java

@@ -4,6 +4,7 @@ import com.jtxt.demo.model.Exam;
 import com.jtxt.demo.model.LearningMaterial;
 import com.jtxt.demo.model.Question;
 import com.jtxt.demo.model.TagToResources;
+import com.jtxt.demo.repository.TagToResourcesRepository;
 import com.jtxt.demo.service.ExamService;
 import com.jtxt.demo.service.LearningMaterialService;
 import com.jtxt.demo.service.QuestionService;
@@ -23,6 +24,8 @@ public class TagController {
     LearningMaterialService materialService;
     @Autowired
     ExamService examService;
+    @Autowired
+    TagToResourcesRepository tagToResourcesRepository;
 
     @GetMapping("/tags/{tag}")
     public ResponseEntity<?> getTag(@PathVariable String tag) {
@@ -81,4 +84,10 @@ public class TagController {
         }
         return new ResponseEntity<>(HttpStatus.OK);
     }
+
+    @DeleteMapping("/admin/tags")
+    public ResponseEntity<?> removeAllTags() {
+        tagToResourcesRepository.deleteAll();
+        return new ResponseEntity<>(HttpStatus.OK);
+    }
 }

+ 4 - 0
src/main/java/com/jtxt/demo/controller/UserController.java

@@ -1,6 +1,7 @@
 package com.jtxt.demo.controller;
 
 import com.jtxt.demo.jwt.JwtTokenProvider;
+import com.jtxt.demo.model.Group;
 import com.jtxt.demo.model.LearningMaterial;
 import com.jtxt.demo.model.User;
 import com.jtxt.demo.service.GroupService;
@@ -17,6 +18,7 @@ import java.security.Principal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
+import java.util.List;
 
 import static com.jtxt.demo.util.Utils.CHINA_ZONE;
 
@@ -38,6 +40,8 @@ public class UserController {
     // 删除某个用户
     @DeleteMapping("/admin/users")
     public ResponseEntity<?> deleteUser(@RequestBody User user){
+        List<Group> groups = groupService.findAllGroupsByUserName(user.getUserName());
+        groups.forEach(g -> groupService.deleteGroup(g));
         userService.deleteUser(user.getUserName());
         return new ResponseEntity<>(HttpStatus.OK);
     }

+ 4 - 0
src/main/java/com/jtxt/demo/model/LearningMaterial.java

@@ -7,6 +7,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
 
 import java.time.LocalDateTime;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @Document
@@ -30,6 +31,9 @@ public class LearningMaterial {
     private List<String> tags;
 
     public List<String> getTags() {
+        if (tags == null) {
+            tags = new ArrayList<>();
+        }
         return tags;
     }
 

+ 1 - 1
src/main/java/com/jtxt/demo/repository/ReadHistoryRepository.java

@@ -6,5 +6,5 @@ import org.springframework.data.mongodb.repository.MongoRepository;
 import java.util.Optional;
 
 public interface ReadHistoryRepository extends MongoRepository<ReadHistory, String> {
-    Optional<ReadHistory> findByMaterialIdAndUserId(String materialId, String userId);
+    ReadHistory findOneByMaterialIdAndUserId(String materialId, String userId);
 }

+ 20 - 5
src/main/java/com/jtxt/demo/service/ExamServiceImpl.java

@@ -137,15 +137,28 @@ public class ExamServiceImpl implements ExamService {
 
     public List<String> randomlyPickQuestionsByEngineerType(int number, String engineerType, boolean isWeekly) {
         // 判断用户是否已经完成今日必读,否则要先选中今日必读
-        List<String> dateResources = tagToResourcesService
-                .findResourcesByTag(isWeekly ? Utils.getWeekTag(): Utils.getTodayTag())
-                .getQuestions();
-        List<String> typeResources = tagToResourcesService.findResourcesByTag(engineerType).getQuestions();
+        List<String> dateResources = new ArrayList<>();
+        TagToResources resources = tagToResourcesService
+                .findResourcesByTag(isWeekly ? Utils.getWeekTag(): Utils.getTodayTag());
+        if (resources != null) {
+            dateResources = resources.getQuestions();
+        }
+        List<String> typeResources = new ArrayList<>();
+        if (engineerType != null) {
+            TagToResources resources2 = tagToResourcesService.findResourcesByTag(engineerType);
+            if (resources2 != null) {
+                typeResources = resources2.getQuestions();
+            }
+        }
         List<String> questionList = dateResources.stream().filter(typeResources::contains).collect(Collectors.toList());
         if (isWeekly) {
             // 每周必答 只选中符合条件的问题,不再随机补充。
             return questionList;
         }
+        if (typeResources.size() < 1) {
+            // No resources of this engineer type
+            return questionList;
+        }
         while (questionList.size() < number) {
             // 需要再随机选出问题补足number个问题
             String randomId = typeResources.get((int) (Math.random() * typeResources.size()));
@@ -177,7 +190,9 @@ public class ExamServiceImpl implements ExamService {
     @Override
     public ExamHistory endExam(ExamHistory examHistory) {
         ExamHistory examHistoryInDb = examHistoryRepository.findByUserIdAndExamId(examHistory.getUserId(), examHistory.getExamId());
-
+        if (examHistoryInDb == null) {
+            return null;
+        }
         examHistoryInDb.setEndTime(LocalDateTime.now(CHINA_ZONE));
         examHistoryInDb.setUserAnswers(examHistory.getUserAnswers());
         if (examHistory.getPoints() == 0) {

+ 1 - 1
src/main/java/com/jtxt/demo/service/LearningMaterialService.java

@@ -13,7 +13,7 @@ public interface LearningMaterialService {
     boolean deleteMaterial(LearningMaterial material);
     LearningMaterial editMaterial(LearningMaterial updatedMaterial);
     void likeMaterial(LearningMaterial material, User user, boolean isLike);
-    void readMaterial(LearningMaterial material, User user);
+    boolean readMaterial(LearningMaterial material, User user);
     boolean isMaterialReadable(LearningMaterial material, String userName);
     boolean isMaterialLikeable(LearningMaterial material, String userName);
     void commentMaterial(Comment comment);

+ 7 - 6
src/main/java/com/jtxt/demo/service/LearningMaterialServiceImpl.java

@@ -100,10 +100,10 @@ public class LearningMaterialServiceImpl implements LearningMaterialService {
 
     @Override
     @Transactional
-    public void readMaterial(LearningMaterial material, User user) {
+    public boolean readMaterial(LearningMaterial material, User user) {
         // 判断用户是否已经读过该文章
-        if (readHistoryRepository.findByMaterialIdAndUserId(material.getId(), user.getUserName()).isPresent()) {
-            return;
+        if (!isMaterialReadable(material, user.getUserName())) {
+            return false;
         }
         material.setReaderCount(material.getReaderCount() + 1);
         repository.save(material);
@@ -118,12 +118,13 @@ public class LearningMaterialServiceImpl implements LearningMaterialService {
             // 非必学内容
             eventService.handleEvent(user.getUserName(), Event.LEARNING_COMPLETE);
         }
+        return true;
     }
     @Override
     public boolean isMaterialReadable(LearningMaterial material, String userName) {
-        Optional<ReadHistory> readHistory = readHistoryRepository
-                .findByMaterialIdAndUserId(material.getId(), userName);
-        return readHistory.isEmpty();
+        ReadHistory readHistory = readHistoryRepository
+                .findOneByMaterialIdAndUserId(material.getId(), userName);
+        return readHistory == null;
     }
 
     @Override

+ 0 - 1
src/main/resources/application.properties

@@ -1,4 +1,3 @@
-server.port=7000
 spring.data.mongodb.host=localhost
 spring.data.mongodb.database=jtxt-dev
 spring.data.mongodb.port=27017