瀏覽代碼

feat: merge dev-cyz add project module

Chen YZ 5 年之前
父節點
當前提交
61db894400
共有 36 個文件被更改,包括 1135 次插入87 次删除
  1. 23 0
      src/main/java/generator/Project.java
  2. 17 0
      src/main/java/seecoder/devcloud/web/dao/ProjectDao.java
  3. 87 0
      src/main/resources/generator/ProjectDao.xml
  4. 4 4
      web/pom.xml
  5. 16 0
      web/src/main/java/seecoder/devcloud/web/aop/TreeLogging.java
  6. 73 0
      web/src/main/java/seecoder/devcloud/web/aspect/TreeLoggingAspect.java
  7. 0 26
      web/src/main/java/seecoder/devcloud/web/controller/TreeNodesController.java
  8. 56 0
      web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java
  9. 44 0
      web/src/main/java/seecoder/devcloud/web/controller/tree/TreeNodesController.java
  10. 47 0
      web/src/main/java/seecoder/devcloud/web/dao/project/ProjectMapper.java
  11. 5 3
      web/src/main/java/seecoder/devcloud/web/dao/provider/TreeNodeProvider.java
  12. 29 0
      web/src/main/java/seecoder/devcloud/web/dao/tree/TreeLogMapper.java
  13. 22 11
      web/src/main/java/seecoder/devcloud/web/dao/tree/TreeNodeMapper.java
  14. 2 0
      web/src/main/java/seecoder/devcloud/web/dao/user/GroupMemberMapper.java
  15. 22 0
      web/src/main/java/seecoder/devcloud/web/enums/OperationEnum.java
  16. 4 3
      web/src/main/java/seecoder/devcloud/web/po/TreeNodePO.java
  17. 21 0
      web/src/main/java/seecoder/devcloud/web/po/project/Project.java
  18. 40 0
      web/src/main/java/seecoder/devcloud/web/po/tree/TreeLog.java
  19. 2 0
      web/src/main/java/seecoder/devcloud/web/po/user/Group.java
  20. 0 11
      web/src/main/java/seecoder/devcloud/web/service/TreeNodeService.java
  21. 57 0
      web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java
  22. 40 3
      web/src/main/java/seecoder/devcloud/web/service/impl/tree/TreeNodeServiceImpl.java
  23. 40 0
      web/src/main/java/seecoder/devcloud/web/service/project/ProjectService.java
  24. 42 0
      web/src/main/java/seecoder/devcloud/web/service/tree/TreeNodeService.java
  25. 28 0
      web/src/main/java/seecoder/devcloud/web/vo/TreeNodeVO.java
  26. 21 0
      web/src/main/java/seecoder/devcloud/web/vo/project/ProjectVO.java
  27. 39 0
      web/src/main/resources/SQLScripts/project.sql
  28. 38 0
      web/src/main/resources/SQLScripts/tree_log.sql
  29. 25 9
      web/src/main/resources/SQLScripts/trees.sql
  30. 55 0
      web/src/main/resources/application-cyz.yml
  31. 1 1
      web/src/main/resources/application.yml
  32. 78 0
      web/src/test/java/seecoder/devcloud/web/dao/project/ProjectMapperTest.java
  33. 43 0
      web/src/test/java/seecoder/devcloud/web/dao/tree/TreeLogMapperTest.java
  34. 16 16
      web/src/test/java/seecoder/devcloud/web/dao/tree/TreeNodeMapperTest.java
  35. 42 0
      web/src/test/java/seecoder/devcloud/web/service/TreeNodeServiceTest.java
  36. 56 0
      web/src/test/java/seecoder/devcloud/web/service/project/ProjectServiceTest.java

+ 23 - 0
src/main/java/generator/Project.java

@@ -0,0 +1,23 @@
+package generator;
+
+import java.io.Serializable;
+import lombok.Data;
+
+/**
+ * project
+ * @author 
+ */
+@Data
+public class Project implements Serializable {
+    private Integer id;
+
+    private String name;
+
+    private String description;
+
+    private String gitRemoteUrl;
+
+    private Integer groupId;
+
+    private static final long serialVersionUID = 1L;
+}

+ 17 - 0
src/main/java/seecoder/devcloud/web/dao/ProjectDao.java

@@ -0,0 +1,17 @@
+package seecoder.devcloud.web.dao;
+
+import generator.Project;
+
+public interface ProjectDao {
+    int deleteByPrimaryKey(Integer id);
+
+    int insert(Project record);
+
+    int insertSelective(Project record);
+
+    Project selectByPrimaryKey(Integer id);
+
+    int updateByPrimaryKeySelective(Project record);
+
+    int updateByPrimaryKey(Project record);
+}

+ 87 - 0
src/main/resources/generator/ProjectDao.xml

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="seecoder.devcloud.web.dao.ProjectDao">
+  <resultMap id="BaseResultMap" type="generator.Project">
+    <id column="id" jdbcType="INTEGER" property="id" />
+    <result column="name" jdbcType="VARCHAR" property="name" />
+    <result column="description" jdbcType="VARCHAR" property="description" />
+    <result column="git_remote_url" jdbcType="VARCHAR" property="gitRemoteUrl" />
+    <result column="group_id" jdbcType="INTEGER" property="groupId" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    id, `name`, description, git_remote_url, group_id
+  </sql>
+  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
+    select 
+    <include refid="Base_Column_List" />
+    from project
+    where id = #{id,jdbcType=INTEGER}
+  </select>
+  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
+    delete from project
+    where id = #{id,jdbcType=INTEGER}
+  </delete>
+  <insert id="insert" keyColumn="id" keyProperty="id" parameterType="generator.Project" useGeneratedKeys="true">
+    insert into project (`name`, description, git_remote_url, 
+      group_id)
+    values (#{name,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{gitRemoteUrl,jdbcType=VARCHAR}, 
+      #{groupId,jdbcType=INTEGER})
+  </insert>
+  <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="generator.Project" useGeneratedKeys="true">
+    insert into project
+    <trim prefix="(" suffix=")" suffixOverrides=",">
+      <if test="name != null">
+        `name`,
+      </if>
+      <if test="description != null">
+        description,
+      </if>
+      <if test="gitRemoteUrl != null">
+        git_remote_url,
+      </if>
+      <if test="groupId != null">
+        group_id,
+      </if>
+    </trim>
+    <trim prefix="values (" suffix=")" suffixOverrides=",">
+      <if test="name != null">
+        #{name,jdbcType=VARCHAR},
+      </if>
+      <if test="description != null">
+        #{description,jdbcType=VARCHAR},
+      </if>
+      <if test="gitRemoteUrl != null">
+        #{gitRemoteUrl,jdbcType=VARCHAR},
+      </if>
+      <if test="groupId != null">
+        #{groupId,jdbcType=INTEGER},
+      </if>
+    </trim>
+  </insert>
+  <update id="updateByPrimaryKeySelective" parameterType="generator.Project">
+    update project
+    <set>
+      <if test="name != null">
+        `name` = #{name,jdbcType=VARCHAR},
+      </if>
+      <if test="description != null">
+        description = #{description,jdbcType=VARCHAR},
+      </if>
+      <if test="gitRemoteUrl != null">
+        git_remote_url = #{gitRemoteUrl,jdbcType=VARCHAR},
+      </if>
+      <if test="groupId != null">
+        group_id = #{groupId,jdbcType=INTEGER},
+      </if>
+    </set>
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+  <update id="updateByPrimaryKey" parameterType="generator.Project">
+    update project
+    set `name` = #{name,jdbcType=VARCHAR},
+      description = #{description,jdbcType=VARCHAR},
+      git_remote_url = #{gitRemoteUrl,jdbcType=VARCHAR},
+      group_id = #{groupId,jdbcType=INTEGER}
+    where id = #{id,jdbcType=INTEGER}
+  </update>
+</mapper>

+ 4 - 4
web/pom.xml

@@ -80,10 +80,10 @@
             <artifactId>mybatis-spring-boot-starter-test</artifactId>
             <version>2.1.4</version>
         </dependency>
-<!--        <dependency>-->
-<!--            <groupId>org.springframework.boot</groupId>-->
-<!--            <artifactId>spring-boot-starter-security</artifactId>-->
-<!--        </dependency>-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-test</artifactId>

+ 16 - 0
web/src/main/java/seecoder/devcloud/web/aop/TreeLogging.java

@@ -0,0 +1,16 @@
+package seecoder.devcloud.web.aop;
+
+import seecoder.devcloud.web.enums.OperationEnum;
+
+import java.lang.annotation.*;
+
+/**
+ * 以注解方式标记日志插入
+ * 要求:参数里带有TreeNodeVO
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface TreeLogging {
+    public OperationEnum value();
+}

+ 73 - 0
web/src/main/java/seecoder/devcloud/web/aspect/TreeLoggingAspect.java

@@ -0,0 +1,73 @@
+package seecoder.devcloud.web.aspect;
+
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import seecoder.devcloud.web.aop.TreeLogging;
+import seecoder.devcloud.web.dao.tree.TreeLogMapper;
+import seecoder.devcloud.web.enums.ResponseEnums;
+import seecoder.devcloud.web.po.tree.TreeLog;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.TreeNodeVO;
+
+import java.lang.reflect.Method;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * 树操作日志类切面,关联@TreeLogging注解
+ */
+@Aspect
+@Component
+public class TreeLoggingAspect {
+    @Autowired
+    TreeLogMapper treeLogMapper;
+
+    @Pointcut("@annotation(seecoder.devcloud.web.aop.TreeLogging)")
+    public void logPointCut() {
+
+    }
+
+    @AfterReturning(pointcut = "logPointCut()", returning = "result")
+    public void doAfterReturning(JoinPoint joinPoint, Response result) {
+        // 只处理成功的情况
+        if (result.getCode().equals(ResponseEnums.OK.getCode())) {
+            TreeLog log = new TreeLog();
+            //从切面织入点处通过反射机制获取织入点处的方法
+            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
+            //获取切入点所在的方法
+            Method method = signature.getMethod();
+            //获取注解,提取操作类型属性
+            TreeLogging logging = method.getAnnotation(TreeLogging.class);
+            if (logging != null) {
+                log.setOperation(logging.value());
+            }
+            //请求的参数
+            Object[] args = joinPoint.getArgs();
+            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+            for (Object arg : args) {
+                if (arg instanceof TreeNodeVO) {
+                    TreeNodeVO node = (TreeNodeVO) arg;
+                    log.setTreeId(node.getId());
+//                    log.setUserId();
+//                    log.setUserName();
+//                    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+//                    HttpSession session = request.getSession();
+//                    读取session中的用户
+//                    User user = (User) session.getAttribute("user");
+//                    请求的IP
+//                    String ip = request.getRemoteAddr();
+//                    TODO:从session中获取userId和userName
+                    log.setTime(sf.format(new Date()));
+                    System.out.println(log);
+                    treeLogMapper.insertTreeLog(log);
+                    break;
+                }
+            }
+        }
+    }
+}

+ 0 - 26
web/src/main/java/seecoder/devcloud/web/controller/TreeNodesController.java

@@ -1,26 +0,0 @@
-package seecoder.devcloud.web.controller;
-
-
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-import seecoder.devcloud.web.po.TreeNode;
-import seecoder.devcloud.web.service.TreeNodeService;
-
-import java.util.List;
-
-@RestController
-public class TreeNodesController {
-    @Autowired
-    private TreeNodeService treeNodeService;
-    //注意 这里混用po和vo了
-    @GetMapping("/all")
-    public List<TreeNode> getAllNodes(){
-        return treeNodeService.getAllNodes();
-    }
-    @GetMapping("/")
-    public String test(){
-        return "123";
-    }
-
-}

+ 56 - 0
web/src/main/java/seecoder/devcloud/web/controller/project/ProjectController.java

@@ -0,0 +1,56 @@
+package seecoder.devcloud.web.controller.project;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.po.project.Project;
+import seecoder.devcloud.web.service.project.ProjectService;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.project.ProjectVO;
+
+import java.util.List;
+
+/**
+ * @author Chenyz
+ * @date 2021/3/10
+ * @description: 项目接口
+ */
+@Api("项目相关API")
+@RestController
+@RequestMapping("/project")
+public class ProjectController {
+    @Autowired
+    ProjectService projectService;
+
+
+    @ApiOperation("根据group获取Project列表")
+    @GetMapping("/listByGroup/{groupId}")
+    public Response<List<Project>> listProjectsByGroupId(@PathVariable("groupId")int groupId){
+        return projectService.listProjectsByGroupId(groupId);
+    }
+
+    @ApiOperation("根据user获取Project列表")
+    @GetMapping("/listByUser/{userId}")
+    public Response<List<Project>> listProjectsByUserId(@PathVariable("userId")int userId){
+        return projectService.listProjectsByUserId(userId);
+    }
+
+    @ApiOperation("根据projectId获取Project")
+    @GetMapping("/{projectId}")
+    public Response<Project> getProjectById(@PathVariable("projectId")int projectId){
+        return projectService.getProjectById(projectId);
+    }
+
+    @ApiOperation("创建项目,传入的参数中不必带有效的projectId字段,返回一个创建后的结果,注入id")
+    @PostMapping("/create")
+    public Response<Project> createProject(ProjectVO project){
+        return projectService.createProject(project);
+    }
+
+    @ApiOperation("根据projectId删除项目")
+    @GetMapping("/delete/{projectId}")
+    public Response deleteProject(@PathVariable("projectId")int projectId){
+        return projectService.deleteProject(projectId);
+    }
+}

+ 44 - 0
web/src/main/java/seecoder/devcloud/web/controller/tree/TreeNodesController.java

@@ -0,0 +1,44 @@
+package seecoder.devcloud.web.controller.tree;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.service.tree.TreeNodeService;
+import seecoder.devcloud.web.vo.Response;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/tree")
+/**
+ * @Author chenyz
+ * @Description 需求树相关操作
+ */
+public class TreeNodesController {
+    @Autowired
+    private TreeNodeService treeNodeService;
+    //注意 这里混用po和vo了
+    @GetMapping("/all")
+    public List<TreeNodePO> getAllNodes(){
+        return treeNodeService.getAllNodes();
+    }
+
+    /**
+     * 获取某个项目所有需求情况
+     * @param projectId
+     * @return
+     */
+    @GetMapping("/{projectId}")
+    public Response listTreeNodesByProjectId(@PathVariable("projectId") int projectId){
+        // TODO
+        return null;
+    }
+
+
+    @PostMapping("/addNode")
+    public Response insertTreeNode(){
+        return null;
+    }
+
+}

+ 47 - 0
web/src/main/java/seecoder/devcloud/web/dao/project/ProjectMapper.java

@@ -0,0 +1,47 @@
+package seecoder.devcloud.web.dao.project;
+
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+import seecoder.devcloud.web.dao.GeneralInsertUpdateSqlProvider;
+import seecoder.devcloud.web.po.project.Project;
+import seecoder.devcloud.web.po.user.Group;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.project.ProjectVO;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface ProjectMapper {
+
+
+    @Select("select * from project")
+    @Results(id="projectMap",value = {
+            @Result(column = "git_remote_url", property = "gitRemoteUrl"),
+            @Result(column = "group_id", property = "groupId")
+    })
+    List<Project> listAll();
+
+    /**
+     * 插入,自增ID
+     */
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "param1.id")
+    int insertProject(Project project, String... ignoredCols);
+
+    @UpdateProvider(type= GeneralInsertUpdateSqlProvider.class, method="updateById")
+    int updateProject(Project project);
+
+    @Select("select * from project where group_id=#{groupId}")
+    @ResultMap(value = "projectMap")
+    List<Project> listProjectsByGroupId(int groupId);
+
+    @Select("select * from project where group_id in(select unique group_id from group_member where user_id=#{userId}")
+    @ResultMap(value = "projectMap")
+    List<Project> listProjectsByUserId(int userId);
+
+    @Select("select * from project where id=#{projectId}")
+    @ResultMap(value = "projectMap")
+    Project getProjectById(int projectId);
+
+}

+ 5 - 3
web/src/main/java/seecoder/devcloud/web/dao/provider/TreeNodeProvider.java

@@ -1,10 +1,10 @@
 package seecoder.devcloud.web.dao.provider;
 
 import org.apache.ibatis.jdbc.SQL;
-import seecoder.devcloud.web.po.TreeNode;
+import seecoder.devcloud.web.po.TreeNodePO;
 
 public class TreeNodeProvider {
-    public String updateTreeNode(TreeNode treeNode){
+    public String updateTreeNode(TreeNodePO TreeNodePO){
         return new SQL() {
             {
                 UPDATE("tree_nodes");
@@ -13,12 +13,14 @@ public class TreeNodeProvider {
                 SET("type=#{type}");
                 SET("priority=#{priority}");
                 SET("state=#{state}");
-                SET("processor=#{processor}");
                 SET("time_to_take=#{timeToTake}");
                 SET("start_time=#{startTime}");
                 SET("end_time=#{endTime}");
                 SET("is_leaf=#{leaf}");
                 SET("group_id=#{groupId}");
+                SET("project_id=#{projectId}");
+                SET("parent_id=#{parentId}");
+                SET("deep=#{deep}");
                 WHERE("id=#{id}");
             }
         }.toString();

+ 29 - 0
web/src/main/java/seecoder/devcloud/web/dao/tree/TreeLogMapper.java

@@ -0,0 +1,29 @@
+package seecoder.devcloud.web.dao.tree;
+
+
+import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
+import seecoder.devcloud.web.dao.GeneralInsertUpdateSqlProvider;
+import seecoder.devcloud.web.po.tree.TreeLog;
+
+import java.util.List;
+
+@Mapper
+@Repository
+public interface TreeLogMapper {
+
+    /**
+     * 插入,自增ID
+     */
+    @InsertProvider(type = GeneralInsertUpdateSqlProvider.class, method = "insert")
+    @Options(useGeneratedKeys = true, keyProperty = "param1.id")
+    int insertTreeLog(TreeLog project, String... ignoredCols);
+
+    @Select("select * from tree_log where tree_id=#{treeId}")
+    @Results(id="treeLogMap",value = {
+            @Result(column = "user_name", property = "userName"),
+            @Result(column = "tree_id", property = "treeId"),
+            @Result(column = "user_id", property = "userId")
+    })
+    List<TreeLog> listTreeLogsByTreeId(int treeId);
+}

+ 22 - 11
web/src/main/java/seecoder/devcloud/web/dao/tree/TreeNodeMapper.java

@@ -3,8 +3,8 @@ package seecoder.devcloud.web.dao.tree;
 
 import org.apache.ibatis.annotations.*;
 import org.springframework.stereotype.Repository;
+import seecoder.devcloud.web.po.TreeNodePO;
 import seecoder.devcloud.web.dao.provider.TreeNodeProvider;
-import seecoder.devcloud.web.po.TreeNode;
 
 import java.util.List;
 
@@ -23,10 +23,12 @@ public interface TreeNodeMapper {
             @Result(column = "start_time", property = "startTime"),
             @Result(column = "end_time", property = "endTime"),
             @Result(column = "group_id", property = "groupId"),
+            @Result(column = "project_id", property = "projectId"),
+            @Result(column = "parent_id", property = "parentId"),
             @Result(column = "state",property = "state"),
             @Result(column = "type",property = "type")
     })
-    List<TreeNode> listAllTreeNodes();
+    List<TreeNodePO> listAllTreeNodes();
 
     /**
      * 根据id获取TreeNode
@@ -35,33 +37,42 @@ public interface TreeNodeMapper {
      */
     @Select({"select * from tree_nodes where id = #{id}"})
     @ResultMap(value = "treeNodeMap")
-    TreeNode getTreeNodeById(@Param("id") int id);
+    TreeNodePO getTreeNodeById(@Param("id") int id);
 
     /**
      * 根据GroupId获取TreeNode
-     * @param id
+     * @param groupId
      * @return
      */
     @Select({"select * from tree_nodes where group_id = #{groupId}"})
     @ResultMap(value = "treeNodeMap")
-    List<TreeNode> listTreeNodesByGroupId(@Param("groupId") int id);
+    List<TreeNodePO> listTreeNodesByGroupId(@Param("groupId") int groupId);
+
+    /**
+     * 根据projectId获取TreeNode
+     * @param projectId
+     * @return
+     */
+    @Select({"select * from tree_nodes where project_id = #{projectId}"})
+    @ResultMap(value = "treeNodeMap")
+    List<TreeNodePO> listTreeNodesByProjectId(@Param("projectId") int projectId);
 
     /**
      * 插入treeNode
-     * @param treeNode
+     * @param TreeNodePO
      * @return treeNode的自增主键
      */
-    @Insert({"insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) " +
-            "VALUES (#{title}, #{description}, #{type}, #{priority}, #{state}, #{processor}, #{timeToTake}, #{startTime}, #{endTime}, #{leaf}, #{groupId})"})
+    @Insert({"insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id,project_id,deep,parent_id) " +
+            "VALUES (#{title}, #{description}, #{type}, #{priority}, #{state}, #{timeToTake}, #{startTime}, #{endTime}, #{leaf}, #{groupId},#{projectId},#{deep},#{parentId})"})
     @Options(useGeneratedKeys = true, keyProperty = "id")
-    int insertTreeNode(TreeNode treeNode);
+    int insertTreeNode(TreeNodePO TreeNodePO);
 
     /**
      * 更新TreeNode
-     * @param treeNode
+     * @param TreeNodePO
      * @return
      */
     @UpdateProvider(type = TreeNodeProvider.class,method = "updateTreeNode")
-    int updateTreeNode(TreeNode treeNode);
+    int updateTreeNode(TreeNodePO TreeNodePO);
 
 }

+ 2 - 0
web/src/main/java/seecoder/devcloud/web/dao/user/GroupMemberMapper.java

@@ -2,6 +2,7 @@ package seecoder.devcloud.web.dao.user;
 
 import jnr.ffi.annotations.In;
 import org.apache.ibatis.annotations.*;
+import org.springframework.stereotype.Repository;
 import seecoder.devcloud.web.po.user.Group;
 import seecoder.devcloud.web.po.user.User;
 
@@ -13,6 +14,7 @@ import java.util.List;
  * @description:
  */
 @Mapper
+@Repository
 public interface GroupMemberMapper {
 
     @Insert("insert into group_member (group_id,user_id) values (#{groupId}, #{userId}) ")

+ 22 - 0
web/src/main/java/seecoder/devcloud/web/enums/OperationEnum.java

@@ -0,0 +1,22 @@
+package seecoder.devcloud.web.enums;
+
+/**
+ * TreeNode操作类型
+ */
+public enum  OperationEnum {
+    START("开启"),
+    RESTART("重新开启"),
+    UPDATE("更新"),
+    FINISH("结束");
+
+    private String value;
+
+    OperationEnum(String value){
+        this.value=value;
+    }
+
+    @Override
+    public String toString(){
+        return value;
+    }
+}

+ 4 - 3
web/src/main/java/seecoder/devcloud/web/po/TreeNode.java → web/src/main/java/seecoder/devcloud/web/po/TreeNodePO.java

@@ -15,18 +15,19 @@ import java.util.Date;
 @AllArgsConstructor
 @NoArgsConstructor
 @EqualsAndHashCode
-public class TreeNode {
+public class TreeNodePO {
     private int id;
     private String title;
     private String description;
     private NodeTypeEnum type;
     private int priority;
     private NodeStateEnum state;
-    private String processor;
     private int timeToTake;
     private String startTime;
     private String endTime;
     private boolean leaf;
     private int groupId;
-
+    private int projectId;
+    private int parentId;
+    private int deep;
 }

+ 21 - 0
web/src/main/java/seecoder/devcloud/web/po/project/Project.java

@@ -0,0 +1,21 @@
+package seecoder.devcloud.web.po.project;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Chenyz
+ * @date 2021/3/10
+ * @description:
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Project {
+    private Integer id;
+    private String name;
+    private String gitRemoteUrl;
+    private String description;
+    private Integer groupId;
+}

+ 40 - 0
web/src/main/java/seecoder/devcloud/web/po/tree/TreeLog.java

@@ -0,0 +1,40 @@
+package seecoder.devcloud.web.po.tree;
+
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import seecoder.devcloud.web.enums.OperationEnum;
+
+/**
+ * 树操作的日志类,用于后序进行数据分析
+ */
+@Data
+@NoArgsConstructor
+public class TreeLog {
+
+    private Integer id;
+
+    /**
+     * 操作时间
+     */
+    private String time;
+
+    /**
+     * 操作类型
+     */
+    private OperationEnum operation;
+
+    /**
+     * 树节点
+     */
+    private Integer treeId;
+
+    /**
+     * 操作人
+     */
+    private Integer userId;
+
+    /**
+     * 操作名
+     */
+    private String userName;
+}

+ 2 - 0
web/src/main/java/seecoder/devcloud/web/po/user/Group.java

@@ -1,6 +1,8 @@
 package seecoder.devcloud.web.po.user;
 
 
+import lombok.Builder;
+import lombok.Data;
 import lombok.AllArgsConstructor;
 import lombok.Builder;
 import lombok.Data;

+ 0 - 11
web/src/main/java/seecoder/devcloud/web/service/TreeNodeService.java

@@ -1,11 +0,0 @@
-package seecoder.devcloud.web.service;
-
-
-
-import seecoder.devcloud.web.po.TreeNode;
-
-import java.util.List;
-
-public interface TreeNodeService {
-    public List<TreeNode> getAllNodes();
-}

+ 57 - 0
web/src/main/java/seecoder/devcloud/web/service/impl/project/ProjectServiceImpl.java

@@ -0,0 +1,57 @@
+package seecoder.devcloud.web.service.impl.project;
+
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import seecoder.devcloud.web.dao.project.ProjectMapper;
+import seecoder.devcloud.web.po.project.Project;
+import seecoder.devcloud.web.service.project.ProjectService;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.project.ProjectVO;
+
+import java.util.List;
+
+@Service
+public class ProjectServiceImpl implements ProjectService {
+    @Autowired
+    ProjectMapper projectMapper;
+
+
+    @Override
+    public Response<List<Project>> listProjectsByGroupId(int groupId) {
+        List<Project> projects = projectMapper.listProjectsByGroupId(groupId);
+        return Response.ok(projects);
+    }
+
+    @Override
+    // TODO:该方法待测试
+    public Response<List<Project>> listProjectsByUserId(int userId) {
+        List<Project> projects = projectMapper.listProjectsByUserId(userId);
+        return Response.ok(projects);
+    }
+
+    @Override
+    public Response<Project> getProjectById(int projectId) {
+        Project project = projectMapper.getProjectById(projectId);
+        return Response.ok(project);
+    }
+
+    @Override
+    public Response<Project> createProject(ProjectVO projectVO) {
+        Project project = new Project();
+        BeanUtils.copyProperties(projectVO,project);
+        try {
+            projectMapper.insertProject(project);
+            // TODO:在对应的gitlab仓库中注册WEBHOOK
+            return Response.ok(project);
+        }catch (Exception e){
+            return Response.badRequest("异常错误");
+        }
+    }
+
+    @Override
+    public Response deleteProject(int projectId) {
+        //TODO:不知道该怎么做,懒删除?还是直接删?
+        return null;
+    }
+}

+ 40 - 3
web/src/main/java/seecoder/devcloud/web/service/impl/tree/TreeNodeServiceImpl.java

@@ -1,11 +1,16 @@
 package seecoder.devcloud.web.service.impl.tree;
 
 
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import seecoder.devcloud.web.aop.TreeLogging;
+import seecoder.devcloud.web.enums.OperationEnum;
+import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.service.tree.TreeNodeService;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.TreeNodeVO;
 import seecoder.devcloud.web.dao.tree.TreeNodeMapper;
-import seecoder.devcloud.web.po.TreeNode;
-import seecoder.devcloud.web.service.TreeNodeService;
 
 import java.util.List;
 
@@ -14,7 +19,39 @@ public class TreeNodeServiceImpl implements TreeNodeService {
     @Autowired
     private TreeNodeMapper treeNodeMapper;
     @Override
-    public List<TreeNode> getAllNodes() {
+    public List<TreeNodePO> getAllNodes() {
+        return treeNodeMapper.listAllTreeNodes();
+    }
+
+    @Override
+    public Response listTreeNodesByProjectId(int projectId) {
+        // TODO:safety check
+        return Response.ok(treeNodeMapper.listTreeNodesByProjectId(projectId));
+    }
+
+    @Override
+    @TreeLogging(OperationEnum.START)
+    public Response insertTreeNode(TreeNodeVO treeNodeVO) {
+        TreeNodePO treeNodePO = new TreeNodePO();
+        BeanUtils.copyProperties(treeNodeVO,treeNodePO);
+        int res = treeNodeMapper.insertTreeNode(treeNodePO);
+        // TODO:safety check
+        return Response.ok();
+    }
+
+    @Override
+    @TreeLogging(OperationEnum.UPDATE)
+    public Response updateTreeNode(TreeNodeVO treeNodeVO) {
+        TreeNodePO treeNodePO = new TreeNodePO();
+        BeanUtils.copyProperties(treeNodeVO,treeNodePO);
+        int res = treeNodeMapper.updateTreeNode(treeNodePO);
+        // TODO:safety check
+        return Response.ok();
+    }
+
+    @Override
+    public Response deleteTreeNode(TreeNodeVO treeNodeVO) {
         return null;
     }
+
 }

+ 40 - 0
web/src/main/java/seecoder/devcloud/web/service/project/ProjectService.java

@@ -0,0 +1,40 @@
+package seecoder.devcloud.web.service.project;
+
+import org.springframework.web.bind.annotation.PathVariable;
+import seecoder.devcloud.web.po.project.Project;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.project.ProjectVO;
+
+import java.util.List;
+
+public interface ProjectService {
+    /**
+     * 根据group找projects
+     */
+    Response<List<Project>> listProjectsByGroupId(int groupId);
+
+    /**
+     * 根据user找Project
+     */
+    Response<List<Project>> listProjectsByUserId(int userId);
+
+    /**
+     * 获取project
+     * @param projectId
+     * @return
+     */
+    Response<Project> getProjectById(int projectId);
+
+    /**
+     * 创建项目
+     * @param project 不包含id
+     * @return 注入id后返回
+     */
+    Response<Project> createProject(ProjectVO project);
+
+    /**
+     * 删除项目,懒删除
+     */
+    Response deleteProject(int projectId);
+
+}

+ 42 - 0
web/src/main/java/seecoder/devcloud/web/service/tree/TreeNodeService.java

@@ -0,0 +1,42 @@
+package seecoder.devcloud.web.service.tree;
+
+
+
+import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.TreeNodeVO;
+
+import java.util.List;
+
+public interface TreeNodeService {
+
+    List<TreeNodePO> getAllNodes();
+
+    /**
+     * 根据项目id获取该项目下的treeNode
+     * @param projectId
+     * @return
+     */
+    Response listTreeNodesByProjectId(int projectId);
+
+    /**
+     * 新增一条需求
+     * @param treeNodeVO
+     * @return
+     */
+    Response insertTreeNode(TreeNodeVO treeNodeVO);
+
+    /**
+     * 更新一条需求
+     * @param treeNodeVO
+     * @return
+     */
+    Response updateTreeNode(TreeNodeVO treeNodeVO);
+
+    /**
+     * 删除一条需求
+     * @param treeNodeVO
+     * @return
+     */
+    Response deleteTreeNode(TreeNodeVO treeNodeVO);
+}

+ 28 - 0
web/src/main/java/seecoder/devcloud/web/vo/TreeNodeVO.java

@@ -0,0 +1,28 @@
+package seecoder.devcloud.web.vo;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import seecoder.devcloud.web.enums.NodeStateEnum;
+import seecoder.devcloud.web.enums.NodeTypeEnum;
+
+@NoArgsConstructor
+@Data
+@AllArgsConstructor
+public class TreeNodeVO {
+    private int id;
+    private int userId; /*操作用户的ID*/
+    private String title;
+    private String description;
+    private NodeTypeEnum type;
+    private int priority;
+    private NodeStateEnum state;
+    private int timeToTake;
+    private String startTime;
+    private String endTime;
+    private boolean leaf;
+    private int groupId;
+    private int projectId;
+    private int parentId;
+    private int deep;
+}

+ 21 - 0
web/src/main/java/seecoder/devcloud/web/vo/project/ProjectVO.java

@@ -0,0 +1,21 @@
+package seecoder.devcloud.web.vo.project;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Chenyz
+ * @date 2021/3/10
+ * @description:
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class ProjectVO {
+    private Integer id;
+    private String name;
+    private String gitRemoteUrl;
+    private String description;
+    private Integer groupId;
+}

+ 39 - 0
web/src/main/resources/SQLScripts/project.sql

@@ -0,0 +1,39 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : localhost_3306
+ Source Server Type    : MySQL
+ Source Server Version : 80018
+ Source Host           : localhost:3306
+ Source Schema         : seecoder
+
+ Target Server Type    : MySQL
+ Target Server Version : 80018
+ File Encoding         : 65001
+
+ Date: 10/03/2021 23:54:40
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for project
+-- ----------------------------
+DROP TABLE IF EXISTS `project`;
+CREATE TABLE `project`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `description` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `git_remote_url` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
+  `group_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of project
+-- ----------------------------
+INSERT INTO `project` VALUES (1, '前端', 'DevCloud前端', 'http://gogs.seecoder.cn/HuangKaiSheng/seecoder-devcloud-frontend/src/master', 1);
+INSERT INTO `project` VALUES (2, '后端开发', '后端测试测试测试测试测试', 'http://gogs.seecoder.cn/WengPuHong/seecoder-devcloud', 1);
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 38 - 0
web/src/main/resources/SQLScripts/tree_log.sql

@@ -0,0 +1,38 @@
+/*
+ Navicat Premium Data Transfer
+
+ Source Server         : localhost_3306
+ Source Server Type    : MySQL
+ Source Server Version : 80018
+ Source Host           : localhost:3306
+ Source Schema         : seecoder
+
+ Target Server Type    : MySQL
+ Target Server Version : 80018
+ File Encoding         : 65001
+
+ Date: 11/03/2021 09:46:42
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for tree_log
+-- ----------------------------
+DROP TABLE IF EXISTS `tree_log`;
+CREATE TABLE `tree_log`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `time` datetime(0) NULL DEFAULT NULL,
+  `operation` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  `user_id` int(11) NULL DEFAULT NULL,
+  `tree_id` int(11) NULL DEFAULT NULL,
+  `user_name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of tree_log
+-- ----------------------------
+
+SET FOREIGN_KEY_CHECKS = 1;

+ 25 - 9
web/src/main/resources/SQLScripts/trees.sql

@@ -1,4 +1,17 @@
 SET foreign_key_checks = 0;
+# 需求执行者
+drop table if exists treenode_processor;
+create table treenode_processor
+(
+    id           int auto_increment,
+    PRIMARY KEY (id),
+    tree_node_id int not null ,
+    processor_id int not null,
+    processor_name varchar(64) not null
+);
+insert into treenode_processor(tree_node_id, processor_id, processor_name) VALUES (1,1,"qinliu");
+
+# 需求节点
 drop table if exists tree_nodes;
 create table tree_nodes
 (
@@ -8,37 +21,40 @@ create table tree_nodes
     type         varchar(32)      default 0                 not null,
     priority     int      default 0                 null,
     state        varchar(32)      default 0                 not null,
-    processor    varchar(64)                        not null,
     time_to_take int      default 0                 not null,
     start_time   datetime default CURRENT_TIMESTAMP null,
     end_time     datetime                           null,
     is_leaf      int      default 0                 null,
     group_id     int                                null,
+    project_id   int                                null,
+    deep         int                                null,
+    parent_id     int                                null,
     constraint tree_nodes_id_uindex
         unique (id)
 );
 
 alter table tree_nodes
     add primary key (id);
-insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) values ("test1","test1","REQUIREMENT",0,"PROCESSING","qinliu",10,"2021-1-1","2021-2-13",1,1);
-insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) values ("test2","test2","REQUIREMENT",0,"PROCESSING","qinliu",10,"2021-1-2","2021-2-13",1,1);
-insert into tree_nodes(title, description, type, priority, state, processor, time_to_take, start_time, end_time, is_leaf, group_id) values ("test3","test3","REQUIREMENT",0,"PROCESSING","qinliu",10,"2021-1-3","2021-2-13",1,1);
+insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id, project_id, deep,parent_id) values ("test1","test1","REQUIREMENT",0,"PROCESSING",10,"2021-1-1","2021-2-13",1,1,1,1,1);
+insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id, project_id, deep,parent_id) values ("test2","test2","REQUIREMENT",0,"PROCESSING",10,"2021-1-2","2021-2-13",1,1,1,1,1);
+insert into tree_nodes(title, description, type, priority, state, time_to_take, start_time, end_time, is_leaf, group_id, project_id, deep,parent_id) values ("test3","test3","REQUIREMENT",0,"PROCESSING",10,"2021-1-3","2021-2-13",1,1,1,1,1);
 
+# 信息 留言
 drop table if exists messages;
-create table messages
+drop table if exists tree_messages;
+create table tree_messages
 (
     message_id   int auto_increment,
     creator      varchar(64)  not null,
     tree_node_id int          null,
     detail       varchar(512) null,
-    constraint messages_message_id_uindex
+    constraint tree_messages_message_id_uindex
         unique (message_id),
     constraint tree_node_fk
         foreign key (tree_node_id) references tree_nodes (id)
             on update cascade on delete cascade
 );
-
-alter table messages
+alter table tree_messages
     add primary key (message_id);
 
 drop table if exists tree_sides;
@@ -56,7 +72,7 @@ create table tree_sides
         foreign key (parent_id) references tree_nodes (id)
             on update cascade on delete cascade
 );
-
+# 树边,暂时用不到了
 alter table tree_sides
     add primary key (side_id);
 

+ 55 - 0
web/src/main/resources/application-cyz.yml

@@ -0,0 +1,55 @@
+spring:
+  datasource:
+    url: jdbc:mysql://localhost:3306/seecoder?allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8&useSSL=false
+    username: root
+    password: 123456
+
+  mail:
+    host: smtp.qq.com
+    username: 370774330@qq.com
+    password: qkoecnzivukvbibi
+    port: 465
+    protocol: smtp
+    properties:
+      mail:
+        smtp:
+          ssl:
+            enable: true
+          socketFactory.class: javax.net.ssl.SSLSocketFactory
+        debug: true
+server:
+  port: 8080
+
+mybatis:
+  configuration:
+    map-underscore-to-camel-case: true
+
+seecoder:
+  k8s:
+    api-server: https://192.168.99.105:8443
+    token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjBmSXc4RlRjNUpBYVpGYWc4QzRDY1MzUWJad1JMdFhKcDI1cngzWGtiRlkifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZXZjbG91ZCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJkZWZhdWx0LXRva2VuLXNicXY4Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImRlZmF1bHQiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NmIxNzU1ZS0zZjE3LTQ1ZTctODFmYi01MTRhODA3NDRhMzQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGV2Y2xvdWQ6ZGVmYXVsdCJ9.W0Y1lR6LBi1ZjylBx35YeqYuq2u2AqH-ayK4FD-LDfC26E89DanOwSv9XLrRMnnDBZFS_ZCRBumbnDeMiS5vw2x7-QnrDqj1M5u9FB2fIJsz2LyUkOhATZZmTzj_Uhewvvg09aDKh16ttj6ZX27m-KVk_6MP-VfiuvZnCVxDbqRkRjK-zsor4ty1CEATPyKK-tvugAwS0RFNHUL94DamfZAq_t1PSnH5ZtEHq0uEMZxY2c7j6u9d_aD9lphm_ZpCy_C8OCHfanM21CQPDHlcJTW_aiOO6bAp8qdc1egPO5uIamHl6Zm0N3RkcsRp4DGOHrltTV9y_cGZHXSWmRHfxw
+    debugging: true
+  gitlab:
+    host: http://gitlab.192.168.99.105.nip.io
+    webHookProxy: http://localhost:3000
+    token: wXDeETv2Kmt-JhiApJ9H
+  mail:
+    from: 370774330@qq.com
+
+
+  jenkins:
+    host: http://192.168.68.79:8082
+    username: root
+    token: 11d7b9e4c1acac481904c25813e2ec1f0a
+  docker:
+    registry: 192.168.68.79:18082
+
+
+
+  registry:
+    host: 192.168.68.79:18082
+    username: admin
+    password: admin123
+    nexus-server: 192.168.68.79:18081
+    repo-name: sec-repo
+    clean-up-task: 83bb8249-71e8-4367-83b3-50c6f7518860

+ 1 - 1
web/src/main/resources/application.yml

@@ -1,3 +1,3 @@
 spring:
   profiles:
-    active: wph
+    active: cyz

+ 78 - 0
web/src/test/java/seecoder/devcloud/web/dao/project/ProjectMapperTest.java

@@ -0,0 +1,78 @@
+package seecoder.devcloud.web.dao.project;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.dao.user.GroupMemberMapper;
+import seecoder.devcloud.web.po.project.Project;
+
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@MybatisTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+public class ProjectMapperTest {
+    @Autowired
+    ProjectMapper projectMapper;
+    @Autowired
+    GroupMemberMapper groupMemberMapper;
+
+    @Test
+    public void testInsert(){
+        Project project = new Project(null,"TEST","JUST A TEST","seecoder.cn",2);
+        projectMapper.insertProject(project);
+        Project project2 = projectMapper.getProjectById(project.getId());
+        assert project.equals(project2);
+    }
+
+    @Test
+    public void testUpdate(){
+        Project project2 = projectMapper.getProjectById(1);
+        project2.setName("modify");
+        project2.setDescription("modify description");
+        project2.setGitRemoteUrl("www.google.com");
+        project2.setGroupId(7);
+        projectMapper.updateProject(project2);
+        Project project = projectMapper.getProjectById(1);
+        System.out.println(project);
+        assert project2.equals(project);
+    }
+
+    @Test
+    public void testListProjectsByGroupId(){
+        List<Project> projects = projectMapper.listProjectsByGroupId(1);
+        boolean res = true;
+        for (Project project:projects){
+            if(project.getGroupId()!=1){
+                res = false;
+                break;
+            }
+        }
+        assert res;
+    }
+
+    /**
+     * 这个因为groupMemberMapper有外键,不好测
+     */
+//    @Test
+    public void testListProjectsByUserId(){
+        Project project = new Project(0,"test","seecoder.cn","decription",2);
+        projectMapper.insertProject(project);
+        // TODO:插入如下两条数据
+//        groupMemberMapper.insert(2,1);
+//        groupMemberMapper.insert(1,1);
+        List<Project> projects = projectMapper.listProjectsByUserId(1);
+        boolean res = true;
+        for (Project project1:projects){
+            System.out.println(project1);
+            if(project1.getGroupId()!=1||project1.getGroupId()!=2){
+                res = false;
+                break;
+            }
+        }
+        assert res;
+    }
+}

+ 43 - 0
web/src/test/java/seecoder/devcloud/web/dao/tree/TreeLogMapperTest.java

@@ -0,0 +1,43 @@
+package seecoder.devcloud.web.dao.tree;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.test.context.junit4.SpringRunner;
+import seecoder.devcloud.web.enums.OperationEnum;
+import seecoder.devcloud.web.po.tree.TreeLog;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@MybatisTest
+@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
+public class TreeLogMapperTest {
+    @Autowired
+    TreeLogMapper treeLogMapper;
+
+    @Test
+    public void testInsertAndSelect(){
+        TreeLog treeLog = new TreeLog();
+        treeLog.setTreeId(1);
+        treeLog.setUserId(1);
+        treeLog.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+        treeLog.setUserName("test");
+        treeLog.setOperation(OperationEnum.START);
+        treeLogMapper.insertTreeLog(treeLog);
+        List<TreeLog> logList = treeLogMapper.listTreeLogsByTreeId(1);
+        boolean res = false;
+        for(TreeLog log:logList){
+            if(log.equals(treeLog)){
+                res = true;
+                System.out.println(log);
+                break;
+            }
+        }
+        assert res;
+    }
+}

+ 16 - 16
web/src/test/java/seecoder/devcloud/web/dataMapper/TreeNodeMapperTest.java → web/src/test/java/seecoder/devcloud/web/dao/tree/TreeNodeMapperTest.java

@@ -1,4 +1,4 @@
-package seecoder.devcloud.web.dataMapper;
+package seecoder.devcloud.web.dao.tree;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -9,7 +9,7 @@ import org.springframework.test.context.junit4.SpringRunner;
 import seecoder.devcloud.web.dao.tree.TreeNodeMapper;
 import seecoder.devcloud.web.enums.NodeStateEnum;
 import seecoder.devcloud.web.enums.NodeTypeEnum;
-import seecoder.devcloud.web.po.TreeNode;
+import seecoder.devcloud.web.po.TreeNodePO;
 
 import java.util.List;
 
@@ -22,37 +22,37 @@ public class TreeNodeMapperTest {
 
     @Test
     public void listAllTreeNodesTest(){
-        List<TreeNode> treeNodes =  treeNodeMapper.listAllTreeNodes();
-        for (TreeNode treeNode:treeNodes){
-            System.out.println(treeNode);
+        List<TreeNodePO> treeNodes =  treeNodeMapper.listAllTreeNodes();
+        for (TreeNodePO TreeNodePO:treeNodes){
+            System.out.println(TreeNodePO);
         }
         assert treeNodes.size()!=0;
     }
 
     @Test
     public void getTreeNodeByIdTest(){
-        TreeNode node = treeNodeMapper.getTreeNodeById(1);
+        TreeNodePO node = treeNodeMapper.getTreeNodeById(1);
         System.out.println(node);
-        TreeNode node1 = new TreeNode(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,"qinliu",10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1);
+        TreeNodePO node1 = new TreeNodePO(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,1,1);
         assert node.equals(node1);
     }
 
     @Test
     public void listTreeNodesByGroupIdTest(){
-        List<TreeNode> treeNodes = treeNodeMapper.listTreeNodesByGroupId(1);
-        TreeNode node1 = new TreeNode(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,"qinliu",10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1);
-        for(TreeNode treeNode:treeNodes){
-            if (treeNode.getId()==1){
-                assert treeNode.equals(node1);
+        List<TreeNodePO> treeNodes = treeNodeMapper.listTreeNodesByGroupId(1);
+        TreeNodePO node1 = new TreeNodePO(1,"test1","test1", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,1,1);
+        for(TreeNodePO TreeNodePO:treeNodes){
+            if (TreeNodePO.getId()==1){
+                assert TreeNodePO.equals(node1);
             }
         }
     }
 
     @Test
     public void insertTreeNodeTest(){
-        TreeNode node1 = new TreeNode(0,"testInsert","testInsert", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,"qinliu",10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1);
+        TreeNodePO node1 = new TreeNodePO(0,"testInsert","testInsert", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,1,1);
         int res = treeNodeMapper.insertTreeNode(node1);
-        TreeNode node = treeNodeMapper.getTreeNodeById(node1.getId());
+        TreeNodePO node = treeNodeMapper.getTreeNodeById(node1.getId());
         System.out.println(node);
         System.out.println(node1);
         assert res==1;
@@ -61,9 +61,9 @@ public class TreeNodeMapperTest {
 
     @Test
     public void updateTreeNodeTest(){
-        TreeNode node1 = new TreeNode(1,"update","update", NodeTypeEnum.TASK,1, NodeStateEnum.FINISHED,"qinliu667",20,"2021-01-10 00:00:00","2021-02-15 00:00:00",false,2);
+        TreeNodePO node1 = new TreeNodePO(1,"update","update", NodeTypeEnum.TASK,1, NodeStateEnum.FINISHED,20,"2021-01-10 00:00:00","2021-02-15 00:00:00",false,2,1,1,1);
         treeNodeMapper.updateTreeNode(node1);
-        TreeNode node = treeNodeMapper.getTreeNodeById(1);
+        TreeNodePO node = treeNodeMapper.getTreeNodeById(1);
         System.out.println(node);
         assert node.equals(node1);
     }

+ 42 - 0
web/src/test/java/seecoder/devcloud/web/service/TreeNodeServiceTest.java

@@ -0,0 +1,42 @@
+package seecoder.devcloud.web.service;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+import seecoder.devcloud.web.DevcloudWebApplication;
+import seecoder.devcloud.web.enums.NodeStateEnum;
+import seecoder.devcloud.web.enums.NodeTypeEnum;
+import seecoder.devcloud.web.po.TreeNodePO;
+import seecoder.devcloud.web.service.tree.TreeNodeService;
+import seecoder.devcloud.web.vo.TreeNodeVO;
+
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = DevcloudWebApplication.class)
+@Transactional
+public class TreeNodeServiceTest {
+    @Autowired
+    TreeNodeService treeNodeService;
+    TreeNodeVO treeNodeVO;
+
+    @Before
+    public void initTreeNodeVO(){
+        treeNodeVO = new TreeNodeVO(1,1,"test5","test5", NodeTypeEnum.REQUIREMENT,0, NodeStateEnum.PROCESSING,10,"2021-01-01 00:00:00","2021-02-13 00:00:00",true,1,1,-1,0);
+    }
+
+    @Test
+    public void testInsert(){
+        treeNodeService.insertTreeNode(treeNodeVO);
+        List<TreeNodePO> treeNodePOList = treeNodeService.getAllNodes();
+        for (TreeNodePO treeNode:treeNodePOList) {
+            System.out.println(treeNode);
+        }
+    }
+}

+ 56 - 0
web/src/test/java/seecoder/devcloud/web/service/project/ProjectServiceTest.java

@@ -0,0 +1,56 @@
+package seecoder.devcloud.web.service.project;
+
+import io.swagger.annotations.Api;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.transaction.annotation.Transactional;
+import seecoder.devcloud.web.DevcloudWebApplication;
+import seecoder.devcloud.web.enums.ResponseEnums;
+import seecoder.devcloud.web.po.project.Project;
+import seecoder.devcloud.web.vo.Response;
+import seecoder.devcloud.web.vo.project.ProjectVO;
+
+import java.util.List;
+
+
+@Api(tags = "GitLab Hook API")
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = DevcloudWebApplication.class)
+@Transactional
+public class ProjectServiceTest {
+    @Autowired
+    ProjectService projectService;
+    ProjectVO projectVO;
+
+    @Before
+    public void initProjectVO(){
+        projectVO  = new ProjectVO(null,"TEST","JUST A TEST","seecoder.cn",2);
+    }
+
+    @Test
+    public void testInsert(){
+        Response<Project> projectResponse = projectService.createProject(projectVO);
+        assert projectResponse.getCode().equals(ResponseEnums.OK.getCode());
+        Project project = projectResponse.getData();
+        System.out.println(project);
+        assert project.getName().equals(projectVO.getName());
+        assert project.getGitRemoteUrl().equals(projectVO.getGitRemoteUrl());
+        assert project.getDescription().equals(projectVO.getDescription());
+        assert project.getGroupId().equals(projectVO.getGroupId());
+    }
+
+    @Test
+    public void testListProjectsByGroupId(){
+        Response<List<Project>>  listResponse = projectService.listProjectsByGroupId(1);
+        assert listResponse.getCode().equals(ResponseEnums.OK.getCode());
+        for(Project project:listResponse.getData()){
+            assert project.getGroupId()==1;
+        }
+    }
+
+
+}