Browse Source

加个起止时间。调整一下作业创建逻辑

GuardOfDawn 7 years ago
parent
commit
c4f979bc8e

+ 7 - 0
src/main/java/nju/seec/SEECdemo/data/dao/assignment/CodeDAO.java

@@ -1,8 +1,15 @@
 package nju.seec.SEECdemo.data.dao.assignment;
 package nju.seec.SEECdemo.data.dao.assignment;
 
 
 import nju.seec.SEECdemo.data.entity.assignment.Code;
 import nju.seec.SEECdemo.data.entity.assignment.Code;
+import nju.seec.SEECdemo.util.enums.AssignmentStatus;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaRepository;
 
 
+import java.util.List;
+
 public interface CodeDAO extends JpaRepository<Code, Integer> {
 public interface CodeDAO extends JpaRepository<Code, Integer> {
     Code findById(int id);
     Code findById(int id);
+
+    List<Code> findByCourseIdAndStatusIs(int courseId, AssignmentStatus status);
+
+    List<Code> findByCourseIdAndStatusIn(int courseId, List<AssignmentStatus> statuses);
 }
 }

+ 2 - 1
src/main/java/nju/seec/SEECdemo/data/dao/assignment/CodeResultDAO.java

@@ -1,5 +1,6 @@
 package nju.seec.SEECdemo.data.dao.assignment;
 package nju.seec.SEECdemo.data.dao.assignment;
 
 
+import nju.seec.SEECdemo.data.entity.assignment.Code;
 import nju.seec.SEECdemo.data.entity.assignment.CodeResult;
 import nju.seec.SEECdemo.data.entity.assignment.CodeResult;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaRepository;
 
 
@@ -8,5 +9,5 @@ import java.util.Set;
 public interface CodeResultDAO extends JpaRepository<CodeResult, Integer> {
 public interface CodeResultDAO extends JpaRepository<CodeResult, Integer> {
     CodeResult findById(int id);
     CodeResult findById(int id);
 
 
-//    Set<CodeResult> save(Set<CodeResult> codeResultSet);
+    CodeResult findByCodeAndGroupId(Code code, int groupId);
 }
 }

+ 9 - 0
src/main/java/nju/seec/SEECdemo/data/entity/assignment/Code.java

@@ -10,6 +10,7 @@ import org.hibernate.annotations.LazyCollection;
 import org.hibernate.annotations.LazyCollectionOption;
 import org.hibernate.annotations.LazyCollectionOption;
 
 
 import javax.persistence.*;
 import javax.persistence.*;
+import java.time.LocalDateTime;
 import java.util.HashSet;
 import java.util.HashSet;
 import java.util.Set;
 import java.util.Set;
 
 
@@ -40,6 +41,14 @@ public class Code {
     @Column(name = "status", columnDefinition = "VARCHAR(255) NOT NULL DEFAULT 'PREPARING'")
     @Column(name = "status", columnDefinition = "VARCHAR(255) NOT NULL DEFAULT 'PREPARING'")
     private AssignmentStatus status = AssignmentStatus.PREPARING;
     private AssignmentStatus status = AssignmentStatus.PREPARING;
 
 
+    @Basic
+    @Column(name = "start_at", nullable = false)
+    private LocalDateTime startAt;
+
+    @Basic
+    @Column(name = "end_at", nullable = false)
+    private LocalDateTime endAt;
+
     @Basic
     @Basic
     @Column(name = "question", nullable = false)
     @Column(name = "question", nullable = false)
     private Long questionId;
     private Long questionId;

+ 1 - 1
src/main/java/nju/seec/SEECdemo/data/entity/assignment/CodeResult.java

@@ -34,7 +34,7 @@ public class CodeResult {
 
 
     @Basic
     @Basic
     @Column(name = "deployNS")
     @Column(name = "deployNS")
-    private String deployNamespace;
+    private Long deployNamespace;
 
 
     @Basic
     @Basic
     @Column(name = "testJob")
     @Column(name = "testJob")

+ 7 - 0
src/main/java/nju/seec/SEECdemo/logic/api/GitlabApi.java

@@ -50,4 +50,11 @@ public interface GitlabApi {
 	 */
 	 */
 	void createCommit(int projectId, String branch, String commitMessage, String email, String username, List<CommitAction> actions) throws GitLabApiException;
 	void createCommit(int projectId, String branch, String commitMessage, String email, String username, List<CommitAction> actions) throws GitLabApiException;
 
 
+	/**
+     * 获取root用户的id
+	 * @Param
+	 * @return
+	 **/
+	Integer getRootUserId();
+
 }
 }

+ 6 - 1
src/main/java/nju/seec/SEECdemo/logic/api/impl/GitlabApiImpl.java

@@ -94,7 +94,7 @@ public class GitlabApiImpl implements GitlabApi {
 	}
 	}
 
 
 	public synchronized void addMemberToGroup(int groupId, int userId) throws GitLabApiException {
 	public synchronized void addMemberToGroup(int groupId, int userId) throws GitLabApiException {
-	    Member member = server.getGroupApi().addMember(groupId, userId, AccessLevel.OWNER);
+	    Member member = server.getGroupApi().addMember(groupId, userId, AccessLevel.MASTER);
     }
     }
 
 
 	@Override
 	@Override
@@ -171,4 +171,9 @@ public class GitlabApiImpl implements GitlabApi {
         commitsApi.createCommit(projectId, branch, commitMessage, null, email, username,actions);
         commitsApi.createCommit(projectId, branch, commitMessage, null, email, username,actions);
     }
     }
 
 
+    @Override
+	public Integer getRootUserId() {
+		return gitlab.getUserId();
+	}
+
 }
 }

+ 9 - 0
src/main/java/nju/seec/SEECdemo/logic/service/CodeService.java

@@ -7,4 +7,13 @@ public interface CodeService {
 
 
     CodeWorkVO createAssignment(int courseId, CodeWorkDTO codeWorkDTO);
     CodeWorkVO createAssignment(int courseId, CodeWorkDTO codeWorkDTO);
 
 
+    /**
+     * @Author zhangyi
+     * @Description 将新建的组,加入到作业中
+     * @Date
+     * @Param
+     * @return
+     **/
+    void groupAddedCheck(int groupId);
+
 }
 }

+ 54 - 27
src/main/java/nju/seec/SEECdemo/logic/service/impl/assignment/AssignmentPaperBuilder.java

@@ -4,6 +4,7 @@ import nju.seec.SEECdemo.data.dao.assignment.CodeDAO;
 import nju.seec.SEECdemo.data.dao.assignment.CodeResultDAO;
 import nju.seec.SEECdemo.data.dao.assignment.CodeResultDAO;
 import nju.seec.SEECdemo.data.entity.assignment.Code;
 import nju.seec.SEECdemo.data.entity.assignment.Code;
 import nju.seec.SEECdemo.data.entity.assignment.CodeResult;
 import nju.seec.SEECdemo.data.entity.assignment.CodeResult;
+import nju.seec.SEECdemo.logic.service.ProjectService;
 import nju.seec.SEECdemo.logic.service.impl.assignment.mock.MockGroup;
 import nju.seec.SEECdemo.logic.service.impl.assignment.mock.MockGroup;
 import nju.seec.SEECdemo.logic.api.GitlabApi;
 import nju.seec.SEECdemo.logic.api.GitlabApi;
 import nju.seec.SEECdemo.logic.api.JenkinsApi;
 import nju.seec.SEECdemo.logic.api.JenkinsApi;
@@ -11,6 +12,8 @@ import nju.seec.SEECdemo.logic.service.impl.assignment.mock.MockQuestion;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.GroupServiceStub;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.GroupServiceStub;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.QuestionServiceStub;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.QuestionServiceStub;
 import nju.seec.SEECdemo.logic.storage.StorageProvider;
 import nju.seec.SEECdemo.logic.storage.StorageProvider;
+import nju.seec.SEECdemo.util.ApplicationProperties;
+import nju.seec.SEECdemo.util.ToolKit;
 import nju.seec.SEECdemo.util.enums.AssignmentStatus;
 import nju.seec.SEECdemo.util.enums.AssignmentStatus;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.FileUtils;
 import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -24,6 +27,8 @@ import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.File;
 import java.io.IOException;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Files;
+import java.time.ZoneId;
+import java.util.Date;
 
 
 @Component
 @Component
 public class AssignmentPaperBuilder {
 public class AssignmentPaperBuilder {
@@ -38,10 +43,11 @@ public class AssignmentPaperBuilder {
 
 
     private final QuestionServiceStub questionServiceStub;
     private final QuestionServiceStub questionServiceStub;
     private final GroupServiceStub groupServiceStub;
     private final GroupServiceStub groupServiceStub;
+    private final ProjectService projectService;
 
 
     @Autowired
     @Autowired
     public AssignmentPaperBuilder(GitlabApi gitlabApi, GitHelper helper, JenkinsApi jenkinsApi, CodeDAO codeDAO, CodeResultDAO codeResultDAO, StorageProvider storageProvider,
     public AssignmentPaperBuilder(GitlabApi gitlabApi, GitHelper helper, JenkinsApi jenkinsApi, CodeDAO codeDAO, CodeResultDAO codeResultDAO, StorageProvider storageProvider,
-                                  QuestionServiceStub questionServiceStub, GroupServiceStub groupServiceStub){
+                                  QuestionServiceStub questionServiceStub, GroupServiceStub groupServiceStub, ProjectService projectService){
         this.gitlabApi = gitlabApi;
         this.gitlabApi = gitlabApi;
         this.helper = helper;
         this.helper = helper;
         this.jenkinsApi = jenkinsApi;
         this.jenkinsApi = jenkinsApi;
@@ -50,46 +56,67 @@ public class AssignmentPaperBuilder {
         this.storageProvider = storageProvider;
         this.storageProvider = storageProvider;
         this.questionServiceStub = questionServiceStub;
         this.questionServiceStub = questionServiceStub;
         this.groupServiceStub = groupServiceStub;
         this.groupServiceStub = groupServiceStub;
+        this.projectService = projectService;
     }
     }
 
 
     @Transactional
     @Transactional
-    public void buildCodePaper(int codeId) throws IOException, GitLabApiException, GitAPIException {
-        Code code = codeDAO.findById(codeId);
-        if (code.getStatus() != AssignmentStatus.PREPARING) return;
+    public void buildCodePaper(Code code) throws IOException, GitAPIException, GitLabApiException {
         File tempDir = Files.createTempDirectory(TEMP_PREFIX).toFile();
         File tempDir = Files.createTempDirectory(TEMP_PREFIX).toFile();
         try {
         try {
+            code.setId(gitlabApi.createProject(code.getUuid()));
             releaseQuestion(code.getQuestionId(), tempDir);
             releaseQuestion(code.getQuestionId(), tempDir);
             code.setInitHash(helper.push(tempDir, code.getUuid()));
             code.setInitHash(helper.push(tempDir, code.getUuid()));
-            // 为群组创建项目,并将组员加入到项目中
-            for(MockGroup group: groupServiceStub.getGroupListByCourse(code.getCourseId())){
-                int projectId = gitlabApi.forkProject(group.getMemberSet().iterator().next(), code.getId(), group.getNamespace());
-                CodeResult codeResult = new CodeResult();
-                codeResult.setId(projectId);
-                codeResult.setGroupId(group.getId());
-                codeResult.setCode(code);
-                // TODO
-                // 创建jenkins上的构建job
-                String buildJob = projectId + "-build";
-                jenkinsApi.createBuildJob(buildJob);
-                codeResult.setBuildJob(buildJob);
-                // 调用kube Api创建该项目的应用空间,并记录其id
-
-                // 创建jenkins上的测试job
-                String testJob = projectId + "-test";
-                jenkinsApi.createTestJob(testJob);
-                codeResult.setTestJob(testJob);
-                codeResultDAO.save(codeResult);
-            }
-            code.setStatus(AssignmentStatus.AVAILABLE);
-        } catch (Exception e) {
+        } catch (GitAPIException | GitLabApiException e) {
             code.setStatus(AssignmentStatus.UNAVAILABLE);
             code.setStatus(AssignmentStatus.UNAVAILABLE);
             throw e;
             throw e;
         } finally {
         } finally {
-            codeDAO.save(code);
             FileUtils.deleteDirectory(tempDir);
             FileUtils.deleteDirectory(tempDir);
         }
         }
     }
     }
 
 
+    @Transactional
+    public void addGroupsToPaper(int codeId) {
+        Code code = codeDAO.findById(codeId);
+        if (code.getStatus() != AssignmentStatus.PREPARING) return;
+        // 为群组创建项目,并将组员加入到项目中
+        try {
+            for(MockGroup group: groupServiceStub.getGroupListByCourse(code.getCourseId())){
+                addGroupToPaper(code, group);
+            }
+            code.setStatus(AssignmentStatus.AVAILABLE);
+        } catch (IOException | GitLabApiException e) {
+            System.out.println("将小组加入作业时发生异常" + ToolKit.format(e));
+            code.setStatus(AssignmentStatus.UNAVAILABLE);
+        }
+        codeDAO.save(code);
+    }
+
+    public void addGroupToPaper(Code code, MockGroup group) throws IOException, GitLabApiException {
+        // fork项目的时候,将项目设置成private的,因为组员设置成了Master权限,而只有组的Owner才能够更项目可见性
+        // (private、internal、public),所以此处用root用户来fork
+        int projectId = gitlabApi.forkProject(gitlabApi.getRootUserId(), code.getId(), group.getNamespace());
+        CodeResult codeResult = new CodeResult();
+        codeResult.setId(projectId);
+        codeResult.setGroupId(group.getId());
+        codeResult.setCode(code);
+        // TODO
+        // 创建jenkins上的构建job
+        String buildJob = projectId + "-build";
+        jenkinsApi.createBuildJob(buildJob);
+        codeResult.setBuildJob(buildJob);
+        // 调用kube Api创建该项目的部署空间,并记录其id
+//                Long projectDeployNameSpace = projectService.createSeecIIProject(group.getName() + code.getUuid(),
+//                        code.getDescription(), // 可以是中文吗?
+//                        Date.from(code.getStartAt().atZone(ZoneId.systemDefault()).toInstant()),
+//                        Date.from(code.getEndAt().atZone(ZoneId.systemDefault()).toInstant()));
+//                codeResult.setDeployNamespace(projectDeployNameSpace);
+        // 创建jenkins上的测试job
+        String testJob = projectId + "-test";
+        jenkinsApi.createTestJob(testJob);
+        codeResult.setTestJob(testJob);
+        codeResultDAO.save(codeResult);
+    }
+
     private void releaseQuestion(Long questionId, File codeDir) throws IOException {
     private void releaseQuestion(Long questionId, File codeDir) throws IOException {
         FileUtils.cleanDirectory(codeDir);
         FileUtils.cleanDirectory(codeDir);
         MockQuestion question = questionServiceStub.getQuestion(questionId);
         MockQuestion question = questionServiceStub.getQuestion(questionId);

+ 92 - 16
src/main/java/nju/seec/SEECdemo/logic/service/impl/assignment/CodeServiceImpl.java

@@ -1,12 +1,17 @@
 package nju.seec.SEECdemo.logic.service.impl.assignment;
 package nju.seec.SEECdemo.logic.service.impl.assignment;
 
 
 import nju.seec.SEECdemo.data.dao.assignment.CodeDAO;
 import nju.seec.SEECdemo.data.dao.assignment.CodeDAO;
+import nju.seec.SEECdemo.data.dao.assignment.CodeResultDAO;
 import nju.seec.SEECdemo.data.entity.assignment.Code;
 import nju.seec.SEECdemo.data.entity.assignment.Code;
+import nju.seec.SEECdemo.data.entity.assignment.CodeResult;
 import nju.seec.SEECdemo.logic.api.GitlabApi;
 import nju.seec.SEECdemo.logic.api.GitlabApi;
 import nju.seec.SEECdemo.logic.service.CodeService;
 import nju.seec.SEECdemo.logic.service.CodeService;
+import nju.seec.SEECdemo.logic.service.InterCodeService;
+import nju.seec.SEECdemo.logic.service.impl.assignment.mock.MockGroup;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.CourseServiceStub;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.CourseServiceStub;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.GroupServiceStub;
 import nju.seec.SEECdemo.logic.service.impl.assignment.stub.GroupServiceStub;
 import nju.seec.SEECdemo.logic.vo.CodeWorkVO;
 import nju.seec.SEECdemo.logic.vo.CodeWorkVO;
+import nju.seec.SEECdemo.logic.vo.InterCodeAppInfoVO;
 import nju.seec.SEECdemo.util.AsyncWrapper;
 import nju.seec.SEECdemo.util.AsyncWrapper;
 import nju.seec.SEECdemo.util.ToolKit;
 import nju.seec.SEECdemo.util.ToolKit;
 import nju.seec.SEECdemo.util.enums.AssignmentStatus;
 import nju.seec.SEECdemo.util.enums.AssignmentStatus;
@@ -17,22 +22,24 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
 import java.io.IOException;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 
 @Component
 @Component
-public class CodeServiceImpl implements CodeService {
+public class CodeServiceImpl implements CodeService, InterCodeService {
 
 
-    private final CodeDAO assignmentDAO;
-    private final GitlabApi gitlabApi;
+    private final CodeDAO codeDAO;
+    private final CodeResultDAO codeResultDAO;
     private final AssignmentPaperBuilder assignmentPaperBuilder;
     private final AssignmentPaperBuilder assignmentPaperBuilder;
     private final AsyncWrapper asyncWrapper;
     private final AsyncWrapper asyncWrapper;
     private final CourseServiceStub courseServiceStub;
     private final CourseServiceStub courseServiceStub;
     private final GroupServiceStub groupServiceStub;
     private final GroupServiceStub groupServiceStub;
 
 
     @Autowired
     @Autowired
-    public CodeServiceImpl(CodeDAO assignmentDAO, GitlabApi gitlabApi, AssignmentPaperBuilder assignmentPaperBuilder,
+    public CodeServiceImpl(CodeDAO codeDAO, CodeResultDAO codeResultDAO, AssignmentPaperBuilder assignmentPaperBuilder,
                            AsyncWrapper asyncWrapper, CourseServiceStub courseServiceStub, GroupServiceStub groupServiceStub){
                            AsyncWrapper asyncWrapper, CourseServiceStub courseServiceStub, GroupServiceStub groupServiceStub){
-        this.assignmentDAO = assignmentDAO;
-        this.gitlabApi = gitlabApi;
+        this.codeDAO = codeDAO;
+        this.codeResultDAO = codeResultDAO;
         this.assignmentPaperBuilder = assignmentPaperBuilder;
         this.assignmentPaperBuilder = assignmentPaperBuilder;
         this.asyncWrapper = asyncWrapper;
         this.asyncWrapper = asyncWrapper;
         this.courseServiceStub = courseServiceStub;
         this.courseServiceStub = courseServiceStub;
@@ -42,22 +49,91 @@ public class CodeServiceImpl implements CodeService {
 
 
     @Override
     @Override
     public CodeWorkVO createAssignment(int courseId, CodeWorkDTO codeWorkDTO) {
     public CodeWorkVO createAssignment(int courseId, CodeWorkDTO codeWorkDTO) {
-        Code assignment = new Code();
-        assignment.setName(codeWorkDTO.getName());
-        assignment.setDescription(codeWorkDTO.getDescription());
-        assignment.setQuestionId(codeWorkDTO.getQuestion());
-        assignment.setUuid(ToolKit.randomUUID());
-        assignment.setCourseId(courseId);
+        Code codework = new Code();
+        codework.setName(codeWorkDTO.getName());
+        codework.setDescription(codeWorkDTO.getDescription());
+        codework.setQuestionId(codeWorkDTO.getQuestion());
+        codework.setUuid(ToolKit.randomUUID());
+        codework.setCourseId(courseId);
+        codework.setStartAt(codeWorkDTO.getStartAt());
+        codework.setEndAt(codeWorkDTO.getEndAt());
         try {
         try {
-            assignment.setId(gitlabApi.createProject(assignment.getUuid()));
-        } catch (Exception e) {
+            assignmentPaperBuilder.buildCodePaper(codework);
+        } catch (IOException | GitAPIException | GitLabApiException e) {
             System.out.println("创建作业时发生异常" + ToolKit.format(e));
             System.out.println("创建作业时发生异常" + ToolKit.format(e));
         }
         }
-        asyncWrapper.asyncInvoke(() -> assignmentPaperBuilder.buildCodePaper(assignment.getId()), 2000);
-        return new CodeWorkVO(assignmentDAO.save(assignment), courseServiceStub.getCourse(courseId).getName(),
+        asyncWrapper.asyncInvoke(()->assignmentPaperBuilder.addGroupsToPaper(codework.getId()), 2000);
+        return new CodeWorkVO(codeDAO.save(codework),courseServiceStub.getCourse(courseId).getName(),
                 groupServiceStub.getGroupListByCourse(courseId));
                 groupServiceStub.getGroupListByCourse(courseId));
     }
     }
 
 
+    /**
+     * 获取jenkins的构建job名称
+     * @param codeAssignmentId
+     * @param groupId
+     * @return
+     */
+    @Override
+    public String getJenkinsBuildJobName(int codeAssignmentId, int groupId) {
+        Code code = codeDAO.findById(codeAssignmentId);
+        CodeResult codeResult = codeResultDAO.findByCodeAndGroupId(code, groupId);
+        return codeResult!=null?codeResult.getBuildJob():null;
+    }
+
+    /**
+     * 查询一个作业下一个小组的应部署应用必要信息
+     * @param codeAssignmentId 作业id
+     * @param groupId 小组id
+     * @return
+     */
+    @Override
+    public InterCodeAppInfoVO getInfo(int codeAssignmentId, int groupId) {
+        Code code = codeDAO.findById(codeAssignmentId);
+        CodeResult codeResult = codeResultDAO.findByCodeAndGroupId(code, groupId);
+        InterCodeAppInfoVO codeAppInfoVO = new InterCodeAppInfoVO();
+        codeAppInfoVO.setId(codeResult.getId());
+        codeAppInfoVO.setProjectId(codeResult.getDeployNamespace());
+        codeAppInfoVO.setApplicationName(code.getUuid() + codeResult.getGroupId());
+        return codeAppInfoVO;
+    }
+
+    /**
+     * 获取jenkins的测试job名称
+     * @param codeAssignmentId
+     * @param groupId
+     * @return
+     */
+    @Override
+    public String getJenkinsTestJobName(int codeAssignmentId, int groupId) {
+        Code code = codeDAO.findById(codeAssignmentId);
+        CodeResult codeResult = codeResultDAO.findByCodeAndGroupId(code, groupId);
+        return codeResult!=null?codeResult.getTestJob():null;
+    }
+
+
+    public void groupAddedCheck(int groupId){
+        MockGroup group = groupServiceStub.getGroup(groupId);
+        List<AssignmentStatus> statuses = new ArrayList(){{
+            add(AssignmentStatus.AVAILABLE);
+            add(AssignmentStatus.PREPARING);
+        }};
+        try {
+            List<Code> codeList = codeDAO.findByCourseIdAndStatusIn(group.getCourseId(), statuses);
+            List<Code> preparingList = new ArrayList<>();
+            // TODO
+            // 对于AVAILABLE的作业,直接将组加入;对于PREPARING的作业,需要等到其状态变更结束后(AVAILABLE或UNAVAILABLE),
+            // 再根据其状态判断:AVAILABLE,判断该组是否已经在作业中,不在则加入;UNAVAILABLE,则不做操作。
+            for (Code code:codeList) {
+                if (code.getStatus()==AssignmentStatus.AVAILABLE) {
+                    assignmentPaperBuilder.addGroupToPaper(code, group);
+                } else {
+                    preparingList.add(code);
+                }
+            }
+        } catch (IOException | GitLabApiException e) {
+            System.out.println("将小组加入作业时发生异常" + ToolKit.format(e));
+        }
+    }
 
 
 
 
 }
 }

+ 1 - 1
src/main/java/nju/seec/SEECdemo/logic/vo/InterCodeAppInfoVO.java

@@ -5,6 +5,6 @@ import lombok.Data;
 @Data
 @Data
 public class InterCodeAppInfoVO {
 public class InterCodeAppInfoVO {
     private int id;
     private int id;
-    private int projectId;
+    private Long projectId;
     private String applicationName;
     private String applicationName;
 }
 }

+ 2 - 0
src/main/java/nju/seec/SEECdemo/util/ApplicationProperties.java

@@ -47,6 +47,8 @@ public class ApplicationProperties {
 		@NotEmpty
 		@NotEmpty
 		private String username = "root";
 		private String username = "root";
 		@NotEmpty
 		@NotEmpty
+		private Integer userId = 1;
+		@NotEmpty
 		private String token;
 		private String token;
 
 
 		public String getGitProxy() {
 		public String getGitProxy() {

+ 32 - 0
src/main/java/nju/seec/SEECdemo/util/serializer/TimestampLocalDateDeserializer.java

@@ -0,0 +1,32 @@
+package nju.seec.SEECdemo.util.serializer;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+
+import java.io.IOException;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+
+public class TimestampLocalDateDeserializer extends JsonDeserializer<LocalDateTime> {
+	@Override
+	public LocalDateTime deserialize(JsonParser p, DeserializationContext context) throws IOException {
+		Long epochSecond = null;
+		if (p.hasToken(JsonToken.VALUE_NUMBER_INT)) {
+			epochSecond = p.getLongValue();
+		} else if (p.hasToken(JsonToken.VALUE_STRING)) {
+			String value = p.getText().trim();
+			try {
+				epochSecond = Long.valueOf(value);
+			} catch (NumberFormatException e) {
+				epochSecond = null;
+			}
+		}
+		if (epochSecond != null) {
+			return LocalDateTime.ofInstant(Instant.ofEpochSecond(epochSecond), ZoneId.systemDefault());
+		}
+		return null;
+	}
+}

+ 29 - 0
src/main/java/nju/seec/SEECdemo/util/serializer/TimestampLocalDateTimeSerializer.java

@@ -0,0 +1,29 @@
+package nju.seec.SEECdemo.util.serializer;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+
+public class TimestampLocalDateTimeSerializer extends LocalDateTimeSerializer {
+	@Override
+	protected LocalDateTimeSerializer withFormat(Boolean useTimestamp, DateTimeFormatter f, JsonFormat.Shape shape) {
+		return this;
+	}
+
+	@Override
+	public void serialize(LocalDateTime value, JsonGenerator g, SerializerProvider provider) throws IOException {
+		g.writeNumber(value.atZone(ZoneId.systemDefault()).toEpochSecond());
+	}
+
+	@Override
+	public void serializeWithType(LocalDateTime value, JsonGenerator g, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
+		serialize(value, g, provider);
+	}
+}

+ 3 - 2
src/main/java/nju/seec/SEECdemo/web/controller/CodeController.java

@@ -2,6 +2,7 @@ package nju.seec.SEECdemo.web.controller;
 
 
 import nju.seec.SEECdemo.logic.service.CodeService;
 import nju.seec.SEECdemo.logic.service.CodeService;
 import nju.seec.SEECdemo.web.dto.CodeWorkDTO;
 import nju.seec.SEECdemo.web.dto.CodeWorkDTO;
+import nju.seec.SEECdemo.web.response.EmptyResponse;
 import nju.seec.SEECdemo.web.response.ResourceResponse;
 import nju.seec.SEECdemo.web.response.ResourceResponse;
 import nju.seec.SEECdemo.web.response.Response;
 import nju.seec.SEECdemo.web.response.Response;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -9,7 +10,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import org.springframework.web.bind.annotation.*;
 
 
 @RestController
 @RestController
-@RequestMapping("/api")
+@RequestMapping("/api/assignment")
 public class CodeController {
 public class CodeController {
 
 
     @Autowired
     @Autowired
@@ -19,7 +20,7 @@ public class CodeController {
         this.codeService = codeService;
         this.codeService = codeService;
     }
     }
 
 
-    @PostMapping("/teacher/course/{courseId:\\d+}/assignment/code")
+    @PostMapping("/course/{courseId:\\d+}/code")
     public Response create(@PathVariable int courseId, @RequestBody @Validated(PostMapping.class) CodeWorkDTO codeWorkDTO){
     public Response create(@PathVariable int courseId, @RequestBody @Validated(PostMapping.class) CodeWorkDTO codeWorkDTO){
         return new ResourceResponse(codeService.createAssignment(courseId, codeWorkDTO));
         return new ResourceResponse(codeService.createAssignment(courseId, codeWorkDTO));
     }
     }

+ 16 - 0
src/main/java/nju/seec/SEECdemo/web/dto/CodeWorkDTO.java

@@ -1,10 +1,26 @@
 package nju.seec.SEECdemo.web.dto;
 package nju.seec.SEECdemo.web.dto;
 
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import lombok.Data;
 import lombok.Data;
+import nju.seec.SEECdemo.util.serializer.TimestampLocalDateDeserializer;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
 
 
 @Data
 @Data
 public class CodeWorkDTO {
 public class CodeWorkDTO {
     private String name;
     private String name;
     private String description;
     private String description;
     private Long question;
     private Long question;
+    @JsonProperty("start_at")
+    @JsonDeserialize(using = TimestampLocalDateDeserializer.class)
+    @NotNull(message = "请填写考试开始时间!", groups = {PostMapping.class, PutMapping.class})
+    private LocalDateTime startAt;
+    @JsonProperty("end_at")
+    @JsonDeserialize(using = TimestampLocalDateDeserializer.class)
+    @NotNull(message = "请填写考试结束时间!", groups = {PostMapping.class, PutMapping.class})
+    private LocalDateTime endAt;
 }
 }