浏览代码

增加了测试用例管理和临时加了登录入口

linyk 3 年之前
父节点
当前提交
afaf8e3c94
共有 80 个文件被更改,包括 2114 次插入40 次删除
  1. 0 0
      core/src/main/java/com/mooctest/crowd/domain/controller/TestUserController.java
  2. 4 0
      core/src/main/java/com/mooctest/crowd/domain/dao/CrowdTestTaskDao.java
  3. 17 0
      core/src/main/java/com/mooctest/crowd/domain/dao/DefectDao.java
  4. 2 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TaskToUserDao.java
  5. 18 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestCaseCodeDao.java
  6. 18 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestCaseDao.java
  7. 14 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestEnvDao.java
  8. 14 0
      core/src/main/java/com/mooctest/crowd/domain/dao/TestToolDao.java
  9. 2 0
      core/src/main/java/com/mooctest/crowd/domain/dao/UserDao.java
  10. 5 3
      core/src/main/java/com/mooctest/crowd/domain/domainobject/CrowdTestTask.java
  11. 54 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/Defect.java
  12. 67 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCase.java
  13. 10 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCaseCode.java
  14. 18 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestCaseExamRecord.java
  15. 19 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestEnv.java
  16. 14 0
      core/src/main/java/com/mooctest/crowd/domain/domainobject/TestTool.java
  17. 36 0
      core/src/main/java/com/mooctest/crowd/domain/env/DefectType.java
  18. 30 0
      core/src/main/java/com/mooctest/crowd/domain/env/Priority.java
  19. 32 0
      core/src/main/java/com/mooctest/crowd/domain/env/Seriousness.java
  20. 30 0
      core/src/main/java/com/mooctest/crowd/domain/env/TestCaseExamStatus.java
  21. 30 0
      core/src/main/java/com/mooctest/crowd/domain/env/TestStatus.java
  22. 5 0
      core/src/main/java/com/mooctest/crowd/domain/env/base/IEnum.java
  23. 22 0
      core/src/main/java/com/mooctest/crowd/domain/env/tools/EnumTools.java
  24. 60 0
      core/src/main/java/com/mooctest/crowd/domain/model/DefectPO.java
  25. 21 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestCaseCodePO.java
  26. 73 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestCasePO.java
  27. 37 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestEnvPO.java
  28. 27 0
      core/src/main/java/com/mooctest/crowd/domain/model/TestToolPO.java
  29. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/DefectTypeConverter.java
  30. 32 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/EnumConverter.java
  31. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/PriorityConverter.java
  32. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/SeriousnessConverter.java
  33. 10 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/TestCaseExamStatusConverter.java
  34. 9 0
      core/src/main/java/com/mooctest/crowd/domain/model/converter/TestStatusConverter.java
  35. 21 0
      core/src/main/java/com/mooctest/crowd/domain/page/DOPage.java
  36. 19 0
      core/src/main/java/com/mooctest/crowd/domain/repository/CrowdTestTaskRepo.java
  37. 133 0
      core/src/main/java/com/mooctest/crowd/domain/repository/DefectRepo.java
  38. 6 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ICrowdTaskRepo.java
  39. 17 0
      core/src/main/java/com/mooctest/crowd/domain/repository/IDefectRepo.java
  40. 5 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ITestCaseCodeRepo.java
  41. 15 0
      core/src/main/java/com/mooctest/crowd/domain/repository/ITestCaseRepo.java
  42. 2 0
      core/src/main/java/com/mooctest/crowd/domain/repository/IUserRepo.java
  43. 32 0
      core/src/main/java/com/mooctest/crowd/domain/repository/TestCaseCodeRepo.java
  44. 117 0
      core/src/main/java/com/mooctest/crowd/domain/repository/TestCaseRepo.java
  45. 10 3
      core/src/main/java/com/mooctest/crowd/domain/repository/UserRepo.java
  46. 3 0
      site/src/main/java/com/mooctest/crowd/site/SiteApplication.java
  47. 54 0
      site/src/main/java/com/mooctest/crowd/site/command/DefectAddedCommand.java
  48. 49 0
      site/src/main/java/com/mooctest/crowd/site/command/DefectUpdatedCommand.java
  49. 20 0
      site/src/main/java/com/mooctest/crowd/site/command/Login2Command.java
  50. 52 0
      site/src/main/java/com/mooctest/crowd/site/command/TestCaseAddedCommand.java
  51. 50 0
      site/src/main/java/com/mooctest/crowd/site/command/TestCaseUpdatedCommand.java
  52. 1 0
      site/src/main/java/com/mooctest/crowd/site/constants/UploadType.java
  53. 0 0
      site/src/main/java/com/mooctest/crowd/site/controller/CommonController.java
  54. 9 0
      site/src/main/java/com/mooctest/crowd/site/controller/CrowdProjectController.java
  55. 70 0
      site/src/main/java/com/mooctest/crowd/site/controller/CrowdTaskController.java
  56. 108 0
      site/src/main/java/com/mooctest/crowd/site/controller/TestCaseController.java
  57. 25 5
      site/src/main/java/com/mooctest/crowd/site/controller/UploadController.java
  58. 16 1
      site/src/main/java/com/mooctest/crowd/site/controller/UserController.java
  59. 3 2
      site/src/main/java/com/mooctest/crowd/site/controller/interceptor/AuthCheckInterceptor.java
  60. 17 0
      site/src/main/java/com/mooctest/crowd/site/data/dto/TestCaseExamCommand.java
  61. 11 0
      site/src/main/java/com/mooctest/crowd/site/data/dto/TestCaseSearchDTO.java
  62. 10 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleProjectDataVO.java
  63. 11 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleTaskDataVO.java
  64. 12 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/SimpleUserTaskDataVO.java
  65. 11 0
      site/src/main/java/com/mooctest/crowd/site/data/vo/TaskUserSimpleData.java
  66. 3 3
      site/src/main/java/com/mooctest/crowd/site/service/CrowdProjectService.java
  67. 6 0
      site/src/main/java/com/mooctest/crowd/site/service/CrowdTaskService.java
  68. 17 0
      site/src/main/java/com/mooctest/crowd/site/service/DefectService.java
  69. 21 0
      site/src/main/java/com/mooctest/crowd/site/service/TestCaseService.java
  70. 4 0
      site/src/main/java/com/mooctest/crowd/site/service/UploadService.java
  71. 0 0
      site/src/main/java/com/mooctest/crowd/site/service/UserService.java
  72. 16 5
      site/src/main/java/com/mooctest/crowd/site/service/impl/CrowdProjectServiceImpl.java
  73. 42 11
      site/src/main/java/com/mooctest/crowd/site/service/impl/CrowdTaskServiceImpl.java
  74. 77 0
      site/src/main/java/com/mooctest/crowd/site/service/impl/DefectServiceImpl.java
  75. 32 1
      site/src/main/java/com/mooctest/crowd/site/service/impl/OSSUploadServiceImpl.java
  76. 171 0
      site/src/main/java/com/mooctest/crowd/site/service/impl/TestCaseServiceImpl.java
  77. 0 0
      site/src/main/java/com/mooctest/crowd/site/service/impl/UserServiceImpl.java
  78. 1 1
      site/src/main/java/com/mooctest/crowd/site/util/GenerateFlowCodeUtil.java
  79. 10 0
      site/src/main/java/com/mooctest/crowd/site/util/RequestUtils.java
  80. 48 5
      site/src/main/resources/application.yml

文件差异内容过多而无法显示
+ 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);
 }

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

@@ -0,0 +1,17 @@
+package com.mooctest.crowd.domain.dao;
+
+import com.mooctest.crowd.domain.model.DefectPO;
+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);
+}

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

@@ -30,4 +30,6 @@ 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);
 }

+ 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);
+}

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

@@ -0,0 +1,18 @@
+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;
+
+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);
+}

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

@@ -0,0 +1,14 @@
+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);
+}

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

@@ -0,0 +1,14 @@
+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 TestToolDao extends PagingAndSortingRepository<TestEnvPO, Long>, CrudRepository<TestEnvPO, Long>,
+        JpaRepository<TestEnvPO, Long>, JpaSpecificationExecutor<TestEnvPO> {
+    List<TestEnvPO> findAllByTaskCodeAndUserId(String taskCode, Long userId);
+}

+ 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

@@ -172,9 +172,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()));
             }

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

@@ -0,0 +1,54 @@
+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;
+}

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

@@ -0,0 +1,67 @@
+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;
+}

+ 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;
+}

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

@@ -0,0 +1,19 @@
+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 String devCount; //设备数量
+    private String devConfig; //设备硬件配置
+    private String opeSys; //操作系统
+    private String middleware; //中间件
+    private String db; //数据库
+    private String browser; //浏览器
+    private String supportSoftware; //支持软件
+}

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

@@ -0,0 +1,14 @@
+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; //用途
+}

+ 36 - 0
core/src/main/java/com/mooctest/crowd/domain/env/DefectType.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;
+
+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);
+    }
+}

+ 30 - 0
core/src/main/java/com/mooctest/crowd/domain/env/Priority.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 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);
+    }
+}

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

@@ -0,0 +1,32 @@
+package com.mooctest.crowd.domain.env;
+
+import com.mooctest.crowd.domain.env.base.IEnum;
+import com.mooctest.crowd.domain.env.tools.EnumTools;
+
+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);
+    }
+}

+ 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);
+    }
+}

+ 30 - 0
core/src/main/java/com/mooctest/crowd/domain/env/TestStatus.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 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);
+    }
+}

+ 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));
+    }
+}

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

@@ -0,0 +1,60 @@
+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;
+}

+ 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;
+}

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

@@ -0,0 +1,73 @@
+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)})
+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;
+}

+ 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());
+    }
+
 }

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

@@ -0,0 +1,133 @@
+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 -> {
+            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);
+            }
+            return defect;
+        });
+        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());
+    }
+
+    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;
+    }
+}

+ 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);
 }

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

@@ -0,0 +1,17 @@
+package com.mooctest.crowd.domain.repository;
+
+import com.mooctest.crowd.domain.domainobject.Defect;
+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);
+}

+ 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);
+}

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

@@ -0,0 +1,15 @@
+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;
+
+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);
+}

+ 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;
+    }
+}

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

@@ -0,0 +1,117 @@
+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;
+
+@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);
+    }
+
+    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;
+    }
+
+}

+ 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
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;
 

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

@@ -0,0 +1,54 @@
+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;
+}

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

@@ -0,0 +1,49 @@
+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;
+}

+ 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;
+}

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

@@ -0,0 +1,52 @@
+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;
+}

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

@@ -0,0 +1,50 @@
+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;
+}

+ 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/";

文件差异内容过多而无法显示
+ 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

@@ -11,8 +11,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;
@@ -23,6 +25,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;
@@ -271,4 +274,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)));
+    }
 }

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

@@ -1,7 +1,10 @@
 package com.mooctest.crowd.site.controller;
 
+import com.mooctest.crowd.domain.domainobject.TestCase;
+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;
@@ -10,7 +13,13 @@ import com.mooctest.crowd.site.data.dto.TaskSquareDTO;
 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.data.vo.SimpleTaskDataVO;
+import com.mooctest.crowd.site.data.vo.SimpleUserTaskDataVO;
+import com.mooctest.crowd.site.data.vo.TaskUserSimpleData;
+import com.mooctest.crowd.site.data.vo.UserVO;
 import com.mooctest.crowd.site.service.CrowdTaskService;
+import com.mooctest.crowd.site.service.TestCaseService;
+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 +27,10 @@ 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.stream.Collectors;
 
 /**
  * @author: Diors.Po
@@ -34,6 +45,8 @@ public class CrowdTaskController{
 
     @Autowired
     private CrowdTaskService taskService;
+    @Autowired
+    private TestCaseService testCaseService;
 
     @RequestMapping(value = "/project/{projectCode}/task/{taskCode}", method = RequestMethod.GET)
     public TaskDetailsDTO getTask(@PathVariable("projectCode") String projectCode, @PathVariable("taskCode") String taskCode, HttpSession session){
@@ -152,4 +165,61 @@ 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));
+        }
+        taskService.commitTask(page.getDatas().get(0).getProjectCode(), taskCode, userId);
+        return new ResponseVO(ServerCode.SUCCESS);
+    }
+
 }

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

@@ -0,0 +1,108 @@
+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 javax.servlet.http.HttpServletRequest;
+
+@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);
+    }
+
+    @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);
+    }
+}

+ 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);
+    }
 }

+ 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;

+ 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;
+}

+ 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;
+}

+ 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);
 }

+ 6 - 0
site/src/main/java/com/mooctest/crowd/site/service/CrowdTaskService.java

@@ -5,6 +5,8 @@ import com.mooctest.crowd.site.data.dto.TaskDetailsDTO;
 import com.mooctest.crowd.site.data.dto.TaskSquareDTO;
 import com.mooctest.crowd.site.data.tfidf.JabaResult;
 import com.mooctest.crowd.site.data.vo.CrowdTaskVO;
+import com.mooctest.crowd.site.data.vo.SimpleTaskDataVO;
+import com.mooctest.crowd.site.data.vo.SimpleUserTaskDataVO;
 
 import java.util.List;
 
@@ -46,4 +48,8 @@ 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);
 }

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

@@ -0,0 +1,17 @@
+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.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, String taskCode, Integer pageNo, Integer pageSize);
+}

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

@@ -0,0 +1,21 @@
+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.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);
+}

+ 4 - 0
site/src/main/java/com/mooctest/crowd/site/service/UploadService.java

@@ -15,6 +15,10 @@ public interface UploadService {
 
     String uploadReport(MultipartFile file, Long userId);
 
+    String uploadTestCaseFile(MultipartFile file, Long userId);
+
+    String uploadTestCaseImage(MultipartFile file, Long userId);
+
     String uploadRequirment(MultipartFile file, Long userId);
 
     String uploadAPK(MultipartFile file, Long userId);

文件差异内容过多而无法显示
+ 0 - 0
site/src/main/java/com/mooctest/crowd/site/service/UserService.java


+ 16 - 5
site/src/main/java/com/mooctest/crowd/site/service/impl/CrowdProjectServiceImpl.java

@@ -8,7 +8,9 @@ import com.mooctest.crowd.domain.exception.BaseException;
 import com.mooctest.crowd.domain.exception.Excel2ProjectException;
 import com.mooctest.crowd.domain.exception.HaveNotPartAuthException;
 import com.mooctest.crowd.domain.factory.CrowdTestProjectFactory;
+import com.mooctest.crowd.domain.model.CrowdTestProjectPO;
 import com.mooctest.crowd.domain.model.ResourceTokenPO;
+import com.mooctest.crowd.domain.model.TaskToUserPO;
 import com.mooctest.crowd.domain.model.UserTaskCountPO;
 import com.mooctest.crowd.domain.repository.CommonRepo;
 import com.mooctest.crowd.domain.repository.CrowdTestProjectRepo;
@@ -38,10 +40,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
 import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
@@ -520,7 +519,19 @@ public class CrowdProjectServiceImpl implements CrowdProjectService {
 		return userProjectDTO;
 	}
 
-	private List<CrowdTestProject> transferExcel2Projects(Long userId,MultipartFile file) {
+    @Override
+    public List<SimpleProjectDataVO> findSimpleProjectDatasByRegionalManagerId(Long regionalManagerId) {
+        List<CrowdTestProjectPO> crowdTestProjectPOs = projectDao.findByRegionalManagerIdAndIsDeleted(regionalManagerId, DeletedStatus.isNotDeleted);
+        return crowdTestProjectPOs.stream().map(project -> {
+            SimpleProjectDataVO simpleProjectDataVO = new SimpleProjectDataVO();
+            simpleProjectDataVO.setCode(project.getCode());
+            simpleProjectDataVO.setName(project.getName());
+            simpleProjectDataVO.setId(project.getId());
+            return simpleProjectDataVO;
+        }).collect(Collectors.toList());
+    }
+
+    private List<CrowdTestProject> transferExcel2Projects(Long userId,MultipartFile file) {
         List<String> logList = new ArrayList<>();
         List<CrowdTestProject> projects = new ArrayList<>();
         Workbook workbook = null;

+ 42 - 11
site/src/main/java/com/mooctest/crowd/site/service/impl/CrowdTaskServiceImpl.java

@@ -1,20 +1,12 @@
 package com.mooctest.crowd.site.service.impl;
 
-import com.mooctest.crowd.domain.dao.CrowdTestTaskDao;
-import com.mooctest.crowd.domain.dao.EndPointDao;
-import com.mooctest.crowd.domain.dao.ResourceTokenDao;
-import com.mooctest.crowd.domain.dao.UserToRoleDao;
+import com.mooctest.crowd.domain.dao.*;
 import com.mooctest.crowd.domain.domainobject.*;
 import com.mooctest.crowd.domain.exception.BaseException;
 import com.mooctest.crowd.domain.exception.CrowdTestTaskNotExistException;
 import com.mooctest.crowd.domain.exception.UnauthorizedException;
-import com.mooctest.crowd.domain.model.EndPointPO;
-import com.mooctest.crowd.domain.model.ResourceTokenPO;
-import com.mooctest.crowd.domain.model.UserToRolePO;
-import com.mooctest.crowd.domain.repository.CommonRepo;
-import com.mooctest.crowd.domain.repository.CrowdTestProjectRepo;
-import com.mooctest.crowd.domain.repository.CrowdTestTaskRepo;
-import com.mooctest.crowd.domain.repository.UserRepo;
+import com.mooctest.crowd.domain.model.*;
+import com.mooctest.crowd.domain.repository.*;
 import com.mooctest.crowd.domain.util.Converter;
 import com.mooctest.crowd.domain.util.MD5Base64Util;
 import com.mooctest.crowd.site.command.CrowdTestTaskCommand;
@@ -24,6 +16,8 @@ import com.mooctest.crowd.site.data.enums.ProjectType;
 import com.mooctest.crowd.site.data.tfidf.JabaResult;
 import com.mooctest.crowd.site.data.tfidf.TFIDFAnalyzer;
 import com.mooctest.crowd.site.data.vo.CrowdTaskVO;
+import com.mooctest.crowd.site.data.vo.SimpleTaskDataVO;
+import com.mooctest.crowd.site.data.vo.SimpleUserTaskDataVO;
 import com.mooctest.crowd.site.mediator.ViewMediator;
 import com.mooctest.crowd.site.service.CrowdTaskService;
 import com.mooctest.crowd.site.util.GenerateFlowCodeUtil;
@@ -32,6 +26,7 @@ import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -73,6 +68,12 @@ public class CrowdTaskServiceImpl implements CrowdTaskService {
     @Autowired
     private UserToRoleDao userToRoleDao;
 
+    @Autowired
+    private TaskToUserDao taskToUserDao;
+
+    @Autowired
+    private TestCaseRepo testCaseRepo;
+
     @Override
     public List<CrowdTaskVO> findMoreHotTasks() {
         return viewMediator.findMoreHotTasks();
@@ -259,5 +260,35 @@ public class CrowdTaskServiceImpl implements CrowdTaskService {
         }
     }
 
+    @Override
+    public List<SimpleUserTaskDataVO> findSimpleTaskDatasByUserId(Long userId) {
+        Map<String, TaskToUserPO> taskCodeMap = new LinkedHashMap();
+        taskToUserDao.findByUserId(userId).stream().forEach(taskToUserPO -> {
+            taskCodeMap.put(taskToUserPO.getTaskCode(), taskToUserPO);
+        });
+        return taskDao.findAllByCodeIn(taskCodeMap.keySet()).stream().map(taskPO -> {
+            SimpleUserTaskDataVO simpleUserTaskDataVO = new SimpleUserTaskDataVO();
+            simpleUserTaskDataVO.setName(taskPO.getName());
+            simpleUserTaskDataVO.setCode(taskPO.getCode());
+            simpleUserTaskDataVO.setId(taskPO.getId());
+            simpleUserTaskDataVO.setIsCommitted(taskCodeMap.get(taskPO.getCode()).getIsCommitted());
+            simpleUserTaskDataVO.setStatus(taskPO.getStatus());
+            return simpleUserTaskDataVO;
+        }).collect(Collectors.toList());
+
+    }
+
+    @Override
+    public List<SimpleTaskDataVO> findSimpleTaskDatasByProjectCode(String projectCode) {
+        return crowdTestTaskRepo.findAllByCrowdTestProjectCode(projectCode).stream().map(crowdTestTask -> {
+            SimpleTaskDataVO simpleTaskDataVO = new SimpleTaskDataVO();
+            simpleTaskDataVO.setName(crowdTestTask.getName());
+            simpleTaskDataVO.setCode(crowdTestTask.getCode());
+            simpleTaskDataVO.setId(crowdTestTask.getId());
+            simpleTaskDataVO.setStatus(crowdTestTask.getStatus());
+            return simpleTaskDataVO;
+        }).collect(Collectors.toList());
+    }
+
 }
 

+ 77 - 0
site/src/main/java/com/mooctest/crowd/site/service/impl/DefectServiceImpl.java

@@ -0,0 +1,77 @@
+package com.mooctest.crowd.site.service.impl;
+
+import com.mooctest.crowd.domain.domainobject.Defect;
+import com.mooctest.crowd.domain.domainobject.TestCase;
+import com.mooctest.crowd.domain.exception.BaseException;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.domain.repository.IDefectRepo;
+import com.mooctest.crowd.domain.repository.ITestCaseRepo;
+import com.mooctest.crowd.domain.util.Converter;
+import com.mooctest.crowd.site.command.DefectAddedCommand;
+import com.mooctest.crowd.site.command.DefectUpdatedCommand;
+import com.mooctest.crowd.site.service.DefectService;
+import com.mooctest.crowd.site.util.GenerateFlowCodeUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.sql.Timestamp;
+
+@Service
+public class DefectServiceImpl implements DefectService {
+    @Autowired
+    private IDefectRepo defectRepo;
+    @Autowired
+    private ITestCaseRepo testCaseRepo;
+
+    @Override
+    public Defect add(DefectAddedCommand defectAddedCommand) {
+        Long commiterId = defectAddedCommand.getCommiterId();
+        String testCaseCode = defectAddedCommand.getTestCaseCode();
+        String taskCode = defectAddedCommand.getTaskCode();
+        TestCase testCase = testCaseRepo.findByTaskCodeAndTestCaseCode(taskCode, testCaseCode);
+        if (testCase == null) {
+            throw new BaseException("找不到对应的测试用例");
+        }
+        if (!testCase.getDesignerId().equals(commiterId)) {
+            throw new BaseException("当前用户没有此用例的操作权限!");
+        }
+        String projectCode = testCase.getProjectCode();
+        int count = defectRepo.countByTaskCodeAndTestCaseCode(taskCode, testCaseCode) + 1;
+        String code = GenerateFlowCodeUtil.getSequence(count, 2);
+        String defectCode = "DE-".concat(testCaseCode.substring(testCaseCode.indexOf("-") + 1)).concat(code);
+        Defect defect = Converter.convert(Defect.class, defectAddedCommand);
+        defect.setCode(defectCode);
+        defect.setProjectCode(projectCode);
+        defect.setCommitTime(new Timestamp(System.currentTimeMillis()));
+        defectRepo.save(defect);
+        return defect;
+    }
+
+    @Override
+    public void delete(Long commiterId, Long id) {
+        Defect defect = defectRepo.findById(id);
+        if (!defect.getCommiterId().equals(commiterId)) {
+            throw new BaseException("当前用户无权限操作该缺陷");
+        }
+        defectRepo.deleteById(id);
+    }
+
+    @Override
+    public Defect update(DefectUpdatedCommand defectUpdatedCommand) {
+        Defect defect = defectRepo.findById(defectUpdatedCommand.getId());
+        if (defect == null) {
+            throw new RuntimeException("缺陷不存在");
+        }
+        if (!defect.getCommiterId().equals(defectUpdatedCommand.getCommiterId())) {
+            throw new BaseException("当前用户无权限操作该缺陷");
+        }
+        Converter.copy(defect, defectUpdatedCommand);
+        defectRepo.save(defect);
+        return defect;
+    }
+
+    @Override
+    public DOPage<Defect> findUserDefects(Long commiterId, String taskCode, Integer pageNo, Integer pageSize) {
+        return defectRepo.findUserDefects(commiterId, taskCode, pageNo, pageSize);
+    }
+}

+ 32 - 1
site/src/main/java/com/mooctest/crowd/site/service/impl/OSSUploadServiceImpl.java

@@ -1,13 +1,16 @@
 package com.mooctest.crowd.site.service.impl;
 
+import com.mooctest.crowd.domain.exception.BaseException;
 import com.mooctest.crowd.site.constants.UploadType;
 import com.mooctest.crowd.site.service.FileService;
 import com.mooctest.crowd.site.service.UploadService;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ArrayUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 
+import java.util.Locale;
 import java.util.UUID;
 
 /**
@@ -18,7 +21,8 @@ import java.util.UUID;
 @Slf4j
 @Service
 public class OSSUploadServiceImpl implements UploadService {
-
+    public static final String[] TEST_CASE_IMG_EXTS = {"png", "jpg", "jpeg"};
+    public static final String[] TEST_CASE_FILE_EXTS = {"doc", "docx", "txt", "xls", "xlsx", "pdf"};
 //    @Autowired
 //    private OSS ossClient;
     @Autowired
@@ -42,6 +46,33 @@ public class OSSUploadServiceImpl implements UploadService {
     }
 
     @Override
+    public String uploadTestCaseFile(MultipartFile file, Long userId) {
+        String originalFilename = file.getOriginalFilename();
+        String ext = originalFilename.substring(file.getOriginalFilename().lastIndexOf(".") + 1);
+        if (!ArrayUtils.contains(TEST_CASE_FILE_EXTS, ext.toLowerCase())) {
+            throw new BaseException("文件类型不支持");
+        }
+        String fileName = UploadType.TEST_CASE+file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."))+"_"
+                +userId+"_"
+                +System.currentTimeMillis()+"."
+                +ext;
+        return doUpload(fileName, file);
+    }
+
+    @Override
+    public String uploadTestCaseImage(MultipartFile file, Long userId) {
+        String originalFilename = file.getOriginalFilename();
+        String ext = originalFilename.substring(file.getOriginalFilename().lastIndexOf(".") + 1);
+        if (!ArrayUtils.contains(TEST_CASE_IMG_EXTS, ext.toLowerCase())) {
+            throw new BaseException("文件类型不支持");
+        }
+        String fileName = UploadType.TEST_CASE+userId+"_"+UUID.randomUUID()+"_"
+                +System.currentTimeMillis()+"."
+                +ext;
+        return doUpload(fileName, file);
+    }
+
+    @Override
     public String uploadRequirment(MultipartFile file, Long userId) {
         String fileName = UploadType.REQUIREMENT_FILE+file.getOriginalFilename().substring(0,file.getOriginalFilename().lastIndexOf("."))+"_"
                 +userId+"_"

+ 171 - 0
site/src/main/java/com/mooctest/crowd/site/service/impl/TestCaseServiceImpl.java

@@ -0,0 +1,171 @@
+package com.mooctest.crowd.site.service.impl;
+
+import com.alibaba.druid.util.StringUtils;
+import com.mooctest.crowd.domain.dao.CrowdTestProjectDao;
+import com.mooctest.crowd.domain.dao.TaskToUserDao;
+import com.mooctest.crowd.domain.domainobject.*;
+import com.mooctest.crowd.domain.env.TestCaseExamStatus;
+import com.mooctest.crowd.domain.env.TestStatus;
+import com.mooctest.crowd.domain.exception.BaseException;
+import com.mooctest.crowd.domain.exception.CrowdTestProjectNotExistException;
+import com.mooctest.crowd.domain.exception.CrowdTestTaskNotExistException;
+import com.mooctest.crowd.domain.model.CrowdTestProjectPO;
+import com.mooctest.crowd.domain.model.TaskToUserPO;
+import com.mooctest.crowd.domain.page.DOPage;
+import com.mooctest.crowd.domain.repository.*;
+import com.mooctest.crowd.domain.util.Converter;
+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.service.TestCaseService;
+import com.mooctest.crowd.site.util.GenerateFlowCodeUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+@Service
+public class TestCaseServiceImpl implements TestCaseService {
+    @Autowired
+    private ITestCaseRepo testCaseRepo;
+    @Autowired
+    private ICrowdTaskRepo crowdTaskRepo;
+    @Autowired
+    private ITestCaseCodeRepo testCaseCodeRepo;
+    @Autowired
+    private DefectRepo defectRepo;
+    @Autowired
+    private CrowdTestProjectDao crowdTestProjectDao;
+    @Autowired
+    private TaskToUserDao taskToUserDao;
+
+    @Override
+    @Transactional
+    public TestCase add(TestCaseAddedCommand testCaseAddedCommand) {
+        Long designerId = testCaseAddedCommand.getDesignerId();
+        String taskCode = testCaseAddedCommand.getTaskCode();
+        CrowdTestTask task = crowdTaskRepo.findByCode(taskCode);
+        if (task == null) {
+            throw new CrowdTestTaskNotExistException();
+        }
+        List<TaskToUser> taskToUsers = crowdTaskRepo.findAllTaskToUserByTaskCode(taskCode);
+        if(!taskToUsers.stream().anyMatch(taskToUser -> taskToUser.getUserId().equals(designerId))) {
+            throw new BaseException("当前用户没有此任务的操作权限!");
+        }
+        String projectCode = task.getCrowdTestProjectCode();
+        List<CrowdTestTask> tasks = crowdTaskRepo.findAllByCrowdTestProjectCode(projectCode);
+        int index = -1;
+        for(int i = 0; i < tasks.size(); i++) {
+            if (tasks.get(i).getCode().equals(taskCode)) {
+                index = i;
+                break;
+            }
+        }
+        if (index < 0) {
+            throw new RuntimeException("找不到匹配的任务");
+        }
+        int ind = testCaseCodeRepo.getNewestIndByTaskCode(taskCode);
+        String code1 = GenerateFlowCodeUtil.getSequence(index + 1, 2);
+        String code2 = GenerateFlowCodeUtil.getSequence(ind, 4);
+        String testCaseCode = "TC-".concat(code1).concat(code2);
+        TestCase testCase = Converter.convert(TestCase.class, testCaseAddedCommand);
+        testCase.setCode(testCaseCode);
+        testCase.setProjectCode(task.getCrowdTestProjectCode());
+        testCase.setDesignTime(new Timestamp(System.currentTimeMillis()));
+        testCase.setExamStatus(TestCaseExamStatus.WAIT);
+        testCaseRepo.save(testCase);
+        return testCase;
+    }
+
+    @Override
+    public void delete(Long designerId, Long id) {
+        TestCase testCase = testCaseRepo.findById(id);
+        if (!testCase.getDesignerId().equals(designerId)) {
+            throw new BaseException("当前用户无权限操作该用例");
+        }
+        testCaseRepo.deleteById(id);
+    }
+
+    @Override
+    public TestCase update(TestCaseUpdatedCommand testCaseUpdatedCommand) {
+        TestCase testCase = testCaseRepo.findById(testCaseUpdatedCommand.getId());
+        if (testCase == null) {
+            throw new RuntimeException("用例不存在");
+        }
+        if (!testCase.getDesignerId().equals(testCaseUpdatedCommand.getDesignerId())) {
+            throw new BaseException("当前用户无权限操作该用例");
+        }
+        Converter.copy(testCase, testCaseUpdatedCommand);
+        testCaseRepo.save(testCase);
+        return testCase;
+    }
+
+    @Override
+    public DOPage<TestCase> find(Long designerId, Long readUserId, String taskCode, Integer pageNo, Integer pageSize, TestCaseSearchDTO testCaseSearchDTO) {
+        if (!readUserId.equals(designerId)) {
+            CrowdTestTask crowdTestTask = crowdTaskRepo.findByCode(taskCode);
+            if (crowdTestTask == null) {
+                throw new CrowdTestTaskNotExistException();
+            }
+            CrowdTestProjectPO crowdTestProjectPO = crowdTestProjectDao.findByCodeAndIsDeleted(crowdTestTask.getCrowdTestProjectCode(), DeletedStatus.isNotDeleted);
+            if (crowdTestProjectPO == null) {
+                throw new CrowdTestProjectNotExistException();
+            }
+            if (!crowdTestProjectPO.getRegionalManagerId().equals(readUserId)) {
+                throw new BaseException("当前用户无权获取该数据");
+            }
+        }
+        DOPage<TestCase> page = testCaseRepo.find(designerId, taskCode, pageNo, pageSize, testCaseSearchDTO.getTestStatus(), testCaseSearchDTO.getExamStatus());
+        Map<String, TestCase> testCaseCodeMap = new HashMap();
+        page.getDatas().stream().forEach(testCase -> {
+            testCase.setDefects(new ArrayList());
+            testCaseCodeMap.put(testCase.getCode(), testCase);
+        });
+        List<Defect> defects = defectRepo.findAllByTaskCodeAndTestCaseCodeIn(taskCode, testCaseCodeMap.keySet());
+        defects.stream().forEach(defect -> {
+            testCaseCodeMap.get(defect.getTestCaseCode()).getDefects().add(defect);
+        });
+        return page;
+    }
+
+    @Override
+    @Transactional
+    public void exam(TestCaseExamCommand testCaseExamCommand) {
+        if (testCaseExamCommand.getExamStatus().equals(TestCaseExamStatus.INVALID.toString())) {
+            if (StringUtils.isEmpty(testCaseExamCommand.getExamDescr())) {
+                throw new BaseException("审核结果为无效时,需要填写审核结果说明!");
+            }
+        }
+        TestCase testCase = testCaseRepo.findById(testCaseExamCommand.getId());
+        if (testCase == null) {
+            throw new BaseException("测试用例不存在!");
+        }
+        CrowdTestTask task = crowdTaskRepo.findByCode(testCase.getTaskCode());
+        if (task == null) {
+            throw new CrowdTestTaskNotExistException();
+        }
+        CrowdTestProjectPO projectPO = crowdTestProjectDao.findByCodeAndIsDeleted(task.getCrowdTestProjectCode(), DeletedStatus.isNotDeleted);
+        if (projectPO == null) {
+            throw new CrowdTestProjectNotExistException();
+        }
+        if (!testCaseExamCommand.getExamerId().equals(projectPO.getRegionalManagerId())) {
+            throw new BaseException("当前用户无权审核该测试用例!");
+        }
+        TaskToUserPO taskToUserPO = taskToUserDao.findByUserIdAndTaskCode(testCase.getDesignerId(), testCase.getTaskCode());
+        if (taskToUserPO.getIsCommitted() != 1) {
+            throw new BaseException("当前测试用例还未提交,不能审核!");
+        }
+        if (task.getStatus() == CrowdTestTask.HAS_FINISHED) {
+            throw new BaseException("当前任务已经结束,不能审核该任务的测试用例!");
+        }
+        testCaseRepo.exam(testCaseExamCommand.getId(), TestCaseExamStatus.valueOf(testCaseExamCommand.getExamStatus()),
+                testCaseExamCommand.getExamDescr());
+    }
+}

文件差异内容过多而无法显示
+ 0 - 0
site/src/main/java/com/mooctest/crowd/site/service/impl/UserServiceImpl.java


+ 1 - 1
site/src/main/java/com/mooctest/crowd/site/util/GenerateFlowCodeUtil.java

@@ -50,7 +50,7 @@ public class GenerateFlowCodeUtil {
         return generateFlowCode("TASK-"+type);
     }
 
-    private static String getSequence(int seq, int length){
+    public static String getSequence(int seq, int length){
         String str = String.valueOf(seq);
         if (str.length()>length)
             return str;

+ 10 - 0
site/src/main/java/com/mooctest/crowd/site/util/RequestUtils.java

@@ -0,0 +1,10 @@
+package com.mooctest.crowd.site.util;
+
+import javax.servlet.http.HttpServletRequest;
+
+public class RequestUtils {
+    public static Long getUserId(HttpServletRequest request) {
+        String userId = (String)request.getSession().getAttribute("userId");
+        return Long.valueOf(userId);
+    }
+}

+ 48 - 5
site/src/main/resources/application.yml

@@ -1,6 +1,6 @@
 spring:
   profiles:
-     active: dev
+     active: localhost
   cache:
     guava:
       spec: expireAfterWrite=30s
@@ -10,10 +10,7 @@ spring:
     validationQuery: SELECT 1
   jpa:
     show-sql: true
-  hibernate:
-    ddl-auto: validate
-    naming-strategy: org.hibernate.cfg.ImprovedNamingStrategy
-  properties.hibernate.dialect: org.hibernate.dialect.MySQL5Dialect
+    properties.hibernate.dialect: org.hibernate.dialect.MySQL5InnoDBDialect
   servlet:
     multipart:
       enabled: true
@@ -213,3 +210,49 @@ user:
 
 website:
   domain: 127.0.0.1
+
+---
+# 私有云版本-本地测试
+spring:
+  profiles: localhost
+  datasource:
+    url: jdbc:mysql://127.0.0.1:3306/crowd-test-service?useSSL=false&useUnicode=yes&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
+    username: root
+    password: 123456
+  redis:
+    host: localhost
+    port: 6379
+    password:
+    jedis:
+      pool:
+        max-active: 8
+        max-idle: 8
+        max-wait: -1
+        min-idle: 0
+    database: 0
+
+#  redis:
+#    host: 127.0.0.1
+#    password:
+#    pool:
+#      max-active: 8
+#      max-idle: 8
+#      max-wait: -1
+#      min-idle: 0
+#    port: 6379
+
+feature:
+  client:
+    oss: true
+
+file:
+  save:
+    path:
+
+user:
+  service:
+    baseUrl: http://127.0.0.1:8081
+#    baseUrl: http://59.42.10.53:8081
+
+website:
+  domain: 127.0.0.1

部分文件因为文件数量过多而无法显示