Quellcode durchsuchen

Merge branch 'dev' into 'master'

Dev

See merge request tuosi-crowd-test-service/tuosi-backend!7
郭超 vor 3 Jahren
Ursprung
Commit
0c94458f81
100 geänderte Dateien mit 2851 neuen und 45 gelöschten Zeilen
  1. 1 0
      .idea/encodings.xml
  2. 2 0
      .idea/tuosi-backend.iml
  3. 124 0
      .idea/uiDesigner.xml
  4. 0 0
      core/src/main/java/com/mooctest/crowd/domain/controller/TestUserController.java
  5. 4 0
      core/src/main/java/com/mooctest/crowd/domain/dao/CrowdTestTaskDao.java
  6. 21 0
      core/src/main/java/com/mooctest/crowd/domain/dao/DefectDao.java
  7. 7 0
      core/src/main/java/com/mooctest/crowd/domain/dao/ExceptionLogDao.java
  8. 4 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TaskToUserDao.java
  9. 18 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestCaseCodeDao.java
  10. 27 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestCaseDao.java
  11. 16 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestEnvDao.java
  12. 16 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestToolDao.java
  13. 2 0
      core/src/main/java/com/mooctest/crowd/domain/dao/UserDao.java
  14. 5 3
      core/src/main/java/com/mooctest/crowd/domain/domainobject/CrowdTestTask.java
  15. 56 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/Defect.java
  16. 14 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/ExceptionLog.java
  17. 72 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCase.java
  18. 10 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCaseCode.java
  19. 18 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCaseExamRecord.java
  20. 20 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestEnv.java
  21. 15 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestTool.java
  22. 42 0
      core/src/main/java/com/mooctest/crowd/domain/env/DefectType.java
  23. 36 0
      core/src/main/java/com/mooctest/crowd/domain/env/Priority.java
  24. 38 0
      core/src/main/java/com/mooctest/crowd/domain/env/Seriousness.java
  25. 30 0
      core/src/main/java/com/mooctest/crowd/domain/env/TestCaseExamStatus.java
  26. 36 0
      core/src/main/java/com/mooctest/crowd/domain/env/TestStatus.java
  27. 5 0
      core/src/main/java/com/mooctest/crowd/domain/env/base/IEnum.java
  28. 22 0
      core/src/main/java/com/mooctest/crowd/domain/env/tools/EnumTools.java
  29. 62 0
      core/src/main/java/com/mooctest/crowd/domain/model/DefectPO.java
  30. 24 0
      core/src/main/java/com/mooctest/crowd/domain/model/ExceptionLogPO.java
  31. 21 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestCaseCodePO.java
  32. 80 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestCasePO.java
  33. 37 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestEnvPO.java
  34. 27 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestToolPO.java
  35. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/DefectTypeConverter.java
  36. 32 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/EnumConverter.java
  37. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/PriorityConverter.java
  38. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/SeriousnessConverter.java
  39. 10 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/TestCaseExamStatusConverter.java
  40. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/TestStatusConverter.java
  41. 21 0
      core/src/main/java/com/mooctest/crowd/domain/page/DOPage.java
  42. 19 0
      core/src/main/java/com/mooctest/crowd/domain/repository/CrowdTestTaskRepo.java
  43. 131 0
      core/src/main/java/com/mooctest/crowd/domain/repository/DefectRepo.java
  44. 21 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ExceptionLogRepository.java
  45. 6 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ICrowdTaskRepo.java
  46. 20 0
      core/src/main/java/com/mooctest/crowd/domain/repository/IDefectRepo.java
  47. 8 0
      core/src/main/java/com/mooctest/crowd/domain/repository/IExceptionLogRepository.java
  48. 5 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ITestCaseCodeRepo.java
  49. 20 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ITestCaseRepo.java
  50. 13 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ITestEnvRepo.java
  51. 13 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ITestToolRepo.java
  52. 2 0
      core/src/main/java/com/mooctest/crowd/domain/repository/IUserRepo.java
  53. 32 0
      core/src/main/java/com/mooctest/crowd/domain/repository/TestCaseCodeRepo.java
  54. 136 0
      core/src/main/java/com/mooctest/crowd/domain/repository/TestCaseRepo.java
  55. 48 0
      core/src/main/java/com/mooctest/crowd/domain/repository/TestEnvRepo.java
  56. 49 0
      core/src/main/java/com/mooctest/crowd/domain/repository/TestToolRepo.java
  57. 10 3
      core/src/main/java/com/mooctest/crowd/domain/repository/UserRepo.java
  58. 3 0
      core/src/main/java/com/mooctest/crowd/domain/util/Converter.java
  59. 16 1
      site/pom.xml
  60. 3 0
      site/src/main/java/com/mooctest/crowd/site/SiteApplication.java
  61. 55 0
      site/src/main/java/com/mooctest/crowd/site/command/DefectAddedCommand.java
  62. 50 0
      site/src/main/java/com/mooctest/crowd/site/command/DefectUpdatedCommand.java
  63. 20 0
      site/src/main/java/com/mooctest/crowd/site/command/Login2Command.java
  64. 54 0
      site/src/main/java/com/mooctest/crowd/site/command/TestCaseAddedCommand.java
  65. 51 0
      site/src/main/java/com/mooctest/crowd/site/command/TestCaseUpdatedCommand.java
  66. 29 0
      site/src/main/java/com/mooctest/crowd/site/command/TestEnvAddedCommand.java
  67. 29 0
      site/src/main/java/com/mooctest/crowd/site/command/TestEnvUpdatedCommand.java
  68. 20 0
      site/src/main/java/com/mooctest/crowd/site/command/TestToolAddedCommand.java
  69. 19 0
      site/src/main/java/com/mooctest/crowd/site/command/TestToolUpdatedCommand.java
  70. 52 0
      site/src/main/java/com/mooctest/crowd/site/configuration/RedisConfiguration.java
  71. 2 2
      site/src/main/java/com/mooctest/crowd/site/configuration/WebMvcConfiguration.java
  72. 1 0
      site/src/main/java/com/mooctest/crowd/site/constants/UploadType.java
  73. 0 0
      site/src/main/java/com/mooctest/crowd/site/controller/CommonController.java
  74. 9 0
      site/src/main/java/com/mooctest/crowd/site/controller/CrowdProjectController.java
  75. 107 0
      site/src/main/java/com/mooctest/crowd/site/controller/CrowdTaskController.java
  76. 142 0
      site/src/main/java/com/mooctest/crowd/site/controller/TestCaseController.java
  77. 69 0
      site/src/main/java/com/mooctest/crowd/site/controller/TestEnvController.java
  78. 64 0
      site/src/main/java/com/mooctest/crowd/site/controller/TestToolController.java
  79. 67 0
      site/src/main/java/com/mooctest/crowd/site/controller/TesterController.java
  80. 25 5
      site/src/main/java/com/mooctest/crowd/site/controller/UploadController.java
  81. 16 1
      site/src/main/java/com/mooctest/crowd/site/controller/UserController.java
  82. 69 9
      site/src/main/java/com/mooctest/crowd/site/controller/advice/ExceptionAdvice.java
  83. 3 2
      site/src/main/java/com/mooctest/crowd/site/controller/interceptor/AuthCheckInterceptor.java
  84. 3 0
      site/src/main/java/com/mooctest/crowd/site/controller/interceptor/SysAdminCheckInterceptor.java
  85. 6 0
      site/src/main/java/com/mooctest/crowd/site/data/TaskOperationControl.java
  86. 17 0
      site/src/main/java/com/mooctest/crowd/site/data/dto/TestCaseExamCommand.java
  87. 11 0
      site/src/main/java/com/mooctest/crowd/site/data/dto/TestCaseSearchDTO.java
  88. 10 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleProjectDataVO.java
  89. 11 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleTaskDataVO.java
  90. 12 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleUserTaskDataVO.java
  91. 97 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/TaskMoreInfoVO.java
  92. 39 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/TaskStatisticsVO.java
  93. 11 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/TaskUserSimpleData.java
  94. 33 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/TesterTaskVO.java
  95. 17 15
      site/src/main/java/com/mooctest/crowd/site/mediator/impl/WebMediatorImpl.java
  96. 3 3
      site/src/main/java/com/mooctest/crowd/site/service/CrowdProjectService.java
  97. 9 1
      site/src/main/java/com/mooctest/crowd/site/service/CrowdTaskService.java
  98. 21 0
      site/src/main/java/com/mooctest/crowd/site/service/DefectService.java
  99. 7 0
      site/src/main/java/com/mooctest/crowd/site/service/ExceptionLogService.java
  100. 25 0
      site/src/main/java/com/mooctest/crowd/site/service/TestCaseService.java

+ 1 - 0
.idea/encodings.xml

@@ -3,5 +3,6 @@
   <component name="Encoding">
     <file url="file://$PROJECT_DIR$/core/src/main/java" charset="UTF-8" />
     <file url="file://$PROJECT_DIR$/site/src/main/java" charset="UTF-8" />
+    <file url="PROJECT" charset="UTF-8" />
   </component>
 </project>

+ 2 - 0
.idea/tuosi-backend.iml

@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4" />

+ 124 - 0
.idea/uiDesigner.xml

@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Palette2">
+    <group name="Swing">
+      <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
+      </item>
+      <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
+        <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
+        <initial-values>
+          <property name="text" value="Button" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="RadioButton" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="CheckBox" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
+        <initial-values>
+          <property name="text" value="Label" />
+        </initial-values>
+      </item>
+      <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
+          <preferred-size width="150" height="-1" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
+          <preferred-size width="150" height="50" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
+          <preferred-size width="200" height="200" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
+      </item>
+      <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
+      </item>
+      <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
+          <preferred-size width="-1" height="20" />
+        </default-constraints>
+      </item>
+      <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
+        <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
+      </item>
+      <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
+        <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
+      </item>
+    </group>
+  </component>
+</project>

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
core/src/main/java/com/mooctest/crowd/domain/controller/TestUserController.java


+ 4 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/CrowdTestTaskDao.java

@@ -12,6 +12,7 @@ import org.springframework.data.repository.PagingAndSortingRepository;
 import org.springframework.data.repository.query.Param;
 
 import javax.transaction.Transactional;
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -76,4 +77,7 @@ public interface CrowdTestTaskDao extends CrudRepository<CrowdTestTaskPO, Long>,
     @Modifying
     @Query(nativeQuery = true, value = "update crowd_test_task set CTT_STATUS= ?1 where CTT_CODE=?2")
     void updateStatusById(@Param("status") int status, @Param("code") String code);
+
+    @Query("select cttp from CrowdTestTaskPO cttp where cttp.code in (:codes) and cttp.isDeleted=0")
+    List<CrowdTestTaskPO> findAllByCodeIn(Collection<String> codes);
 }

+ 21 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/DefectDao.java

@@ -0,0 +1,21 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.DefectPO;
+import com.mooctest.crowd.domain.model.TestCasePO;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface DefectDao extends PagingAndSortingRepository<DefectPO, Long>, CrudRepository<DefectPO, Long>,
+        JpaRepository<DefectPO, Long>, JpaSpecificationExecutor<DefectPO> {
+    int countByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode);
+    List<DefectPO> findAllByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode);
+    List<DefectPO> findAllByTaskCodeAndTestCaseCodeIn(String taskCode, Collection<String> testCaseCodes);
+    DefectPO findByTaskCodeAndCommiterIdAndImportCode(String taskCode, Long commiterId, String importCode);
+    int countAllByTaskCode(String taskCode);
+    List<DefectPO> findAllByTaskCode(String taskCode);
+}

+ 7 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/ExceptionLogDao.java

@@ -0,0 +1,7 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.ExceptionLogPO;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface ExceptionLogDao extends JpaRepository<ExceptionLogPO, Long> {
+}

+ 4 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/TaskToUserDao.java

@@ -30,4 +30,8 @@ public interface TaskToUserDao extends CrudRepository<TaskToUserPO,Long> {
 
     @Query(value = "SELECT new com.mooctest.crowd.domain.model.RankCountInfo(SUM(t.isCommitted), t.userId) FROM TaskToUserPO t where t.userId is not null and t.isCommitted=1 GROUP BY t.userId ORDER BY SUM(t.isCommitted) DESC")
     List<RankCountInfo> findTotalCountOfUser();
+
+    TaskToUserPO findByUserIdAndTaskCode(Long userId, String taskCode);
+
+    int countAllByTaskCode(String taskCode);
 }

+ 18 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/TestCaseCodeDao.java

@@ -0,0 +1,18 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.TestCaseCodePO;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+public interface TestCaseCodeDao extends PagingAndSortingRepository<TestCaseCodePO, Long>, CrudRepository<TestCaseCodePO, Long>,
+        JpaRepository<TestCaseCodePO, Long>, JpaSpecificationExecutor<TestCaseCodePO> {
+    @Modifying
+    @Query("update TestCaseCodePO tccp set tccp.ind = tccp.ind + 1 where tccp.taskCode =:taskCode")
+    void addIndByTaskCode(String taskCode);
+    @Query(value = "select * from test_case_code tcc where tcc.task_code =:taskCode for update", nativeQuery = true)
+    TestCaseCodePO findByTaskCodeForUpdate(String taskCode);
+}

+ 27 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/TestCaseDao.java

@@ -0,0 +1,27 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.TestCasePO;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.PagingAndSortingRepository;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+
+public interface TestCaseDao extends PagingAndSortingRepository<TestCasePO, Long>, CrudRepository<TestCasePO, Long>,
+        JpaRepository<TestCasePO, Long>, JpaSpecificationExecutor<TestCasePO> {
+    TestCasePO findByTaskCodeAndCode(String taskCode, String code);
+    @Modifying
+    @Query("update TestCasePO tcp set tcp.examStatus=:examStatus, tcp.examDescr=:examDescr where tcp.id=:id")
+    void exam(@Param("id") Long id, @Param("examStatus") Byte examStatus, @Param("examDescr") String examDescr);
+    @Modifying
+    @Query("update TestCasePO tcp set tcp.associatedCode=:associatedCode where tcp.id=:id")
+    void updateAssociatedCodeById(@Param("id") Long id, @Param("associatedCode") String associatedCode);
+    TestCasePO findByTaskCodeAndDesignerIdAndImportCode(String taskCode, Long designerId, String importCode);
+    int countAllByTaskCode(String taskCode);
+    int countAllByTaskCodeAndExamStatus(String taskCode, Byte examStatus);
+    List<TestCasePO> findAllByTaskCode(String taskCode);
+}

+ 16 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/TestEnvDao.java

@@ -0,0 +1,16 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.TestEnvPO;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+public interface TestEnvDao extends PagingAndSortingRepository<TestEnvPO, Long>, CrudRepository<TestEnvPO, Long>,
+        JpaRepository<TestEnvPO, Long>, JpaSpecificationExecutor<TestEnvPO> {
+    List<TestEnvPO> findAllByTaskCodeAndUserId(String taskCode, Long userId);
+    void deleteById(Long id);
+    List<TestEnvPO> findAllByTaskCode(String taskCode);
+}

+ 16 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/TestToolDao.java

@@ -0,0 +1,16 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.TestToolPO;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.PagingAndSortingRepository;
+
+import java.util.List;
+
+public interface TestToolDao extends PagingAndSortingRepository<TestToolPO, Long>, CrudRepository<TestToolPO, Long>,
+        JpaRepository<TestToolPO, Long>, JpaSpecificationExecutor<TestToolPO> {
+    List<TestToolPO> findAllByTaskCodeAndUserId(String taskCode, Long userId);
+    void deleteById(Long id);
+    List<TestToolPO> findAllByTaskCode(String taskCode);
+}

+ 2 - 0
core/src/main/java/com/mooctest/crowd/domain/dao/UserDao.java

@@ -31,4 +31,6 @@ public interface UserDao extends PagingAndSortingRepository<UserPO, Long>, JpaSp
 
     @Override
     long count();
+
+    UserPO findByEmail(String email);
 }

+ 5 - 3
core/src/main/java/com/mooctest/crowd/domain/domainobject/CrowdTestTask.java

@@ -173,9 +173,11 @@ public class CrowdTestTask {
             TaskToUser taskToUser = taskToUserOptional.get();
             if (taskToUser.getIsAccepted() == 0) {
                 throw new CrowdTestTaskException("当前用户未接受此任务");
-            } else if (taskToUser.getHasReport() == 0) {
-                throw new CrowdTestTaskException("当前用户未提交报告");
-            } else {
+            }
+//            else if (taskToUser.getHasReport() == 0) {
+//                throw new CrowdTestTaskException("当前用户未提交报告");
+//            }
+            else {
                 taskToUser.setIsCommitted(1);
                 taskToUser.setCommitTaskTime(new Timestamp(System.currentTimeMillis()));
             }

+ 56 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/Defect.java

@@ -0,0 +1,56 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import com.mooctest.crowd.domain.env.DefectType;
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.Seriousness;
+import lombok.Data;
+import java.sql.Timestamp;
+
+import java.util.List;
+
+//缺陷
+@Data
+public class Defect {
+    private Long id;
+    //缺陷编号
+    private String code;
+    //用例编号
+    private String testCaseCode;
+    //任务编号
+    private String taskCode;
+    //项目编号
+    private String projectCode;
+    //缺陷描述
+    private String descr;
+    //严重等级
+    private Seriousness seriousness;
+    //优先级
+    private Priority priority;
+    //缺陷类型
+    private DefectType defectType;
+    //前置条件
+    private String preconditions;
+    //环境配置
+    private String envConfig;
+    //操作步骤
+    private String opeSteps;
+    //输入数据
+    private String inputDatas;
+    //预期结果
+    private String expectedResult;
+    //实际结果
+    private String testResult;
+    //附件列表
+    private List<String> files;
+    //截图列表
+    private List<String> screenshots;
+    //其他说明
+    private String others;
+    //提交人员id
+    private Long commiterId;
+    //提交人员名字
+    private String commiterName;
+    //提交日期
+    private Timestamp commitTime;
+    private String importCode;
+}

+ 14 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/ExceptionLog.java

@@ -0,0 +1,14 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import lombok.*;
+
+import java.sql.Timestamp;
+
+@Data
+public class ExceptionLog {
+    private String id;
+    private String uri;
+    private String params;
+    private String exception;
+    private Timestamp addTime;
+}

+ 72 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCase.java

@@ -0,0 +1,72 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import lombok.Data;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+//测试用例
+@Data
+public class TestCase {
+    private Long id;
+    //用例编号,项目内唯一,全局不唯一
+    private String code;
+    //任务编号
+    private String taskCode;
+    //项目编号
+    private String projectCode;
+    //用例名字
+    private String name;
+    //用例描述
+    private String descr;
+    //前置条件
+    private String preconditions;
+    //环境配置
+    private String envConfig;
+    //优先级
+    private Priority priority;
+    //操作步骤
+    private String opeSteps;
+    //输入数据
+    private String inputDatas;
+    //预期结果
+    private String expectedResult;
+    //评判标准
+    private String evaCriteria;
+    //其他说明
+    private String others;
+    //设计人员id
+    private Long designerId;
+    //设计人员名字
+    private String designerName;
+    //设计时间
+    private Timestamp designTime;
+    //测试人员id
+    private Long testerId;
+    //测试人员名字
+    private String testerName;
+    //测试时间
+    private Timestamp testTime;
+    //测试结果
+    private String testResult;
+    //测试结果状态
+    private TestStatus testStatus;
+    //附件列表
+    private List<String> files;
+    //截图列表
+    private List<String> screenshots;
+    //审核状态
+    private TestCaseExamStatus examStatus;
+    //审核说明
+    private String examDescr;
+    //关联需求
+    private String demand;
+    private List<Defect> defects;
+    //从文档中导进来的原始测试用例号
+    private String importCode;
+    //关联的测试用例的code
+    private String associatedCode;
+}

+ 10 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCaseCode.java

@@ -0,0 +1,10 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import lombok.Data;
+
+@Data
+public class TestCaseCode {
+    private Long id;
+    private String taskCode;
+    private int ind;
+}

+ 18 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCaseExamRecord.java

@@ -0,0 +1,18 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import lombok.Data;
+
+import java.sql.Timestamp;
+
+@Data
+public class TestCaseExamRecord {
+    private Long id;
+    //审核结构id
+    private Long examerId;
+    //审核机构名字
+    private String examerName;
+    //审核的用例id
+    private Long testCaseId;
+    //操作时间
+    private Timestamp opeTime;
+}

+ 20 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/TestEnv.java

@@ -0,0 +1,20 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import lombok.Data;
+
+//测试环境
+@Data
+public class TestEnv {
+    private Long id;
+    private String taskCode;
+    private Long userId;
+    private String devName; //设备名称
+    private String devModel; //设备型号
+    private Integer devCount; //设备数量
+    private String devConfig; //设备硬件配置
+    private String opeSys; //操作系统
+    private String middleware; //中间件
+    private String db; //数据库
+    private String browser; //浏览器
+    private String supportSoftware; //支持软件
+}

+ 15 - 0
core/src/main/java/com/mooctest/crowd/domain/domainobject/TestTool.java

@@ -0,0 +1,15 @@
+package com.mooctest.crowd.domain.domainobject;
+
+import lombok.Data;
+
+//测试工具
+@Data
+public class TestTool {
+    private Long id;
+    private String taskCode;
+    private Long userId;
+    private String name; //名字
+    private String version; //版本
+    private String producerFrom; //生产商/来源
+    private String purpose; //用途
+}

+ 42 - 0
core/src/main/java/com/mooctest/crowd/domain/env/DefectType.java

@@ -0,0 +1,42 @@
+package com.mooctest.crowd.domain.env;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+import com.mooctest.crowd.domain.env.tools.EnumTools;
+
+import java.util.Arrays;
+
+public enum DefectType implements IEnum<Byte> {
+    FUNCTIONALITY((byte)1, "功能性"),
+    COMPATIBILITY((byte)2, "兼容性"),
+    INFORMATION_SECURITY((byte)3, "信息安全性"),
+    RELIABILITY((byte)4, "可靠性"),
+    USE((byte)5, "易用性"),
+    PERFORMANCE((byte)6, "性能效率"),
+    PORTABILITY((byte)6, "可移植性"),
+    MAINTAINABILITY((byte)6, "维护性"),
+    OTHER((byte)100, "其他");
+
+    private byte value;
+    private String name;
+    private DefectType(byte value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    @Override
+    public Byte getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public static DefectType fromValue(byte value) {
+        return EnumTools.get(values(), value);
+    }
+
+    public static DefectType fromName(String name) {
+        return Arrays.stream(values()).filter(defectType -> defectType.getName().equals(name)).findFirst().get();
+    }
+}

+ 36 - 0
core/src/main/java/com/mooctest/crowd/domain/env/Priority.java

@@ -0,0 +1,36 @@
+package com.mooctest.crowd.domain.env;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+import com.mooctest.crowd.domain.env.tools.EnumTools;
+
+import java.util.Arrays;
+
+public enum Priority implements IEnum<Byte> {
+    HIGH((byte)10, "高"),
+    MID((byte)20, "中"),
+    LOW((byte)30, "低");
+
+    private byte value;
+    private String name;
+    private Priority(byte value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    @Override
+    public Byte getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public static Priority fromValue(byte value) {
+        return EnumTools.get(values(), value);
+    }
+
+    public static Priority fromName(String name) {
+        return Arrays.stream(values()).filter(priority -> priority.getName().equals(name)).findFirst().get();
+    }
+}

+ 38 - 0
core/src/main/java/com/mooctest/crowd/domain/env/Seriousness.java

@@ -0,0 +1,38 @@
+package com.mooctest.crowd.domain.env;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+import com.mooctest.crowd.domain.env.tools.EnumTools;
+
+import java.util.Arrays;
+
+public enum Seriousness implements IEnum<Byte> {
+    VERY_HIGH((byte)1, "致命"),
+    HIGH((byte)2, "严重"),
+    MID((byte)3, "一般"),
+    LOW((byte)4, "轻微"),
+    VERY_LOW((byte)5, "建议");
+
+    private byte value;
+    private String name;
+    private Seriousness(byte value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    @Override
+    public Byte getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public static Seriousness fromValue(byte value) {
+        return EnumTools.get(values(), value);
+    }
+
+    public static Seriousness fromName(String name) {
+        return Arrays.stream(values()).filter(seriousness -> seriousness.getName().equals(name)).findFirst().get();
+    }
+}

+ 30 - 0
core/src/main/java/com/mooctest/crowd/domain/env/TestCaseExamStatus.java

@@ -0,0 +1,30 @@
+package com.mooctest.crowd.domain.env;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+import com.mooctest.crowd.domain.env.tools.EnumTools;
+
+public enum TestCaseExamStatus implements IEnum<Byte> {
+    WAIT((byte)0, "待审核"),
+    VALID((byte)1, "有效"),
+    INVALID((byte)2, "无效");
+
+    private byte value;
+    private String name;
+    private TestCaseExamStatus(byte value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    @Override
+    public Byte getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public static TestCaseExamStatus fromValue(byte value) {
+        return EnumTools.get(values(), value);
+    }
+}

+ 36 - 0
core/src/main/java/com/mooctest/crowd/domain/env/TestStatus.java

@@ -0,0 +1,36 @@
+package com.mooctest.crowd.domain.env;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+import com.mooctest.crowd.domain.env.tools.EnumTools;
+
+import java.util.Arrays;
+
+public enum TestStatus implements IEnum<Byte> {
+    WAIT((byte)0, "待测试"),
+    PASS((byte)1, "通过"),
+    NO_PASS((byte)2, "不通过");
+
+    private byte value;
+    private String name;
+    private TestStatus(byte value, String name) {
+        this.value = value;
+        this.name = name;
+    }
+
+    @Override
+    public Byte getValue() {
+        return value;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public static TestStatus fromValue(byte value) {
+        return EnumTools.get(values(), value);
+    }
+
+    public static TestStatus fromName(String name) {
+        return Arrays.stream(values()).filter(testStatus -> testStatus.getName().equals(name)).findFirst().get();
+    }
+}

+ 5 - 0
core/src/main/java/com/mooctest/crowd/domain/env/base/IEnum.java

@@ -0,0 +1,5 @@
+package com.mooctest.crowd.domain.env.base;
+
+public interface IEnum<ValType> {
+    ValType getValue();
+}

+ 22 - 0
core/src/main/java/com/mooctest/crowd/domain/env/tools/EnumTools.java

@@ -0,0 +1,22 @@
+package com.mooctest.crowd.domain.env.tools;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+
+public class EnumTools {
+    public EnumTools() {
+    }
+
+    public static <T extends IEnum> T get(T[] values, Object val) {
+        IEnum[] var2 = values;
+        int var3 = values.length;
+
+        for(int var4 = 0; var4 < var3; ++var4) {
+            T result = (T)var2[var4];
+            if (result.getValue() == val) {
+                return result;
+            }
+        }
+
+        throw new RuntimeException(String.format("没有匹配到值为'%s'的枚举类型", val));
+    }
+}

+ 62 - 0
core/src/main/java/com/mooctest/crowd/domain/model/DefectPO.java

@@ -0,0 +1,62 @@
+package com.mooctest.crowd.domain.model;
+
+import com.mooctest.crowd.domain.env.DefectType;
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.Seriousness;
+import com.mooctest.crowd.domain.model.converter.DefectTypeConverter;
+import com.mooctest.crowd.domain.model.converter.PriorityConverter;
+import com.mooctest.crowd.domain.model.converter.SeriousnessConverter;
+import lombok.Data;
+
+import javax.persistence.*;
+import java.sql.Timestamp;
+
+@Data
+@Entity
+@Table(name = "defect")
+public class DefectPO {
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "code", length = 11, nullable = false)
+    private String code;
+    @Column(name = "test_case_code", length = 9, nullable = false)
+    private String testCaseCode;
+    @Column(name = "task_code", length = 30, nullable = false)
+    private String taskCode;
+    @Column(name = "project_code", length = 30, nullable = false)
+    private String projectCode;
+    @Column(name = "descr", length = 500, nullable = true)
+    private String descr;
+    @Column(name = "seriousness", nullable = false)
+    private Byte seriousness;
+    @Column(name = "priority", nullable = false)
+    private Byte priority;
+    @Column(name = "defect_type", nullable = false)
+    private Byte defectType;
+    @Column(name = "preconditions", length = 500, nullable = true)
+    private String preconditions;
+    @Column(name = "env_config", length = 300, nullable = true)
+    private String envConfig;
+    @Column(name = "ope_steps", length = 300, nullable = true)
+    private String opeSteps;
+    @Column(name = "input_datas", length = 200, nullable = true)
+    private String inputDatas;
+    @Column(name = "expected_result", length = 200, nullable = true)
+    private String expectedResult;
+    @Column(name = "test_result", length = 200, nullable = false)
+    private String testResult;
+    @Column(name = "files", length = 500, nullable = true)
+    private String files;
+    @Column(name = "screen_shots", length = 500, nullable = true)
+    private String screenshots;
+    @Column(name = "others", length = 300, nullable = true)
+    private String others;
+    @Column(name = "commiter_id", nullable = false)
+    private Long commiterId;
+    @Column(name = "commiter_time", nullable = false)
+    private Timestamp commitTime;
+    @Column(name = "import_code", length = 9, nullable = true)
+    private String importCode;
+}

+ 24 - 0
core/src/main/java/com/mooctest/crowd/domain/model/ExceptionLogPO.java

@@ -0,0 +1,24 @@
+package com.mooctest.crowd.domain.model;
+
+import lombok.*;
+
+import javax.persistence.*;
+import java.sql.Timestamp;
+
+@Data
+@Entity
+@Table(name = "exception_log")
+public class ExceptionLogPO {
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "exception", columnDefinition = "text", nullable = false)
+    private String exception;
+    @Column(name = "uri", length = 50, nullable = true)
+    private String uri;
+    @Column(name = "params", length = 500, nullable = true)
+    private String params;
+    @Column(name = "add_time", nullable = false)
+    private Timestamp addTime;
+}

+ 21 - 0
core/src/main/java/com/mooctest/crowd/domain/model/TestCaseCodePO.java

@@ -0,0 +1,21 @@
+package com.mooctest.crowd.domain.model;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Data
+@Entity
+@Table(name = "test_case_code", indexes = {
+        @Index(columnList = "task_code", name = "task_code_ind", unique = true)
+})
+public class TestCaseCodePO {
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "task_code", length = 30, nullable = false)
+    private String taskCode;
+    @Column(name = "ind", nullable = false)
+    private int ind;
+}

+ 80 - 0
core/src/main/java/com/mooctest/crowd/domain/model/TestCasePO.java

@@ -0,0 +1,80 @@
+package com.mooctest.crowd.domain.model;
+
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.model.converter.PriorityConverter;
+import com.mooctest.crowd.domain.model.converter.TestCaseExamStatusConverter;
+import com.mooctest.crowd.domain.model.converter.TestStatusConverter;
+import lombok.Data;
+
+import javax.persistence.*;
+import java.sql.Timestamp;
+
+@Data
+@Entity
+@Table(name = "test_case", indexes = {
+        @Index(columnList = "code,project_code", name = "code_project_code_ind", unique = true),
+        @Index(columnList = "task_code,designer_id,import_code", name="task_code_designer_id_import_code_ind", unique = true)
+})
+public class TestCasePO {
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "code", length = 9, nullable = false)
+    private String code;
+    @Column(name = "task_code", length = 30, nullable = false)
+    private String taskCode;
+    @Column(name = "project_code", length = 30, nullable = false)
+    private String projectCode;
+    @Column(name = "name", length = 23, nullable = false)
+    private String name;
+    @Column(name = "descr", length = 500, nullable = true)
+    private String descr;
+    @Column(name = "preconditions", length = 500, nullable = true)
+    private String preconditions;
+    @Column(name = "env_config", length = 300, nullable = true)
+    private String envConfig;
+    @Column(name = "priority", nullable = false)
+//    @Convert(converter = PriorityConverter.class)
+    private Byte priority;
+    @Column(name = "ope_steps", length = 300, nullable = true)
+    private String opeSteps;
+    @Column(name = "input_datas", length = 200, nullable = true)
+    private String inputDatas;
+    @Column(name = "expected_result", length = 200, nullable = true)
+    private String expectedResult;
+    @Column(name = "eva_criteria", length = 100, nullable = true)
+    private String evaCriteria;
+    @Column(name = "others", length = 300, nullable = true)
+    private String others;
+    @Column(name = "designer_id", nullable = false)
+    private Long designerId;
+    @Column(name = "design_time", nullable = false)
+    private Timestamp designTime;
+    @Column(name = "tester_id", nullable = true)
+    private Long testerId;
+    @Column(name = "test_time", nullable = true)
+    private Timestamp testTime;
+    @Column(name = "test_result", length = 200, nullable = true)
+    private String testResult;
+    @Column(name = "test_status", nullable = false)
+//    @Convert(converter = TestStatusConverter.class)
+    private Byte testStatus;
+    @Column(name = "files", length = 500, nullable = true)
+    private String files;
+    @Column(name = "screen_shots", length = 500, nullable = true)
+    private String screenshots;
+    @Column(name = "exam_status", nullable = false)
+//    @Convert(converter = TestCaseExamStatusConverter.class)
+    private Byte examStatus;
+    @Column(name = "exam_descr", length = 200, nullable = true)
+    private String examDescr;
+    @Column(name = "demand", length = 400, nullable = true)
+    private String demand;
+    @Column(name = "import_code", length = 9, nullable = true)
+    private String importCode;
+    @Column(name = "associated_code", length = 9, nullable = true)
+    private String associatedCode;
+}

+ 37 - 0
core/src/main/java/com/mooctest/crowd/domain/model/TestEnvPO.java

@@ -0,0 +1,37 @@
+package com.mooctest.crowd.domain.model;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Data
+@Entity
+@Table(name = "test_env")
+public class TestEnvPO {
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "task_code", length = 30, nullable = false)
+    private String taskCode;
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+    @Column(name = "dev_name", length = 50, nullable = false)
+    private String devName; //设备名称
+    @Column(name = "dev_model", length = 30, nullable = true)
+    private String devModel; //设备型号
+    @Column(name = "dev_count", nullable = false)
+    private Integer devCount; //设备数量
+    @Column(name = "dev_config", length = 100, nullable = false)
+    private String devConfig; //设备硬件配置
+    @Column(name = "ope_sys", length = 50, nullable = false)
+    private String opeSys; //操作系统
+    @Column(name = "middleware", length = 50, nullable = true)
+    private String middleware; //中间件
+    @Column(name = "db", length = 30, nullable = true)
+    private String db; //数据库
+    @Column(name = "browser", length = 50, nullable = true)
+    private String browser; //浏览器
+    @Column(name = "support_software", length = 100, nullable = true)
+    private String supportSoftware; //支持软件
+}

+ 27 - 0
core/src/main/java/com/mooctest/crowd/domain/model/TestToolPO.java

@@ -0,0 +1,27 @@
+package com.mooctest.crowd.domain.model;
+
+import lombok.Data;
+
+import javax.persistence.*;
+
+@Data
+@Entity
+@Table(name = "test_tool")
+public class TestToolPO {
+    @Id
+    @Column(name = "id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Long id;
+    @Column(name = "task_code", length = 30, nullable = false)
+    private String taskCode;
+    @Column(name = "user_id", nullable = false)
+    private Long userId;
+    @Column(name = "name", length = 50, nullable = false)
+    private String name; //名字
+    @Column(name = "version", length = 50, nullable = true)
+    private String version; //版本
+    @Column(name = "producer_from", length = 70, nullable = true)
+    private String producerFrom; //生产商/来源
+    @Column(name = "purpose", length = 100, nullable = true)
+    private String purpose; //用途
+}

+ 9 - 0
core/src/main/java/com/mooctest/crowd/domain/model/converter/DefectTypeConverter.java

@@ -0,0 +1,9 @@
+package com.mooctest.crowd.domain.model.converter;
+
+import com.mooctest.crowd.domain.env.DefectType;
+
+public class DefectTypeConverter extends EnumConverter<DefectType, Byte> {
+    public DefectTypeConverter() {
+        super(DefectType.class);
+    }
+}

+ 32 - 0
core/src/main/java/com/mooctest/crowd/domain/model/converter/EnumConverter.java

@@ -0,0 +1,32 @@
+package com.mooctest.crowd.domain.model.converter;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+
+import javax.persistence.AttributeConverter;
+
+public abstract class EnumConverter<ATTR extends Enum<ATTR> & IEnum<DB>, DB> implements AttributeConverter<ATTR, DB> {
+
+    private final Class<ATTR> clazz;
+
+    public EnumConverter(Class<ATTR> clazz) {
+        this.clazz = clazz;
+    }
+
+    @Override
+    public DB convertToDatabaseColumn(ATTR attribute) {
+        return attribute != null ? attribute.getValue() : null;
+    }
+
+    @Override
+    public ATTR convertToEntityAttribute(DB dbData) {
+        if (dbData == null) return null;
+        ATTR[] enums = clazz.getEnumConstants();
+        for (ATTR e : enums) {
+            if (e.getValue().equals(dbData)) {
+                return e;
+            }
+        }
+        throw new UnsupportedOperationException("枚举转化异常。枚举【" + clazz.getSimpleName() + "】,数据库库中的值为:【" + dbData + "】");
+    }
+
+}

+ 9 - 0
core/src/main/java/com/mooctest/crowd/domain/model/converter/PriorityConverter.java

@@ -0,0 +1,9 @@
+package com.mooctest.crowd.domain.model.converter;
+
+import com.mooctest.crowd.domain.env.Priority;
+
+public class PriorityConverter extends EnumConverter<Priority, Byte> {
+    public PriorityConverter() {
+        super(Priority.class);
+    }
+}

+ 9 - 0
core/src/main/java/com/mooctest/crowd/domain/model/converter/SeriousnessConverter.java

@@ -0,0 +1,9 @@
+package com.mooctest.crowd.domain.model.converter;
+
+import com.mooctest.crowd.domain.env.Seriousness;
+
+public class SeriousnessConverter extends EnumConverter<Seriousness, Byte> {
+    public SeriousnessConverter() {
+        super(Seriousness.class);
+    }
+}

+ 10 - 0
core/src/main/java/com/mooctest/crowd/domain/model/converter/TestCaseExamStatusConverter.java

@@ -0,0 +1,10 @@
+package com.mooctest.crowd.domain.model.converter;
+
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+
+public class TestCaseExamStatusConverter extends EnumConverter<TestCaseExamStatus, Byte> {
+    public TestCaseExamStatusConverter() {
+        super(TestCaseExamStatus.class);
+    }
+}

+ 9 - 0
core/src/main/java/com/mooctest/crowd/domain/model/converter/TestStatusConverter.java

@@ -0,0 +1,9 @@
+package com.mooctest.crowd.domain.model.converter;
+
+import com.mooctest.crowd.domain.env.TestStatus;
+
+public class TestStatusConverter extends EnumConverter<TestStatus, Byte> {
+    public TestStatusConverter() {
+        super(TestStatus.class);
+    }
+}

+ 21 - 0
core/src/main/java/com/mooctest/crowd/domain/page/DOPage.java

@@ -0,0 +1,21 @@
+package com.mooctest.crowd.domain.page;
+
+import lombok.*;
+
+import java.util.List;
+
+@Getter
+@Setter
+public class DOPage<T> {
+    private Integer pageNo; //从0开始
+    private Integer pageSize;
+    private Long totalCount;
+    private List<T> datas;
+
+    public DOPage(int pageNo, int pageSize, long totalCount, List<T> datas) {
+        this.pageNo = pageNo;
+        this.pageSize = pageSize;
+        this.totalCount = totalCount;
+        this.datas = datas;
+    }
+}

+ 19 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/CrowdTestTaskRepo.java

@@ -7,6 +7,7 @@ import com.mooctest.crowd.domain.domainobject.CrowdTestTask;
 import com.mooctest.crowd.domain.domainobject.EndPoint;
 import com.mooctest.crowd.domain.domainobject.TaskToUser;
 import com.mooctest.crowd.domain.model.CrowdTestProjectPO;
+import com.mooctest.crowd.domain.model.CrowdTestTaskPO;
 import com.mooctest.crowd.domain.model.TaskToUserPO;
 import com.mooctest.crowd.domain.util.Converter;
 import lombok.extern.slf4j.Slf4j;
@@ -75,4 +76,22 @@ public class CrowdTestTaskRepo implements ICrowdTaskRepo{
         return endPointDao.findAll().stream().filter(endPointPO -> endPointPO.getIsShowed() == 1).map(endPointPO -> Converter.convert(EndPoint.class, endPointPO)).collect(Collectors.toList());
     }
 
+    @Override
+    public CrowdTestTask findByCode(String code) {
+        CrowdTestTaskPO taskPO = taskDao.findByCodeAndIsDeleted(code, 0);
+        return Converter.convert(CrowdTestTask.class, taskPO);
+    }
+
+    @Override
+    public List<CrowdTestTask> findAllByCrowdTestProjectCode(String crowdTestProjectCode) {
+        List<CrowdTestTaskPO> taskPOs = taskDao.findByCrowdTestProjectCodeAndIsDeleted(crowdTestProjectCode, 0);
+        return taskPOs.stream().map(taskPO -> Converter.convert(CrowdTestTask.class, taskPO)).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<TaskToUser> findAllTaskToUserByTaskCode(String taskCode) {
+        return taskToUserDao.findByTaskCode(taskCode).stream().map(taskToUserPO ->
+                Converter.convert(TaskToUser.class, taskToUserPO)).collect(Collectors.toList());
+    }
+
 }

+ 131 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/DefectRepo.java

@@ -0,0 +1,131 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.dao.DefectDao;
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.env.DefectType;
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.Seriousness;
+import com.mooctest.crowd.domain.model.DefectPO;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.domain.util.Converter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import javax.persistence.criteria.Predicate;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Service
+public class DefectRepo implements IDefectRepo{
+    @Autowired
+    private DefectDao defectDao;
+
+    @Override
+    public void save(Defect defect) {
+        DefectPO defectPO = Converter.convert(DefectPO.class, defect);
+        if(!CollectionUtils.isEmpty(defect.getFiles())) {
+            defectPO.setFiles(Strings.join(defect.getFiles(), ','));
+        }else {
+            defectPO.setFiles(null);
+        }
+        if(!CollectionUtils.isEmpty(defect.getScreenshots())) {
+            defectPO.setScreenshots(Strings.join(defect.getScreenshots(), ','));
+        }else {
+            defectPO.setScreenshots(null);
+        }
+        defectPO.setDefectType(defect.getDefectType().getValue());
+        defectPO.setSeriousness(defect.getSeriousness().getValue());
+        defectPO.setPriority(defect.getPriority().getValue());
+        defectDao.save(defectPO);
+        defect.setId(defectPO.getId());
+    }
+
+    @Override
+    public DOPage<Defect> findUserDefects(Long commiterId, String taskCode, Integer pageNo, Integer pageSize) {
+        Pageable pageable = PageRequest.of(pageNo, pageSize);
+        Specification<DefectPO> specification = (a, q, cb) -> {
+            Predicate predicate = cb.conjunction();
+            if(commiterId != null) {
+                predicate.getExpressions().add(cb.equal(a.get("commiterId"), commiterId));
+            }
+            if(StringUtils.isNotEmpty(taskCode)) {
+                predicate.getExpressions().add(cb.equal(a.get("taskCode"), taskCode));
+            }
+            return predicate;
+        };
+        Page<Defect> page = defectDao.findAll(specification, pageable).map(defectPO -> poToDO(defectPO));
+        DOPage<Defect> doPage = new DOPage(pageNo, pageSize, page.getTotalElements(), page.getContent());
+        return doPage;
+    }
+
+    @Override
+    public Defect findById(Long id) {
+        DefectPO defectPO = defectDao.findById(id).get();
+        if (defectPO == null) {
+            return null;
+        }
+        return poToDO(defectPO);
+    }
+
+    @Override
+    public void deleteById(Long id) {
+        defectDao.deleteById(id);
+    }
+
+    @Override
+    public int countByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode) {
+        return defectDao.countByTaskCodeAndTestCaseCode(taskCode,testCaseCode);
+    }
+
+    @Override
+    public List<Defect> findAllByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode) {
+        List<DefectPO> defectPOs = defectDao.findAllByTaskCodeAndTestCaseCode(taskCode, testCaseCode);
+        return defectPOs.stream().map(defectPO -> poToDO(defectPO)).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<Defect> findAllByTaskCodeAndTestCaseCodeIn(String taskCode, Collection<String> testCaseCodes) {
+        List<DefectPO> defectPOs = defectDao.findAllByTaskCodeAndTestCaseCodeIn(taskCode, testCaseCodes);
+        return defectPOs.stream().map(defectPO -> poToDO(defectPO)).collect(Collectors.toList());
+    }
+
+    @Override
+    public Defect findByTaskCodeAndCommiterIdAndImportCode(String taskCode, Long commiterId, String importCode) {
+        return poToDO(defectDao.findByTaskCodeAndCommiterIdAndImportCode(taskCode, commiterId, importCode));
+    }
+
+    @Override
+    public List<Defect> findAllByTaskCode(String taskCode) {
+        List<DefectPO> defectPOs = defectDao.findAllByTaskCode(taskCode);
+        return defectPOs.stream().map(defectPO -> poToDO(defectPO)).collect(Collectors.toList());
+    }
+
+    private Defect poToDO(DefectPO defectPO) {
+        Defect defect = Converter.convert(Defect.class, defectPO);
+        if (StringUtils.isNotEmpty(defectPO.getFiles())) {
+            defect.setFiles(Arrays.asList(defectPO.getFiles().split(",")));
+        } else {
+            defect.setFiles(Collections.EMPTY_LIST);
+        }
+        if (StringUtils.isNotEmpty(defectPO.getScreenshots())) {
+            defect.setScreenshots(Arrays.asList(defectPO.getScreenshots().split(",")));
+        } else {
+            defect.setScreenshots(Collections.EMPTY_LIST);
+        }
+        defect.setDefectType(DefectType.fromValue(defectPO.getDefectType()));
+        defect.setPriority(Priority.fromValue(defectPO.getPriority()));
+        defect.setSeriousness(Seriousness.fromValue(defectPO.getSeriousness()));
+        return defect;
+    }
+}

+ 21 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/ExceptionLogRepository.java

@@ -0,0 +1,21 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.dao.ExceptionLogDao;
+import com.mooctest.crowd.domain.domainobject.ExceptionLog;
+import com.mooctest.crowd.domain.model.ExceptionLogPO;
+import com.mooctest.crowd.domain.util.Converter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+
+@Component
+public class ExceptionLogRepository implements IExceptionLogRepository {
+    @Autowired
+    private ExceptionLogDao exceptionLogDao;
+
+    @Override
+    public void save(ExceptionLog exceptionLog) {
+        ExceptionLogPO exceptionLogPO = Converter.convert(ExceptionLogPO.class, exceptionLog);
+        exceptionLogDao.save(exceptionLogPO);
+    }
+}

+ 6 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/ICrowdTaskRepo.java

@@ -15,4 +15,10 @@ public interface ICrowdTaskRepo {
      void deleteTaskToUser(TaskToUser taskToUser);
 
      List<EndPoint> getEndPointShowList();
+
+     CrowdTestTask findByCode(String code);
+
+     List<CrowdTestTask> findAllByCrowdTestProjectCode(String crowdTestProjectCode);
+
+     List<TaskToUser> findAllTaskToUserByTaskCode(String taskCode);
 }

+ 20 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/IDefectRepo.java

@@ -0,0 +1,20 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.page.DOPage;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface IDefectRepo {
+    void save(Defect defect);
+    DOPage<Defect> findUserDefects(Long commiterId, String taskCode, Integer pageNo, Integer pageSize);
+    Defect findById(Long id);
+    void deleteById(Long id);
+    int countByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode);
+    List<Defect> findAllByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode);
+    List<Defect> findAllByTaskCodeAndTestCaseCodeIn(String taskCode, Collection<String> testCaseCodes);
+    Defect findByTaskCodeAndCommiterIdAndImportCode(String taskCode, Long commiterId, String importCode);
+    List<Defect> findAllByTaskCode(String taskCode);
+}

+ 8 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/IExceptionLogRepository.java

@@ -0,0 +1,8 @@
+package com.mooctest.crowd.domain.repository;
+
+
+import com.mooctest.crowd.domain.domainobject.ExceptionLog;
+
+public interface IExceptionLogRepository {
+    void save(ExceptionLog exceptionLogDO);
+}

+ 5 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/ITestCaseCodeRepo.java

@@ -0,0 +1,5 @@
+package com.mooctest.crowd.domain.repository;
+
+public interface ITestCaseCodeRepo {
+    int getNewestIndByTaskCode(String taskCode);
+}

+ 20 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/ITestCaseRepo.java

@@ -0,0 +1,20 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.page.DOPage;
+
+import java.util.List;
+
+public interface ITestCaseRepo {
+    void save(TestCase testCase);
+    DOPage<TestCase> find(Long designerId, String taskCode, Integer pageNo, Integer pageSize, TestStatus testStatus, TestCaseExamStatus examStatus);
+    TestCase findById(Long id);
+    void deleteById(Long id);
+    TestCase findByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode);
+    void exam(Long id, TestCaseExamStatus examStatus, String examDescr);
+    void updateAssociatedCodeById(Long id, String associatedCode);
+    TestCase findByTaskCodeAndDesignerIdAndImportCode(String taskCode, Long designerId, String importCode);
+    List<TestCase> findAllByTaskCode(String taskCode);
+}

+ 13 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/ITestEnvRepo.java

@@ -0,0 +1,13 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.domainobject.TestEnv;
+
+import java.util.List;
+
+public interface ITestEnvRepo {
+    void save(TestEnv testEnv);
+    List<TestEnv> findAllByTaskCodeAndUserId(String taskCode, Long userId);
+    void deleteById(Long id);
+    TestEnv findById(Long id);
+    List<TestEnv> findAllByTaskCode(String taskCode);
+}

+ 13 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/ITestToolRepo.java

@@ -0,0 +1,13 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.domainobject.TestTool;
+
+import java.util.List;
+
+public interface ITestToolRepo {
+    void save(TestTool testTool);
+    List<TestTool> findAllByTaskCodeAndUserId(String taskCode, Long userId);
+    void deleteById(Long id);
+    TestTool findById(Long id);
+    List<TestTool> findAllByTaskCode(String taskCode);
+}

+ 2 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/IUserRepo.java

@@ -42,4 +42,6 @@ public interface IUserRepo {
     User saveUserAndRole(User user);
 
     List<User> getApplyEvaluationAgencyByIsAuthenticated();
+
+    User getByEmail(String email) throws UserNotExistException, RoleNotFoundException;
 }

+ 32 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/TestCaseCodeRepo.java

@@ -0,0 +1,32 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.dao.TestCaseCodeDao;
+import com.mooctest.crowd.domain.model.TestCaseCodePO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import static org.springframework.transaction.annotation.Propagation.REQUIRES_NEW;
+
+@Service
+public class TestCaseCodeRepo implements ITestCaseCodeRepo{
+    @Autowired
+    private TestCaseCodeDao testCaseCodeDao;
+
+    @Override
+    @Transactional(propagation = REQUIRES_NEW)
+    public int getNewestIndByTaskCode(String taskCode) {
+        TestCaseCodePO testCaseCodePO = testCaseCodeDao.findByTaskCodeForUpdate(taskCode);
+        int ind = 1;
+        if (testCaseCodePO == null) {
+            testCaseCodePO = new TestCaseCodePO();
+            testCaseCodePO.setTaskCode(taskCode);
+            testCaseCodePO.setInd(ind);
+            testCaseCodeDao.save(testCaseCodePO);
+        } else {
+            ind = testCaseCodePO.getInd() + 1;
+            testCaseCodeDao.addIndByTaskCode(taskCode);
+        }
+        return ind;
+    }
+}

+ 136 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/TestCaseRepo.java

@@ -0,0 +1,136 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.dao.TestCaseDao;
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.model.TestCasePO;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.domain.util.Converter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import javax.persistence.criteria.Predicate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class TestCaseRepo implements ITestCaseRepo{
+    @Autowired
+    private TestCaseDao testCaseDao;
+
+    @Override
+    public void save(TestCase testCase) {
+        TestCasePO testCasePO = Converter.convert(TestCasePO.class, testCase);
+        if(!CollectionUtils.isEmpty(testCase.getFiles())) {
+            testCasePO.setFiles(Strings.join(testCase.getFiles(), ','));
+        }else {
+            testCasePO.setFiles(null);
+        }
+        if(!CollectionUtils.isEmpty(testCase.getScreenshots())) {
+            testCasePO.setScreenshots(Strings.join(testCase.getScreenshots(), ','));
+        }else {
+            testCasePO.setScreenshots(null);
+        }
+        testCasePO.setPriority(testCase.getPriority().getValue());
+        testCasePO.setTestStatus(testCase.getTestStatus().getValue());
+        testCasePO.setExamStatus(testCase.getExamStatus().getValue());
+        testCaseDao.save(testCasePO);
+        testCase.setId(testCasePO.getId());
+    }
+
+    @Override
+    public DOPage<TestCase> find(Long designerId, String taskCode, Integer pageNo, Integer pageSize, TestStatus testStatus, TestCaseExamStatus examStatus) {
+        Pageable pageable = PageRequest.of(pageNo, pageSize);
+        Specification<TestCasePO> specification = (a, q, cb) -> {
+            Predicate predicate = cb.conjunction();
+            if(designerId != null) {
+                predicate.getExpressions().add(cb.equal(a.get("designerId"), designerId));
+            }
+            if(StringUtils.isNotEmpty(taskCode)) {
+                predicate.getExpressions().add(cb.equal(a.get("taskCode"), taskCode));
+            }
+            if(testStatus != null) {
+                predicate.getExpressions().add(cb.equal(a.get("testStatus"), testStatus.getValue()));
+            }
+            if(examStatus != null) {
+                predicate.getExpressions().add(cb.equal(a.get("examStatus"), examStatus.getValue()));
+            }
+            return predicate;
+        };
+        Page<TestCase> page = testCaseDao.findAll(specification, pageable).map(testCasePO -> poToDO(testCasePO));
+        DOPage<TestCase> doPage = new DOPage(pageNo, pageSize, page.getTotalElements(), page.getContent());
+        return doPage;
+    }
+
+    @Override
+    public TestCase findById(Long id) {
+        TestCasePO testCasePO = testCaseDao.findById(id).get();
+        return poToDO(testCasePO);
+    }
+
+    @Override
+    public void deleteById(Long id) {
+        testCaseDao.deleteById(id);
+    }
+
+    @Override
+    public TestCase findByTaskCodeAndTestCaseCode(String taskCode, String testCaseCode) {
+        TestCasePO testCasePO = testCaseDao.findByTaskCodeAndCode(taskCode, testCaseCode);
+        return poToDO(testCasePO);
+    }
+
+    @Override
+    public void exam(Long id, TestCaseExamStatus examStatus, String examDescr) {
+        testCaseDao.exam(id, examStatus.getValue(), examDescr);
+    }
+
+    @Override
+    public void updateAssociatedCodeById(Long id, String associatedCode) {
+        testCaseDao.updateAssociatedCodeById(id, associatedCode);
+    }
+
+    @Override
+    public TestCase findByTaskCodeAndDesignerIdAndImportCode(String taskCode, Long designerId, String importCode) {
+        TestCasePO testCasePO = testCaseDao.findByTaskCodeAndDesignerIdAndImportCode(taskCode, designerId, importCode);
+        return poToDO(testCasePO);
+    }
+
+    @Override
+    public List<TestCase> findAllByTaskCode(String taskCode) {
+        List<TestCasePO> testCasePOs = testCaseDao.findAllByTaskCode(taskCode);
+        return testCasePOs.stream().map(testCasePO -> poToDO(testCasePO)).collect(Collectors.toList());
+    }
+
+    private TestCase poToDO(TestCasePO testCasePO) {
+        if (testCasePO == null) {
+            return null;
+        }
+        TestCase testCase = Converter.convert(TestCase.class, testCasePO);
+        if (StringUtils.isNotEmpty(testCasePO.getFiles())) {
+            testCase.setFiles(Arrays.asList(testCasePO.getFiles().split(",")));
+        } else {
+            testCase.setFiles(Collections.EMPTY_LIST);
+        }
+        if (StringUtils.isNotEmpty(testCasePO.getScreenshots())) {
+            testCase.setScreenshots(Arrays.asList(testCasePO.getScreenshots().split(",")));
+        } else {
+            testCase.setScreenshots(Collections.EMPTY_LIST);
+        }
+        testCase.setPriority(Priority.fromValue(testCasePO.getPriority()));
+        testCase.setTestStatus(TestStatus.fromValue(testCasePO.getTestStatus()));
+        testCase.setExamStatus(TestCaseExamStatus.fromValue(testCasePO.getExamStatus()));
+        return testCase;
+    }
+
+}

+ 48 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/TestEnvRepo.java

@@ -0,0 +1,48 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.dao.TestEnvDao;
+import com.mooctest.crowd.domain.domainobject.TestEnv;
+import com.mooctest.crowd.domain.model.TestCasePO;
+import com.mooctest.crowd.domain.model.TestEnvPO;
+import com.mooctest.crowd.domain.util.Converter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class TestEnvRepo implements ITestEnvRepo {
+    @Autowired
+    private TestEnvDao testEnvDao;
+
+    @Override
+    public void save(TestEnv testEnv) {
+        TestEnvPO testEnvPO = Converter.convert(TestEnvPO.class, testEnv);
+        testEnvDao.save(testEnvPO);
+        testEnv.setId(testEnvPO.getId());
+    }
+
+    @Override
+    public List<TestEnv> findAllByTaskCodeAndUserId(String taskCode, Long userId) {
+        List<TestEnvPO> testEnvPOs = testEnvDao.findAllByTaskCodeAndUserId(taskCode, userId);
+        return testEnvPOs.stream().map(testEnvPO -> Converter.convert(TestEnv.class, testEnvPO)).collect(Collectors.toList());
+    }
+
+    @Override
+    public void deleteById(Long id) {
+        testEnvDao.deleteById(id);
+    }
+
+    @Override
+    public TestEnv findById(Long id) {
+        TestEnvPO testEnvPO = testEnvDao.findById(id).get();
+        return Converter.convert(TestEnv.class, testEnvPO);
+    }
+
+    @Override
+    public List<TestEnv> findAllByTaskCode(String taskCode) {
+        List<TestEnvPO> testEnvPOs = testEnvDao.findAllByTaskCode(taskCode);
+        return testEnvPOs.stream().map(testEnvPO -> Converter.convert(TestEnv.class, testEnvPO)).collect(Collectors.toList());
+    }
+}

+ 49 - 0
core/src/main/java/com/mooctest/crowd/domain/repository/TestToolRepo.java

@@ -0,0 +1,49 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.dao.TestToolDao;
+import com.mooctest.crowd.domain.domainobject.TestEnv;
+import com.mooctest.crowd.domain.domainobject.TestTool;
+import com.mooctest.crowd.domain.model.TestEnvPO;
+import com.mooctest.crowd.domain.model.TestToolPO;
+import com.mooctest.crowd.domain.util.Converter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Component
+public class TestToolRepo implements ITestToolRepo {
+    @Autowired
+    private TestToolDao testToolDao;
+
+    @Override
+    public void save(TestTool testTool) {
+        TestToolPO testToolPO = Converter.convert(TestToolPO.class, testTool);
+        testToolDao.save(testToolPO);
+        testToolPO.setId(testToolPO.getId());
+    }
+
+    @Override
+    public List<TestTool> findAllByTaskCodeAndUserId(String taskCode, Long userId) {
+        List<TestToolPO> testToolPOs = testToolDao.findAllByTaskCodeAndUserId(taskCode, userId);
+        return testToolPOs.stream().map(testToolPO -> Converter.convert(TestTool.class, testToolPO)).collect(Collectors.toList());
+    }
+
+    @Override
+    public void deleteById(Long id) {
+        testToolDao.deleteById(id);
+    }
+
+    @Override
+    public TestTool findById(Long id) {
+        TestToolPO testToolPO = testToolDao.findById(id).orElse(null);
+        return Converter.convert(TestTool.class, testToolPO);
+    }
+
+    @Override
+    public List<TestTool> findAllByTaskCode(String taskCode) {
+        List<TestToolPO> testToolPOs = testToolDao.findAllByTaskCode(taskCode);
+        return testToolPOs.stream().map(testToolPO -> Converter.convert(TestTool.class, testToolPO)).collect(Collectors.toList());
+    }
+}

+ 10 - 3
core/src/main/java/com/mooctest/crowd/domain/repository/UserRepo.java

@@ -454,9 +454,16 @@ public class UserRepo implements IUserRepo {
         return userResult;
     }
 
-
-
-
+    @Override
+    public User getByEmail(String email) throws UserNotExistException, RoleNotFoundException {
+        UserPO userPO = userDao.findByEmail(email);
+        if (userPO == null) {
+            throw new UserNotExistException("用户不存在");
+        } else {
+            User user = getUserAndRoleAndPermissionByUserPO(userPO);
+            return user;
+        }
+    }
 
     private User getEvaluationInfo(User userResult) {
         /*获取测评机构信息*/

+ 3 - 0
core/src/main/java/com/mooctest/crowd/domain/util/Converter.java

@@ -21,6 +21,9 @@ public class Converter {
 
     public static <T> T convert(Class<T> targetClass, Object source) {
         try {
+            if (source == null) {
+                return null;
+            }
             T target = targetClass.newInstance();
             BeanCopier copier = getCopier(source.getClass(), targetClass);
             copier.copy(source, target, primitiveConverter);

+ 16 - 1
site/pom.xml

@@ -36,7 +36,7 @@
 			<groupId>mysql</groupId>
 			<artifactId>mysql-connector-java</artifactId>
 			<scope>runtime</scope>
-			<version>5.1.6</version>
+<!--			<version>5.1.6</version>-->
 		</dependency>
 		<dependency>
 			<groupId>org.projectlombok</groupId>
@@ -131,6 +131,21 @@
 			<artifactId>easypoi-annotation</artifactId>
 			<version>3.0.3</version>
 		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi</artifactId>
+			<version>4.1.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml</artifactId>
+			<version>4.1.2</version>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.poi</groupId>
+			<artifactId>poi-ooxml-schemas</artifactId>
+			<version>4.1.2</version>
+		</dependency>
 		<!-- Shiro -->
 		<dependency>
 			<groupId>org.apache.shiro</groupId>

+ 3 - 0
site/src/main/java/com/mooctest/crowd/site/SiteApplication.java

@@ -2,8 +2,11 @@ package com.mooctest.crowd.site;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
 import org.springframework.boot.web.servlet.ServletComponentScan;
 import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
 import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.scheduling.annotation.EnableScheduling;
 

+ 55 - 0
site/src/main/java/com/mooctest/crowd/site/command/DefectAddedCommand.java

@@ -0,0 +1,55 @@
+package com.mooctest.crowd.site.command;
+
+import com.mooctest.crowd.domain.env.DefectType;
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.Seriousness;
+import com.mooctest.crowd.domain.env.TestStatus;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class DefectAddedCommand {
+    //用例编号
+    @NotEmpty(message = "用例编号不能为空")
+    private String testCaseCode;
+    //任务编号
+    @NotEmpty(message = "任务编号不能为空")
+    private String taskCode;
+    @NotEmpty(message = "缺陷描述不能为空")
+    private String descr;
+    @NotEmpty(message = "严重等级不能为空")
+    private Seriousness seriousness;
+    //前置条件
+    private String preconditions;
+    //环境配置
+    private String envConfig;
+    //优先级
+    @NotNull(message = "优先级不能为空")
+    private Priority priority;
+    //缺陷类型
+    @NotNull(message = "缺陷类型不能为空")
+    private DefectType defectType;
+    //操作步骤
+    private String opeSteps;
+    //输入数据
+    private String inputDatas;
+    //预期结果
+    private String expectedResult;
+    //评判标准
+    private String evaCriteria;
+    //其他说明
+    private String others;
+    //提交人员id
+    private Long commiterId;
+    //测试结果
+    @NotEmpty(message = "测试结果不能为空")
+    private String testResult;
+    //附件列表
+    private List<String> files;
+    //截图列表
+    private List<String> screenshots;
+    private String importCode;
+}

+ 50 - 0
site/src/main/java/com/mooctest/crowd/site/command/DefectUpdatedCommand.java

@@ -0,0 +1,50 @@
+package com.mooctest.crowd.site.command;
+
+import com.mooctest.crowd.domain.env.DefectType;
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.Seriousness;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class DefectUpdatedCommand {
+    @NotNull(message = "id不能为空")
+    private Long id;
+    @NotEmpty(message = "缺陷描述不能为空")
+    private String descr;
+    @NotEmpty(message = "严重等级不能为空")
+    private Seriousness seriousness;
+    //前置条件
+    private String preconditions;
+    //环境配置
+    private String envConfig;
+    //优先级
+    @NotNull(message = "优先级不能为空")
+    private Priority priority;
+    //缺陷类型
+    @NotNull(message = "缺陷类型不能为空")
+    private DefectType defectType;
+    //操作步骤
+    private String opeSteps;
+    //输入数据
+    private String inputDatas;
+    //预期结果
+    private String expectedResult;
+    //评判标准
+    private String evaCriteria;
+    //其他说明
+    private String others;
+    //提交人员id
+    @NotNull(message = "提交人员不能为空")
+    private Long commiterId;
+    //测试结果
+    private String testResult;
+    //附件列表
+    private List<String> files;
+    //截图列表
+    private List<String> screenshots;
+    private String importCode;
+}

+ 20 - 0
site/src/main/java/com/mooctest/crowd/site/command/Login2Command.java

@@ -0,0 +1,20 @@
+package com.mooctest.crowd.site.command;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+
+/**
+ * @Author: xuexb
+ * @Date: 2019.7.5 14:24
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Login2Command {
+    private String email;
+    private String password;
+}

+ 54 - 0
site/src/main/java/com/mooctest/crowd/site/command/TestCaseAddedCommand.java

@@ -0,0 +1,54 @@
+package com.mooctest.crowd.site.command;
+
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.TestStatus;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class TestCaseAddedCommand {
+    //任务编号
+    @NotEmpty(message = "任务编号不能为空")
+    private String taskCode;
+    //用例名字
+    @NotEmpty(message = "用例名字不能为空")
+    private String name;
+    //用例描述
+    private String descr;
+    //前置条件
+    private String preconditions;
+    //环境配置
+    private String envConfig;
+    //优先级
+    @NotNull(message = "优先级不能为空")
+    private Priority priority;
+    //操作步骤
+    private String opeSteps;
+    //输入数据
+    private String inputDatas;
+    //预期结果
+    private String expectedResult;
+    //评判标准
+    private String evaCriteria;
+    //其他说明
+    private String others;
+    //设计人员id
+    @NotNull(message = "设计人员不能为空")
+    private Long designerId;
+    //测试结果
+    private String testResult;
+    //测试结果状态
+    @NotNull(message = "测试结果状态不能为空")
+    private TestStatus testStatus;
+    //附件列表
+    private List<String> files;
+    //截图列表
+    private List<String> screenshots;
+    //关联需求
+    private String demand;
+    private String associatedCode;
+    private String importCode;
+}

+ 51 - 0
site/src/main/java/com/mooctest/crowd/site/command/TestCaseUpdatedCommand.java

@@ -0,0 +1,51 @@
+package com.mooctest.crowd.site.command;
+
+import com.mooctest.crowd.domain.env.Priority;
+import com.mooctest.crowd.domain.env.TestStatus;
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class TestCaseUpdatedCommand {
+    //id
+    @NotNull(message = "id不能为空")
+    private Long id;
+    //用例名字
+    @NotEmpty(message = "用例名字不能为空")
+    private String name;
+    //用例描述
+    private String descr;
+    //前置条件
+    private String preconditions;
+    //环境配置
+    private String envConfig;
+    //优先级
+    @NotNull(message = "优先级不能为空")
+    private Priority priority;
+    //操作步骤
+    private String opeSteps;
+    //输入数据
+    private String inputDatas;
+    //预期结果
+    private String expectedResult;
+    //评判标准
+    private String evaCriteria;
+    //其他说明
+    private String others;
+    private Long designerId;
+    //测试结果
+    private String testResult;
+    //测试结果状态
+    @NotNull(message = "测试结果状态不能为空")
+    private TestStatus testStatus;
+    //附件列表
+    private List<String> files;
+    //截图列表
+    private List<String> screenshots;
+    //关联需求
+    private String demand;
+    private String associatedCode;
+}

+ 29 - 0
site/src/main/java/com/mooctest/crowd/site/command/TestEnvAddedCommand.java

@@ -0,0 +1,29 @@
+package com.mooctest.crowd.site.command;
+
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class TestEnvAddedCommand {
+    @NotEmpty(message = "任务编号不能为空")
+    private String taskCode;
+    @NotNull(message = "用户id不能为空")
+    private Long userId;
+    @NotEmpty(message = "设备名字不能为空")
+    private String devName; //设备名称
+    private String devModel; //设备型号
+    @NotNull(message = "设备数量不能为空")
+    @Min(value = 1, message = "设备数量不能小于1")
+    private Integer devCount; //设备数量
+    @NotEmpty(message = "硬件配置不能为空")
+    private String devConfig; //设备硬件配置
+    @NotEmpty(message = "操作系统不能为空")
+    private String opeSys; //操作系统
+    private String middleware; //中间件
+    private String db; //数据库
+    private String browser; //浏览器
+    private String supportSoftware; //支持软件
+}

+ 29 - 0
site/src/main/java/com/mooctest/crowd/site/command/TestEnvUpdatedCommand.java

@@ -0,0 +1,29 @@
+package com.mooctest.crowd.site.command;
+
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class TestEnvUpdatedCommand {
+    @NotNull(message = "id不能为空")
+    private Long id;
+    @NotNull(message = "用户id不能为空")
+    private Long userId;
+    @NotEmpty(message = "设备名字不能为空")
+    private String devName; //设备名称
+    private String devModel; //设备型号
+    @NotNull(message = "设备数量不能为空")
+    @Min(value = 1, message = "设备数量不能小于1")
+    private Integer devCount; //设备数量
+    @NotEmpty(message = "硬件配置不能为空")
+    private String devConfig; //设备硬件配置
+    @NotEmpty(message = "操作系统不能为空")
+    private String opeSys; //操作系统
+    private String middleware; //中间件
+    private String db; //数据库
+    private String browser; //浏览器
+    private String supportSoftware; //支持软件
+}

+ 20 - 0
site/src/main/java/com/mooctest/crowd/site/command/TestToolAddedCommand.java

@@ -0,0 +1,20 @@
+package com.mooctest.crowd.site.command;
+
+import lombok.Data;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class TestToolAddedCommand {
+    @NotEmpty(message = "任务编号不能为空")
+    private String taskCode;
+    @NotNull(message = "用户id不能为空")
+    private Long userId;
+    @NotEmpty(message = "工具名字不能为空")
+    private String name; //名字
+    private String version; //版本
+    private String producerFrom; //生产商/来源
+    private String purpose; //用途
+}

+ 19 - 0
site/src/main/java/com/mooctest/crowd/site/command/TestToolUpdatedCommand.java

@@ -0,0 +1,19 @@
+package com.mooctest.crowd.site.command;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class TestToolUpdatedCommand {
+    @NotNull(message = "id不能为空")
+    private Long id;
+    @NotNull(message = "用户id不能为空")
+    private Long userId;
+    @NotEmpty(message = "工具名字不能为空")
+    private String name; //名字
+    private String version; //版本
+    private String producerFrom; //生产商/来源
+    private String purpose; //用途
+}

+ 52 - 0
site/src/main/java/com/mooctest/crowd/site/configuration/RedisConfiguration.java

@@ -0,0 +1,52 @@
+package com.mooctest.crowd.site.configuration;
+
+import com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.listener.RedisMessageListenerContainer;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+@Configuration
+@AutoConfigureAfter(RedisAutoConfiguration.class)
+public class RedisConfiguration {
+    @Bean
+    @SuppressWarnings("all")
+    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory factory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
+        template.setConnectionFactory(factory);
+        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+//        FastJsonRedisSerializer fastJsonRedisSerializer = new FastJsonRedisSerializer(Object.class);  不用该序列化器,该序列化器会调用OssDynamicJsonSerializer然后存入redis,导致反序列化报错
+        GenericFastJsonRedisSerializer fastJsonRedisSerializer = new GenericFastJsonRedisSerializer();
+        ObjectMapper om = new ObjectMapper();
+        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        // key采用String的序列化方式
+        template.setKeySerializer(stringRedisSerializer);
+        // hash的key也采用String的序列化方式
+        template.setHashKeySerializer(stringRedisSerializer);
+        // value序列化方式采用jackson
+        template.setValueSerializer(fastJsonRedisSerializer);
+        // hash的value序列化方式采用jackson
+        template.setHashValueSerializer(fastJsonRedisSerializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    @Bean
+    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory) {
+        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
+        container.setConnectionFactory(connectionFactory);
+        return container;
+    }
+
+}

+ 2 - 2
site/src/main/java/com/mooctest/crowd/site/configuration/WebMvcConfiguration.java

@@ -29,10 +29,10 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
     public void addInterceptors(InterceptorRegistry registry) {
         registry.addInterceptor(fileCheckInterceptor)
                 .addPathPatterns("/api/files/**");
-//        registry.addInterceptor(authCheckInterceptor)
+        registry.addInterceptor(authCheckInterceptor);
 //                .excludePathPatterns("/api/common/**")
 //                .addPathPatterns("/**");
-//        registry.addInterceptor(sysAdminCheckInterceptor)
+        registry.addInterceptor(sysAdminCheckInterceptor);
 //                .addPathPatterns("/api/user/**");
     }
     }

+ 1 - 0
site/src/main/java/com/mooctest/crowd/site/constants/UploadType.java

@@ -10,6 +10,7 @@ public class UploadType {
     public static final String REQUIREMENT_FILE = "RequirementDoc/";
     public static final String APK = "Apk/";
     public static final String REPORT = "Report/";
+    public static final String TEST_CASE = "TestCase/";
     public static final String IMAGE = "Image/";
     public static final String AUTH_INFO = "AuthInfo/";
     public static final String OTHERS = "Others/";

Datei-Diff unterdrückt, da er zu groß ist
+ 0 - 0
site/src/main/java/com/mooctest/crowd/site/controller/CommonController.java


+ 9 - 0
site/src/main/java/com/mooctest/crowd/site/controller/CrowdProjectController.java

@@ -12,8 +12,10 @@ import com.mooctest.crowd.site.data.dto.UserProjectDTO;
 import com.mooctest.crowd.site.data.response.ResponseVO;
 import com.mooctest.crowd.site.data.response.ServerCode;
 import com.mooctest.crowd.site.data.vo.RegionalManagerVO;
+import com.mooctest.crowd.site.data.vo.SimpleTaskDataVO;
 import com.mooctest.crowd.site.service.CrowdProjectService;
 import com.mooctest.crowd.site.util.FileUtil;
+import com.mooctest.crowd.site.util.RequestUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
@@ -24,6 +26,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 import java.io.IOException;
 import java.util.List;
@@ -272,4 +275,10 @@ public class CrowdProjectController{
         Long userId = Long.parseLong(userIdStr);
         return new ResponseVO<>(ServerCode.SUCCESS, projectService.getProjectByToken(projectCode, taskCode, userId, token));
     }
+
+    @LoginRequired
+    @RequestMapping(value = "/api/simpleprojectdatas", method = RequestMethod.GET)
+    public ResponseVO<List<SimpleTaskDataVO>> getSimpleProjectDatas(HttpServletRequest request){
+        return new ResponseVO(ServerCode.SUCCESS, projectService.findSimpleProjectDatasByRegionalManagerId(RequestUtils.getUserId(request)));
+    }
 }

+ 107 - 0
site/src/main/java/com/mooctest/crowd/site/controller/CrowdTaskController.java

@@ -1,16 +1,26 @@
 package com.mooctest.crowd.site.controller;
 
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.domainobject.TestEnv;
+import com.mooctest.crowd.domain.env.TestStatus;
 import com.mooctest.crowd.domain.exception.BaseException;
 import com.mooctest.crowd.domain.exception.UnauthorizedException;
+import com.mooctest.crowd.domain.page.DOPage;
 import com.mooctest.crowd.site.annotation.LoginRequired;
 import com.mooctest.crowd.site.command.CrowdTestTaskCommand;
 import com.mooctest.crowd.site.command.TaskDataBoardCommand;
 import com.mooctest.crowd.site.data.dto.TaskDetailsDTO;
 import com.mooctest.crowd.site.data.dto.TaskSquareDTO;
+import com.mooctest.crowd.site.data.vo.*;
 import com.mooctest.crowd.site.data.response.ResponseVO;
 import com.mooctest.crowd.site.data.response.ServerCode;
 import com.mooctest.crowd.site.data.tfidf.JabaResult;
 import com.mooctest.crowd.site.service.CrowdTaskService;
+import com.mooctest.crowd.site.service.TestCaseService;
+import com.mooctest.crowd.site.service.TestEnvService;
+import com.mooctest.crowd.site.service.TestToolService;
+import com.mooctest.crowd.site.util.RedisHelper;
+import com.mooctest.crowd.site.util.RequestUtils;
 import io.swagger.annotations.Api;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -18,8 +28,11 @@ import org.springframework.validation.BindingResult;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 import java.util.List;
+import java.util.UUID;
+import java.util.stream.Collectors;
 
 /**
  * @author: Diors.Po
@@ -34,6 +47,14 @@ public class CrowdTaskController{
 
     @Autowired
     private CrowdTaskService taskService;
+    @Autowired
+    private TestCaseService testCaseService;
+    @Autowired
+    private TestEnvService testEnvService;
+    @Autowired
+    private TestToolService testToolService;
+    @Autowired
+    private RedisHelper redisHelper;
 
     @RequestMapping(value = "/project/{projectCode}/task/{taskCode}", method = RequestMethod.GET)
     public TaskDetailsDTO getTask(@PathVariable("projectCode") String projectCode, @PathVariable("taskCode") String taskCode, HttpSession session){
@@ -152,4 +173,90 @@ public class CrowdTaskController{
         Long userId = Long.parseLong((String)session.getAttribute("userId"));
         return new ResponseVO<>(ServerCode.SUCCESS, taskService.getToken(projectCode, taskCode, userId));
     }
+
+    @LoginRequired
+    @RequestMapping(value = "/simpleusertaskdatas", method = RequestMethod.GET)
+    public ResponseVO<List<SimpleUserTaskDataVO>> getSimpleUserTaskDatas(HttpServletRequest request){
+        return new ResponseVO(ServerCode.SUCCESS, taskService.findSimpleTaskDatasByUserId(RequestUtils.getUserId(request)));
+    }
+
+    @RequestMapping(value = "/simpletaskdatas/{projectCode}", method = RequestMethod.GET)
+    public ResponseVO<List<SimpleTaskDataVO>> getSimpleTaskDatasByProject(@PathVariable String projectCode){
+        return new ResponseVO(ServerCode.SUCCESS, taskService.findSimpleTaskDatasByProjectCode(projectCode));
+    }
+
+    @LoginRequired
+    @RequestMapping(value = "/project/{projectCode}/task/{taskCode}/taskusers", method = RequestMethod.GET)
+    public ResponseVO<List<TaskUserSimpleData>> getTaskUserDatas(HttpServletRequest request, @PathVariable("projectCode") String projectCode, @PathVariable("taskCode") String taskCode){
+        return new ResponseVO(ServerCode.SUCCESS, taskService.getTaskDetails(projectCode, taskCode, RequestUtils.getUserId(request))
+                .getAcceptedUserList().stream().map(taskToUserVO -> {
+            UserVO userVO = taskToUserVO.getUserVO();
+            TaskUserSimpleData taskUserSimpleData = new TaskUserSimpleData();
+            taskUserSimpleData.setUsername(userVO.getUserName());
+            taskUserSimpleData.setName(userVO.getName());
+            taskUserSimpleData.setId(userVO.getId());
+            taskUserSimpleData.setIsCommitted(taskToUserVO.getIsCommitted());
+            return taskUserSimpleData;
+        }).collect(Collectors.toList()));
+    }
+
+    @LoginRequired
+    @RequestMapping(value = "/task/{taskCode}/commit", method = RequestMethod.PUT)
+    public ResponseVO commitTask2(HttpServletRequest request, @PathVariable("taskCode") String taskCode){
+        Long userId = RequestUtils.getUserId(request);
+        DOPage<TestCase> page = testCaseService.find(userId, userId, taskCode, 0, 1000, null);
+        if (page.getDatas().size() == 0) {
+            return new ResponseVO(ServerCode.ERROR, "提交的任务未包含测试用例!");
+        }
+        long count = page.getDatas().stream().filter(testCase ->
+            testCase.getTestStatus().equals(TestStatus.WAIT)
+        ).count();
+        if (count > 0) {
+            return new ResponseVO(ServerCode.ERROR, String.format("测试用例中存在%d条未测试的记录,请确认并更新未测试记录的测试结论!", count));
+        }
+        count = page.getDatas().stream().filter(testCase ->
+            testCase.getTestStatus().equals(TestStatus.NO_PASS) && testCase.getDefects().size() == 0
+        ).count();
+        if (count > 0) {
+            return new ResponseVO(ServerCode.ERROR, String.format("测试用例中存在%d条测试未通过且未包含缺陷的记录,请确认并添加至少一条缺陷记录!", count));
+        }
+        count = page.getDatas().stream().filter(testCase ->
+                testCase.getTestStatus().equals(TestStatus.PASS) && testCase.getDefects().size() > 0
+        ).count();
+        if (count > 0) {
+            return new ResponseVO(ServerCode.ERROR, String.format("测试用例中存在%d条测试通过却包含缺陷的记录,请确认并删除多余的缺陷记录!", count));
+        }
+        List<TestEnv> testEnvs = testEnvService.findAllByTaskCodeAndUserId(taskCode, userId, userId);
+        if (testEnvs.size() == 0) {
+            return new ResponseVO(ServerCode.ERROR, "请补充测试的环境信息");
+        }
+        taskService.commitTask(page.getDatas().get(0).getProjectCode(), taskCode, userId);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+
+    @LoginRequired
+    @RequestMapping(value = "/task/{taskCode}/statistics", method = RequestMethod.GET)
+    public ResponseVO<TaskStatisticsVO> getTaskStatistics(HttpServletRequest request, @PathVariable("taskCode") String taskCode) {
+        Long userId = RequestUtils.getUserId(request);
+        return new ResponseVO(ServerCode.SUCCESS, taskService.getTaskStatistics(userId, taskCode));
+    }
+
+    @LoginRequired
+    @RequestMapping(value = "/task/{taskCode}/completion", method = RequestMethod.GET)
+    public ResponseVO<Double> getTaskCompletion(HttpServletRequest request, @PathVariable("taskCode") String taskCode) {
+        Long userId = RequestUtils.getUserId(request);
+        String token = UUID.randomUUID().toString();
+        redisHelper.hset("token", token, userId, 360000);
+        System.out.println("token=======" + token);
+        return new ResponseVO(ServerCode.SUCCESS, 0.0d);
+    }
+
+    @RequestMapping(value = "/task/{taskCode}/moreinfo", method = RequestMethod.GET)
+    public ResponseVO<TaskMoreInfoVO> getTaskMoreInfo(String token, @PathVariable("taskCode") String taskCode){
+        Long userId = (Long)redisHelper.hget("token", token);
+        if (userId == null) {
+            throw new BaseException("token无效");
+        }
+        return new ResponseVO(ServerCode.SUCCESS, taskService.getTaskMoreInfo(userId, taskCode));
+    }
 }

+ 142 - 0
site/src/main/java/com/mooctest/crowd/site/controller/TestCaseController.java

@@ -0,0 +1,142 @@
+package com.mooctest.crowd.site.controller;
+
+import com.alibaba.druid.util.StringUtils;
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.site.annotation.LoginRequired;
+import com.mooctest.crowd.site.command.DefectAddedCommand;
+import com.mooctest.crowd.site.command.DefectUpdatedCommand;
+import com.mooctest.crowd.site.command.TestCaseAddedCommand;
+import com.mooctest.crowd.site.command.TestCaseUpdatedCommand;
+import com.mooctest.crowd.site.data.dto.TestCaseExamCommand;
+import com.mooctest.crowd.site.data.dto.TestCaseSearchDTO;
+import com.mooctest.crowd.site.data.response.ResponseVO;
+import com.mooctest.crowd.site.data.response.ServerCode;
+import com.mooctest.crowd.site.service.DefectService;
+import com.mooctest.crowd.site.service.TestCaseService;
+import com.mooctest.crowd.site.util.RequestUtils;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+@RestController
+@RequestMapping("/api/testcase")
+@Api(tags = "测试用例接口")
+public class TestCaseController {
+    @Autowired
+    private TestCaseService testCaseService;
+    @Autowired
+    private DefectService defectService;
+
+    @PostMapping(value = "/")
+    @LoginRequired
+    public ResponseVO<Long> add(HttpServletRequest request, @RequestBody TestCaseAddedCommand testCaseAddedCommand) {
+        testCaseAddedCommand.setDesignerId(RequestUtils.getUserId(request));
+        TestCase testCase = testCaseService.add(testCaseAddedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, testCase.getId());
+    }
+
+    @PutMapping(value = "/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO update(HttpServletRequest request, @PathVariable Long id, @Validated @RequestBody TestCaseUpdatedCommand testCaseUpdatedCommand) {
+        testCaseUpdatedCommand.setId(id);
+        testCaseUpdatedCommand.setDesignerId(RequestUtils.getUserId(request));
+        testCaseService.update(testCaseUpdatedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, null);
+    }
+
+    @DeleteMapping(value = "/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO delete(HttpServletRequest request, @PathVariable Long id) {
+        testCaseService.delete(RequestUtils.getUserId(request), id);
+        return new ResponseVO(ServerCode.SUCCESS, null);
+    }
+
+    @GetMapping(value = "/designer/{taskCode}/{designerId:\\d+}/{pageNo:\\d+}/{pageSize:\\d+}")
+    @LoginRequired
+    public ResponseVO<DOPage<TestCase>> list(HttpServletRequest request, @PathVariable String taskCode,
+                                             @PathVariable Long designerId, @PathVariable Integer pageNo,
+                                             @PathVariable Integer pageSize, String testStatus, String examStatus) {
+        if (designerId.equals(0L)) {
+            designerId = RequestUtils.getUserId(request);
+        }
+        TestCaseSearchDTO testCaseSearchDTO = new TestCaseSearchDTO();
+        testCaseSearchDTO.setTestStatus(StringUtils.isEmpty(testStatus) ? null : TestStatus.valueOf(testStatus));
+        testCaseSearchDTO.setExamStatus(StringUtils.isEmpty(examStatus) ? null : TestCaseExamStatus.valueOf(examStatus));
+
+        DOPage<TestCase> page = testCaseService.find(designerId, RequestUtils.getUserId(request), taskCode, pageNo, pageSize, testCaseSearchDTO);
+        return new ResponseVO<>(ServerCode.SUCCESS, page);
+    }
+
+    @GetMapping(value = "/designer/defects/{taskCode}/{committerId:\\d+}/{pageNo:\\d+}/{pageSize:\\d+}")
+    @LoginRequired
+    public ResponseVO<DOPage<Defect>> defectList(HttpServletRequest request, @PathVariable String taskCode,
+                                             @PathVariable Long committerId, @PathVariable Integer pageNo,
+                                             @PathVariable Integer pageSize, String testStatus, String examStatus) {
+        if (committerId.equals(0L)) {
+            committerId = RequestUtils.getUserId(request);
+        }
+        TestCaseSearchDTO testCaseSearchDTO = new TestCaseSearchDTO();
+        testCaseSearchDTO.setTestStatus(StringUtils.isEmpty(testStatus) ? null : TestStatus.valueOf(testStatus));
+        testCaseSearchDTO.setExamStatus(StringUtils.isEmpty(examStatus) ? null : TestCaseExamStatus.valueOf(examStatus));
+
+        DOPage<Defect> page = defectService.findUserDefects(committerId, RequestUtils.getUserId(request), taskCode, pageNo, pageSize);
+        return new ResponseVO(ServerCode.SUCCESS, page);
+    }
+
+    @PostMapping(value = "/defect")
+    @LoginRequired
+    public ResponseVO<Long> addDefect(HttpServletRequest request, @RequestBody DefectAddedCommand defectAddedCommand) {
+        defectAddedCommand.setCommiterId(RequestUtils.getUserId(request));
+        Defect defect = defectService.add(defectAddedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, defect.getId());
+    }
+
+    @PutMapping(value = "/defect/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO updateDefect(HttpServletRequest request, @RequestBody DefectUpdatedCommand defectUpdatedCommand) {
+        defectUpdatedCommand.setCommiterId(RequestUtils.getUserId(request));
+        Defect defect = defectService.update(defectUpdatedCommand);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+
+    @DeleteMapping(value = "/defect/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO deleteDefect(HttpServletRequest request, @PathVariable Long id) {
+        defectService.delete(RequestUtils.getUserId(request), id);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+
+    @PutMapping(value = "/exam/{id}")
+    @LoginRequired
+    public ResponseVO exam(HttpServletRequest request, @PathVariable Long id, @RequestBody TestCaseExamCommand testCaseExamCommand) {
+        testCaseExamCommand.setExamerId(RequestUtils.getUserId(request));
+        testCaseExamCommand.setId(id);
+        testCaseService.exam(testCaseExamCommand);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+
+    @PostMapping(value = "/upload/{taskCode}")
+    @LoginRequired
+    public ResponseVO uploadTestCases(HttpServletRequest request, MultipartFile file, @PathVariable String taskCode) throws IOException {
+        Long userId = RequestUtils.getUserId(request);
+        testCaseService.importTestCases(file.getBytes(), taskCode, userId);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+
+    @PostMapping(value = "/uploaddefects/{taskCode}")
+    @LoginRequired
+    public ResponseVO uploadDefects(HttpServletRequest request, MultipartFile file, @PathVariable String taskCode) throws IOException {
+        Long userId = RequestUtils.getUserId(request);
+        defectService.importDefects(file.getBytes(), taskCode, userId);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+}

+ 69 - 0
site/src/main/java/com/mooctest/crowd/site/controller/TestEnvController.java

@@ -0,0 +1,69 @@
+package com.mooctest.crowd.site.controller;
+
+import com.alibaba.druid.util.StringUtils;
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.domainobject.TestEnv;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.site.annotation.LoginRequired;
+import com.mooctest.crowd.site.command.*;
+import com.mooctest.crowd.site.data.dto.TestCaseExamCommand;
+import com.mooctest.crowd.site.data.dto.TestCaseSearchDTO;
+import com.mooctest.crowd.site.data.response.ResponseVO;
+import com.mooctest.crowd.site.data.response.ServerCode;
+import com.mooctest.crowd.site.service.DefectService;
+import com.mooctest.crowd.site.service.TestCaseService;
+import com.mooctest.crowd.site.service.TestEnvService;
+import com.mooctest.crowd.site.util.RequestUtils;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/testenv")
+@Api(tags = "测试环境接口")
+public class TestEnvController {
+    @Autowired
+    private TestEnvService testEnvService;
+
+    @PostMapping(value = "/")
+    @LoginRequired
+    public ResponseVO<Long> add(HttpServletRequest request, @RequestBody TestEnvAddedCommand testEnvAddedCommand) {
+        testEnvAddedCommand.setUserId(RequestUtils.getUserId(request));
+        TestEnv testEnv = testEnvService.add(testEnvAddedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, testEnv.getId());
+    }
+
+    @PutMapping(value = "/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO update(HttpServletRequest request, @PathVariable Long id, @Validated @RequestBody TestEnvUpdatedCommand testEnvUpdatedCommand) {
+        testEnvUpdatedCommand.setId(id);
+        testEnvUpdatedCommand.setUserId(RequestUtils.getUserId(request));
+        testEnvService.update(testEnvUpdatedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, null);
+    }
+
+    @DeleteMapping(value = "/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO delete(HttpServletRequest request, @PathVariable Long id) {
+        testEnvService.delete(id, RequestUtils.getUserId(request));
+        return new ResponseVO(ServerCode.SUCCESS, null);
+    }
+
+    @GetMapping(value = "/designer/{taskCode}/{designerId:\\d+}/")
+    @LoginRequired
+    public ResponseVO<List<TestEnv>> list(HttpServletRequest request, @PathVariable String taskCode,
+                                             @PathVariable Long designerId) {
+        if (designerId.equals(0L)) {
+            designerId = RequestUtils.getUserId(request);
+        }
+        List<TestEnv> testEnvs = testEnvService.findAllByTaskCodeAndUserId(taskCode, designerId, RequestUtils.getUserId(request));
+        return new ResponseVO<>(ServerCode.SUCCESS, testEnvs);
+    }
+}

+ 64 - 0
site/src/main/java/com/mooctest/crowd/site/controller/TestToolController.java

@@ -0,0 +1,64 @@
+package com.mooctest.crowd.site.controller;
+
+import com.mooctest.crowd.domain.domainobject.TestEnv;
+import com.mooctest.crowd.domain.domainobject.TestTool;
+import com.mooctest.crowd.site.annotation.LoginRequired;
+import com.mooctest.crowd.site.command.TestEnvAddedCommand;
+import com.mooctest.crowd.site.command.TestEnvUpdatedCommand;
+import com.mooctest.crowd.site.command.TestToolAddedCommand;
+import com.mooctest.crowd.site.command.TestToolUpdatedCommand;
+import com.mooctest.crowd.site.data.response.ResponseVO;
+import com.mooctest.crowd.site.data.response.ServerCode;
+import com.mooctest.crowd.site.service.TestEnvService;
+import com.mooctest.crowd.site.service.TestToolService;
+import com.mooctest.crowd.site.util.RequestUtils;
+import io.swagger.annotations.Api;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+@RestController
+@RequestMapping("/api/testtool")
+@Api(tags = "测试环境接口")
+public class TestToolController {
+    @Autowired
+    private TestToolService testToolService;
+
+    @PostMapping(value = "/")
+    @LoginRequired
+    public ResponseVO<Long> add(HttpServletRequest request, @RequestBody TestToolAddedCommand testToolAddedCommand) {
+        testToolAddedCommand.setUserId(RequestUtils.getUserId(request));
+        TestTool testTool = testToolService.add(testToolAddedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, testTool.getId());
+    }
+
+    @PutMapping(value = "/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO update(HttpServletRequest request, @PathVariable Long id, @Validated @RequestBody TestToolUpdatedCommand testToolUpdatedCommand) {
+        testToolUpdatedCommand.setId(id);
+        testToolUpdatedCommand.setUserId(RequestUtils.getUserId(request));
+        testToolService.update(testToolUpdatedCommand);
+        return new ResponseVO(ServerCode.SUCCESS, null);
+    }
+
+    @DeleteMapping(value = "/{id:\\d+}")
+    @LoginRequired
+    public ResponseVO delete(HttpServletRequest request, @PathVariable Long id) {
+        testToolService.delete(id, RequestUtils.getUserId(request));
+        return new ResponseVO(ServerCode.SUCCESS, null);
+    }
+
+    @GetMapping(value = "/designer/{taskCode}/{designerId:\\d+}/")
+    @LoginRequired
+    public ResponseVO<List<TestTool>> list(HttpServletRequest request, @PathVariable String taskCode,
+                                             @PathVariable Long designerId) {
+        if (designerId.equals(0L)) {
+            designerId = RequestUtils.getUserId(request);
+        }
+        List<TestTool> testTools = testToolService.findAllByTaskCodeAndUserId(taskCode, designerId, RequestUtils.getUserId(request));
+        return new ResponseVO<>(ServerCode.SUCCESS, testTools);
+    }
+}

+ 67 - 0
site/src/main/java/com/mooctest/crowd/site/controller/TesterController.java

@@ -0,0 +1,67 @@
+package com.mooctest.crowd.site.controller;
+
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.domainobject.User;
+import com.mooctest.crowd.domain.env.Seriousness;
+import com.mooctest.crowd.domain.util.Converter;
+import com.mooctest.crowd.site.data.response.ResponseVO;
+import com.mooctest.crowd.site.data.response.ServerCode;
+import com.mooctest.crowd.site.data.vo.TesterTaskVO;
+import com.mooctest.crowd.site.service.DefectService;
+import com.mooctest.crowd.site.service.UserService;
+import com.mooctest.crowd.site.util.RequestUtils;
+import io.swagger.annotations.Api;
+import org.apache.http.client.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+
+@RestController
+@RequestMapping("/api/tester")
+@Api(tags = "测试人员接口")
+public class TesterController {
+    @Autowired
+    private DefectService defectService;
+    @Autowired
+    private UserService userService;
+
+    @GetMapping(value = "/task/{userId}/{taskCode}")
+    public ResponseVO<TesterTaskVO> getTesterTaskInfo(HttpServletRequest request,  @PathVariable("userId") Long userId, @PathVariable("taskCode") String taskCode){
+        List<Defect> defects = defectService.findUserDefects(userId, RequestUtils.getUserId(request), taskCode, 0, 1000).getDatas();
+        List<TesterTaskVO.DefectInfoVO> defectInfoVOs = new ArrayList();
+        Map<String, Integer> defectSeriCountMap = new LinkedHashMap() {{
+            put(Seriousness.VERY_HIGH.getName(), 0);
+            put(Seriousness.HIGH.getName(), 0);
+            put(Seriousness.MID.getName(), 0);
+            put(Seriousness.LOW.getName(), 0);
+            put(Seriousness.VERY_LOW.getName(), 0);
+        }};
+        defects.stream().forEach(defect -> {
+            String seriName = defect.getSeriousness().getName();
+            TesterTaskVO.DefectInfoVO defectInfoVO = new TesterTaskVO.DefectInfoVO();
+            defectInfoVO.setId(defect.getId());
+            defectInfoVO.setDescr(defect.getDescr());
+            defectInfoVO.setCommitTime(DateUtils.formatDate(new Date(defect.getCommitTime().getTime()), "yy-MM-dd HH:mm"));
+            defectInfoVOs.add(defectInfoVO);
+            defectSeriCountMap.put(seriName, defectSeriCountMap.get(seriName) + 1);
+        });
+        List<Integer> defectSeriCounts = new ArrayList();
+        for(String key: defectSeriCountMap.keySet()) {
+            defectSeriCounts.add(defectSeriCountMap.get(key));
+        }
+        User user = userService.getById(userId);
+        TesterTaskVO.TesterInfoVO testerInfo = Converter.convert(TesterTaskVO.TesterInfoVO.class, user);
+        testerInfo.setCreateTime(DateUtils.formatDate(new Date(user.getCreateTime().getTime()), "yyyy-MM-dd HH:mm"));
+        TesterTaskVO testerTaskVO = new TesterTaskVO();
+        testerTaskVO.setTester(testerInfo);
+        testerTaskVO.setDefects(defectInfoVOs);
+        testerTaskVO.setDefectSeriCounts(defectSeriCounts);
+        return new ResponseVO<>(ServerCode.SUCCESS, testerTaskVO);
+    }
+
+}

+ 25 - 5
site/src/main/java/com/mooctest/crowd/site/controller/UploadController.java

@@ -1,6 +1,7 @@
 package com.mooctest.crowd.site.controller;
 
 import com.mooctest.crowd.site.service.UploadService;
+import com.mooctest.crowd.site.util.RequestUtils;
 import io.swagger.annotations.Api;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PathVariable;
@@ -9,6 +10,8 @@ import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.servlet.http.HttpServletRequest;
+
 /**
  * @author: Diors.Po
  * @Email: 171256175@qq.com
@@ -23,27 +26,32 @@ public class UploadController {
     private UploadService uploadService;
 
     @RequestMapping(value = "/requirementfile/{userId}", method = RequestMethod.POST)
-    public String uploadRequirementDoc(MultipartFile file, @PathVariable("userId") Long userId){
+    public String uploadRequirementDoc(HttpServletRequest request, MultipartFile file, @PathVariable("userId") Long userId){
+        userId = RequestUtils.getUserId(request);
         return uploadService.uploadRequirment(file, userId);
     }
 
     @RequestMapping(value = "/apk/{userId}", method = RequestMethod.POST)
-    public String uploadApk(MultipartFile file, @PathVariable("userId") Long userId){
+    public String uploadApk(HttpServletRequest request, MultipartFile file, @PathVariable("userId") Long userId){
+        userId = RequestUtils.getUserId(request);
         return uploadService.uploadAPK(file, userId);
     }
 
     @RequestMapping(value = "/report/{userId}", method = RequestMethod.POST)
-    public String uploadReport(MultipartFile file, @PathVariable("userId") Long userId){
+    public String uploadReport(HttpServletRequest request, MultipartFile file, @PathVariable("userId") Long userId){
+        userId = RequestUtils.getUserId(request);
         return uploadService.uploadReport(file, userId);
     }
 
     @RequestMapping(value = "/image/{userId}", method = RequestMethod.POST)
-    public String uploadImage(MultipartFile file, @PathVariable("userId") Long userId){
+    public String uploadImage(HttpServletRequest request, MultipartFile file, @PathVariable("userId") Long userId){
+        userId = RequestUtils.getUserId(request);
         return uploadService.uploadImage(file, userId);
     }
 
     @RequestMapping(value = "/authinfo/{userId}", method = RequestMethod.POST)
-    public String uploadAuthInfo(MultipartFile file, @PathVariable("userId") Long userId){
+    public String uploadAuthInfo(HttpServletRequest request, MultipartFile file, @PathVariable("userId") Long userId){
+        userId = RequestUtils.getUserId(request);
         return uploadService.uploadAuthInfo(file, userId);
     }
 
@@ -51,4 +59,16 @@ public class UploadController {
     public String uploadGeneralFile(MultipartFile file){
         return uploadService.uploadGeneralFile(file);
     }
+
+    @RequestMapping(value = "/testcasefile/", method = RequestMethod.POST)
+    public String uploadTestCaseFile(HttpServletRequest request, MultipartFile file){
+        Long userId = RequestUtils.getUserId(request);
+        return uploadService.uploadTestCaseFile(file, userId);
+    }
+
+    @RequestMapping(value = "/testcaseimage/", method = RequestMethod.POST)
+    public String uploadTestCaseImage(HttpServletRequest request, MultipartFile file){
+        Long userId = RequestUtils.getUserId(request);
+        return uploadService.uploadTestCaseImage(file, userId);
+    }
 }

+ 16 - 1
site/src/main/java/com/mooctest/crowd/site/controller/UserController.java

@@ -2,6 +2,7 @@ package com.mooctest.crowd.site.controller;
 
 import com.mooctest.crowd.domain.IpAddress.AddressUtils;
 import com.mooctest.crowd.domain.IpAddress.Area;
+import com.mooctest.crowd.domain.domainobject.User;
 import com.mooctest.crowd.domain.exception.*;
 import com.mooctest.crowd.site.annotation.LoginRequired;
 import com.mooctest.crowd.site.annotation.SysAdminRequired;
@@ -19,6 +20,7 @@ import com.mooctest.crowd.site.service.UserService;
 import com.mooctest.crowd.site.util.DataUtils;
 import io.swagger.annotations.Api;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.validation.BindingResult;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
@@ -42,7 +44,8 @@ public class UserController extends BaseController{
     private PersonalAuthService personalAuthService;
     @Autowired
     private EnterpriseAuthService enterpriseAuthService;
-
+    @Value("${spring.profiles.active}")
+    private String springProfilsActive;
 
     @Autowired
     private UserService userService;
@@ -338,4 +341,16 @@ public class UserController extends BaseController{
         return area;
     }
 
+    @RequestMapping(value = "/login2", method = RequestMethod.POST)
+    public ResponseVO login2(@RequestBody Login2Command login2Command, BindingResult result, HttpServletRequest request) throws PasswordErrorException, AccountNotExistException, BadRequestException {
+        if (result.hasErrors())
+            throw new BadRequestException(result.getFieldError().getDefaultMessage());
+        if (!"localhost".equals(springProfilsActive)) {
+            throw new BaseException("接口不存在");
+        }
+        User user = userService.loginByEmailAndPwd(login2Command.getEmail(), login2Command.getPassword());
+        request.getSession().setAttribute("userId", user.getId()+"");
+        request.getSession().setAttribute("userName", user.getEmail());
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
 }

+ 69 - 9
site/src/main/java/com/mooctest/crowd/site/controller/advice/ExceptionAdvice.java

@@ -1,14 +1,31 @@
 package com.mooctest.crowd.site.controller.advice;
 
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.mooctest.crowd.domain.domainobject.ExceptionLog;
 import com.mooctest.crowd.domain.exception.*;
 import com.mooctest.crowd.site.constants.ResponseConstant;
+import com.mooctest.crowd.site.service.ExceptionLogService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.catalina.util.RequestUtil;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.HttpRequestMethodNotSupportedException;
-import org.springframework.web.bind.annotation.ExceptionHandler;
-import org.springframework.web.bind.annotation.ResponseBody;
-import org.springframework.web.bind.annotation.ResponseStatus;
-import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.context.request.NativeWebRequest;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.Enumeration;
 
 /**
  * @author: Diors.Po
@@ -18,11 +35,13 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
 @Slf4j
 @RestControllerAdvice
 public class ExceptionAdvice {
+    @Autowired
+    private ExceptionLogService exceptionLogService;
 
     @ExceptionHandler(BaseException.class)
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public String handleException(Exception e){
-        log.error("访问出错:"+e.getMessage(), e);
+        logException(e);
         if (e instanceof AccountNotExistException){
             return ResponseConstant.USER_NOT_EXISTS;
         } else if (e instanceof NullPointerException){
@@ -63,14 +82,14 @@ public class ExceptionAdvice {
     @ExceptionHandler(UnauthorizedException.class)
     @ResponseStatus(HttpStatus.UNAUTHORIZED)
     public String handleUnauthorized(UnauthorizedException e){
-        log.info("401:未经认证的请求");
+        logException(e);
         return e.getMessage();
     }
 
     @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
     @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
     public String handlMethodNotAllowdd(HttpRequestMethodNotSupportedException e){
-        log.info("method not allowdd", e);
+        logException(e);
         return e.getMessage();
     }
 
@@ -78,7 +97,7 @@ public class ExceptionAdvice {
     @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
     @ResponseBody
     public String handleSystemException(Exception e){
-        log.error("System Error: "+e.getMessage(), e);
+        logException(e);
 //        return "系统异常 " + e.getMessage();
         return e.getMessage();
     }
@@ -86,7 +105,48 @@ public class ExceptionAdvice {
     @ExceptionHandler(Excel2ProjectException.class)
     @ResponseStatus(HttpStatus.BAD_REQUEST)
     public String handleExcel2ProjectException(Excel2ProjectException e){
-        log.error("Excel表中存在错误:"+e.getErrorLogs());
+        logException(e);
         return "Excel表中存在错误:"+ e.getErrorLogs();
     }
+
+    public void logException(Exception e) {
+        e.printStackTrace();
+        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+        HttpServletRequest request = requestAttributes.getRequest();
+        String exception = ExceptionUtils.getStackTrace(e);
+        String uri = request.getRequestURI();
+        String contentType = request.getContentType();
+        String params = "";
+        if (contentType.toLowerCase().contains("application/json")) {
+//            params = (String)request.getAttribute("REQ_JSON_BODY");
+//            int index = params.indexOf("password:");
+//            if (index != -1) {
+//                params = params.replace(params.substring(index, params.indexOf("\r\n", index)), "password: ******");
+//            }
+        } else {
+            Enumeration<String> paramNames = request.getParameterNames();
+            StringBuilder paramSb = new StringBuilder();
+            while(paramNames.hasMoreElements()) {
+                String paramName = paramNames.nextElement();
+                String[] paramVals = request.getParameterValues(paramName);
+                if (paramName.equals("password")) {
+                    paramVals[0] = "******";
+                }
+                String paramValues = StringUtils.joinWith("$$", paramVals);
+                paramSb.append(paramName).append("=").append(paramValues).append("&");
+            }
+            if (paramSb.length() > 1) {
+                params = paramSb.substring(0, paramSb.length() - 1);
+            }
+        }
+        ExceptionLog exceptionLog = new ExceptionLog();
+        exceptionLog.setException(exception);
+        exceptionLog.setUri(uri);
+        exceptionLog.setParams(params);
+        try {
+            exceptionLogService.save(exceptionLog);
+        } catch (Exception e1) {
+            e1.printStackTrace();
+        }
+    }
 }

+ 3 - 2
site/src/main/java/com/mooctest/crowd/site/controller/interceptor/AuthCheckInterceptor.java

@@ -3,6 +3,7 @@ package com.mooctest.crowd.site.controller.interceptor;
 import com.mooctest.crowd.domain.exception.BaseException;
 import com.mooctest.crowd.domain.exception.UnauthorizedException;
 import com.mooctest.crowd.site.annotation.LoginRequired;
+import com.mooctest.crowd.site.util.RequestUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import org.springframework.web.method.HandlerMethod;
@@ -23,10 +24,10 @@ public class AuthCheckInterceptor extends HandlerInterceptorAdapter {
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
         if (hasLoginRequired(handler)){
             log.info("需要认证的接口访问行为");
-            if (request.getSession().getAttribute("userId") == null)
+            if (RequestUtils.getUserId(request) == null)
                 throw new UnauthorizedException();
             else
-                log.info("用户已登录, userId:"+request.getSession().getAttribute("userId"));
+                log.info("用户已登录, userId:"+ RequestUtils.getUserId(request));
         }else
             log.info("无需认证的接口访问");
         return true;

+ 3 - 0
site/src/main/java/com/mooctest/crowd/site/controller/interceptor/SysAdminCheckInterceptor.java

@@ -6,7 +6,9 @@ import com.mooctest.crowd.domain.repository.UserRepo;
 import com.mooctest.crowd.site.annotation.SysAdminRequired;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.MethodParameter;
 import org.springframework.stereotype.Component;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.method.HandlerMethod;
 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
@@ -54,4 +56,5 @@ public class SysAdminCheckInterceptor extends HandlerInterceptorAdapter {
         }
         return false;
     }
+
 }

+ 6 - 0
site/src/main/java/com/mooctest/crowd/site/data/TaskOperationControl.java

@@ -22,6 +22,8 @@ public class TaskOperationControl {
     private boolean writeReport = false;
     private boolean taskDemonstrate = false;
     private boolean taskRecommend = false;
+    private boolean testCaseExam = false;
+    private boolean testCaseManage = false;
 
     public void hasAll(){
         this.receive = true;
@@ -32,6 +34,8 @@ public class TaskOperationControl {
         this.uploadReport = true;
         this.taskDemonstrate = true;
         this.taskRecommend = true;
+        this.testCaseExam = true;
+        this.testCaseManage = true;
     }
 
     public void noAll(){
@@ -44,5 +48,7 @@ public class TaskOperationControl {
         this.writeReport = false;
         this.taskDemonstrate = false;
         this.taskRecommend = false;
+        this.testCaseExam = false;
+        this.testCaseManage = false;
     }
 }

+ 17 - 0
site/src/main/java/com/mooctest/crowd/site/data/dto/TestCaseExamCommand.java

@@ -0,0 +1,17 @@
+package com.mooctest.crowd.site.data.dto;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Data
+public class TestCaseExamCommand {
+    @NotNull(message = "id不能为空")
+    private Long id;
+    @NotEmpty(message = "审核结果不能为空")
+    private String examStatus;
+    private String examDescr;
+    @NotNull(message = "审核人员id不能为空")
+    private Long examerId;
+}

+ 11 - 0
site/src/main/java/com/mooctest/crowd/site/data/dto/TestCaseSearchDTO.java

@@ -0,0 +1,11 @@
+package com.mooctest.crowd.site.data.dto;
+
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import lombok.Data;
+
+@Data
+public class TestCaseSearchDTO {
+    private TestStatus testStatus;
+    private TestCaseExamStatus examStatus;
+}

+ 10 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleProjectDataVO.java

@@ -0,0 +1,10 @@
+package com.mooctest.crowd.site.data.vo;
+
+import lombok.Data;
+
+@Data
+public class SimpleProjectDataVO {
+    private String name;
+    private String code;
+    private Long id;
+}

+ 11 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleTaskDataVO.java

@@ -0,0 +1,11 @@
+package com.mooctest.crowd.site.data.vo;
+
+import lombok.Data;
+
+@Data
+public class SimpleTaskDataVO {
+    private String name;
+    private String code;
+    private int status;
+    private Long id;
+}

+ 12 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleUserTaskDataVO.java

@@ -0,0 +1,12 @@
+package com.mooctest.crowd.site.data.vo;
+
+import lombok.Data;
+
+@Data
+public class SimpleUserTaskDataVO {
+    private String name;
+    private String code;
+    private int isCommitted;
+    private int status;
+    private Long id;
+}

+ 97 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/TaskMoreInfoVO.java

@@ -0,0 +1,97 @@
+package com.mooctest.crowd.site.data.vo;
+
+import com.mooctest.crowd.domain.domainobject.*;
+import lombok.Data;
+
+import java.sql.Timestamp;
+import java.util.List;
+
+@Data
+public class TaskMoreInfoVO {
+    private ProjectInfoVO project;
+    private TaskInfoVO task;
+    private ReceivingOrgInfoVO receivingOrg;
+    private DemandUnitInfoVO demandUnit;
+    private List<TesterInfoVO> testers;
+    private List<TestCase> testCases;
+    private List<Defect> defects;
+    private List<TestEnv> testEnvs;
+    private List<TestTool> testTools;
+
+    @Data
+    public static class TaskInfoVO {
+        private Long id;
+        private String name;
+        private String code;
+        private String type;
+        private String description;
+        private String requirementFile;
+        private Long distributionType;
+        private String distributionProvince;
+        private String distributionCity;
+        private Double quotedPrice;
+        private Double fixedPrice;
+        private int status;
+        private Timestamp deadTime;
+        private Timestamp endTime;
+        private Timestamp createTime;
+    }
+
+    @Data
+    public static class ProjectInfoVO {
+        private Long id;
+        private String name;
+        private String code;
+        private Long projectDistributionTypeId;
+        private String fieldType;
+        private String applicationType;
+        private String type;
+        private String description;
+        private String projectFile;
+        private String requirementFile;
+        private String distributionProvince;
+        private String distributionCity;
+        private String valuationStandard;
+        private Double quotedPrice;
+        private Double fixedPrice;
+        private Double restPrice;
+        private String entrustUnit;
+        private int status;
+        private Timestamp deadTime;
+        private Timestamp endTime;
+        private Timestamp createTime;
+    }
+
+    @Data
+    public static class TesterInfoVO {
+        private Long id;
+        private String name;
+        private String gender;
+        private String province;
+        private String city;
+        private String photoUrl;
+        private String unit;
+        private String county;
+        private String address;
+    }
+
+    @Data
+    public static class DemandUnitInfoVO {
+        private Long id;
+        private String name;
+        private String address;
+        private String province;
+        private String city;
+        private String county;
+    }
+
+    @Data
+    public static class ReceivingOrgInfoVO {
+        private Long id;
+        private String name;
+        private String address;
+        private String province;
+        private String city;
+        private String county;
+    }
+}

+ 39 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/TaskStatisticsVO.java

@@ -0,0 +1,39 @@
+package com.mooctest.crowd.site.data.vo;
+
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class TaskStatisticsVO {
+    private int testerCount;
+    private int testCaseCount;
+    private int validTestCaseCount;
+    private int noExamedTestCaseCount;
+    private int defectCount;
+    private String taskName;
+    private String taskCode;
+    private String projectCode;
+    private String projectName;
+    private String createTime;
+    private String endTime;
+    private int status;
+    private String statusDescr;
+    private List<TesterVO> testers;
+    //发包单位
+    private String companyName;
+    //发包单位城市
+    private String companyCity;
+    private List<Integer> defectSeriCounts;
+    private Map<String, Integer> defectTypeCountMap;
+    private Map<Integer, Integer> defectTimeCountMap;
+
+    @Data
+    public static class TesterVO {
+        private long id;
+        private String name;
+        private int score;
+        private String city;
+    }
+}

+ 11 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/TaskUserSimpleData.java

@@ -0,0 +1,11 @@
+package com.mooctest.crowd.site.data.vo;
+
+import lombok.Data;
+
+@Data
+public class TaskUserSimpleData {
+    private String name;
+    private Long id;
+    private String username;
+    private Integer isCommitted;
+}

+ 33 - 0
site/src/main/java/com/mooctest/crowd/site/data/vo/TesterTaskVO.java

@@ -0,0 +1,33 @@
+package com.mooctest.crowd.site.data.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TesterTaskVO {
+    private TesterInfoVO tester;
+    private List<DefectInfoVO> defects;
+    private List<Integer> defectSeriCounts;
+
+    @Data
+    public static class TesterInfoVO {
+        private Long id;
+        private String name;
+        private String gender;
+        private String province;
+        private String city;
+        private String photoUrl;
+        private String unit;
+        private String county;
+        private String address;
+        private String createTime;
+    }
+
+    @Data
+    public static class DefectInfoVO {
+        private Long id;
+        private String descr;
+        private String commitTime;
+    }
+}

+ 17 - 15
site/src/main/java/com/mooctest/crowd/site/mediator/impl/WebMediatorImpl.java

@@ -1713,12 +1713,22 @@ public class WebMediatorImpl implements ViewMediator {
         Optional<EndPointPO> endPointPOOptional = endPointDao.findByTaskCode(task.getCode());
         TaskOperationControl taskOperationControl = new TaskOperationControl();
 
-        if (user == null || task.getStatus() == CrowdTestTaskStatus.HAS_TIME_OUT) {
+        if (user == null) {
             return taskOperationControl;
         }
 
-        // 任务已结束,如果存在配置项的任务展示token则显示 任务面板按钮
-        if(task.getStatus() == CrowdTestTaskStatus.HAS_FINISHED){
+        if (user.getRoleList().stream().anyMatch(role -> role.getName().equals("SystemAdministrator"))
+                || (user.getRegionalManager() != null && user.getId().equals(project.getRegionalManagerId()))) {
+            taskOperationControl.setTestCaseExam(true);
+        }
+
+        List<TaskToUser> acceptedUserList = task.getAcceptedUserList();
+        Optional<TaskToUser> taskToUserOptional = acceptedUserList.stream().filter(taskToUser -> taskToUser.getUserId().equals(user.getId())).findFirst();
+        if (taskToUserOptional.isPresent()) {
+            taskOperationControl.setTestCaseManage(true);
+        }
+
+        if(task.getStatus() == CrowdTestTaskStatus.HAS_FINISHED){// 任务已结束,如果存在配置项的任务展示token则显示 任务面板按钮
             if(endPointPOOptional.isPresent()){
                 if(endPointPOOptional.get().getToken() != null &&  !endPointPOOptional.get().getToken().equals("")){
                     taskOperationControl.setTaskDemonstrate(true);
@@ -1728,10 +1738,7 @@ public class WebMediatorImpl implements ViewMediator {
             //区域管理员或系统管理员视角
             if (user.getRoleList().stream().anyMatch(role -> role.getName().equals("SystemAdministrator"))
                     || (user.getRegionalManager() != null && user.getId().equals(project.getRegionalManagerId()))) {
-                List<TaskToUser> acceptedUserList = task.getAcceptedUserList();
-                Optional<TaskToUser> taskToUserOptional = acceptedUserList.stream().filter(taskToUser -> taskToUser.getUserId().equals(user.getId())).findFirst();
                 if (task.getStatus() < CrowdTestTaskStatus.HAS_RECEIVED) {
-
                     taskOperationControl.setUpdate(true);
                     taskOperationControl.setTaskRecommend(true);
                     taskOperationControl.setReceive(true);
@@ -1740,10 +1747,10 @@ public class WebMediatorImpl implements ViewMediator {
                         taskOperationControl.setWriteReport(true);
                     }
                 }else if(task.getStatus() == CrowdTestTaskStatus.HAS_RECEIVED&&taskToUserOptional.isPresent()){
-                        taskOperationControl.setUploadReport(true);
-                        if (taskToUserOptional.get().getHasReport() == 1 && taskToUserOptional.get().getIsCommitted() == 0) {
-                            taskOperationControl.setFinish(true);
-                        } else if (taskToUserOptional.get().getHasReport() == 1 && taskToUserOptional.get().getIsCommitted() == 1) {
+                    taskOperationControl.setUploadReport(true);
+                    if (taskToUserOptional.get().getHasReport() == 1 && taskToUserOptional.get().getIsCommitted() == 0) {
+                        taskOperationControl.setFinish(true);
+                    } else if (taskToUserOptional.get().getHasReport() == 1 && taskToUserOptional.get().getIsCommitted() == 1) {
                         taskOperationControl.setFinish(false);
                         taskOperationControl.setUploadReport(false);
                     }
@@ -1772,9 +1779,6 @@ public class WebMediatorImpl implements ViewMediator {
             else if (AuthCheckServiceImpl.isAgency(user) && task.getStatus() != CrowdTestTaskStatus.HAS_REJECTED) {
                 if ((task.getDistributionType() == 0 && task.getEvaluationAgencyId().equals(user.getId()))
                         || (task.getDistributionType() == 2 && task.getStatus() >= CrowdTestTaskStatus.HAS_RECEIVED)) {
-                    List<TaskToUser> acceptedUserList = task.getAcceptedUserList();
-                    Optional<TaskToUser> taskToUserOptional = acceptedUserList.stream().filter(taskToUser -> taskToUser.getUserId().equals(user.getId())).findFirst();
-
                     if (taskToUserOptional.isPresent()) {
                         // 已接收用户
                         if (task.getStatus() == CrowdTestTaskStatus.HAS_RELEASED) {
@@ -1830,8 +1834,6 @@ public class WebMediatorImpl implements ViewMediator {
             }
         }
 
-
-
         System.out.println(taskOperationControl);
         return taskOperationControl;
     }

+ 3 - 3
site/src/main/java/com/mooctest/crowd/site/service/CrowdProjectService.java

@@ -5,9 +5,7 @@ import com.mooctest.crowd.site.command.CrowdTestProjectCommand;
 import com.mooctest.crowd.site.command.GenerateProjectCommand;
 import com.mooctest.crowd.site.data.dto.ProjectDetailsDTO;
 import com.mooctest.crowd.site.data.dto.UserProjectDTO;
-import com.mooctest.crowd.site.data.vo.CrowdProjectVO;
-import com.mooctest.crowd.site.data.vo.CrowdTestProjectVO;
-import com.mooctest.crowd.site.data.vo.RegionalManagerVO;
+import com.mooctest.crowd.site.data.vo.*;
 import org.springframework.data.domain.Pageable;
 import org.springframework.web.multipart.MultipartFile;
 
@@ -65,4 +63,6 @@ public interface CrowdProjectService {
     List<CrowdTestProject> getByProject();
 
     UserProjectDTO getProjectByToken(String projectCode, String taskCode, Long userId, String token);
+
+    List<SimpleProjectDataVO> findSimpleProjectDatasByRegionalManagerId(Long regionalManagerId);
 }

+ 9 - 1
site/src/main/java/com/mooctest/crowd/site/service/CrowdTaskService.java

@@ -3,8 +3,8 @@ package com.mooctest.crowd.site.service;
 import com.mooctest.crowd.site.command.CrowdTestTaskCommand;
 import com.mooctest.crowd.site.data.dto.TaskDetailsDTO;
 import com.mooctest.crowd.site.data.dto.TaskSquareDTO;
+import com.mooctest.crowd.site.data.vo.*;
 import com.mooctest.crowd.site.data.tfidf.JabaResult;
-import com.mooctest.crowd.site.data.vo.CrowdTaskVO;
 
 import java.util.List;
 
@@ -46,4 +46,12 @@ public interface CrowdTaskService {
     List<JabaResult> getTaskWord(String projectCode, String taskCode);
 
     String getToken(String projectCode, String taskCode, Long userId);
+
+    List<SimpleUserTaskDataVO> findSimpleTaskDatasByUserId(Long userId);
+
+    List<SimpleTaskDataVO> findSimpleTaskDatasByProjectCode(String projectCode);
+
+    TaskStatisticsVO getTaskStatistics(Long userId, String taskCode);
+
+    TaskMoreInfoVO getTaskMoreInfo(Long userId, String taskCode);
 }

+ 21 - 0
site/src/main/java/com/mooctest/crowd/site/service/DefectService.java

@@ -0,0 +1,21 @@
+package com.mooctest.crowd.site.service;
+
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.site.command.DefectAddedCommand;
+import com.mooctest.crowd.site.command.DefectUpdatedCommand;
+import org.springframework.validation.annotation.Validated;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Validated
+public interface DefectService {
+    Defect add(@Validated DefectAddedCommand defectAddedCommand);
+    void delete(@NotNull(message = "提交者id不能为空") Long commiterId, @NotNull(message = "id不能为空") Long id);
+    Defect update(@Validated DefectUpdatedCommand defectUpdatedCommand);
+    DOPage<Defect> findUserDefects(@NotNull(message = "提交者id不能为空") Long commiterId, @NotNull(message = "读用户id不能为空") Long readUserId, String taskCode, Integer pageNo, Integer pageSize);
+    void importDefects(@NotNull(message = "文件内容不能为空") byte[] bs,
+                         @NotEmpty(message = "任务编号不能为空") String taskCode,
+                         @NotNull(message = "用户id不能为空") Long userId);
+}

+ 7 - 0
site/src/main/java/com/mooctest/crowd/site/service/ExceptionLogService.java

@@ -0,0 +1,7 @@
+package com.mooctest.crowd.site.service;
+
+import com.mooctest.crowd.domain.domainobject.ExceptionLog;
+
+public interface ExceptionLogService {
+    public void save(ExceptionLog exceptionLog);
+}

+ 25 - 0
site/src/main/java/com/mooctest/crowd/site/service/TestCaseService.java

@@ -0,0 +1,25 @@
+package com.mooctest.crowd.site.service;
+
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.site.command.TestCaseAddedCommand;
+import com.mooctest.crowd.site.command.TestCaseUpdatedCommand;
+import com.mooctest.crowd.site.data.dto.TestCaseExamCommand;
+import com.mooctest.crowd.site.data.dto.TestCaseSearchDTO;
+import org.springframework.validation.annotation.Validated;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+@Validated
+public interface TestCaseService {
+    TestCase add(@Validated TestCaseAddedCommand testCaseAddedCommand);
+    void delete(@NotNull(message = "设计者id不能为空") Long designerId, @NotNull(message = "id不能为空") Long id);
+    TestCase update(@Validated TestCaseUpdatedCommand testCaseUpdatedCommand);
+    DOPage<TestCase> find(Long designerId, Long readUserId, String taskCode, Integer pageNo, Integer pageSize, TestCaseSearchDTO testCaseSearchDTO);
+    void exam(@Validated TestCaseExamCommand testCaseExamCommand);
+    void importTestCases(@NotNull(message = "文件内容不能为空") byte[] bs,
+                         @NotEmpty(message = "任务编号不能为空") String taskCode,
+                         @NotNull(message = "用户id不能为空") Long userId);
+}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.