Эх сурвалжийг харах

Merge remote-tracking branch 'origin/dev' into dev

wangliang 4 жил өмнө
parent
commit
77162d110d
19 өөрчлөгдсөн 751 нэмэгдсэн , 1 устгасан
  1. 36 0
      themis-business/src/main/java/com/qmth/themis/business/bean/exam/QrMobileMonitorParamBean.java
  2. 34 0
      themis-business/src/main/java/com/qmth/themis/business/bean/exam/QrResponseBean.java
  3. 55 0
      themis-business/src/main/java/com/qmth/themis/business/bean/exam/QrUploadParamBean.java
  4. 57 0
      themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationBean.java
  5. 45 0
      themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationMonitorBean.java
  6. 35 0
      themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationParamBean.java
  7. 44 0
      themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationUploadBean.java
  8. 10 0
      themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java
  9. 87 0
      themis-business/src/main/java/com/qmth/themis/business/cache/MobileAuthCacheUtil.java
  10. 15 1
      themis-business/src/main/java/com/qmth/themis/business/cache/RedisKeyHelper.java
  11. 23 0
      themis-business/src/main/java/com/qmth/themis/business/enums/MobileModeEnum.java
  12. 10 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEMobileService.java
  13. 14 0
      themis-business/src/main/java/com/qmth/themis/business/service/TEQrcodeService.java
  14. 67 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEMobileServiceImpl.java
  15. 95 0
      themis-business/src/main/java/com/qmth/themis/business/service/impl/TEQrcodeServiceImpl.java
  16. 8 0
      themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java
  17. 43 0
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEMobileController.java
  18. 71 0
      themis-exam/src/main/java/com/qmth/themis/exam/api/TEQrcodeController.java
  19. 2 0
      themis-exam/src/main/resources/application.properties

+ 36 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/exam/QrMobileMonitorParamBean.java

@@ -0,0 +1,36 @@
+package com.qmth.themis.business.bean.exam;
+
+import com.qmth.themis.common.enums.Source;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("获取移动端监考二维码参数信息")
+public class QrMobileMonitorParamBean {
+
+	
+	@ApiModelProperty("监考源")
+	private Source source;
+	
+	@ApiModelProperty("考试记录ID")
+	private Long recordId;
+
+	public Source getSource() {
+		return source;
+	}
+
+	public void setSource(Source source) {
+		this.source = source;
+	}
+
+	public Long getRecordId() {
+		return recordId;
+	}
+
+	public void setRecordId(Long recordId) {
+		this.recordId = recordId;
+	}
+
+	
+
+}

+ 34 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/exam/QrResponseBean.java

@@ -0,0 +1,34 @@
+package com.qmth.themis.business.bean.exam;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("获取二维码返回信息")
+public class QrResponseBean {
+
+	
+	@ApiModelProperty("二维码内容")
+	private String content;
+	
+	@ApiModelProperty("expireTime")
+	private Long expireTime;
+
+	public String getContent() {
+		return content;
+	}
+
+	public void setContent(String content) {
+		this.content = content;
+	}
+
+	public Long getExpireTime() {
+		return expireTime;
+	}
+
+	public void setExpireTime(Long expireTime) {
+		this.expireTime = expireTime;
+	}
+
+	
+
+}

+ 55 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/exam/QrUploadParamBean.java

@@ -0,0 +1,55 @@
+package com.qmth.themis.business.bean.exam;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("二维码上传作答参数")
+public class QrUploadParamBean {
+	
+	@ApiModelProperty("考试记录id")
+	private Long recordId;
+	
+	@ApiModelProperty("大题号")
+	private Integer mainNumber;
+
+	@ApiModelProperty("小题号")
+	private Integer subNumber;
+	
+	@ApiModelProperty("套题子题序号")
+	private Integer subIndex;
+
+	public Long getRecordId() {
+		return recordId;
+	}
+
+	public void setRecordId(Long recordId) {
+		this.recordId = recordId;
+	}
+
+	public Integer getMainNumber() {
+		return mainNumber;
+	}
+
+	public void setMainNumber(Integer mainNumber) {
+		this.mainNumber = mainNumber;
+	}
+
+	public Integer getSubNumber() {
+		return subNumber;
+	}
+
+	public void setSubNumber(Integer subNumber) {
+		this.subNumber = subNumber;
+	}
+
+	public Integer getSubIndex() {
+		return subIndex;
+	}
+
+	public void setSubIndex(Integer subIndex) {
+		this.subIndex = subIndex;
+	}
+	
+
+	
+}

+ 57 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationBean.java

@@ -0,0 +1,57 @@
+package com.qmth.themis.business.bean.mobile;
+
+import com.qmth.themis.business.enums.MobileModeEnum;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("登录返回信息")
+public class MobileAuthorizationBean {
+
+	
+	@ApiModelProperty("功能模式")
+	private MobileModeEnum mode;
+	
+	@ApiModelProperty("时间戳")
+	private Long time;
+	
+	@ApiModelProperty("sessionId")
+	private Long sessionId;
+	
+	@ApiModelProperty("考试记录id")
+	private Long recordId;
+
+	public MobileModeEnum getMode() {
+		return mode;
+	}
+
+	public void setMode(MobileModeEnum mode) {
+		this.mode = mode;
+	}
+
+	public Long getTime() {
+		return time;
+	}
+
+	public void setTime(Long time) {
+		this.time = time;
+	}
+
+	public Long getSessionId() {
+		return sessionId;
+	}
+
+	public void setSessionId(Long sessionId) {
+		this.sessionId = sessionId;
+	}
+
+	public Long getRecordId() {
+		return recordId;
+	}
+
+	public void setRecordId(Long recordId) {
+		this.recordId = recordId;
+	}
+
+	
+}

+ 45 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationMonitorBean.java

@@ -0,0 +1,45 @@
+package com.qmth.themis.business.bean.mobile;
+
+import com.qmth.themis.common.enums.Source;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("登录返回信息")
+public class MobileAuthorizationMonitorBean  extends MobileAuthorizationBean{
+
+	
+	@ApiModelProperty("监控线路标识")
+	private String monitorKey;
+	
+	@ApiModelProperty("当前设备代表的视频源: mobile_first|mobile_second")
+	private Source monitorVideoSource;
+
+	@ApiModelProperty("是否启用当前设备的音频播放与麦克风采集")
+	private Boolean monitorAudioEnable;
+
+	public String getMonitorKey() {
+		return monitorKey;
+	}
+
+	public void setMonitorKey(String monitorKey) {
+		this.monitorKey = monitorKey;
+	}
+
+	public Source getMonitorVideoSource() {
+		return monitorVideoSource;
+	}
+
+	public void setMonitorVideoSource(Source monitorVideoSource) {
+		this.monitorVideoSource = monitorVideoSource;
+	}
+
+	public Boolean getMonitorAudioEnable() {
+		return monitorAudioEnable;
+	}
+
+	public void setMonitorAudioEnable(Boolean monitorAudioEnable) {
+		this.monitorAudioEnable = monitorAudioEnable;
+	}
+	
+}

+ 35 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationParamBean.java

@@ -0,0 +1,35 @@
+package com.qmth.themis.business.bean.mobile;
+
+import com.qmth.themis.business.enums.MobileModeEnum;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("获取登录详细信息")
+public class MobileAuthorizationParamBean {
+
+	
+	@ApiModelProperty("功能模式")
+	private MobileModeEnum mode;
+	
+	@ApiModelProperty("临时授权码")
+	private String code;
+
+	public MobileModeEnum getMode() {
+		return mode;
+	}
+
+	public void setMode(MobileModeEnum mode) {
+		this.mode = mode;
+	}
+
+	public String getCode() {
+		return code;
+	}
+
+	public void setCode(String code) {
+		this.code = code;
+	}
+	
+
+}

+ 44 - 0
themis-business/src/main/java/com/qmth/themis/business/bean/mobile/MobileAuthorizationUploadBean.java

@@ -0,0 +1,44 @@
+package com.qmth.themis.business.bean.mobile;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("登录返回信息")
+public class MobileAuthorizationUploadBean extends MobileAuthorizationBean{
+
+	
+	@ApiModelProperty("大题号")
+	private Integer mainNumber;
+	
+	@ApiModelProperty("小题号")
+	private Integer subNumber;
+	
+	@ApiModelProperty("套题子题号")
+	private Integer subIndex;
+
+	public Integer getMainNumber() {
+		return mainNumber;
+	}
+
+	public void setMainNumber(Integer mainNumber) {
+		this.mainNumber = mainNumber;
+	}
+
+	public Integer getSubNumber() {
+		return subNumber;
+	}
+
+	public void setSubNumber(Integer subNumber) {
+		this.subNumber = subNumber;
+	}
+
+	public Integer getSubIndex() {
+		return subIndex;
+	}
+
+	public void setSubIndex(Integer subIndex) {
+		this.subIndex = subIndex;
+	}
+
+	
+}

+ 10 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/ExamRecordCacheUtil.java

@@ -157,5 +157,15 @@ public class ExamRecordCacheUtil {
 		return (Integer) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "inProcessLivenessVerifyCount");
 	}
 	
+	public static void setMonitorKey(Long recordId, String monitorKey) {
+		redisUtil.set(RedisKeyHelper.examRecordCacheKey(recordId), "monitorKey", monitorKey);
+		examRecordService.dataUpdateMq(recordId, "monitorKey", monitorKey);
+	}
+	
+	public static String getMonitorKey(Long recordId) {
+		return (String) redisUtil.get(RedisKeyHelper.examRecordCacheKey(recordId), "monitorKey");
+	}
+	
+	
 	
 }

+ 87 - 0
themis-business/src/main/java/com/qmth/themis/business/cache/MobileAuthCacheUtil.java

@@ -0,0 +1,87 @@
+package com.qmth.themis.business.cache;
+
+import com.qmth.themis.business.constant.SpringContextHolder;
+import com.qmth.themis.business.enums.MobileModeEnum;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.enums.Source;
+
+/**移动端临时认证
+ * @Description: 
+ * @Author: xiatian
+ * @Date: 2020-08-14
+ */
+public class MobileAuthCacheUtil {
+	private static RedisUtil redisUtil = SpringContextHolder.getBean(RedisUtil.class);
+
+	public static void setMode(MobileModeEnum mode,String code) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "mode", mode);
+	}
+	
+	public static MobileModeEnum getMode(MobileModeEnum mode,String code) {
+		return (MobileModeEnum) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "mode");
+	}
+	
+	public static void setCode(MobileModeEnum mode,String code) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "code", code);
+	}
+	
+	public static String getCode(MobileModeEnum mode,String code) {
+		return (String) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "code");
+	}
+	
+	public static void setRecordId(MobileModeEnum mode,String code,Long recordId) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "recordId", recordId);
+	}
+	
+	public static Long getRecordId(MobileModeEnum mode,String code) {
+		return (Long) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "recordId");
+	}
+	
+	public static void setMainNumber(MobileModeEnum mode,String code,Integer mainNumber) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "mainNumber", mainNumber);
+	}
+	
+	public static Integer getMainNumber(MobileModeEnum mode,String code) {
+		return (Integer) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "mainNumber");
+	}
+	
+	public static void setSubNumber(MobileModeEnum mode,String code,Integer subNumber) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "subNumber", subNumber);
+	}
+	
+	public static Integer getSubNumber(MobileModeEnum mode,String code) {
+		return (Integer) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "subNumber");
+	}
+	
+	public static void setSubIndex(MobileModeEnum mode,String code,Integer subIndex) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "subIndex", subIndex);
+	}
+	
+	public static Integer getSubIndex(MobileModeEnum mode,String code) {
+		return (Integer) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "subIndex");
+	}
+	
+	public static void setMonitorKey(MobileModeEnum mode,String code,String monitorKey) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "monitorKey", monitorKey);
+	}
+	
+	public static String getMonitorKey(MobileModeEnum mode,String code) {
+		return (String) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "monitorKey");
+	}
+	
+	public static void setMonitorVideoSource(MobileModeEnum mode,String code,Source monitorVideoSource) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "monitorVideoSource", monitorVideoSource);
+	}
+	
+	public static Source getMonitorVideoSource(MobileModeEnum mode,String code) {
+		return (Source) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "monitorVideoSource");
+	}
+	
+	public static void setMonitorAudioEnable(MobileModeEnum mode,String code,Boolean monitorAudioEnable) {
+		redisUtil.set(RedisKeyHelper.mobileAuthCacheKey(mode, code), "monitorAudioEnable", monitorAudioEnable);
+	}
+	
+	public static Boolean getMonitorAudioEnable(MobileModeEnum mode,String code) {
+		return (Boolean) redisUtil.get(RedisKeyHelper.mobileAuthCacheKey(mode, code), "monitorAudioEnable");
+	}
+}

+ 15 - 1
themis-business/src/main/java/com/qmth/themis/business/cache/RedisKeyHelper.java

@@ -1,5 +1,7 @@
 package com.qmth.themis.business.cache;
 
+import com.qmth.themis.business.enums.MobileModeEnum;
+
 public class RedisKeyHelper {
 	private static String underLine = "_";
 
@@ -48,6 +50,11 @@ public class RedisKeyHelper {
 	 * 场次-考试记录
 	 */
 	private static String examActivityRecordKeyPrefix = "exam_activity_record::";
+	
+	/**
+	 * 移动端临时认证
+	 */
+	private static String mobileAuthKeyPrefix = "mobile_auth_";
 	/**
 	 * 场次
 	 * 
@@ -160,5 +167,12 @@ public class RedisKeyHelper {
 		return examActivityRecordKeyPrefix + activityId;
 	}
 	
-
+	/**移动端临时认证大key
+	 * @param mode
+	 * @param code
+	 * @return
+	 */
+	public static String mobileAuthCacheKey(MobileModeEnum mode,String code) {
+		return mobileAuthKeyPrefix + mode.name().toLowerCase()+underLine+code;
+	}
 }

+ 23 - 0
themis-business/src/main/java/com/qmth/themis/business/enums/MobileModeEnum.java

@@ -0,0 +1,23 @@
+package com.qmth.themis.business.enums;
+
+/**
+ * @Description:
+ * @Author: xiatian
+ * @Date: 2020-08-14
+ */
+public enum MobileModeEnum {
+
+	PHOTO_UPLOAD("PHOTO_UPLOAD"),
+
+	AUDIO_UPLOAD("AUDIO_UPLOAD"), MOBILE_MONITOR("MOBILE_MONITOR");
+
+	private String title;
+
+	private MobileModeEnum(String title) {
+		this.title = title;
+	}
+
+	public String getTitle() {
+		return title;
+	}
+}

+ 10 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEMobileService.java

@@ -0,0 +1,10 @@
+package com.qmth.themis.business.service;
+
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationBean;
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationParamBean;
+
+public interface TEMobileService {
+
+	public MobileAuthorizationBean authorization(MobileAuthorizationParamBean param);
+
+}

+ 14 - 0
themis-business/src/main/java/com/qmth/themis/business/service/TEQrcodeService.java

@@ -0,0 +1,14 @@
+package com.qmth.themis.business.service;
+
+import com.qmth.themis.business.bean.exam.QrMobileMonitorParamBean;
+import com.qmth.themis.business.bean.exam.QrResponseBean;
+import com.qmth.themis.business.bean.exam.QrUploadParamBean;
+import com.qmth.themis.business.enums.MobileModeEnum;
+
+public interface TEQrcodeService {
+
+	QrResponseBean mobileMonitor(QrMobileMonitorParamBean param);
+
+	QrResponseBean upload(QrUploadParamBean param,MobileModeEnum mode);
+
+}

+ 67 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEMobileServiceImpl.java

@@ -0,0 +1,67 @@
+package com.qmth.themis.business.service.impl;
+
+import javax.annotation.Resource;
+
+import org.springframework.stereotype.Service;
+
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationBean;
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationMonitorBean;
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationParamBean;
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationUploadBean;
+import com.qmth.themis.business.cache.MobileAuthCacheUtil;
+import com.qmth.themis.business.enums.MobileModeEnum;
+import com.qmth.themis.business.service.TEMobileService;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.enums.Source;
+import com.qmth.themis.common.exception.BusinessException;
+
+@Service
+public class TEMobileServiceImpl implements TEMobileService {
+
+    @Resource
+    RedisUtil redisUtil;
+	
+	@Override
+	public MobileAuthorizationBean authorization(MobileAuthorizationParamBean param) {
+		MobileModeEnum mode=param.getMode();
+		String code=param.getCode();
+		MobileAuthorizationBean ret=null;
+		if(MobileModeEnum.MOBILE_MONITOR.equals(mode)) {
+			ret=monitorAuthorization(mode, code);
+		}else if(MobileModeEnum.PHOTO_UPLOAD.equals(mode)||MobileModeEnum.AUDIO_UPLOAD.equals(mode)) {
+			ret=answerUploadAuthorization(mode, code);
+		}
+		return ret;
+	}
+	
+	private MobileAuthorizationBean monitorAuthorization(MobileModeEnum mode,String code) {
+		Long recordId=MobileAuthCacheUtil.getRecordId(mode, code);
+		String monitorKey=MobileAuthCacheUtil.getMonitorKey(mode, code);
+		Source monitorVideoSource=MobileAuthCacheUtil.getMonitorVideoSource(mode, code);
+		Boolean monitorAudioEnable=MobileAuthCacheUtil.getMonitorAudioEnable(mode, code);
+		if(MobileAuthCacheUtil.getMode(mode, code)==null) {
+			throw new BusinessException("二维码已过期");
+		}
+		MobileAuthorizationMonitorBean ret=new MobileAuthorizationMonitorBean();
+		ret.setRecordId(recordId);
+		ret.setMonitorKey(monitorKey);
+		ret.setMonitorVideoSource(monitorVideoSource);
+		ret.setMonitorAudioEnable(monitorAudioEnable);
+		return ret;
+	}
+	private MobileAuthorizationBean answerUploadAuthorization(MobileModeEnum mode,String code) {
+		Long recordId=MobileAuthCacheUtil.getRecordId(mode, code);
+		Integer mainNumber=MobileAuthCacheUtil.getMainNumber(mode, code);
+		Integer subNumber=MobileAuthCacheUtil.getSubNumber(mode, code);
+		Integer subIndex=MobileAuthCacheUtil.getSubIndex(mode, code);
+		if(MobileAuthCacheUtil.getMode(mode, code)==null) {
+			throw new BusinessException("二维码已过期");
+		}
+		MobileAuthorizationUploadBean ret=new MobileAuthorizationUploadBean();
+		ret.setRecordId(recordId);
+		ret.setMainNumber(mainNumber);
+		ret.setSubNumber(subNumber);
+		ret.setSubIndex(subIndex);
+		return ret;
+	}
+}

+ 95 - 0
themis-business/src/main/java/com/qmth/themis/business/service/impl/TEQrcodeServiceImpl.java

@@ -0,0 +1,95 @@
+package com.qmth.themis.business.service.impl;
+
+import java.util.Date;
+import java.util.UUID;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang3.time.DateUtils;
+import org.springframework.stereotype.Service;
+
+import com.qmth.themis.business.bean.exam.QrMobileMonitorParamBean;
+import com.qmth.themis.business.bean.exam.QrResponseBean;
+import com.qmth.themis.business.bean.exam.QrUploadParamBean;
+import com.qmth.themis.business.cache.ExamRecordCacheUtil;
+import com.qmth.themis.business.cache.MobileAuthCacheUtil;
+import com.qmth.themis.business.cache.RedisKeyHelper;
+import com.qmth.themis.business.cache.bean.ExamCacheBean;
+import com.qmth.themis.business.config.SystemConfig;
+import com.qmth.themis.business.enums.MobileModeEnum;
+import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
+import com.qmth.themis.business.service.TEExamService;
+import com.qmth.themis.business.service.TEQrcodeService;
+import com.qmth.themis.business.util.RedisUtil;
+import com.qmth.themis.common.enums.Source;
+
+@Service
+public class TEQrcodeServiceImpl implements TEQrcodeService {
+	
+	//二维码过期时间(秒)
+	private final static int qrExpireTime=120;
+	
+	@Resource
+	TEExamService examService;
+	@Resource
+	RedisUtil redisUtil;
+	@Resource
+	SystemConfig systemConfig;
+
+	@Override
+	public QrResponseBean mobileMonitor(QrMobileMonitorParamBean param) {
+		String domain = systemConfig.getProperty("wxapp.upload.url");
+		String code=uuid();
+		MobileModeEnum mode=MobileModeEnum.MOBILE_MONITOR;
+		MobileAuthCacheUtil.setMode(mode, code);
+		MobileAuthCacheUtil.setCode(mode, code);
+		MobileAuthCacheUtil.setRecordId(mode, code, param.getRecordId());
+		MobileAuthCacheUtil.setMonitorKey(mode, code, ExamRecordCacheUtil.getMonitorKey(param.getRecordId()));
+		MobileAuthCacheUtil.setMonitorVideoSource(mode, code, param.getSource());
+		MobileAuthCacheUtil.setMonitorAudioEnable(mode, code, getMonitorAudioEnable(param));
+		Long expireTime=DateUtils.addSeconds(new Date(), qrExpireTime).getTime();
+		redisUtil.expire(RedisKeyHelper.mobileAuthCacheKey(mode, code), qrExpireTime);
+		QrResponseBean ret=new QrResponseBean();
+		ret.setExpireTime(expireTime);
+		ret.setContent(domain+"/"+mode.name().toLowerCase()+"/"+code);
+		return ret;
+	}
+
+	private Boolean getMonitorAudioEnable(QrMobileMonitorParamBean param) {
+		Long examId = ExamRecordCacheUtil.getExamId(param.getRecordId());
+		ExamCacheBean exam = examService.getExamCacheBean(examId);
+		String monitorVideoSource = exam.getMonitorVideoSource();
+		if (!monitorVideoSource.toUpperCase().contains(MonitorVideoSourceEnum.CLIENT_SCREEN.name())
+				&& !monitorVideoSource.toUpperCase().contains(MonitorVideoSourceEnum.CLIENT_CAMERA.name())
+				&& Source.mobile_monitor_first.equals(param.getSource())) {
+			return true;
+		}else {
+			return false;
+		}
+	}
+	
+    private String uuid() {
+        return UUID.randomUUID().toString().replaceAll("-", "");
+    }
+
+	@Override
+	public QrResponseBean upload(QrUploadParamBean param,MobileModeEnum mode) {
+		String domain = systemConfig.getProperty("wxapp.upload.url");
+		String code=uuid();
+		MobileAuthCacheUtil.setMode(mode, code);
+		MobileAuthCacheUtil.setCode(mode, code);
+		MobileAuthCacheUtil.setRecordId(mode, code, param.getRecordId());
+		MobileAuthCacheUtil.setMainNumber(mode, code, param.getMainNumber());
+		MobileAuthCacheUtil.setSubNumber(mode, code, param.getSubNumber());
+		if(param.getSubIndex()!=null) {
+			MobileAuthCacheUtil.setSubIndex(mode, code, param.getSubIndex());
+		}
+		Long expireTime=DateUtils.addSeconds(new Date(), qrExpireTime).getTime();
+		redisUtil.expire(RedisKeyHelper.mobileAuthCacheKey(mode, code), qrExpireTime);
+		QrResponseBean ret=new QrResponseBean();
+		ret.setExpireTime(expireTime);
+		ret.setContent(domain+"/"+mode.name().toLowerCase()+"/"+code);
+		return ret;
+	}
+
+}

+ 8 - 0
themis-business/src/main/java/com/qmth/themis/business/util/RedisUtil.java

@@ -299,4 +299,12 @@ public class RedisUtil {
     public void setForHash(String key, Map<String, Object> map) {
         redisTemplate.opsForHash().putAll(key, map);
     }
+    
+    /**设置过期时间(秒)
+     * @param key
+     * @param timeOutSecond
+     */
+    public void expire(String key,int timeOutSecond) {
+        redisTemplate.expire(key, timeOutSecond, TimeUnit.SECONDS);
+    }
 }

+ 43 - 0
themis-exam/src/main/java/com/qmth/themis/exam/api/TEMobileController.java

@@ -0,0 +1,43 @@
+package com.qmth.themis.exam.api;
+
+import javax.annotation.Resource;
+
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.qmth.themis.business.bean.mobile.MobileAuthorizationParamBean;
+import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TEMobileService;
+import com.qmth.themis.common.exception.BusinessException;
+import com.qmth.themis.common.util.Result;
+import com.qmth.themis.common.util.ResultUtil;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(tags = "移动端接口")
+@RestController
+@RequestMapping("/${prefix.url.mobile}")
+public class TEMobileController {
+	
+	@Resource
+	MqDtoService mqDtoService;
+	
+	@Resource
+	TEMobileService mobileService;
+
+	@ApiOperation(value = "获取登录详细信息")
+	@RequestMapping(value = "/authorization", method = RequestMethod.POST)
+	public Result authorization(@RequestBody MobileAuthorizationParamBean param) {
+		if (param.getMode() == null) {
+			throw new BusinessException("mode不能为空");
+		}
+		if (param.getCode() == null) {
+			throw new BusinessException("code不能为空");
+		}
+		return ResultUtil.ok(mobileService.authorization(param));
+	}
+
+}

+ 71 - 0
themis-exam/src/main/java/com/qmth/themis/exam/api/TEQrcodeController.java

@@ -0,0 +1,71 @@
+package com.qmth.themis.exam.api;
+
+import javax.annotation.Resource;
+
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.qmth.themis.business.bean.exam.QrMobileMonitorParamBean;
+import com.qmth.themis.business.bean.exam.QrUploadParamBean;
+import com.qmth.themis.business.enums.MobileModeEnum;
+import com.qmth.themis.business.service.MqDtoService;
+import com.qmth.themis.business.service.TEQrcodeService;
+import com.qmth.themis.common.enums.Source;
+import com.qmth.themis.common.exception.BusinessException;
+import com.qmth.themis.common.util.Result;
+import com.qmth.themis.common.util.ResultUtil;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(tags = "二维码接口")
+@RestController
+@RequestMapping("/${prefix.url.exam}/qrcode")
+public class TEQrcodeController {
+
+	@Resource
+	MqDtoService mqDtoService;
+
+	@Resource
+	TEQrcodeService qrcodeService;
+	
+
+	@ApiOperation(value = "获取移动端监考二维码")
+	@RequestMapping(value = "/mobile_monitor", method = RequestMethod.POST)
+	public Result mobileMonitor(@RequestBody QrMobileMonitorParamBean param) {
+		if (param.getRecordId() == null) {
+			throw new BusinessException("recordId不能为空");
+		}
+		if (param.getSource() == null) {
+			throw new BusinessException("source不能为空");
+		}
+		if (!Source.mobile_monitor_first.equals(param.getSource())
+				&& !Source.mobile_monitor_first.equals(param.getSource())) {
+			throw new BusinessException("source 错误");
+		}
+		return ResultUtil.ok(qrcodeService.mobileMonitor(param));
+	}
+
+	@ApiOperation(value = "获取移动端监考二维码")
+	@RequestMapping(value = "/{uploadType}", method = RequestMethod.POST)
+	public Result mobileMonitor(@PathVariable String uploadType,@RequestBody QrUploadParamBean param) {
+		if (param.getRecordId() == null) {
+			throw new BusinessException("recordId不能为空");
+		}
+		if (param.getMainNumber() == null) {
+			throw new BusinessException("MainNumber不能为空");
+		}
+		if (param.getSubNumber() == null) {
+			throw new BusinessException("SubNumber不能为空");
+		}
+		MobileModeEnum mode=MobileModeEnum.valueOf(uploadType.toUpperCase());
+		if (!MobileModeEnum.PHOTO_UPLOAD.equals(mode)
+				&& !MobileModeEnum.AUDIO_UPLOAD.equals(mode)) {
+			throw new BusinessException("uploadType 错误");
+		}
+		return ResultUtil.ok(qrcodeService.upload(param,mode));
+	}
+}

+ 2 - 0
themis-exam/src/main/resources/application.properties

@@ -146,6 +146,8 @@ spring.resources.static-locations=file:${sys.config.serverUpload},classpath:/MET
 prefix.url.exam=api/oe
 prefix.url.mobile=api/mobile
 
+wxapp.upload.url=http://wxapp2.qmth.com.cn
+
 #\u65E0\u9700\u9274\u6743\u7684url
 no.auth.urls=/webjars/**,/druid/**,/swagger-ui.html,/doc.html,/swagger-resources/**,/v2/api-docs,/webjars/springfox-swagger-ui/**,/api/oe/student/login,/api/oe/sys/env,/file/**,/upload/**,/client/**,/base_photo/**,/frontend/**,/api/oe/exam/short_code,/api/oe/monitor/live_url,/api/oe/monitor/call/apply,/api/oe/monitor/call/cancel,/api/oe/monitor/call/list,/api/oe/monitor/call/query
 common.system.urls=/api/oe/student/logout,/api/oe/exam/file/upload