فهرست منبع

update package

deason 7 سال پیش
والد
کامیت
39339a3e75
17فایلهای تغییر یافته به همراه775 افزوده شده و 499 حذف شده
  1. 0 4
      src/main/java/cn/com/qmth/examcloud/app/controller/version_1_0/UserAuthRestController.java
  2. 1 4
      src/main/java/cn/com/qmth/examcloud/app/core/config/AccessInterceptor.java
  3. 7 95
      src/main/java/cn/com/qmth/examcloud/app/service/DeviceRecordService.java
  4. 7 35
      src/main/java/cn/com/qmth/examcloud/app/service/ExamAdminService.java
  5. 42 168
      src/main/java/cn/com/qmth/examcloud/app/service/NetExamService.java
  6. 7 25
      src/main/java/cn/com/qmth/examcloud/app/service/QuestionPoolService.java
  7. 9 0
      src/main/java/cn/com/qmth/examcloud/app/service/RedisService.java
  8. 7 66
      src/main/java/cn/com/qmth/examcloud/app/service/SmsService.java
  9. 6 15
      src/main/java/cn/com/qmth/examcloud/app/service/UpYunService.java
  10. 10 87
      src/main/java/cn/com/qmth/examcloud/app/service/UserAuthService.java
  11. 120 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/DeviceRecordServiceImpl.java
  12. 59 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/ExamAdminServiceImpl.java
  13. 208 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/NetExamServiceImpl.java
  14. 49 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/QuestionPoolServiceImpl.java
  15. 90 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/SmsServiceImpl.java
  16. 35 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/UpYunServiceImpl.java
  17. 118 0
      src/main/java/cn/com/qmth/examcloud/app/service/impl/UserAuthServiceImpl.java

+ 0 - 4
src/main/java/cn/com/qmth/examcloud/app/controller/version_1_0/UserAuthRestController.java

@@ -7,11 +7,9 @@
 
 package cn.com.qmth.examcloud.app.controller.version_1_0;
 
-import cn.com.qmth.examcloud.app.core.utils.StrUtils;
 import cn.com.qmth.examcloud.app.model.LoginType;
 import cn.com.qmth.examcloud.app.model.Result;
 import cn.com.qmth.examcloud.app.model.UserInfo;
-import cn.com.qmth.examcloud.app.model.UserToken;
 import cn.com.qmth.examcloud.app.service.RedisService;
 import cn.com.qmth.examcloud.app.service.UserAuthService;
 import io.swagger.annotations.Api;
@@ -23,8 +21,6 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 
-import static cn.com.qmth.examcloud.app.model.Constants.APP_SESSION_EXPIRE_TIME;
-
 /**
  * 认证中心相关接口
  *

+ 1 - 4
src/main/java/cn/com/qmth/examcloud/app/core/config/AccessInterceptor.java

@@ -8,9 +8,6 @@
 package cn.com.qmth.examcloud.app.core.config;
 
 import cn.com.qmth.examcloud.app.model.DeviceRecord;
-import cn.com.qmth.examcloud.app.model.Result;
-import cn.com.qmth.examcloud.app.model.UserInfo;
-import cn.com.qmth.examcloud.app.model.UserToken;
 import cn.com.qmth.examcloud.app.service.DeviceRecordService;
 import cn.com.qmth.examcloud.app.service.RedisService;
 import cn.com.qmth.examcloud.app.service.UserAuthService;
@@ -25,7 +22,7 @@ import javax.servlet.http.HttpServletResponse;
 import java.util.Date;
 import java.util.Map;
 
-import static cn.com.qmth.examcloud.app.model.Constants.*;
+import static cn.com.qmth.examcloud.app.model.Constants.PARAM_PASSWORD;
 
 /**
  * @author: fengdesheng

+ 7 - 95
src/main/java/cn/com/qmth/examcloud/app/service/DeviceRecordService.java

@@ -1,114 +1,26 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-20 11:02:44.
+ * Created by Deason on 2018-07-31 17:15:16.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
-import cn.com.qmth.examcloud.app.dao.DeviceRecordRepository;
 import cn.com.qmth.examcloud.app.model.DeviceRecord;
 import cn.com.qmth.examcloud.app.model.Result;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageRequest;
-import org.springframework.data.domain.Pageable;
-import org.springframework.data.domain.Sort;
-import org.springframework.data.jpa.domain.Specification;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-
-import javax.persistence.criteria.CriteriaBuilder;
-import javax.persistence.criteria.CriteriaQuery;
-import javax.persistence.criteria.Predicate;
-import javax.persistence.criteria.Root;
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * 设备访问记录Service
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class DeviceRecordService {
-    private static Logger log = LoggerFactory.getLogger(DeviceRecordService.class);
-    @Autowired
-    private DeviceRecordRepository deviceRecordRepository;
+public interface DeviceRecordService {
 
-    @SuppressWarnings("unchecked")
-    public Result<Page<DeviceRecord>> getDeviceRecordList(DeviceRecord params, Integer pageNo, Integer pageSize) {
-        Specification<DeviceRecord> spec = null;
-        if (params != null) {
-            spec = new Specification<DeviceRecord>() {
-                @Override
-                public Predicate toPredicate(Root<DeviceRecord> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
-                    List<Predicate> predicates = new ArrayList<>();
-                    if (StringUtils.isNotBlank(params.getSystem())) {
-                        predicates.add(builder.equal(root.get("system"), params.getSystem().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getDeviceId())) {
-                        predicates.add(builder.equal(root.get("deviceId"), params.getDeviceId().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getNetType())) {
-                        predicates.add(builder.equal(root.get("netType"), params.getNetType().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getBrand())) {
-                        predicates.add(builder.equal(root.get("brand"), params.getBrand().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getModel())) {
-                        predicates.add(builder.equal(root.get("model"), params.getModel().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getSysVersion())) {
-                        predicates.add(builder.equal(root.get("sysVersion"), params.getSysVersion().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getAppVersion())) {
-                        predicates.add(builder.equal(root.get("appVersion"), params.getAppVersion().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getAppCode())) {
-                        predicates.add(builder.equal(root.get("appCode"), params.getAppCode().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getPatchCode())) {
-                        predicates.add(builder.equal(root.get("patchCode"), params.getPatchCode().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getAccount())) {
-                        predicates.add(builder.equal(root.get("account"), params.getAccount().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getLoginKey())) {
-                        predicates.add(builder.equal(root.get("loginKey"), params.getLoginKey().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getLoginToken())) {
-                        predicates.add(builder.equal(root.get("loginToken"), params.getLoginToken().trim()));
-                    }
-                    if (StringUtils.isNotBlank(params.getUrl())) {
-                        predicates.add(builder.like(root.get("url"), "%" + params.getUrl().trim() + "%"));
-                    }
-                    if (StringUtils.isNotBlank(params.getIp())) {
-                        predicates.add(builder.equal(root.get("ip"), params.getIp().trim()));
-                    }
-                    return builder.and(predicates.toArray(new Predicate[predicates.size()]));
-                }
-            };
-        }
-        if (pageNo < 1) {
-            pageNo = 1;
-        }
-        if (pageSize < 1) {
-            pageSize = 1;
-        }
-        Sort sort = new Sort(Sort.Direction.DESC, "id");
-        Pageable pageable = new PageRequest(pageNo - 1, pageSize, sort);
-        Page<DeviceRecord> page = deviceRecordRepository.findAll(spec, pageable);
-        return new Result<>().success(page);
-    }
+    Result<Page<DeviceRecord>> getDeviceRecordList(DeviceRecord params, Integer pageNo, Integer pageSize);
 
-    @Async
-    public void addDeviceRecord(DeviceRecord deviceRecord) {
-        Assert.notNull(deviceRecord, "DeviceRecord must not be null.");
-        deviceRecordRepository.save(deviceRecord);
-    }
+    void addDeviceRecord(DeviceRecord deviceRecord);
 
 }

+ 7 - 35
src/main/java/cn/com/qmth/examcloud/app/service/ExamAdminService.java

@@ -1,52 +1,24 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-16 17:49:05.
+ * Created by Deason on 2018-07-31 17:29:12.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
 import cn.com.qmth.examcloud.app.model.Result;
-import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 
 /**
  * 考务业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class ExamAdminService {
-    private static Logger log = LoggerFactory.getLogger(ExamAdminService.class);
-    @Autowired
-    private PropertyService propertyService;
+public interface ExamAdminService {
 
-    public Result getPracticeExamList(String key, String token, String studentId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_exam_work/exam_student/query?student_id=%s", propertyService.getExamAdminUrl(), studentId);
-        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
-        if (result.isSuccess()) {
-            String data = result.getData();
-            //替换掉图片标签内容
-            data = HttpUtils.replaceImages(data);
-            //过滤掉为空的属性
-            data = HttpUtils.filterNullAttributes(data);
-            result.setData(data);
-        }
-        return result;
-    }
+    Result getPracticeExamList(String key, String token, String studentId) throws Exception;
 
-    public Result getExamInfo(String key, String token, Long examId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_exam_work/exam/%s", propertyService.getExamAdminUrl(), examId);
-        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
-        if (result.isSuccess()) {
-            //过滤掉为空的属性
-            result.setData(HttpUtils.filterNullAttributes(result.getData()));
-        }
-        return result;
-    }
+    Result getExamInfo(String key, String token, Long examId) throws Exception;
 
 }

+ 42 - 168
src/main/java/cn/com/qmth/examcloud/app/service/NetExamService.java

@@ -1,185 +1,59 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-16 17:49:59.
+ * Created by Deason on 2018-07-31 17:31:34.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
-import cn.com.qmth.examcloud.app.core.exception.ApiException;
-import cn.com.qmth.examcloud.app.core.utils.DateUtils;
-import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
-import cn.com.qmth.examcloud.app.core.utils.JsonMapper;
-import cn.com.qmth.examcloud.app.model.Constants;
 import cn.com.qmth.examcloud.app.model.Result;
-import okhttp3.FormBody;
-import okhttp3.MediaType;
-import okhttp3.MultipartBody;
-import okhttp3.RequestBody;
-import org.apache.commons.io.FilenameUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static cn.com.qmth.examcloud.app.model.Constants.FILE_TYPE_PDF;
-import static cn.com.qmth.examcloud.app.model.Constants.FILE_TYPE_ZIP;
 
 /**
  * 网考业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class NetExamService {
-    private static Logger log = LoggerFactory.getLogger(NetExamService.class);
-    @Autowired
-    private PropertyService propertyService;
-
-    public Result getCurrentTime(String key, String token) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/online_exam_course/currentTime", propertyService.getNetExamUrl());
-        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
-        if (result.isSuccess()) {
-            //转换日期格式
-            result.setData(DateUtils.formatLongDate(result.getData()));
-        }
-        return result;
-    }
-
-    public Result getOfflineExamCourseList(String key, String token) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/offline_exam/getOfflineCourse", propertyService.getNetExamUrl());
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result startOfflineExamRecord(String key, String token, String examStudentId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/offline_exam/start?examStudentId=%s", propertyService.getNetExamUrl(), examStudentId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result uploadPaperAnswer(String key, String token, String examRecordId, byte[] fileBytes, String fileName, String md5) throws Exception {
-        Assert.notNull(examRecordId, "FileName must not be null.");
-        Assert.notNull(fileName, "ExamRecordId must not be null.");
-        String fileType = FilenameUtils.getExtension(fileName.toLowerCase());
-        if (!FILE_TYPE_ZIP.equals(fileType) && !FILE_TYPE_PDF.equals(fileType)) {
-            throw new ApiException("FileType must be zip or pdf.");
-        }
-        if (fileBytes.length == 0) {
-            throw new ApiException("File must be not empty.");
-        }
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/offline_exam/%s/submit", propertyService.getNetExamUrl(), examRecordId);
-        MultipartBody.Builder form = new MultipartBody.Builder().setType(MultipartBody.FORM);
-        RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), fileBytes);
-        form.addFormDataPart("file", fileName, body);
-        form.addFormDataPart("fileType", fileType);
-        form.addFormDataPart("md5", md5 != null ? md5 : "");
-        return HttpUtils.doPost(requestUrl, form.build(), key, token);
-    }
-
-    public Result getPracticeExamCourseList(String key, String token, String examId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/practice_course?examId=%s", propertyService.getNetExamUrl(), examId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordHeartbeat(String key, String token, String examRecordId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_control/heartbeat?examRecordId=%s", propertyService.getNetExamUrl(), examRecordId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result startPracticeExamRecord(String key, String token, String examStudentId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_control/start?stu_exam_info_id=%s", propertyService.getNetExamUrl(), examStudentId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordPaperStructList(String key, String token, String examRecordId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_question/paper_struct?exam_record_id=%s", propertyService.getNetExamUrl(), examRecordId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordPaperQuestionList(String key, String token, String examRecordId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_question?exam_record_id=%s", propertyService.getNetExamUrl(), examRecordId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordPaperQuestionDetail(String key, String token, String questionId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_question/question?question_id=%s", propertyService.getNetExamUrl(), questionId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result updateExamRecordPaperQuestionAnswer(String key, String token, String examQuestionId, String studentAnswer) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_question/%s", propertyService.getNetExamUrl(), examQuestionId);
-        Map<String, String> params = new HashMap<>();
-        params.put("examQuestionId", examQuestionId);
-        params.put("stuAnswer", studentAnswer);
-        String json = new JsonMapper().toJson(params);
-        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
-        return HttpUtils.doPut(requestUrl, formBody, key, token);
-    }
-
-    public Result submitPracticeExamRecord(String key, String token, String examRecordId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_control/submit?examRecordId=%s", propertyService.getNetExamUrl(), examRecordId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result checkOnlineExamRecord(String key, String token) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_record/checkExam", propertyService.getNetExamUrl());
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
+public interface NetExamService {
+
+    Result getCurrentTime(String key, String token) throws Exception;
+
+    Result getOfflineExamCourseList(String key, String token) throws Exception;
+
+    Result startOfflineExamRecord(String key, String token, String examStudentId) throws Exception;
+
+    Result uploadPaperAnswer(String key, String token, String examRecordId, byte[] fileBytes, String fileName, String md5) throws Exception;
+
+    Result getPracticeExamCourseList(String key, String token, String examId) throws Exception;
+
+    Result getExamRecordHeartbeat(String key, String token, String examRecordId) throws Exception;
+
+    Result startPracticeExamRecord(String key, String token, String examStudentId) throws Exception;
+
+    Result getExamRecordPaperStructList(String key, String token, String examRecordId) throws Exception;
+
+    Result getExamRecordPaperQuestionList(String key, String token, String examRecordId) throws Exception;
+
+    Result getExamRecordPaperQuestionDetail(String key, String token, String questionId) throws Exception;
+
+    Result updateExamRecordPaperQuestionAnswer(String key, String token, String examQuestionId, String studentAnswer) throws Exception;
+
+    Result submitPracticeExamRecord(String key, String token, String examRecordId) throws Exception;
+
+    Result checkOnlineExamRecord(String key, String token) throws Exception;
 
     @Deprecated
-    public Result getExamRecordPracticeTotalInfo(String key, String token, String examStudentId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/practice_course/%s", propertyService.getNetExamUrl(), examStudentId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordPracticeHistoryList(String key, String token, String examStudentId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/practice_record?examStudentId=%s", propertyService.getNetExamUrl(), examStudentId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordTotalInfo(String key, String token, String examRecordId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/practice_detail?examRecordId=%s", propertyService.getNetExamUrl(), examRecordId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordQuestionDetailList(String key, String token, String examRecordId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_oe/report/exam_detail_report/paper_question?exam_record_id=%s", propertyService.getNetExamUrl(), examRecordId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result getExamRecordQuestionAudioPlayTimes(String key, String token, String questionId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_question_playtimes?questionId=%s", propertyService.getNetExamUrl(), questionId);
-        return HttpUtils.doGet(requestUrl, key, token);
-    }
-
-    public Result updateExamRecordQuestionAudioPlayTimes(String key, String token, String questionId, String mediaName) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exam_question_playtimes", propertyService.getNetExamUrl());
-        RequestBody formBody = new FormBody.Builder()
-                .add("questionId", questionId)
-                .add("mediaName", mediaName)
-                .build();
-        return HttpUtils.doPost(requestUrl, formBody, key, token);
-    }
+    Result getExamRecordPracticeTotalInfo(String key, String token, String examStudentId) throws Exception;
+
+    Result getExamRecordPracticeHistoryList(String key, String token, String examStudentId) throws Exception;
+
+    Result getExamRecordTotalInfo(String key, String token, String examRecordId) throws Exception;
+
+    Result getExamRecordQuestionDetailList(String key, String token, String examRecordId) throws Exception;
+
+    Result getExamRecordQuestionAudioPlayTimes(String key, String token, String questionId) throws Exception;
+
+    Result updateExamRecordQuestionAudioPlayTimes(String key, String token, String questionId, String mediaName) throws Exception;
 
 }

+ 7 - 25
src/main/java/cn/com/qmth/examcloud/app/service/QuestionPoolService.java

@@ -1,42 +1,24 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-16 15:00:21.
+ * Created by Deason on 2018-07-31 17:34:46.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
 import cn.com.qmth.examcloud.app.model.Result;
-import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
 
 /**
  * 题库业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class QuestionPoolService {
-    private static Logger log = LoggerFactory.getLogger(QuestionPoolService.class);
-    @Autowired
-    private PropertyService propertyService;
+public interface QuestionPoolService {
 
-    public String downloadPaper(String paperId, String orgName) throws Exception {
-        //封装请求参数
-        return String.format("%s/api/ecs_ques/paper/export/%s/PAPER/%s/%s/offLine", propertyService.getQuestionPoolUrl(), paperId, orgName, paperId);
-    }
+    String downloadPaper(String paperId, String orgName) throws Exception;
 
-    public Result getPaperDetail(String key, String token, String paperId) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_ques/paper/%s", propertyService.getQuestionPoolUrl(), paperId);
-        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
-        if (result.isSuccess()) {
-            //过滤掉为空的属性
-            result.setData(HttpUtils.filterNullAttributes(result.getData()));
-        }
-        return result;
-    }
+    Result getPaperDetail(String key, String token, String paperId) throws Exception;
 
 }

+ 9 - 0
src/main/java/cn/com/qmth/examcloud/app/service/RedisService.java

@@ -1,3 +1,10 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:53:48.
+ * *************************************************
+ */
+
 package cn.com.qmth.examcloud.app.service;
 
 import cn.com.qmth.examcloud.app.core.exception.ApiException;
@@ -17,6 +24,8 @@ import java.util.concurrent.TimeUnit;
 import static cn.com.qmth.examcloud.app.model.Constants.APP_SESSION_USER_KEY_PREFIX;
 
 /**
+ * Redis接口服务类
+ *
  * @author: fengdesheng
  * @since: 2018/7/16
  */

+ 7 - 66
src/main/java/cn/com/qmth/examcloud/app/service/SmsService.java

@@ -1,83 +1,24 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-23 14:55:35.
+ * Created by Deason on 2018-07-31 17:36:02.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
-import cn.com.qmth.examcloud.app.model.Constants;
-import cn.com.qmth.examcloud.app.model.ResBody;
 import cn.com.qmth.examcloud.app.model.Result;
-import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
-import cn.com.qmth.examcloud.app.core.utils.JsonMapper;
-import cn.com.qmth.examcloud.app.core.utils.StrUtils;
-import okhttp3.FormBody;
-import okhttp3.MediaType;
-import okhttp3.RequestBody;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * 短信服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class SmsService {
-    private static Logger log = LoggerFactory.getLogger(SmsService.class);
-    @Autowired
-    private PropertyService propertyService;
-
-    public Result<String> sendSmsCode(String key, String token, String phone) throws Exception {
-        Assert.notNull(phone, "Phone must be not null.");
-        Assert.isTrue(StrUtils.isMobile(phone), "Phone is wrong number.");
-        //生成code
-        String code = StrUtils.randomNumber().toString();
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exchange/inner/sendSms/sendIdentifyingCode", propertyService.getSmsUrl());
-        Map<String, String> params = new HashMap<>();
-        params.put("phone", phone);//手机号码
-        params.put("code", code);//验证码
-        params.put("sign", propertyService.getSmsSign());//签名
-        params.put("templateCode", propertyService.getSmsTemplate());//短信模板
-        String json = new JsonMapper().toJson(params);
-        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
-        //发送短信
-        Result<String> result = HttpUtils.doPost(requestUrl, formBody, key, token);
-        return this.parseResult(result);
-    }
+public interface SmsService {
 
-    public Result<String> checkSmsCode(String key, String token, String phone, String code) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/exchange/inner/sendSms/checkIdentifyingCode", propertyService.getSmsUrl());
-        Map<String, String> params = new HashMap<>();
-        params.put("phone", phone);
-        params.put("code", code);
-        String json = new JsonMapper().toJson(params);
-        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
-        Result<String> result = HttpUtils.doPost(requestUrl, formBody, key, token);
-        return this.parseResult(result);
-    }
+    Result<String> sendSmsCode(String key, String token, String phone) throws Exception;
 
-    private Result<String> parseResult(Result<String> result) {
-        if (!result.isSuccess()) {
-            return result;
-        }
-        ResBody body = new JsonMapper().fromJson(result.getData(), ResBody.class);
-        if (body != null && body.getSuccess() != null) {
-            if (body.getSuccess() == true) {
-                return new Result().success();
-            } else {
-                return new Result().error(body.getReturnMsg());
-            }
-        }
-        return result;
-    }
+    Result<String> checkSmsCode(String key, String token, String phone, String code) throws Exception;
 
 }

+ 6 - 15
src/main/java/cn/com/qmth/examcloud/app/service/UpYunService.java

@@ -1,29 +1,20 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-16 17:48:25.
+ * Created by Deason on 2018-07-31 17:39:29.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
 /**
  * 又拍云文件服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class UpYunService {
-    private static Logger log = LoggerFactory.getLogger(UpYunService.class);
-    @Autowired
-    private PropertyService propertyService;
+public interface UpYunService {
 
-    public String downloadPaperAnswer(String filePath) throws Exception {
-        //封装请求参数
-        return String.format("%s/%s", propertyService.getUpYunUrl(), filePath);
-    }
+    String downloadPaperAnswer(String filePath) throws Exception;
 
 }

+ 10 - 87
src/main/java/cn/com/qmth/examcloud/app/service/UserAuthService.java

@@ -1,108 +1,31 @@
 /*
  * *************************************************
  * Copyright (c) 2018 QMTH. All Rights Reserved.
- * Created by Deason on 2018-07-16 17:48:37.
+ * Created by Deason on 2018-07-31 17:40:42.
  * *************************************************
  */
 
 package cn.com.qmth.examcloud.app.service;
 
-import cn.com.qmth.examcloud.app.core.utils.HttpBuilder;
-import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
-import cn.com.qmth.examcloud.app.core.utils.JsonMapper;
-import cn.com.qmth.examcloud.app.model.Constants;
-import cn.com.qmth.examcloud.app.model.ResBody;
 import cn.com.qmth.examcloud.app.model.Result;
 import cn.com.qmth.examcloud.app.model.UserInfo;
-import okhttp3.*;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.Assert;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static cn.com.qmth.examcloud.app.model.Constants.PARAM_KEY;
-import static cn.com.qmth.examcloud.app.model.Constants.PARAM_TOKEN;
 
 /**
  * 认证中心业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/31
  */
-@Service
-public class UserAuthService {
-    private static Logger log = LoggerFactory.getLogger(UserAuthService.class);
-    @Autowired
-    private PropertyService propertyService;
+public interface UserAuthService {
 
-    public Result<UserInfo> login(String account, String password, String accountType, Long rootOrgId, String domain) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_core/auth/login", propertyService.getUserAuthUrl());
-        Map<String, String> params = new HashMap<>();
-        params.put("accountValue", account);
-        params.put("password", password);
-        params.put("accountType", accountType);
-        params.put("rootOrgId", rootOrgId != null ? rootOrgId.toString() : "");
-        params.put("domain", domain);
-        String json = new JsonMapper().toJson(params);
-        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
-        Request request = new Request.Builder()
-                .url(requestUrl)
-                .post(formBody)
-                .build();
-        //执行请求
-        Response response = HttpBuilder.client.getInstance().newCall(request).execute();
-        String bodyStr = response.body().string();
-        if (response.isSuccessful()) {
-            JsonMapper mapper = new JsonMapper();
-            UserInfo userInfo = mapper.fromJson(bodyStr, UserInfo.class);
-            return new Result().success(userInfo);
-        } else {
-            log.warn("Http response is " + bodyStr);
-            ResBody body = new JsonMapper().fromJson(bodyStr, ResBody.class);
-            if (body != null && body.getCode() != null) {
-                return new Result().error(body.getDesc());
-            }
-            return new Result().error(bodyStr);
-        }
-    }
+    Result<UserInfo> login(String account, String password, String accountType, Long rootOrgId, String domain) throws Exception;
 
-    public Result logout(String key, String token) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_core/auth/logout", propertyService.getUserAuthUrl());
-        RequestBody formBody = new FormBody.Builder()
-                .add(PARAM_KEY, key)
-                .add(PARAM_TOKEN, token)
-                .build();
-        return HttpUtils.doPost(requestUrl, formBody, key, token);
-    }
+    Result logout(String key, String token) throws Exception;
 
-    public Result getUserInfo(String key, String token) throws Exception {
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_core/auth/getLoginUser", propertyService.getUserAuthUrl());
-        RequestBody formBody = new FormBody.Builder()
-                .add(PARAM_KEY, key)
-                .add(PARAM_TOKEN, token)
-                .build();
-        //todo 待补充'头像、手机号、年级'字段
-        return HttpUtils.doPost(requestUrl, formBody, key, token);
-    }
+    Result getUserInfo(String key, String token) throws Exception;
 
-    public Result updatePassword(String key, String token, Long userId, String password) throws Exception {
-        Assert.notNull(userId, "UserId must be not null.");
-        //封装请求参数
-        final String requestUrl = String.format("%s/api/ecs_core/user/password", propertyService.getUserAuthUrl());
-        RequestBody formBody = new FormBody.Builder()
-                .add("userId", userId.toString())
-                .add("password", password)
-                .build();
-        return HttpUtils.doPut(requestUrl, formBody, key, token);
-    }
+    Result updatePassword(String key, String token, Long userId, String password) throws Exception;
 
-    public Result userBindingPhone(String key, String token, Long userId, String phone, String code) {
-        //todo
-        return new Result().error();
-    }
+    Result userBindingPhone(String key, String token, Long userId, String phone, String code);
 
 }

+ 120 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/DeviceRecordServiceImpl.java

@@ -0,0 +1,120 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:14:51.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.dao.DeviceRecordRepository;
+import cn.com.qmth.examcloud.app.model.DeviceRecord;
+import cn.com.qmth.examcloud.app.model.Result;
+import cn.com.qmth.examcloud.app.service.DeviceRecordService;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 设备访问记录Service
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class DeviceRecordServiceImpl implements DeviceRecordService {
+    private static Logger log = LoggerFactory.getLogger(DeviceRecordServiceImpl.class);
+    @Autowired
+    private DeviceRecordRepository deviceRecordRepository;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Result<Page<DeviceRecord>> getDeviceRecordList(DeviceRecord params, Integer pageNo, Integer pageSize) {
+        Specification<DeviceRecord> spec = null;
+        if (params != null) {
+            spec = new Specification<DeviceRecord>() {
+                @Override
+                public Predicate toPredicate(Root<DeviceRecord> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
+                    List<Predicate> predicates = new ArrayList<>();
+                    if (StringUtils.isNotBlank(params.getSystem())) {
+                        predicates.add(builder.equal(root.get("system"), params.getSystem().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getDeviceId())) {
+                        predicates.add(builder.equal(root.get("deviceId"), params.getDeviceId().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getNetType())) {
+                        predicates.add(builder.equal(root.get("netType"), params.getNetType().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getBrand())) {
+                        predicates.add(builder.equal(root.get("brand"), params.getBrand().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getModel())) {
+                        predicates.add(builder.equal(root.get("model"), params.getModel().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getSysVersion())) {
+                        predicates.add(builder.equal(root.get("sysVersion"), params.getSysVersion().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getAppVersion())) {
+                        predicates.add(builder.equal(root.get("appVersion"), params.getAppVersion().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getAppCode())) {
+                        predicates.add(builder.equal(root.get("appCode"), params.getAppCode().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getPatchCode())) {
+                        predicates.add(builder.equal(root.get("patchCode"), params.getPatchCode().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getAccount())) {
+                        predicates.add(builder.equal(root.get("account"), params.getAccount().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getLoginKey())) {
+                        predicates.add(builder.equal(root.get("loginKey"), params.getLoginKey().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getLoginToken())) {
+                        predicates.add(builder.equal(root.get("loginToken"), params.getLoginToken().trim()));
+                    }
+                    if (StringUtils.isNotBlank(params.getUrl())) {
+                        predicates.add(builder.like(root.get("url"), "%" + params.getUrl().trim() + "%"));
+                    }
+                    if (StringUtils.isNotBlank(params.getIp())) {
+                        predicates.add(builder.equal(root.get("ip"), params.getIp().trim()));
+                    }
+                    return builder.and(predicates.toArray(new Predicate[predicates.size()]));
+                }
+            };
+        }
+        if (pageNo < 1) {
+            pageNo = 1;
+        }
+        if (pageSize < 1) {
+            pageSize = 1;
+        }
+        Sort sort = new Sort(Sort.Direction.DESC, "id");
+        Pageable pageable = new PageRequest(pageNo - 1, pageSize, sort);
+        Page<DeviceRecord> page = deviceRecordRepository.findAll(spec, pageable);
+        return new Result<>().success(page);
+    }
+
+    @Async
+    @Override
+    public void addDeviceRecord(DeviceRecord deviceRecord) {
+        Assert.notNull(deviceRecord, "DeviceRecord must not be null.");
+        deviceRecordRepository.save(deviceRecord);
+    }
+
+}

+ 59 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/ExamAdminServiceImpl.java

@@ -0,0 +1,59 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:19:06.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
+import cn.com.qmth.examcloud.app.model.Result;
+import cn.com.qmth.examcloud.app.service.ExamAdminService;
+import cn.com.qmth.examcloud.app.service.PropertyService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 考务业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class ExamAdminServiceImpl implements ExamAdminService {
+    private static Logger log = LoggerFactory.getLogger(ExamAdminServiceImpl.class);
+    @Autowired
+    private PropertyService propertyService;
+
+    @Override
+    public Result getPracticeExamList(String key, String token, String studentId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_exam_work/exam_student/query?student_id=%s", propertyService.getExamAdminUrl(), studentId);
+        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
+        if (result.isSuccess()) {
+            String data = result.getData();
+            //替换掉图片标签内容
+            data = HttpUtils.replaceImages(data);
+            //过滤掉为空的属性
+            data = HttpUtils.filterNullAttributes(data);
+            result.setData(data);
+        }
+        return result;
+    }
+
+    @Override
+    public Result getExamInfo(String key, String token, Long examId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_exam_work/exam/%s", propertyService.getExamAdminUrl(), examId);
+        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
+        if (result.isSuccess()) {
+            //过滤掉为空的属性
+            result.setData(HttpUtils.filterNullAttributes(result.getData()));
+        }
+        return result;
+    }
+
+}

+ 208 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/NetExamServiceImpl.java

@@ -0,0 +1,208 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:19:06.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.core.exception.ApiException;
+import cn.com.qmth.examcloud.app.core.utils.DateUtils;
+import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
+import cn.com.qmth.examcloud.app.core.utils.JsonMapper;
+import cn.com.qmth.examcloud.app.model.Constants;
+import cn.com.qmth.examcloud.app.model.Result;
+import cn.com.qmth.examcloud.app.service.NetExamService;
+import cn.com.qmth.examcloud.app.service.PropertyService;
+import okhttp3.FormBody;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.RequestBody;
+import org.apache.commons.io.FilenameUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static cn.com.qmth.examcloud.app.model.Constants.FILE_TYPE_PDF;
+import static cn.com.qmth.examcloud.app.model.Constants.FILE_TYPE_ZIP;
+
+/**
+ * 网考业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class NetExamServiceImpl implements NetExamService {
+    private static Logger log = LoggerFactory.getLogger(NetExamServiceImpl.class);
+    @Autowired
+    private PropertyService propertyService;
+
+    @Override
+    public Result getCurrentTime(String key, String token) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/online_exam_course/currentTime", propertyService.getNetExamUrl());
+        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
+        if (result.isSuccess()) {
+            //转换日期格式
+            result.setData(DateUtils.formatLongDate(result.getData()));
+        }
+        return result;
+    }
+
+    @Override
+    public Result getOfflineExamCourseList(String key, String token) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/offline_exam/getOfflineCourse", propertyService.getNetExamUrl());
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result startOfflineExamRecord(String key, String token, String examStudentId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/offline_exam/start?examStudentId=%s", propertyService.getNetExamUrl(), examStudentId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result uploadPaperAnswer(String key, String token, String examRecordId, byte[] fileBytes, String fileName, String md5) throws Exception {
+        Assert.notNull(examRecordId, "FileName must not be null.");
+        Assert.notNull(fileName, "ExamRecordId must not be null.");
+        String fileType = FilenameUtils.getExtension(fileName.toLowerCase());
+        if (!FILE_TYPE_ZIP.equals(fileType) && !FILE_TYPE_PDF.equals(fileType)) {
+            throw new ApiException("FileType must be zip or pdf.");
+        }
+        if (fileBytes.length == 0) {
+            throw new ApiException("File must be not empty.");
+        }
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/offline_exam/%s/submit", propertyService.getNetExamUrl(), examRecordId);
+        MultipartBody.Builder form = new MultipartBody.Builder().setType(MultipartBody.FORM);
+        RequestBody body = RequestBody.create(MediaType.parse("application/octet-stream"), fileBytes);
+        form.addFormDataPart("file", fileName, body);
+        form.addFormDataPart("fileType", fileType);
+        form.addFormDataPart("md5", md5 != null ? md5 : "");
+        return HttpUtils.doPost(requestUrl, form.build(), key, token);
+    }
+
+    @Override
+    public Result getPracticeExamCourseList(String key, String token, String examId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/practice_course?examId=%s", propertyService.getNetExamUrl(), examId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordHeartbeat(String key, String token, String examRecordId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_control/heartbeat?examRecordId=%s", propertyService.getNetExamUrl(), examRecordId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result startPracticeExamRecord(String key, String token, String examStudentId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_control/start?stu_exam_info_id=%s", propertyService.getNetExamUrl(), examStudentId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordPaperStructList(String key, String token, String examRecordId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_question/paper_struct?exam_record_id=%s", propertyService.getNetExamUrl(), examRecordId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordPaperQuestionList(String key, String token, String examRecordId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_question?exam_record_id=%s", propertyService.getNetExamUrl(), examRecordId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordPaperQuestionDetail(String key, String token, String questionId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_question/question?question_id=%s", propertyService.getNetExamUrl(), questionId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result updateExamRecordPaperQuestionAnswer(String key, String token, String examQuestionId, String studentAnswer) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_question/%s", propertyService.getNetExamUrl(), examQuestionId);
+        Map<String, String> params = new HashMap<>();
+        params.put("examQuestionId", examQuestionId);
+        params.put("stuAnswer", studentAnswer);
+        String json = new JsonMapper().toJson(params);
+        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
+        return HttpUtils.doPut(requestUrl, formBody, key, token);
+    }
+
+    @Override
+    public Result submitPracticeExamRecord(String key, String token, String examRecordId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_control/submit?examRecordId=%s", propertyService.getNetExamUrl(), examRecordId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result checkOnlineExamRecord(String key, String token) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_record/checkExam", propertyService.getNetExamUrl());
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordPracticeTotalInfo(String key, String token, String examStudentId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/practice_course/%s", propertyService.getNetExamUrl(), examStudentId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordPracticeHistoryList(String key, String token, String examStudentId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/practice_record?examStudentId=%s", propertyService.getNetExamUrl(), examStudentId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordTotalInfo(String key, String token, String examRecordId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/practice_detail?examRecordId=%s", propertyService.getNetExamUrl(), examRecordId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordQuestionDetailList(String key, String token, String examRecordId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_oe/report/exam_detail_report/paper_question?exam_record_id=%s", propertyService.getNetExamUrl(), examRecordId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result getExamRecordQuestionAudioPlayTimes(String key, String token, String questionId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_question_playtimes?questionId=%s", propertyService.getNetExamUrl(), questionId);
+        return HttpUtils.doGet(requestUrl, key, token);
+    }
+
+    @Override
+    public Result updateExamRecordQuestionAudioPlayTimes(String key, String token, String questionId, String mediaName) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exam_question_playtimes", propertyService.getNetExamUrl());
+        RequestBody formBody = new FormBody.Builder()
+                .add("questionId", questionId)
+                .add("mediaName", mediaName)
+                .build();
+        return HttpUtils.doPost(requestUrl, formBody, key, token);
+    }
+
+}

+ 49 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/QuestionPoolServiceImpl.java

@@ -0,0 +1,49 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:19:06.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
+import cn.com.qmth.examcloud.app.model.Result;
+import cn.com.qmth.examcloud.app.service.PropertyService;
+import cn.com.qmth.examcloud.app.service.QuestionPoolService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 题库业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class QuestionPoolServiceImpl implements QuestionPoolService {
+    private static Logger log = LoggerFactory.getLogger(QuestionPoolServiceImpl.class);
+    @Autowired
+    private PropertyService propertyService;
+
+    @Override
+    public String downloadPaper(String paperId, String orgName) throws Exception {
+        //封装请求参数
+        return String.format("%s/api/ecs_ques/paper/export/%s/PAPER/%s/%s/offLine", propertyService.getQuestionPoolUrl(), paperId, orgName, paperId);
+    }
+
+    @Override
+    public Result getPaperDetail(String key, String token, String paperId) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_ques/paper/%s", propertyService.getQuestionPoolUrl(), paperId);
+        Result<String> result = HttpUtils.doGet(requestUrl, key, token);
+        if (result.isSuccess()) {
+            //过滤掉为空的属性
+            result.setData(HttpUtils.filterNullAttributes(result.getData()));
+        }
+        return result;
+    }
+
+}

+ 90 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/SmsServiceImpl.java

@@ -0,0 +1,90 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:19:06.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
+import cn.com.qmth.examcloud.app.core.utils.JsonMapper;
+import cn.com.qmth.examcloud.app.core.utils.StrUtils;
+import cn.com.qmth.examcloud.app.model.Constants;
+import cn.com.qmth.examcloud.app.model.ResBody;
+import cn.com.qmth.examcloud.app.model.Result;
+import cn.com.qmth.examcloud.app.service.PropertyService;
+import cn.com.qmth.examcloud.app.service.SmsService;
+import okhttp3.FormBody;
+import okhttp3.MediaType;
+import okhttp3.RequestBody;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 短信服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class SmsServiceImpl implements SmsService {
+    private static Logger log = LoggerFactory.getLogger(SmsServiceImpl.class);
+    @Autowired
+    private PropertyService propertyService;
+
+    @Override
+    public Result<String> sendSmsCode(String key, String token, String phone) throws Exception {
+        Assert.notNull(phone, "Phone must be not null.");
+        Assert.isTrue(StrUtils.isMobile(phone), "Phone is wrong number.");
+        //生成code
+        String code = StrUtils.randomNumber().toString();
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exchange/inner/sendSms/sendIdentifyingCode", propertyService.getSmsUrl());
+        Map<String, String> params = new HashMap<>();
+        params.put("phone", phone);//手机号码
+        params.put("code", code);//验证码
+        params.put("sign", propertyService.getSmsSign());//签名
+        params.put("templateCode", propertyService.getSmsTemplate());//短信模板
+        String json = new JsonMapper().toJson(params);
+        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
+        //发送短信
+        Result<String> result = HttpUtils.doPost(requestUrl, formBody, key, token);
+        return this.parseResult(result);
+    }
+
+    @Override
+    public Result<String> checkSmsCode(String key, String token, String phone, String code) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/exchange/inner/sendSms/checkIdentifyingCode", propertyService.getSmsUrl());
+        Map<String, String> params = new HashMap<>();
+        params.put("phone", phone);
+        params.put("code", code);
+        String json = new JsonMapper().toJson(params);
+        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
+        Result<String> result = HttpUtils.doPost(requestUrl, formBody, key, token);
+        return this.parseResult(result);
+    }
+
+    private Result<String> parseResult(Result<String> result) {
+        if (!result.isSuccess()) {
+            return result;
+        }
+        ResBody body = new JsonMapper().fromJson(result.getData(), ResBody.class);
+        if (body != null && body.getSuccess() != null) {
+            if (body.getSuccess() == true) {
+                return new Result().success();
+            } else {
+                return new Result().error(body.getReturnMsg());
+            }
+        }
+        return result;
+    }
+
+}

+ 35 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/UpYunServiceImpl.java

@@ -0,0 +1,35 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:19:06.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.service.PropertyService;
+import cn.com.qmth.examcloud.app.service.UpYunService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 又拍云文件服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class UpYunServiceImpl implements UpYunService {
+    private static Logger log = LoggerFactory.getLogger(UpYunServiceImpl.class);
+    @Autowired
+    private PropertyService propertyService;
+
+    @Override
+    public String downloadPaperAnswer(String filePath) throws Exception {
+        //封装请求参数
+        return String.format("%s/%s", propertyService.getUpYunUrl(), filePath);
+    }
+
+}

+ 118 - 0
src/main/java/cn/com/qmth/examcloud/app/service/impl/UserAuthServiceImpl.java

@@ -0,0 +1,118 @@
+/*
+ * *************************************************
+ * Copyright (c) 2018 QMTH. All Rights Reserved.
+ * Created by Deason on 2018-07-31 17:19:06.
+ * *************************************************
+ */
+
+package cn.com.qmth.examcloud.app.service.impl;
+
+import cn.com.qmth.examcloud.app.core.utils.HttpBuilder;
+import cn.com.qmth.examcloud.app.core.utils.HttpUtils;
+import cn.com.qmth.examcloud.app.core.utils.JsonMapper;
+import cn.com.qmth.examcloud.app.model.Constants;
+import cn.com.qmth.examcloud.app.model.ResBody;
+import cn.com.qmth.examcloud.app.model.Result;
+import cn.com.qmth.examcloud.app.model.UserInfo;
+import cn.com.qmth.examcloud.app.service.PropertyService;
+import cn.com.qmth.examcloud.app.service.UserAuthService;
+import okhttp3.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static cn.com.qmth.examcloud.app.model.Constants.PARAM_KEY;
+import static cn.com.qmth.examcloud.app.model.Constants.PARAM_TOKEN;
+
+/**
+ * 认证中心业务服务接口
+ *
+ * @author: fengdesheng
+ * @since: 2018/7/16
+ */
+@Service
+public class UserAuthServiceImpl implements UserAuthService {
+    private static Logger log = LoggerFactory.getLogger(UserAuthServiceImpl.class);
+    @Autowired
+    private PropertyService propertyService;
+
+    @Override
+    public Result<UserInfo> login(String account, String password, String accountType, Long rootOrgId, String domain) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_core/auth/login", propertyService.getUserAuthUrl());
+        Map<String, String> params = new HashMap<>();
+        params.put("accountValue", account);
+        params.put("password", password);
+        params.put("accountType", accountType);
+        params.put("rootOrgId", rootOrgId != null ? rootOrgId.toString() : "");
+        params.put("domain", domain);
+        String json = new JsonMapper().toJson(params);
+        RequestBody formBody = FormBody.create(MediaType.parse(Constants.CHARSET_JSON_UTF8), json);
+        Request request = new Request.Builder()
+                .url(requestUrl)
+                .post(formBody)
+                .build();
+        //执行请求
+        Response response = HttpBuilder.client.getInstance().newCall(request).execute();
+        String bodyStr = response.body().string();
+        if (response.isSuccessful()) {
+            JsonMapper mapper = new JsonMapper();
+            UserInfo userInfo = mapper.fromJson(bodyStr, UserInfo.class);
+            return new Result().success(userInfo);
+        } else {
+            log.warn("Http response is " + bodyStr);
+            ResBody body = new JsonMapper().fromJson(bodyStr, ResBody.class);
+            if (body != null && body.getCode() != null) {
+                return new Result().error(body.getDesc());
+            }
+            return new Result().error(bodyStr);
+        }
+    }
+
+    @Override
+    public Result logout(String key, String token) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_core/auth/logout", propertyService.getUserAuthUrl());
+        RequestBody formBody = new FormBody.Builder()
+                .add(PARAM_KEY, key)
+                .add(PARAM_TOKEN, token)
+                .build();
+        return HttpUtils.doPost(requestUrl, formBody, key, token);
+    }
+
+    @Override
+    public Result getUserInfo(String key, String token) throws Exception {
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_core/auth/getLoginUser", propertyService.getUserAuthUrl());
+        RequestBody formBody = new FormBody.Builder()
+                .add(PARAM_KEY, key)
+                .add(PARAM_TOKEN, token)
+                .build();
+        //todo 待补充'头像、手机号、年级'字段
+        return HttpUtils.doPost(requestUrl, formBody, key, token);
+    }
+
+    @Override
+    public Result updatePassword(String key, String token, Long userId, String password) throws Exception {
+        Assert.notNull(userId, "UserId must be not null.");
+        //封装请求参数
+        final String requestUrl = String.format("%s/api/ecs_core/user/password", propertyService.getUserAuthUrl());
+        RequestBody formBody = new FormBody.Builder()
+                .add("userId", userId.toString())
+                .add("password", password)
+                .build();
+        return HttpUtils.doPut(requestUrl, formBody, key, token);
+    }
+
+    @Override
+    public Result userBindingPhone(String key, String token, Long userId, String phone, String code) {
+        //todo
+        return new Result().error();
+    }
+
+}