Просмотр исходного кода

feat: Zhurui 完成门户Coder部分

Leone 4 лет назад
Родитель
Сommit
2f6569cf71

+ 11 - 0
pom.xml

@@ -97,6 +97,17 @@
             <artifactId>fastjson</artifactId>
             <version>1.2.79</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.5.2</version>
+        </dependency>
     </dependencies>
 
     <dependencyManagement>

+ 5 - 0
seecoder-portal-server/pom.xml

@@ -141,6 +141,11 @@
             <artifactId>mybatis-plus-boot-starter</artifactId>
             <version>3.4.2</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.5.13</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 30 - 0
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/service/ExamService.java

@@ -1,7 +1,9 @@
 package cn.seecoder.seecoderportalserver.service;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import org.springframework.web.multipart.MultipartFile;
 
 public interface ExamService {
     JSONArray findCoderRecommendExams();
@@ -22,6 +24,34 @@ public interface ExamService {
 
     JSONObject createCoderExam(JSONObject examDTO);
 
+    JSONObject deleteCoderExam(int examId);
+
+    JSONObject updateCoderExam(int examId, JSONObject examDTO);
+
+    JSONObject getCoderExamByExamId(int examId);
+
+    JSONObject getCoderProblemByProblemId(int problemId);
+
+    JSONObject createCoderProblem(JSONObject problemDTO, MultipartFile file);
+
+    JSONObject deleteCoderProblem(int problemId);
+
+    JSONObject updateCoderProblem(int problemId, String path, MultipartFile file);
+
+    JSONObject getProblemFile(int problemId, String filename);
+
+    JSONObject getResultByExamId(int examId);
+
+    JSONObject getResultByResultId(int resultId);
+
+    JSONObject getCommitByCommitId(int commitId);
+
+    JSONObject getRecordByRecordId(int recordId);
+
+    JSONObject getExamConsole(int examId);
+
+    JSONObject changeShowConsole(int examId, boolean showConsole);
+
     //--------------------------------------------------------
 
     JSONArray findEvalRecommendExams();

+ 11 - 0
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/service/HttpService.java

@@ -1,14 +1,25 @@
 package cn.seecoder.seecoderportalserver.service;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import org.apache.http.NameValuePair;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
+import java.util.Map;
 
 public interface HttpService {
     String sendPost(String uri, JSONObject requestBody, String token) throws Exception;
 
+    String sendPostFile(String uri, MultipartFile file, JSONObject requestBody, String token) throws Exception;
+
     String sendGet(String uri, List<NameValuePair> params, String token) throws Exception;
 
+    String sendDelete(String uri, String jsonstr, String token) throws Exception;
+
+    String sendPut(String uri, JSONObject requestBody, String token) throws Exception;
+
+    String sendPutFile(String uri, MultipartFile file, String path, String token) throws Exception;
+
     String getToken();
 }

+ 73 - 0
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/serviceImpl/ExamServiceImpl.java

@@ -9,6 +9,7 @@ import cn.seecoder.seecoderportalserver.web.rest.errors.CustomErrorException;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.util.List;
 
@@ -83,11 +84,83 @@ public class ExamServiceImpl implements ExamService {
         return coderService.createCoderExam(examDTO);
     }
 
+    @Override
+    public JSONObject deleteCoderExam(int examId) {
+        return coderService.deleteCoderExam(examId);
+    }
+
+    @Override
+    public JSONObject updateCoderExam(int examId, JSONObject examDTO) {
+        return coderService.updateCoderExam(examId, examDTO);
+    }
+
+    @Override
+    public JSONObject getCoderExamByExamId(int examId) {
+        return coderService.getCoderExamByExamId(examId);
+    }
+
+    @Override
+    public JSONObject createCoderProblem(JSONObject problemDTO, MultipartFile file) {
+        return coderService.createCoderProblem(problemDTO, file);
+    }
+
+    @Override
+    public JSONObject deleteCoderProblem(int problemId) {
+        return coderService.deleteCoderProblem(problemId);
+    }
+
+    @Override
+    public JSONObject updateCoderProblem(int problemId, String path, MultipartFile file) {
+        return coderService.updateCoderProblem(problemId, path, file);
+    }
+
+    @Override
+    public JSONObject getProblemFile(int problemId, String filename) {
+        return coderService.getProblemFile(problemId, filename);
+    }
+
+    @Override
+    public JSONObject getCoderProblemByProblemId(int problemId) {
+        return coderService.getCoderProblemByProblemId(problemId);
+    }
+
     @Override
     public JSONObject retrievePageProblem(int page, int limit, String typeStr, String name) {
         return coderService.retrievePageProblem(page, limit, typeStr, name);
     }
 
+    @Override
+    public JSONObject getResultByExamId(int examId) {
+        return coderService.getResultByExamId(examId);
+    }
+
+    @Override
+    public JSONObject getResultByResultId(int resultId) {
+        return coderService.getResultByResultId(resultId);
+    }
+
+    @Override
+    public JSONObject getCommitByCommitId(int commitId) {
+        return coderService.getCommitByCommitId(commitId);
+    }
+
+    @Override
+    public JSONObject getRecordByRecordId(int recordId) {
+        return coderService.getRecordByRecordId(recordId);
+    }
+
+    @Override
+    public JSONObject getExamConsole(int examId) {
+        return coderService.getExamConsole(examId);
+    }
+
+    @Override
+    public JSONObject changeShowConsole(int examId, boolean showConsole) {
+        return coderService.changeShowConsole(examId, showConsole);
+    }
+
+    //--------------------------------------------
+
     @Override
     public JSONArray findEvalRecommendExams() {
         JSONArray result = new JSONArray();

+ 108 - 6
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/serviceImpl/HttpServiceImpl.java

@@ -4,24 +4,35 @@ import cn.seecoder.seecoderportalserver.service.HttpService;
 import cn.seecoder.seecoderportalserver.web.rest.errors.CustomErrorException;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
-import org.apache.http.Consts;
-import org.apache.http.HttpEntity;
-import org.apache.http.NameValuePair;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+import org.apache.http.*;
+import org.apache.http.client.ClientProtocolException;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.*;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.entity.ContentType;
 import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.HttpMultipartMode;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.entity.mime.content.StringBody;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HTTP;
+import org.apache.http.protocol.HttpContext;
 import org.apache.http.util.EntityUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 
@@ -42,6 +53,42 @@ public class HttpServiceImpl implements HttpService {
         return result;
     }
 
+    @Override
+    public String sendPostFile(String uri, MultipartFile file, JSONObject requestBody, String token) throws Exception {
+        CloseableHttpClient client = HttpClients.createDefault();
+
+        HttpPost httpPost = new HttpPost(uri); //创建http请求
+        if(token != null) {
+            httpPost.setHeader("Authorization", token); //设置请求头
+        }
+//        httpPost.setConfig(RequestConfig.DEFAULT);
+
+//        httpPost.setHeader("Content-Type", "multipart/form-data;chartset=UTF-8;boundary=----WebKitFormBoundaryAUx8rEOC9qObQ1XE");
+
+        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+//        builder.setCharset(Consts.UTF_8);
+//        builder.setContentType(ContentType.create("multipart/form-data",Consts.UTF_8));
+        builder.setMode(HttpMultipartMode.RFC6532);
+        String fileName = file.getOriginalFilename();
+
+        System.out.println(JSON.toJSONString(requestBody));
+        StringBody contentBody = new StringBody(JSON.toJSONString(requestBody), ContentType.APPLICATION_JSON);
+        builder.addPart("meta", contentBody);
+//        FileBody fb = new FileBody((File) file, ContentType.DEFAULT_BINARY);
+//        builder.addPart("data", )
+        builder.addBinaryBody("data", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);
+//        builder.addBinaryBody("data", file.getBytes());
+
+        HttpEntity multipartEntity = builder.build();
+        httpPost.setEntity(multipartEntity);
+
+        CloseableHttpResponse response = client.execute(httpPost);
+        HttpEntity entity = response.getEntity();
+        String result = EntityUtils.toString(entity);
+        client.close();
+        return result;
+    }
+
     public String sendGet(String uri, List<NameValuePair> params, String token) throws Exception {
         String completedUri;
         if (params != null && !params.isEmpty()) {
@@ -63,6 +110,61 @@ public class HttpServiceImpl implements HttpService {
         return result;
     }
 
+
+    @Override
+    public String sendDelete(String uri, String jsonstr, String token) throws Exception {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpDelete httpDelete = new HttpDelete(uri);
+        httpDelete.setConfig(RequestConfig.DEFAULT);
+        if(token != null) {
+            httpDelete.setHeader("Authorization", token);
+        }
+        CloseableHttpResponse response = httpClient.execute(httpDelete);
+        HttpEntity entity = response.getEntity();
+        String result = EntityUtils.toString(entity);
+        httpClient.close();
+        return result;
+    }
+
+
+    @Override
+    public String sendPut(String uri, JSONObject requestBody, String token) throws Exception {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpPut httpPut = new HttpPut(uri);
+        if(token != null) {
+            httpPut.setHeader("Authorization", token);
+        }
+        httpPut.setHeader("Content-Type", "application/json;chartset=UTF-8");
+        StringEntity stringEntity = new StringEntity(requestBody.toJSONString());
+        httpPut.setEntity(stringEntity);
+        CloseableHttpResponse response = httpClient.execute(httpPut);
+        HttpEntity entity = response.getEntity();
+        String result = EntityUtils.toString(entity);
+        httpClient.close();
+        return result;
+    }
+
+    @Override
+    public String sendPutFile(String uri, MultipartFile file, String path, String token) throws Exception {
+        CloseableHttpClient httpClient = HttpClients.createDefault();
+        HttpPut httpPut = new HttpPut(uri);
+        if(token != null) {
+            httpPut.setHeader("Authorization", token);
+        }
+        String filename = file.getOriginalFilename();
+//        httpPut.setHeader("Content-Type", "application/json;chartset=UTF-8");
+        MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+        builder.addBinaryBody("file", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, filename);
+        builder.addTextBody("path", path);
+        HttpEntity multipartEntity = builder.build();
+        httpPut.setEntity(multipartEntity);
+        CloseableHttpResponse response = httpClient.execute(httpPut);
+        HttpEntity entity = response.getEntity();
+        String result = EntityUtils.toString(entity);
+        httpClient.close();
+        return result;
+    }
+
     public String getToken() {
         String token;
         HttpServletRequest httpServletRequest = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

+ 240 - 2
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/serviceImpl/subsystem/CoderService.java

@@ -9,9 +9,9 @@ import com.alibaba.fastjson.JSONObject;
 import org.apache.http.NameValuePair;
 import org.apache.http.message.BasicNameValuePair;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
 
 @Service("coderService")
 public class CoderService implements SubsystemService {
@@ -57,6 +57,7 @@ public class CoderService implements SubsystemService {
         return JSON.parseObject(result);
     }
 
+
     @Override
     public JSONObject findRecommendExamsByCourseId(int courseId) {
         String uri = "https://coder-server.seec.seecoder.cn/api/unauthorizedCourseExams/" + courseId;
@@ -186,4 +187,241 @@ public class CoderService implements SubsystemService {
         }
         return JSON.parseObject(result);
     }
+
+    /**
+     * 删除Coder课程
+     * @param examId
+     * @return
+     */
+    public JSONObject deleteCoderExam(int examId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendDelete(coderUrlPrefix+"/exam/"+examId, null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+    /**
+     * 更新Coder课程
+     * @param examId
+     * @param examDTO
+     * @return
+     */
+    public JSONObject updateCoderExam(int examId, JSONObject examDTO) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendPut(coderUrlPrefix+"/exam/"+examId, examDTO, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * 根据id获得Coder的考试信息
+     * @param examId
+     * @return
+     */
+    public JSONObject getCoderExamByExamId(int examId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/exam/"+examId,null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * 根据id获取Coder代码题
+     * @param problemId
+     * @return
+     */
+    public JSONObject getCoderProblemByProblemId(int problemId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/problem/"+problemId,null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * TODO 创建Coder代码题,文件上传
+     * @param problemDTO
+     * @param file
+     * @return
+     */
+    public JSONObject createCoderProblem(JSONObject problemDTO, MultipartFile file) {
+        String token = httpService.getToken();
+        String result = null;
+        try{
+            result = httpService.sendPostFile(coderUrlPrefix+"/problem", file, problemDTO, token);
+//            result = httpService.sendPostFile("http://localhost:8081/api/problem", file, problemDTO, token);
+//            HttpPost httpPost = new HttpPost("http://localhost:8081/api/problem");
+
+
+
+        }catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * 根据id删除代码题
+     * @param problemId
+     * @return
+     */
+    public JSONObject deleteCoderProblem(int problemId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendDelete(coderUrlPrefix+"/problem/"+problemId, null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * 更新Coder代码题
+     * @param problemId
+     * @param path
+     * @param file
+     * @return
+     */
+    public JSONObject updateCoderProblem(int problemId, String path, MultipartFile file) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendPutFile(coderUrlPrefix+"/problem/"+problemId, file, path, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * 获取代码题的具体文件信息
+     * @param problemId
+     * @param filename
+     * @return
+     */
+    public JSONObject getProblemFile(int problemId, String filename) {
+        String token = httpService.getToken();
+        List<NameValuePair> params = new ArrayList<>();
+        params.add(new BasicNameValuePair("name", String.valueOf(filename)));
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/problem/"+problemId+"/file", params,token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    /**
+     * 根据id获取考试结果
+     * @param examId
+     * @return
+     */
+    public JSONObject getResultByExamId(int examId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/exam/"+examId+"/result", null, token);
+        }catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+    /**
+     * 根据id获取某个结果的详细信息
+     * @param resultId
+     * @return
+     */
+    public JSONObject getResultByResultId(int resultId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/result/"+resultId, null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+    /**
+     * 根据id获取某次提交的具体信息
+     * @param commitId
+     * @return
+     */
+    public JSONObject getCommitByCommitId(int commitId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/commit/"+commitId, null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+    /**
+     * 根据id获取某次记录的具体信息
+     * @param recordId
+     * @return
+     */
+    public JSONObject getRecordByRecordId(int recordId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/record/"+recordId, null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    public JSONObject getExamConsole(int examId) {
+        String token = httpService.getToken();
+        String result = null;
+        try {
+            result = httpService.sendGet(coderUrlPrefix+"/exam/"+examId+"/showConsole", null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
+
+
+    public JSONObject changeShowConsole(int examId, boolean showConsole) {
+        String token = httpService.getToken();
+        String result = null;
+//        JSONObject requestBody = new JSONObject();
+//        requestBody.put("showConsole", showConsole);
+        try {
+            result = httpService.sendPost(coderUrlPrefix+"/exam/"+examId+"/showConsole?showConsole="+showConsole, null, token);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return JSON.parseObject(result);
+    }
 }

+ 1 - 0
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/web/rest/CourseController.java

@@ -5,6 +5,7 @@ import cn.seecoder.seecoderportalcommon.vo.CourseVO;
 import cn.seecoder.seecoderportalserver.security.SecurityUtils;
 import cn.seecoder.seecoderportalserver.service.CourseService;
 import cn.seecoder.seecoderportalserver.utility.OkResponse;
+import com.alibaba.fastjson.JSONObject;
 import com.nju.edu.paasMonitorClient.MonitorClient;
 import com.nju.edu.paasMonitorClient.entity.Call;
 import com.nju.edu.paasMonitorCommon.enums.SeecSystem;

+ 125 - 1
seecoder-portal-server/src/main/java/cn/seecoder/seecoderportalserver/web/rest/ExamController.java

@@ -3,9 +3,11 @@ package cn.seecoder.seecoderportalserver.web.rest;
 import cn.seecoder.seecoderportalserver.security.SecurityUtils;
 import cn.seecoder.seecoderportalserver.service.ExamService;
 import cn.seecoder.seecoderportalserver.utility.OkResponse;
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 @RestController
 @RequestMapping("/api")
@@ -58,6 +60,8 @@ public class ExamController {
         return OkResponse.of(examService.findCoderStudentExamsByCourseId(courseId));
     }
 
+    //----------------------- Coder系统的原生操作 --------------------------
+
     /**
      * 创建Coder考试
      */
@@ -67,7 +71,61 @@ public class ExamController {
     }
 
     /**
-     * 获取Coder题目列表
+     * 删除Coder考试
+     * @param examId
+     * @return
+     */
+    @DeleteMapping("/coder/exam/{examId:\\d+}/delete")
+    public JSONObject deleteCoderExam(@PathVariable int examId) {
+        return examService.deleteCoderExam(examId);
+    }
+
+    /**
+     * 更新Coder考试
+     * @param examId
+     * @param examDTO
+     * @return
+     */
+    @PutMapping("/coder/exam/{examId:\\d+}/update")
+    public JSONObject updateCoderExam(@PathVariable int examId, @RequestBody JSONObject examDTO) {
+        return examService.updateCoderExam(examId, examDTO);
+    }
+
+    /**
+     * 根据examId获取考试信息
+     * @param examId
+     * @return
+     */
+    @GetMapping("/coder/exam/{examId:\\d+}")
+    public JSONObject getCoderExamByExamId(@PathVariable Integer examId) {
+        return examService.getCoderExamByExamId(examId);
+    }
+
+    /**
+     * 根据examId获取当前考试的控制台权限
+     * @param examId
+     * @return
+     */
+    @GetMapping("/coder/exam/{examId:\\d+}/console")
+    public JSONObject getExamConsole(@PathVariable int examId){
+        return examService.getExamConsole(examId);
+    }
+
+
+    /**
+     * 修改控制台权限
+     * @param examId
+     * @param showConsole
+     * @return
+     */
+    @PostMapping("/coder/exam/{examId:\\d+}/console")
+    public JSONObject changeShowConsole(@PathVariable int examId, @RequestParam boolean showConsole) {
+        return examService.changeShowConsole(examId, showConsole);
+    }
+
+
+    /**
+     * 获取Coder代码题列表
      */
     @GetMapping("/coder/problem")
     public JSONObject retrievePageProblem(@RequestParam(defaultValue = "1") int page,
@@ -77,6 +135,72 @@ public class ExamController {
         return examService.retrievePageProblem(page, limit, typeStr, name);
     }
 
+    /**
+     * 根据id获取coder代码题的详细信息
+     * @param problemId
+     * @return
+     */
+    @GetMapping("/coder/problem/{problemId:\\d+}")
+    public JSONObject getCoderProblemByProblemId(@PathVariable Integer problemId) {
+        return examService.getCoderProblemByProblemId(problemId);
+    }
+
+    /**
+     * 上传代码题
+     * @param problemDTO
+     * @param file
+     * @return
+     */
+    @PostMapping("/coder/problem")
+    public JSONObject createCoderProblem(
+            @RequestPart("meta") JSONObject problemDTO,
+            @RequestPart("data") MultipartFile file) {
+        return examService.createCoderProblem(problemDTO, file);
+    }
+
+
+    @DeleteMapping("/coder/problem/{problemId:\\d+}")
+    public JSONObject deleteCoderProblem(@PathVariable int problemId) {
+        return examService.deleteCoderProblem(problemId);
+    }
+
+
+    @PutMapping("/coder/problem/{problemId:\\d+}")
+    public JSONObject updateCoderProblem(
+            @PathVariable int problemId,
+            @RequestPart String path,
+            @RequestPart MultipartFile file
+    ) {
+        return examService.updateCoderProblem(problemId, path, file);
+    }
+
+
+    @GetMapping("/coder/problem/{problemId:\\d+}/file")
+    public JSONObject getProblemFile(@PathVariable int problemId, @RequestParam("name") String filename) {
+        return examService.getProblemFile(problemId, filename);
+    }
+
+    @GetMapping("/coder/exam/{examId:\\d+}/result")
+    public JSONObject getResultByExamId(@PathVariable int examId) {
+        return examService.getResultByExamId(examId);
+    }
+
+    @GetMapping("/coder/result/{resultId:\\d+}")
+    public JSONObject getResultByResultId(@PathVariable int resultId) {
+        return examService.getResultByResultId(resultId);
+    }
+
+    @GetMapping("/coder/commit/{commitId:\\d+}")
+    public JSONObject getCommitByCommitId(@PathVariable int commitId) {
+        return examService.getCommitByCommitId(commitId);
+    }
+
+    @GetMapping("/coder/record/{recordId:\\d+}")
+    public JSONObject getRecordByRecordId(@PathVariable int recordId) {
+        return examService.getRecordByRecordId(recordId);
+    }
+
+
     //--------------------------------------------------------
 
     @GetMapping("/eval/exam/recommend")