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

Merge remote-tracking branch 'origin/master'

周箭河 5 лет назад
Родитель
Сommit
e7a3f29e6a
33 измененных файлов с 524 добавлено и 316 удалено
  1. 0 7
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/controller/RoomController.java
  2. 1 9
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/RoomDao.java
  3. 16 28
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/RoomMemberDao.java
  4. 3 5
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/UserDao.java
  5. 0 3
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/WhiteboardDao.java
  6. 85 52
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/mec/im/IMHelper.java
  7. 1 0
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/pojo/RoomMember.java
  8. 54 0
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/pojo/UrisDto.java
  9. 149 158
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/service/Impl/RoomServiceImpl.java
  10. 0 12
      edu-im/edu-im-server/src/main/java/com/keao/edu/im/service/RoomService.java
  11. 25 1
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dao/ExamRegistrationDao.java
  12. 11 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dao/ExamReviewDao.java
  13. 11 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dao/StudentExamResultDao.java
  14. 11 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dto/ExamCertificationDto.java
  15. 11 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dto/NeedCheckingDetailDto.java
  16. 12 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/ExamRegistrationService.java
  17. 10 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamCertificationServiceImpl.java
  18. 1 1
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamOrganizationRelationServiceImpl.java
  19. 35 1
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamRegistrationServiceImpl.java
  20. 1 1
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamRoomServiceImpl.java
  21. 7 21
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamRoomStudentRelationServiceImpl.java
  22. 9 2
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExaminationBasicServiceImpl.java
  23. 7 0
      edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/StudentServiceImpl.java
  24. 18 5
      edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamRegistrationMapper.xml
  25. 4 1
      edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamReviewMapper.xml
  26. 2 2
      edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamRoomMapper.xml
  27. 8 2
      edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamRoomStudentRelationMapper.xml
  28. 7 2
      edu-user/edu-user-biz/src/main/resources/config/mybatis/StudentExamResultMapper.xml
  29. 2 2
      edu-user/edu-user-biz/src/main/resources/config/mybatis/StudentMapper.xml
  30. 11 0
      edu-user/edu-user-client-api/src/main/java/com/keao/edu/user/api/entity/ExamRoomStudentRelation.java
  31. 1 1
      edu-user/edu-user-server/src/main/java/com/keao/edu/user/controller/AppVersionInfoController.java
  32. 7 0
      edu-user/edu-user-server/src/main/java/com/keao/edu/user/controller/ExamRegistrationController.java
  33. 4 0
      edu-user/edu-user-server/src/main/java/com/keao/edu/user/controller/TaskController.java

+ 0 - 7
edu-im/edu-im-server/src/main/java/com/keao/edu/im/controller/RoomController.java

@@ -61,13 +61,6 @@ public class RoomController{
         return new BaseResponse<>(result);
     }
 
-    @RequestMapping(value = "/joinFailure", method = RequestMethod.POST)
-    public Object joinFailure(String roomId,String userId)
-            throws Exception {
-        roomService.joinFailure(roomId,userId);
-        return new BaseResponse<>();
-    }
-
     @RequestMapping(value = "/statusSync")
     public Object statusSync(@RequestBody String body) throws Exception {
         ChannelStateNotify notify = JSONObject.parseObject(body, ChannelStateNotify.class);

+ 1 - 9
edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/RoomDao.java

@@ -14,25 +14,17 @@ import java.util.List;
  */
 @Repository
 public interface RoomDao extends JpaRepository<Room, Long> {
-    public List<Room> findByRid(String rid);
+    public Room findByRid(String rid);
 
-    @Transactional
     @Modifying
     public int deleteByRid(String rid);
 
     public boolean existsByRid(String rid);
 
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_room set display=?2 where rid=?1", nativeQuery = true)
     public int updateDisplayByRid(String rid, String display);
 
-    @Transactional
-    @Modifying
-    @Query(value = "update rongyun_room set play_midi_json=?2 where rid=?1", nativeQuery = true)
-    public int updatePlayMidiByRid(String rid, String playMidi);
-
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_room set whiteboard_name_index=?2 where rid=?1", nativeQuery = true)
     public int updateWhiteboardNameIndexByRid(String rid, int whiteboardNameIndex);

+ 16 - 28
edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/RoomMemberDao.java

@@ -6,7 +6,6 @@ import org.springframework.data.jpa.repository.Lock;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.data.jpa.repository.Query;
 import org.springframework.stereotype.Repository;
-import org.springframework.transaction.annotation.Transactional;
 
 import javax.persistence.LockModeType;
 import java.util.List;
@@ -16,58 +15,47 @@ import java.util.List;
  */
 @Repository
 public interface RoomMemberDao extends JpaRepository<RoomMember, Long> {
-    public List<RoomMember> findByRid(String rid);
+    List<RoomMember> findByRid(String rid);
 
-    public RoomMember findByRidAndUid(String rid, String uid);
+    List<RoomMember> findByRidAndMsidFlag(String rid,boolean msidFlag);
 
-    public List<RoomMember> findByRidAndRole(String rid, int role);
+    @Lock(LockModeType.PESSIMISTIC_WRITE)
+    RoomMember findByRidAndUid(String rid, String uid);
 
-    public List<RoomMember> findByUid(String uid);
+    List<RoomMember> findByRidAndRole(String rid, int role);
 
-    public int countByRidAndRole(String rid, int role);
+    List<RoomMember> findByUid(String uid);
 
     @Modifying
-    @Transactional
-    public int deleteByRid(String roomId);
+    int deleteByRid(String roomId);
 
     @Query(value = "select count(*) from rongyun_room_member where rid=?1", nativeQuery = true)
-    public int countByRid(String roomId);
+    int countByRid(String roomId);
 
-    @Query(value = "select count(*) from rongyun_room_member where rid=?1 and role!=?2", nativeQuery = true)
-    public int countByRidAndExcludeRole(String roomId, int excludeRole);
-
-    @Transactional
     @Modifying
     @Query(value = "delete from rongyun_room_member where rid=?1 and uid=?2", nativeQuery = true)
-    public int deleteUserByRidAndUid(String rid, String uid);
+    int deleteUserByRidAndUid(String rid, String uid);
 
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_room_member set role=?3 where rid=?1 and uid=?2", nativeQuery = true)
-    public int updateRoleByRidAndUid(String rid, String uid, int role);
+    int updateRoleByRidAndUid(String rid, String uid, int role);
 
-    @Transactional
     @Modifying
-    @Query(value = "update rongyun_room_member set role=?3 where rid=?1 and role=?2", nativeQuery = true)
-    public int updateRoleByRidAndRole(String rid, int role);
+    @Query(value = "update rongyun_room_member set msid_flag=?3 where rid=?1 and uid=?2", nativeQuery = true)
+    int updateMsidFlagByRidAndUid(String rid, String uid,int msidFlag);
 
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_room_member set camera=?3 where rid=?1 and uid=?2", nativeQuery = true)
-    public int updateCameraByRidAndUid(String rid, String uid, boolean camera);
+    int updateCameraByRidAndUid(String rid, String uid, boolean camera);
 
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_room_member set mic=?3 where rid=?1 and uid=?2", nativeQuery = true)
-    public int updateMicByRidAndUid(String rid, String uid, boolean mic);
+    int updateMicByRidAndUid(String rid, String uid, boolean mic);
 
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_room_member set music_mode=?3 where rid=?1 and uid=?2", nativeQuery = true)
-    public int updateMusicByRidAndUid(String rid, String uid, boolean musicMode);
-
-    public boolean existsByRidAndUid(String rid, String uid);
+    int updateMusicByRidAndUid(String rid, String uid, boolean musicMode);
 
-    public boolean existsByRidAndRole(String rid, int role);
+    boolean existsByRidAndUid(String rid, String uid);
 
 }

+ 3 - 5
edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/UserDao.java

@@ -2,23 +2,21 @@ package com.keao.edu.im.dao;
 
 import com.keao.edu.im.pojo.UserInfo;
 import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Lock;
 import org.springframework.data.jpa.repository.Modifying;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.util.List;
+import javax.persistence.LockModeType;
 
 /**
  * Created by weiqinxiao on 2019/2/25.
  */
 @Repository
 public interface UserDao extends JpaRepository<UserInfo, Long> {
-    //will query with "select * from TABLE where user_id = 'userId'"
-    public List<UserInfo> findByUid(String uid);
 
-    public List<UserInfo> findByName(String name);
+    UserInfo findByUid(String uid);
 
-    @Transactional
     @Modifying
     public int deleteByUid(String uid);
 }

+ 0 - 3
edu-im/edu-im-server/src/main/java/com/keao/edu/im/dao/WhiteboardDao.java

@@ -20,16 +20,13 @@ public interface WhiteboardDao extends JpaRepository<Whiteboard, Long> {
 
     public int deleteByRid(String rid);
 
-    @Transactional
     @Modifying
     public int deleteByWbid(String wbid);
 
-    @Transactional
     @Modifying
     @Query(value = "delete from rongyun_whiteboard where rid=?1 and creator=?2", nativeQuery = true)
     public int deleteByRidAndCreator(String rid, String creator);
 
-    @Transactional
     @Modifying
     @Query(value = "update rongyun_whiteboard set cur_pg=?3 where wbid=?2 and rid=?1", nativeQuery = true)
     public int updatePageByRidAndWbid(String rid, String wbid, int page);

+ 85 - 52
edu-im/edu-im-server/src/main/java/com/keao/edu/im/mec/im/IMHelper.java

@@ -5,6 +5,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.keao.edu.common.exception.BizException;
 import com.keao.edu.im.api.entity.BaseMessage;
+import com.keao.edu.im.dao.RoomMemberDao;
 import com.keao.edu.im.http.HttpHelper;
 import com.keao.edu.im.pojo.IMApiResultInfo;
 import com.keao.edu.im.pojo.IMTokenInfo;
@@ -30,6 +31,8 @@ public class IMHelper {
 
     @Autowired
     HttpHelper httpHelper;
+    @Autowired
+    RoomMemberDao roomMemberDao;
 
     @Autowired
     private RedisTemplate<String,String> redisTemplate;
@@ -232,26 +235,16 @@ public class IMHelper {
      * 开始录制
      * @param roomId
      * @param registrationId
-     * @param roomMembers
      * @return
      * @throws Exception
      */
-    public void startRecord(String roomId, Long registrationId, List<RoomMember> roomMembers) throws Exception {
+    public void startRecord(String roomId, Long registrationId) throws Exception {
         if (roomId == null) {
             throw new IllegalArgumentException("Paramer 'roomId' is required");
         }
-        if (roomMembers == null || roomMembers.size() == 0) {
-            throw new IllegalArgumentException("Paramer 'roomMembers' is can not be null");
-        }
-        JSONObject paramJson = new JSONObject();
 
-        String sessionId = redisTemplate.opsForValue().get("sessionId:" + roomId);
-        if(StringUtils.isEmpty(sessionId)){
-            sessionId = roomQuery(roomId);
-            redisTemplate.opsForValue().set("sessionId:" + roomId,sessionId);
-        }
-        paramJson.put("sessionId",sessionId);
-//        paramJson.put("sessionId",roomQuery(roomId));
+        JSONObject paramJson = new JSONObject();
+        paramJson.put("sessionId",roomQuery(roomId));
 
         JSONObject config = new JSONObject();
         config.put("mode",3);
@@ -263,33 +256,48 @@ public class IMHelper {
         config.put("renderMode",1);
         config.put("hostUserId","");
         config.put("hostStreamId","");
+        againRecord(paramJson,registrationId,roomId,config);
+    }
 
+    @Async
+    public void againRecord(JSONObject paramJson,Long registrationId,String roomId,JSONObject config) throws Exception {
+        List<RoomMember> roomMembers = roomMemberDao.findByRidAndMsidFlag(roomId,true);
+        if (roomMembers == null || roomMembers.size() == 0) {
+            throw new IllegalArgumentException("Paramer 'roomMembers' is can not be null");
+        }
         config.put("input",getInput(roomMembers));
         paramJson.put("config",config);
         String body = paramJson.toJSONString();
-        againRecord(body,registrationId,roomId);
-    }
-
-    @Async
-    public void againRecord(String body,Long registrationId,String roomId) throws Exception {
         HttpURLConnection conn = httpHelper.createIMRtcPostHttpConnection("/rtc/record/start.json", "application/json",roomId);
         httpHelper.setBodyParameter(body, conn);
         IMApiResultInfo resultInfo = JSON.parseObject(httpHelper.returnResult(conn, body), IMApiResultInfo.class);
         if(resultInfo.getResultCode() == 10000){
             redisTemplate.opsForValue().set(resultInfo.getRecordId(),registrationId.toString());
-        }else {
+        }else if(resultInfo.getResultCode() == 47032 || resultInfo.getResultCode() == 47002){
             log.error("直播视频录制失败:body : {},resultInfo : {} 准备重试",body,resultInfo);
             int i = 1;
             while (i<=3){
-                Thread.sleep(5000l);
+                redisTemplate.delete("sessionId:" + roomId);
+                Thread.sleep(3000l);
+                List<RoomMember> members = roomMemberDao.findByRidAndMsidFlag(roomId,true);
+                if (members == null || members.size() == 0) {
+                    throw new IllegalArgumentException("Paramer 'roomMembers' is can not be null");
+                }
+                if(i == 3){
+                    config.put("input",getSignInput(roomMembers));
+                }else {
+                    config.put("input",getInput(roomMembers));
+                }
+                paramJson.put("config",config);
+                body = paramJson.toJSONString();
+                log.error("直播视频录制第{}次重试:body : {}",i,body);
                 HttpURLConnection connection = httpHelper.createIMRtcPostHttpConnection("/rtc/record/start.json", "application/json", roomId);
                 httpHelper.setBodyParameter(body, connection);
                 IMApiResultInfo imApiResultInfo = JSON.parseObject(httpHelper.returnResult(connection, body), IMApiResultInfo.class);
-                log.error("直播视频录制失败:resultInfo : {} 第{}次重试",imApiResultInfo,i);
                 i++;
                 if(imApiResultInfo.getResultCode() == 10000){
                     redisTemplate.opsForValue().set(imApiResultInfo.getRecordId(),registrationId.toString());
-                    log.info("直播视频录制成功:第{}次重试",i);
+                    log.info("直播视频录制第{}次重试成功",i);
                     return;
                 }
                 if(i > 3){
@@ -303,32 +311,27 @@ public class IMHelper {
     /**
      * 更改录制布局
      * @param roomId
-     * @param roomMembers
      * @return
      * @throws Exception
      */
     @Async
-    public IMApiResultInfo configRecord(String roomId, List<RoomMember> roomMembers) throws Exception {
+    public IMApiResultInfo configRecord(String roomId) throws Exception {
         if (roomId == null) {
             throw new IllegalArgumentException("Paramer 'roomId' is required");
         }
-        if (roomMembers == null || roomMembers.size() == 0) {
+        List<RoomMember> members = roomMemberDao.findByRidAndMsidFlag(roomId,true);
+        if (members == null || members.size() == 0) {
             throw new IllegalArgumentException("Paramer 'roomMembers' is can not be null");
         }
         JSONObject paramJson = new JSONObject();
-        String sessionId = redisTemplate.opsForValue().get("sessionId:" + roomId);
-        if(StringUtils.isEmpty(sessionId)){
-            sessionId = roomQuery(roomId);
-            redisTemplate.opsForValue().set("sessionId:" + roomId,sessionId);
-        }
-        paramJson.put("sessionId",sessionId);
-//        paramJson.put("sessionId",roomQuery(roomId));
+        paramJson.put("sessionId",roomQuery(roomId));
+
         paramJson.put("mixLayout",1);
         paramJson.put("renderMode",1);
         paramJson.put("hostUserId","");
         paramJson.put("hostStreamId","");
 
-        paramJson.put("input",getInput(roomMembers));
+        paramJson.put("input",getInput(members));
         String body = paramJson.toJSONString();
 
         HttpURLConnection conn = httpHelper.createIMRtcPostHttpConnection("/rtc/record/config.json", "application/json",roomId);
@@ -338,6 +341,7 @@ public class IMHelper {
     }
 
     private JSONObject getInput(List<RoomMember> roomMembers){
+
         JSONArray videos = new JSONArray();
         boolean isMaster = true;
 
@@ -379,30 +383,48 @@ public class IMHelper {
         return input;
     }
 
+    private JSONObject getSignInput(List<RoomMember> roomMembers){
+
+        JSONArray videos = new JSONArray();
+        int size = roomMembers.size();
+        for (int i = 0; i < size; i++) {
+            RoomMember roomMember = roomMembers.get(i);
+            JSONObject video = new JSONObject();
+            video.put("userId",roomMember.getUid());
+            video.put("streamId",roomMember.getUid() + "_RongCloudRTC");
+            if(roomMember.getRole() == 3 || i == size - 1){
+                video.put("x",0);
+                video.put("y",0);
+                video.put("width",1);
+                video.put("height",1);
+                videos.add(video);
+                break;
+            }
+        }
+        JSONObject input = new JSONObject();
+        input.put("video",videos);
+        return input;
+    }
+
     /**
      * 结束录制
      * @param roomId
      * @return
      * @throws Exception
      */
+    @Async
     public IMApiResultInfo stopRecord(String roomId) throws Exception {
         if (roomId == null) {
             throw new IllegalArgumentException("Paramer 'roomId' is required");
         }
         JSONObject paramJson = new JSONObject();
-        String sessionId = redisTemplate.opsForValue().get("sessionId:" + roomId);
-        if(StringUtils.isEmpty(sessionId)){
-            sessionId = roomQuery(roomId);
-            redisTemplate.opsForValue().set("sessionId:" + roomId,sessionId);
-        }
-        paramJson.put("sessionId",sessionId);
-//        paramJson.put("sessionId",roomQuery(roomId));
+        paramJson.put("sessionId",roomQuery(roomId));
 
         String body = paramJson.toJSONString();
 
         HttpURLConnection conn = httpHelper.createIMRtcPostHttpConnection("/rtc/record/stop.json", "application/json",roomId);
         httpHelper.setBodyParameter(body, conn);
-
+        redisTemplate.delete("sessionId:" + roomId);
         return JSON.parseObject(httpHelper.returnResult(conn, body), IMApiResultInfo.class);
     }
 
@@ -412,24 +434,35 @@ public class IMHelper {
      * @return
      * @throws Exception
      */
-    public String roomQuery(String roomId) throws Exception {
+    public String roomQuery(String roomId){
         if (StringUtils.isEmpty(roomId)) {
             throw new IllegalArgumentException("Paramer 'roomId' is required");
         }
+        String sessionId = redisTemplate.opsForValue().get("sessionId:" + roomId);
+        if(StringUtils.isNotEmpty(sessionId)){
+            return sessionId;
+        }
         JSONObject jsonObject = new JSONObject();
         jsonObject.put("roomId",roomId);
 
-        HttpURLConnection conn = httpHelper.createIMRtcPostHttpConnection("/rtc/room/query.json", "application/json",null);
-        httpHelper.setBodyParameter(jsonObject.toJSONString(), conn);
-        String returnResult = httpHelper.returnResult(conn, jsonObject.toJSONString());
-        JSONObject resultObject = JSONObject.parseObject(returnResult);
-        String code = resultObject.get("code").toString();
-        if("200".equals(code)){
-            return resultObject.get("sessionId").toString();
-        }else {
-            log.error("获取sessionId失败 returnResult:{}",returnResult);
-            throw new BizException("获取sessionId失败");
+        HttpURLConnection conn = null;
+        try {
+            conn = httpHelper.createIMRtcPostHttpConnection("/rtc/room/query.json", "application/json",null);
+            httpHelper.setBodyParameter(jsonObject.toJSONString(), conn);
+            String returnResult = httpHelper.returnResult(conn, jsonObject.toJSONString());
+            JSONObject resultObject = JSONObject.parseObject(returnResult);
+            String code = resultObject.get("code").toString();
+            if("200".equals(code)){
+                sessionId = resultObject.get("sessionId").toString();
+                redisTemplate.opsForValue().set("sessionId:" + roomId,sessionId);
+            }else {
+                log.error("获取sessionId失败 returnResult:{}",returnResult);
+                throw new BizException("获取sessionId失败");
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
         }
+        return sessionId;
     }
 
 

+ 1 - 0
edu-im/edu-im-server/src/main/java/com/keao/edu/im/pojo/RoomMember.java

@@ -27,6 +27,7 @@ public class RoomMember {
     private @Getter @Setter boolean musicMode = true;
     private @Getter @Setter boolean mic = true;
     private @Getter @Setter boolean hand = false;
+    private @Getter @Setter boolean msidFlag = false;
 
     public RoomMember() {
     }

+ 54 - 0
edu-im/edu-im-server/src/main/java/com/keao/edu/im/pojo/UrisDto.java

@@ -0,0 +1,54 @@
+package com.keao.edu.im.pojo;
+
+public class UrisDto {
+
+	private Integer mediaType;
+
+	private String msid;
+
+	private String uri;
+
+	private String tag;
+
+	private Integer state;
+
+	public Integer getMediaType() {
+		return mediaType;
+	}
+
+	public void setMediaType(Integer mediaType) {
+		this.mediaType = mediaType;
+	}
+
+	public String getMsid() {
+		return msid;
+	}
+
+	public void setMsid(String msid) {
+		this.msid = msid;
+	}
+
+	public String getUri() {
+		return uri;
+	}
+
+	public void setUri(String uri) {
+		this.uri = uri;
+	}
+
+	public String getTag() {
+		return tag;
+	}
+
+	public void setTag(String tag) {
+		this.tag = tag;
+	}
+
+	public Integer getState() {
+		return state;
+	}
+
+	public void setState(Integer state) {
+		this.state = state;
+	}
+}

+ 149 - 158
edu-im/edu-im-server/src/main/java/com/keao/edu/im/service/Impl/RoomServiceImpl.java

@@ -1,5 +1,6 @@
 package com.keao.edu.im.service.Impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.keao.edu.auth.api.client.SysUserFeignService;
 import com.keao.edu.auth.api.entity.SysUser;
 import com.keao.edu.common.exception.BizException;
@@ -32,6 +33,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Isolation;
 import org.springframework.transaction.annotation.Transactional;
@@ -75,7 +77,27 @@ public class RoomServiceImpl implements RoomService {
         return baseResponse;
     }
 
-    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
+    public void exitRoom(String roomId,String userId){
+        List<RoomMember> byRidAndRole = roomMemberDao.findByRidAndRole(roomId, 3);
+        if(byRidAndRole != null && byRidAndRole.size() > 0){
+            log.info("学员加入时,将其他学员退出房间 byRidAndRole{}",byRidAndRole);
+            for (RoomMember e: byRidAndRole) {
+                if(e.getUid().equals(userId)){
+                    continue;
+                }
+                roomMemberDao.deleteUserByRidAndUid(roomId, e.getUid());
+                MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Action_Leave, userId, 3);
+                msg.setUserName(e.getName());
+                userDao.deleteByUid(userId);
+                try {
+                    imHelper.publishMessage(userId, roomId, msg);
+                } catch (Exception e1) {
+                    e1.printStackTrace();
+                }
+            }
+        }
+    }
+
     public void joinRoomSuccess(Long registrationId,String roomId,String userId) throws Exception {
         StudentExamResultApiDto examResult = null;
         log.info("joinRoomSuccess: roomId={}, isAudience={}, isDisableCamera={},isMusicMode={}", roomId);
@@ -85,21 +107,6 @@ public class RoomServiceImpl implements RoomService {
         if(registrationId != null){
             examResult = eduUserFeignService.getExamResult(registrationId);
             roomId = examResult.getRoomId();
-            List<RoomMember> byRidAndRole = roomMemberDao.findByRidAndRole(roomId, 3);
-            if(byRidAndRole != null && byRidAndRole.size() > 0){
-                log.info("学员加入时,将其他学员退出房间 byRidAndRole{}",byRidAndRole);
-                for (RoomMember e: byRidAndRole) {
-                    if(e.getUid().equals(userId)){
-                        continue;
-                    }
-                    roomMemberDao.deleteUserByRidAndUid(roomId, e.getUid());
-                    MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Action_Leave, userId, 3);
-                    msg.setUserName(e.getName());
-                    userDao.deleteByUid(userId);
-                    imHelper.publishMessage(userId, roomId, msg);
-//                    leaveRoom(e.getExamRegistrationId(),roomId,userId);
-                }
-            }
         }
 
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
@@ -113,8 +120,8 @@ public class RoomServiceImpl implements RoomService {
             }
         }
         Date curTime = DateTimeUtils.currentUTC();
-        List<Room> roomList = roomDao.findByRid(roomId);
-        if (roomList.isEmpty()) {
+        Room room = roomDao.findByRid(roomId);
+        if (room == null) {
             saveRoom(roomId, roomId, curTime, null);
         }
         RoleEnum roleEnum;
@@ -138,20 +145,18 @@ public class RoomServiceImpl implements RoomService {
         msg.setCamera(true);
         imHelper.publishMessage(userId, roomId, msg);
 
-        List<UserInfo> userInfoList = userDao.findByUid(userId);
-        if (userInfoList.isEmpty()) {
-            UserInfo userInfo = new UserInfo();
+        UserInfo userInfo = userDao.findByUid(userId);
+        if (userInfo == null) {
+            userInfo = new UserInfo();
             userInfo.setUid(userId);
             userInfo.setName(realName);
             userInfo.setCreateDt(curTime);
             userInfo.setUpdateDt(curTime);
             userDao.save(userInfo);
         } else {
-            UserInfo user = userInfoList.get(0);
-            user.setUpdateDt(curTime);
-            userDao.save(user);
+            userInfo.setUpdateDt(curTime);
+            userDao.save(userInfo);
         }
-        List<RoomMember> roomMembers = roomMemberDao.findByRid(roomId);
         log.info("join success: roomId = {}, userId = {}, userName={}, role = {}", roomId, userId, roleEnum);
         if(registrationId != null){
             if(examResult.getIsFinishedExam() == 1){
@@ -159,10 +164,11 @@ public class RoomServiceImpl implements RoomService {
             }
             this.publishMessage(eduUserFeignService.getPublishMessage(registrationId));
             eduUserFeignService.upsetStudentAttendance(registrationId,0);
-            imHelper.startRecord(roomId, registrationId,roomMembers);
+            imHelper.startRecord(roomId, registrationId);
+//            exitRoom(roomId,userId);
         }else {
             eduUserFeignService.upsetTeacherAttendance(examRoom.getId(),sysUser.getId(),0);
-            imHelper.configRecord(roomId,roomMembers);
+            imHelper.configRecord(roomId);
         }
     }
 
@@ -192,8 +198,8 @@ public class RoomServiceImpl implements RoomService {
             }
         }
         Date curTime = DateTimeUtils.currentUTC();
-        List<Room> roomList = roomDao.findByRid(roomId);
-        if (roomList.isEmpty()) {
+        Room room = roomDao.findByRid(roomId);
+        if (room == null) {
             saveRoom(roomId, roomId, curTime, null);
         }
         RoleEnum roleEnum;
@@ -281,10 +287,12 @@ public class RoomServiceImpl implements RoomService {
         roomMember.setJoinDt(joinTime);
         roomMember.setHeadUrl(headUrl);
         roomMember.setExamRegistrationId(examRegistrationId);
+        if(examRegistrationId != null){
+            roomMember.setMsidFlag(true);
+        }
         roomMemberDao.save(roomMember);
     }
 
-    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
     public void leaveRoomSuccess(Long registrationId,String roomId,String userId) throws Exception {
         if(registrationId != null){
             StudentExamResultApiDto examResult = eduUserFeignService.getExamResult(registrationId);
@@ -297,8 +305,8 @@ public class RoomServiceImpl implements RoomService {
         CheckUtils.checkArgument(userId != null, "userId must't be null");
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
 
-        List<Room> roomList = roomDao.findByRid(roomId);
-        if (roomList.size() == 0) {
+        Room room = roomDao.findByRid(roomId);
+        if (room == null) {
             log.error("room : {} not exist ", roomId);
             return;
         }
@@ -326,7 +334,7 @@ public class RoomServiceImpl implements RoomService {
             imHelper.stopRecord(roomId);
         }else {
             eduUserFeignService.upsetTeacherAttendance(Long.parseLong(roomId),Integer.parseInt(userId),1);
-            imHelper.configRecord(roomId,roomMemberDao.findByRid(roomId));
+            imHelper.configRecord(roomId);
         }
     }
 
@@ -353,11 +361,6 @@ public class RoomServiceImpl implements RoomService {
         imHelper.dismiss(userId,groupId);
     }
 
-    @Override
-    public void joinFailure(String roomId, String userId) {
-        roomMemberDao.deleteUserByRidAndUid(roomId, userId);
-    }
-
     private void deleteWhiteboardByUser(String roomId, String userId) throws Exception {
         List<Whiteboard> whiteboardList = whiteboardDao.findByRidAndCreator(roomId, userId);
         if (!whiteboardList.isEmpty()) {
@@ -373,8 +376,8 @@ public class RoomServiceImpl implements RoomService {
     public void destroyRoom(String roomId) {
         roomDao.deleteByRid(roomId);
         whiteboardDao.deleteByRid(roomId);
-        List<Room> roomList = roomDao.findByRid(roomId);
-        if (roomList.isEmpty()) {
+        Room room = roomDao.findByRid(roomId);
+        if (room == null) {
             List<RoomMember> list = roomMemberDao.findByRid(roomId);
             if (!list.isEmpty()) {
                 try {
@@ -389,15 +392,15 @@ public class RoomServiceImpl implements RoomService {
         }
     }
 
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     @Override
-    public Boolean downgrade(String roomId, List<ReqChangeUserRoleData.ChangedUser> users) throws ApiException, Exception {
+    public Boolean downgrade(String roomId, List<ReqChangeUserRoleData.ChangedUser> users) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(users.size() > 0, "the changed user list must't be null");
         SysUser authUser = sysUserFeignService.queryUserInfo();
         String userId = authUser.getId().toString();
-        List<Room> roomList = roomDao.findByRid(roomId);
-        if (roomList.isEmpty()) {
+        Room room = roomDao.findByRid(roomId);
+        if (room == null) {
             throw new ApiException(ErrorEnum.ERR_ROOM_NOT_EXIST);
         }
 
@@ -412,21 +415,10 @@ public class RoomServiceImpl implements RoomService {
             } else {
                 RoomMember roomMember = roomMemberDao.findByRidAndUid(roomId, changedUserId);
                 if (roomMember != null) {
-                    /*if (changedRole.equals(RoleEnum.RoleAudience)) {
-                        int r = roomMemberDao.updateRoleByRidAndUid(roomId, changedUserId, changedRole.getValue());
-                        RoleChangedMessage.ChangedUser u = new RoleChangedMessage.ChangedUser(changedUserId, changedRole.getValue());
-                        List<UserInfo> userInfoList = userDao.findByUid(changedUserId);
-                        if (!userInfoList.isEmpty()) {
-                            u.setUserName(userInfoList.get(0).getName());
-                        }
-                        changedUsers.add(u);
-                        log.info("change the role: {}, {}, {}, result: {}", roomId, userId, changedRole, r);
-                        result = true;
-                    }*/
-                    if (roomMember.getRole() != Student.getValue() && isUserDisplay(roomList.get(0), roomMember.getUid())) {
+                    if (roomMember.getRole() != Student.getValue() && isUserDisplay(room, roomMember.getUid())) {
                         updateDisplay(roomId, userId, "", 1);
                     } else {
-                        log.info("don't update display: room={}, userRole={}", roomList.get(0), RoleEnum.getEnumByValue(roomMember.getRole()));
+                        log.info("don't update display: room={}, userRole={}", room, RoleEnum.getEnumByValue(roomMember.getRole()));
                     }
                 } else {
                     log.info("role changed fail, not exist: {} - {} - {}", roomId, userId, changedRole);
@@ -442,7 +434,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
+    @Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
     public void destroyRoom(Long roomId,String userId) throws Exception {
 
         CheckUtils.checkArgument(roomId != null, "destroyRoom roomId must't be null");
@@ -450,9 +442,9 @@ public class RoomServiceImpl implements RoomService {
         if(roomMembers != null && roomMembers.size() > 0){
             roomMembers.forEach(e->{
                 MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Action_Kick, e.getUid(), e.getRole());
-                List<UserInfo> userInfoList = userDao.findByUid(e.getUid());
-                if (!userInfoList.isEmpty()) {
-                    msg.setUserName(userInfoList.get(0).getName());
+                UserInfo userInfo = userDao.findByUid(e.getUid());
+                if (userInfo != null) {
+                    msg.setUserName(userInfo.getName());
                 }
                 try {
                     imHelper.publishMessage(userId, e.getRid(), msg, 1);
@@ -479,8 +471,8 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Boolean kickMember(ReqUserData data) throws ApiException, Exception {
+    @Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
+    public Boolean kickMember(ReqUserData data) throws Exception {
         StudentExamResultApiDto examResult = eduUserFeignService.getExamResult(data.getRegistrationId());
         String roomId = examResult.getRoomId();
 
@@ -496,33 +488,19 @@ public class RoomServiceImpl implements RoomService {
             throw new ApiException(ErrorEnum.ERR_USER_NOT_EXIST_IN_ROOM);
         } else {
             MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Action_Kick, data.getUserId(), roomMember.getRole());
-            List<UserInfo> userInfoList = userDao.findByUid(data.getUserId());
-            if (!userInfoList.isEmpty()) {
-                msg.setUserName(userInfoList.get(0).getName());
-            }/*
-            if("recorded".equals(data.getType())){
-                msg.setRoomId("recorded" + roomId);
-            }*/
-            imHelper.stopRecord(roomId);
+            UserInfo userInfo = userDao.findByUid(data.getUserId());
+            if (userInfo != null) {
+                msg.setUserName(userInfo.getName());
+            }
             IMApiResultInfo apiResultInfo = imHelper.publishMessage(userId, roomId, msg, 1);
             if (!apiResultInfo.isSuccess()) {
                 throw new ApiException(ErrorEnum.ERR_MESSAGE_ERROR);
             }
-//            Thread.sleep(50);
             log.info("published msg: msg={}", msg);
-            /*List<Room> roomList = roomDao.findByRid(roomId);
-            if (kickedUsers.get(0).getRole() != Student.getValue() && isUserDisplay(roomList.get(0), userId)) {
-                updateDisplay(roomId, userId, "", 1);
-            } else {
-                log.info("don't update display: room={}, userRole={}", roomId, RoleEnum.getEnumByValue(kickedUsers.get(0).getRole()));
-            }*/
             eduUserFeignService.upsetStudentAttendance(data.getRegistrationId(),1);
+            imHelper.stopRecord(roomId);
         }
         userDao.deleteByUid(data.getUserId());
-        /*IMApiResultInfo apiResultInfo = imHelper.quit(new String[]{data.getUserId()}, roomId);
-        if (!apiResultInfo.isSuccess()) {
-            throw new ApiException(ErrorEnum.ERR_EXIT_ROOM_ERROR, apiResultInfo.getErrorMessage());
-        }*/
         return true;
     }
 
@@ -603,8 +581,8 @@ public class RoomServiceImpl implements RoomService {
         if (resultInfo.isSuccess()) {
             String wbId = resultInfo.getData();
             Date date = DateTimeUtils.currentUTC();
-            List<Room> roomList = roomDao.findByRid(roomId);
-            int whiteboardNameIndex = roomList.get(0).getWhiteboardNameIndex() + 1;
+            Room room = roomDao.findByRid(roomId);
+            int whiteboardNameIndex = room.getWhiteboardNameIndex() + 1;
             String name = "白板" + whiteboardNameIndex;
             roomDao.updateWhiteboardNameIndexByRid(roomId, whiteboardNameIndex);
             Whiteboard wb = new Whiteboard();
@@ -632,7 +610,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean deleteWhiteboard(String roomId, String whiteBoardId) throws ApiException, Exception {
+    public Boolean deleteWhiteboard(String roomId, String whiteBoardId) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(whiteBoardId != null, "whiteBoardId must't be null");
         SysUser authUser = sysUserFeignService.queryUserInfo();
@@ -641,19 +619,19 @@ public class RoomServiceImpl implements RoomService {
         List<Whiteboard> whiteboardList = whiteboardDao.findByRidAndWbid(roomId, whiteBoardId);
         CheckUtils.checkArgument(whiteboardList.size() > 0, "whiteboard not exist");
 
-        List<Room> roomList = roomDao.findByRid(roomId);
-        CheckUtils.checkArgument(!roomList.isEmpty(), "room not exist");
+        Room room = roomDao.findByRid(roomId);
+        CheckUtils.checkArgument(room != null, "room not exist");
 
-        log.info("deleteWhiteboard: room={}, whiteBoardId={}", roomList.get(0), whiteBoardId);
+        log.info("deleteWhiteboard: room={}, whiteBoardId={}", room, whiteBoardId);
 
-        String display = roomList.get(0).getDisplay();
+        String display = room.getDisplay();
         if (display.contains("uri=" + whiteBoardId)) {
             int result = roomDao.updateDisplayByRid(roomId, "");
             log.info("clear room display, room: {}, result: {}", roomId, result);
             DisplayMessage displayMessage = new DisplayMessage("");
             imHelper.publishMessage(userId, roomId, displayMessage, 1);
         } else {
-            log.info("no display to clean: room={}", roomList.get(0));
+            log.info("no display to clean: room={}", room);
         }
 
         String wbRoom = whiteboardList.get(0).getWbRoom();
@@ -671,7 +649,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public List<RoomResult.WhiteboardResult> getWhiteboard(String roomId) throws ApiException, Exception {
+    public List<RoomResult.WhiteboardResult> getWhiteboard(String roomId){
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
 
@@ -688,13 +666,13 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean turnWhiteBoardPage(String roomId, String whiteBoardId, int page) throws ApiException, Exception {
+    public Boolean turnWhiteBoardPage(String roomId, String whiteBoardId, int page) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(whiteBoardId != null, "whiteBoardId must't be null");
         SysUser authUser = sysUserFeignService.queryUserInfo();
         String userId = authUser.getId().toString();
-        List<Room> roomList = roomDao.findByRid(roomId);
-        CheckUtils.checkArgument(!roomList.isEmpty(), "room not exist");
+        Room room = roomDao.findByRid(roomId);
+        CheckUtils.checkArgument(room != null, "room not exist");
 
         int result = whiteboardDao.updatePageByRidAndWbid(roomId, whiteBoardId, page);
         log.info("turn page to: {}, room: {}, wb : {}; r: {}", page, roomId, whiteBoardId, result);
@@ -705,7 +683,8 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean controlDevice(String roomId, String userId, DeviceTypeEnum typeEnum, boolean enable) throws ApiException, Exception {
+    @Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
+    public Boolean controlDevice(String roomId, String userId, DeviceTypeEnum typeEnum, boolean enable) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(userId != null, "userId must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
@@ -739,9 +718,9 @@ public class RoomServiceImpl implements RoomService {
             }
             DeviceStateChangedMessage deviceResourceMessage = new DeviceStateChangedMessage(typeEnum.ordinal(), false);
             deviceResourceMessage.setUserId(userId);
-            List<UserInfo> userInfoList = userDao.findByUid(userId);
-            if (!userInfoList.isEmpty()) {
-                deviceResourceMessage.setUserName(userInfoList.get(0).getName());
+            UserInfo userInfo = userDao.findByUid(userId);
+            if (userInfo != null) {
+                deviceResourceMessage.setUserName(userInfo.getName());
             }
             imHelper.publishMessage(authUser.getId().toString(), roomId, deviceResourceMessage, 1);
         }
@@ -784,7 +763,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean approveControlDevice(String roomId, String ticket) throws ApiException, Exception {
+    public Boolean approveControlDevice(String roomId, String ticket) throws Exception {
         CheckUtils.checkArgument(ticket != null, "ticket must't be null");
         SysUser authUser = sysUserFeignService.queryUserInfo();
         String userId = authUser.getId().toString();
@@ -808,7 +787,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean rejectControlDevice(String roomId, String ticket) throws ApiException, Exception {
+    public Boolean rejectControlDevice(String roomId, String ticket) throws Exception {
         CheckUtils.checkArgument(ticket != null, "ticket must't be null");
         SysUser authUser = sysUserFeignService.queryUserInfo();
         String userId = authUser.getId().toString();
@@ -824,8 +803,8 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
-    public Boolean syncDeviceState(String roomId, DeviceTypeEnum type, boolean enable) throws ApiException, Exception {
+    @Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
+    public Boolean syncDeviceState(String roomId, DeviceTypeEnum type, boolean enable) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
         SysUser authUser = sysUserFeignService.queryUserInfo();
@@ -850,7 +829,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public List<RoomResult.MemberResult> getMembers(String roomId) throws ApiException, Exception {
+    public List<RoomResult.MemberResult> getMembers(String roomId){
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         List<RoomMember> roomMemberList = roomMemberDao.findByRid(roomId);
         if(roomMemberList != null && roomMemberList.size() > 0){
@@ -897,7 +876,8 @@ public class RoomServiceImpl implements RoomService {
     }*/
 
     @Override
-    public Boolean approveSpeech(String roomId, String ticket) throws ApiException, Exception {
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
+    public Boolean approveSpeech(String roomId, String ticket) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
         SysUser authUser = sysUserFeignService.queryUserInfo();
@@ -914,12 +894,12 @@ public class RoomServiceImpl implements RoomService {
         roomMemberDao.updateRoleByRidAndUid(roomId, taskInfo.getApplyUserId(), Student.getValue());
 
         SpeechResultMessage msg = new SpeechResultMessage(SpeechResultMessage.Action_Approve);
-        List<UserInfo> userInfoList = userDao.findByUid(taskInfo.getApplyUserId());
+        UserInfo userInfo = userDao.findByUid(taskInfo.getApplyUserId());
         msg.setOpUserId(userId);
         msg.setOpUserName(authUser.getRealName());
         msg.setReqUserId(taskInfo.getApplyUserId());
-        if (!userInfoList.isEmpty()) {
-            msg.setReqUserName(userInfoList.get(0).getName());
+        if (userInfo != null) {
+            msg.setReqUserName(userInfo.getName());
         }
         msg.setRole(Student.getValue());
         IMApiResultInfo resultInfo = imHelper.publishMessage(userId, taskInfo.getApplyUserId(), roomId, msg);
@@ -930,8 +910,8 @@ public class RoomServiceImpl implements RoomService {
         RoleChangedMessage rcMsg = new RoleChangedMessage(userId);
         List<RoleChangedMessage.ChangedUser> changedUserList = new ArrayList<>();
         RoleChangedMessage.ChangedUser user = new RoleChangedMessage.ChangedUser(taskInfo.getApplyUserId(), Student.getValue());
-        if (!userInfoList.isEmpty()) {
-            user.setUserName(userInfoList.get(0).getName());
+        if (userInfo != null) {
+            msg.setReqUserName(userInfo.getName());
         }
         changedUserList.add(user);
         rcMsg.setUsers(changedUserList);
@@ -941,7 +921,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean rejectSpeech(String roomId, String ticket) throws ApiException, Exception {
+    public Boolean rejectSpeech(String roomId, String ticket) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
         SysUser authUser = sysUserFeignService.queryUserInfo();
@@ -974,7 +954,7 @@ public class RoomServiceImpl implements RoomService {
     }*/
 
     @Override
-    public Boolean transfer(String roomId, String userId) throws ApiException, Exception {
+    public Boolean transfer(String roomId, String userId) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(userId != null, "userId must't be null");
         CheckUtils.checkArgument(!userId.equals(userId), "can't set self role");
@@ -986,20 +966,19 @@ public class RoomServiceImpl implements RoomService {
             throw new ApiException(ErrorEnum.ERR_USER_NOT_EXIST_IN_ROOM);
         }
 
-        List<Room> roomList = roomDao.findByRid(roomId);
-        if (roomList.size() == 0) {
+        Room room = roomDao.findByRid(roomId);
+        if (room == null) {
             log.error("assistant transfer error: {} toUser = {}, opUser={}", roomId, userId, userId);
             throw new ApiException(ErrorEnum.ERR_ROOM_NOT_EXIST);
         }
 
-        if (isUserDisplay(roomList.get(0), userId) || isUserDisplay(roomList.get(0), userId)) {
+        if (isUserDisplay(room, userId) || isUserDisplay(room, userId)) {
             updateDisplay(roomId, userId, "", 1);
         } else {
-            log.info("don't update display: room={}", roomList.get(0));
+            log.info("don't update display: room={}", room);
         }
 
         roomMemberDao.updateRoleByRidAndUid(roomId, userId, Student.getValue());
-//        roomMemberDao.updateRoleByRidAndUid(roomId, userId, RoleEnum.RoleAssistant.getValue());
 
         AssistantTransferMessage msg = new AssistantTransferMessage();
         msg.setOpUserId(userId);
@@ -1013,7 +992,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean inviteUpgradeRole(String roomId, String targetUserId, int targetRole) throws ApiException, Exception {
+    public Boolean inviteUpgradeRole(String roomId, String targetUserId, int targetRole) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(targetUserId != null, "userId must't be null");
         CheckUtils.checkArgument(roomMemberDao.existsByRidAndUid(roomId, targetUserId), "room member not exist");
@@ -1026,8 +1005,6 @@ public class RoomServiceImpl implements RoomService {
             throw new ApiException(ErrorEnum.ERR_USER_NOT_EXIST_IN_ROOM);
         }
 
-//        checkOverMax(roomId, targetUser.get(0), targetRole);
-
         String ticket = IdentifierUtils.uuid();
 
         UpgradeRoleTaskInfo taskInfo = new UpgradeRoleTaskInfo();
@@ -1052,7 +1029,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean approveUpgradeRole(String roomId, String ticket) throws ApiException, Exception {
+    public Boolean approveUpgradeRole(String roomId, String ticket) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(ticket != null, "ticket must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
@@ -1094,7 +1071,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean rejectUpgradeRole(String roomId, String ticket) throws ApiException, Exception {
+    public Boolean rejectUpgradeRole(String roomId, String ticket) throws Exception {
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(ticket != null, "ticket must't be null");
         CheckUtils.checkArgument(roomDao.existsByRid(roomId), "room not exist");
@@ -1114,7 +1091,8 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    public Boolean changeRole(String roomId, String targetUserId, int targetRole) throws ApiException, Exception {
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
+    public Boolean changeRole(String roomId, String targetUserId, int targetRole) throws Exception {
 
         CheckUtils.checkArgument(roomId != null, "roomId must't be null");
         CheckUtils.checkArgument(targetUserId != null, "userId must't be null");
@@ -1142,9 +1120,9 @@ public class RoomServiceImpl implements RoomService {
         if (!teachers.isEmpty()) {
             roomMemberDao.updateRoleByRidAndUid(roomId, teachers.get(0).getUid(), Student.getValue());
             RoleChangedMessage.ChangedUser user = new RoleChangedMessage.ChangedUser(teachers.get(0).getUid(), Student.getValue());
-            List<UserInfo> userInfoList = userDao.findByUid(teachers.get(0).getUid());
-            if (!userInfoList.isEmpty()) {
-                user.setUserName(userInfoList.get(0).getName());
+            UserInfo userInfo = userDao.findByUid(teachers.get(0).getUid());
+            if (userInfo != null) {
+                user.setUserName(userInfo.getName());
             }
             changedUserList.add(user);
         } else {
@@ -1153,9 +1131,9 @@ public class RoomServiceImpl implements RoomService {
 
         roomMemberDao.updateRoleByRidAndUid(roomId, targetUserId, targetRole);
         RoleChangedMessage.ChangedUser user = new RoleChangedMessage.ChangedUser(targetUserId, targetRole);
-        List<UserInfo> userInfoList = userDao.findByUid(targetUserId);
-        if (!userInfoList.isEmpty()) {
-            user.setUserName(userInfoList.get(0).getName());
+        UserInfo userInfo = userDao.findByUid(targetUserId);
+        if (userInfo != null) {
+            user.setUserName(userInfo.getName());
         }
         changedUserList.add(user);
         msg.setUsers(changedUserList);
@@ -1199,6 +1177,7 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class,isolation = Isolation.SERIALIZABLE)
     public void userIMOfflineKick(String userId) {
         List<RoomMember> members = roomMemberDao.findByUid(userId);
         for (RoomMember member : members) {
@@ -1206,11 +1185,11 @@ public class RoomServiceImpl implements RoomService {
             log.info("userIMOfflineKick: roomId={}, {}, role={}", member.getRid(), userId, RoleEnum.getEnumByValue(userRole));
             try {
                 if (userRole == RoleEnum.MainTeacher.getValue() || userRole == RoleEnum.AssistantTeacher.getValue()) {
-                    List<Room> rooms = roomDao.findByRid(member.getRid());
-                    if (rooms.isEmpty()) {
+                    Room room = roomDao.findByRid(member.getRid());
+                    if (room ==null) {
                         break;
                     }
-                    if (isUserDisplay(rooms.get(0), member.getUid())) {
+                    if (isUserDisplay(room, member.getUid())) {
                         updateDisplay(member.getRid(), member.getUid(), "", 0);
                         log.info("memberOnlineStatus offline: roomId={}, {}", member.getRid(), member.getUid());
                     }
@@ -1220,35 +1199,11 @@ public class RoomServiceImpl implements RoomService {
                     roomDao.deleteByRid(member.getRid());
                     deleteWhiteboardByUser(member.getRid(), member.getUid());
                     log.info("dismiss the room: {},userId: {}", member.getRid(),userId);
-
-                    /*IMApiResultInfo apiResultInfo = null;
-                    apiResultInfo = imHelper.dismiss(member.getUid(), member.getRid());
-                    if (apiResultInfo.getCode() == 200) {
-                        roomMemberDao.deleteUserByRidAndUid(member.getRid(), member.getUid());
-                        roomDao.deleteByRid(member.getRid());
-                        deleteWhiteboardByUser(member.getRid(), member.getUid());
-                        log.info("dismiss the room: {},userId: {}", member.getRid(),userId);
-                    } else {
-                        log.error("{} exit {} room error: {}", member.getUid(), member.getRid(), apiResultInfo.getErrorMessage());
-                    }*/
                 } else {
                     roomMemberDao.deleteUserByRidAndUid(member.getRid(), member.getUid());
                     MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Action_Leave, member.getUid(), userRole);
                     msg.setUserName(member.getName());
                     imHelper.publishMessage(member.getUid(), member.getRid(), msg);
-
-                    /*IMApiResultInfo apiResultInfo = null;
-                    apiResultInfo = imHelper.quit(new String[]{member.getUid()}, member.getRid());
-                    if (apiResultInfo.isSuccess()) {
-                        roomMemberDao.deleteUserByRidAndUid(member.getRid(), member.getUid());
-                        MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Action_Leave, member.getUid(), userRole);
-                        msg.setUserName(member.getName());
-                        imHelper.publishMessage(member.getUid(), member.getRid(), msg);
-                        imHelper.quit(new String[]{member.getUid()}, member.getRid());
-                        log.info("quit group: roomId={},userId: {}", member.getRid(), member.getUid());
-                    } else {
-                        log.error("{} exit {} room error: {}", member.getUid(), member.getRid(), apiResultInfo.getErrorMessage());
-                    }*/
                 }
                 userDao.deleteByUid(member.getUid());
             } catch (Exception e) {
@@ -1258,13 +1213,14 @@ public class RoomServiceImpl implements RoomService {
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)
     public boolean statusSync(ChannelStateNotify notify) throws Exception {
-        log.info("statusSync notify:{}",notify);
         String roomId = notify.getChannelId();
         String userId = notify.getUserId();
+
         RoomMember roomMember = roomMemberDao.findByRidAndUid(roomId, userId);
         log.info("statusSync roomMember:{}",roomMember);
+
         if(roomMember == null){
             return false;
         }
@@ -1273,15 +1229,50 @@ public class RoomServiceImpl implements RoomService {
         }else if(notify.getEvent() == 2){
             //房间创建
         }else if(notify.getEvent() == 3){
-            //房间销毁
+            log.info("房间销毁 roomId: {}, userId: {}",roomId, userId);
+            //房间销毁(删除缓存的sessionId)
+            redisTemplate.delete("sessionId:" + roomId);
         }else if(notify.getEvent() == 11){
             //成员加入
+            log.info("成员加入 roomId: {}, userId: {}",roomId, userId);
+//            roomMemberDao.updateMsidByRidAndUid(roomId,userId,msidFlag);
             joinRoomSuccess(roomMember.getExamRegistrationId(),roomId,userId);
         }else if(notify.getEvent() == 12){
             //成员退出
+            log.info("成员退出 roomId: {}, userId: {}",roomId, userId);
+//            roomMemberDao.updateMsidByRidAndUid(roomId,userId,msidFlag);
             leaveRoomSuccess(roomMember.getExamRegistrationId(),roomId,userId);
         }else if(notify.getEvent() == 20){
+            log.info("资源变动 roomId: {}, userId: {}",roomId, userId);
+            boolean msidFlag = false;
+            Integer state = null;
+            List<Member> members = notify.getMembers();
+            if(members != null && members.size() != 0){
+                Object uris = JSONObject.parseObject(members.get(0).getData().toJSONString()).get("uris");
+                if(uris != null){
+                    List<UrisDto> jsonArray = JSONObject.parseArray(uris.toString(),UrisDto.class);
+                    for (UrisDto urisDto : jsonArray) {
+                        //视频流
+                        if(urisDto.getMediaType() == 1){
+                            state = urisDto.getState();
+                            if(state == 1){
+                                msidFlag = true;
+                            }
+                            break;
+                        }else {
+                            //音频流
+                        }
+                    }
+                }
+            }
+            //同步录制资源
             //资源发生变动
+            if(roomMember.isMsidFlag() != msidFlag){
+                roomMemberDao.updateMsidFlagByRidAndUid(roomId,userId,state);
+                if(roomMember.getExamRegistrationId() == null){
+                    imHelper.configRecord(roomId);
+                }
+            }
         }
         return true;
     }

+ 0 - 12
edu-im/edu-im-server/src/main/java/com/keao/edu/im/service/RoomService.java

@@ -96,16 +96,4 @@ public interface RoomService {
      * @param groupId
      */
     void dismissGroup(String userId, String groupId) throws Exception;
-
-    /**
-     * @describe 老师加入房间失败后,删除数据
-     * @apiNote 时光荏苒,认真工作的时间总是过得很快,而我、享受这一刻!
-     * @author zouxuan
-     * @date 2020/8/19
-     * @time 14:16
-     * @param roomId:
-     * @param userId:
-     * @return boolean
-     */
-    void joinFailure(String roomId, String userId);
 }

+ 25 - 1
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dao/ExamRegistrationDao.java

@@ -19,6 +19,30 @@ public interface ExamRegistrationDao extends BaseDAO<Long, ExamRegistration> {
     int batchUpdate(@Param("regists") List<ExamRegistration> regists);
 
     /**
+     * @describe 更新指定考级项目下所有待审核报名学员的状态
+     * @author Joburgess
+     * @date 2020.08.21
+     * @param examId:
+     * @param status:
+     * @param memo:
+     * @return int
+     */
+    int updateRegistStatusByExam(@Param("examId") Long examId,
+                                 @Param("status") StudentRegistrationStatusEnum status,
+                                 @Param("memo") String memo);
+
+    /**
+     * @describe 统计指定考级项目下指定状态的报名学员数量
+     * @author Joburgess
+     * @date 2020.08.21
+     * @param examId:
+     * @param status:
+     * @return int
+     */
+    int countStudentNumWithStatusAndExam(@Param("examId") Long examId,
+                                         @Param("status") StudentRegistrationStatusEnum status);
+
+    /**
      * @param organIds:
      * @return int
      * @describe 统计无教室学员
@@ -47,7 +71,7 @@ public interface ExamRegistrationDao extends BaseDAO<Long, ExamRegistration> {
      * @author Joburgess
      * @date 2020.06.30
      */
-    int countTotalRegistrationStudentNumWithExam(@Param("organIds") List<Integer> organIds,
+    int countTotalAuditPassRegistrationStudentNumWithExam(@Param("organIds") List<Integer> organIds,
                                                  @Param("examId") Long examId);
 
     /**

+ 11 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dao/ExamReviewDao.java

@@ -55,4 +55,15 @@ public interface ExamReviewDao extends BaseDAO<Long, ExamReview> {
      * @return
      */
     int getCloseFlag(Long examRoomId);
+
+    /** 删除评审
+     * @describe
+     * @apiNote 时光荏苒,认真工作的时间总是过得很快,而我、享受这一刻!
+     * @author zouxuan
+     * @date 2020/8/25
+     * @time 15:53
+     * @param examRegistrationId:
+     * @return void
+     */
+    void delByRegistration(@Param("examRegistrationId") Long examRegistrationId);
 }

+ 11 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dao/StudentExamResultDao.java

@@ -134,4 +134,15 @@ public interface StudentExamResultDao extends BaseDAO<Long, StudentExamResult> {
      * @return java.util.Set<java.lang.Long>
      */
     Set<Long> getIsFinishedExamRegistIds(@Param("examId") Long examId);
+
+    /**
+     * @describe 清除视频
+     * @apiNote 时光荏苒,认真工作的时间总是过得很快,而我、享受这一刻!
+     * @author zouxuan
+     * @date 2020/8/24
+     * @time 18:12
+     * @param examRegistrationId:
+     * @return void
+     */
+    void updateVideoExam(Long examRegistrationId);
 }

+ 11 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dto/ExamCertificationDto.java

@@ -46,6 +46,17 @@ public class ExamCertificationDto{
     @ApiModelProperty(value = "考试内容")
     private String songJson;
 
+    @ApiModelProperty(value = "呼叫时长")
+    private Integer callTime;
+
+    public Integer getCallTime() {
+        return callTime;
+    }
+
+    public void setCallTime(Integer callTime) {
+        this.callTime = callTime;
+    }
+
     public String getBaseExamName() {
         return baseExamName;
     }

+ 11 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/dto/NeedCheckingDetailDto.java

@@ -45,6 +45,9 @@ public class NeedCheckingDetailDto {
     @ApiModelProperty(value = "级别")
     private Integer level;
 
+    @ApiModelProperty(value = "学员大概考试时长")
+    private Integer recordMinutes;
+
     @ApiModelProperty(value = "声部")
     private String subjectName;
 
@@ -57,6 +60,14 @@ public class NeedCheckingDetailDto {
     @ApiModelProperty(value = "机构")
     private String tenantId;
 
+    public Integer getRecordMinutes() {
+        return recordMinutes;
+    }
+
+    public void setRecordMinutes(Integer recordMinutes) {
+        this.recordMinutes = recordMinutes;
+    }
+
     public Date getRecordStartTime() {
         return recordStartTime;
     }

+ 12 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/ExamRegistrationService.java

@@ -1,6 +1,7 @@
 package com.keao.edu.user.service;
 
 
+import com.keao.edu.common.entity.HttpResponseResult;
 import com.keao.edu.common.page.PageInfo;
 import com.keao.edu.common.page.QueryInfo;
 import com.keao.edu.common.service.BaseService;
@@ -38,6 +39,17 @@ public interface ExamRegistrationService extends BaseService<Long, ExamRegistrat
    void updateExamRegistrationStatus(Long registId, StudentRegistrationStatusEnum status, String memo);
 
    /**
+    * @describe 更新考级项目中所有待审核学员状态
+    * @author Joburgess
+    * @date 2020.08.21
+    * @param examId:
+    * @param status:
+    * @param memo:
+    * @return void
+    */
+   HttpResponseResult updateExamAllRegistStatus(Long examId, StudentRegistrationStatusEnum status, String memo);
+
+   /**
     * @describe 更新考级报名信息
     * @author Joburgess
     * @date 2020.07.24

+ 10 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamCertificationServiceImpl.java

@@ -5,6 +5,7 @@ import com.keao.edu.auth.api.client.SysUserFeignService;
 import com.keao.edu.auth.api.entity.SysUser;
 import com.keao.edu.common.dal.BaseDAO;
 import com.keao.edu.common.service.impl.BaseServiceImpl;
+import com.keao.edu.user.api.entity.ExamRoomStudentRelation;
 import com.keao.edu.user.api.entity.Student;
 import com.keao.edu.user.dao.*;
 import com.keao.edu.user.dto.BasicNeedCheckingDetailDto;
@@ -91,6 +92,8 @@ public class ExamCertificationServiceImpl extends BaseServiceImpl<Long, ExamCert
 		if(subject != null){
 			needCheckingDetailDto.setSubjectName(subject.getName());
 		}
+		String songRecordMinutes = sysConfigService.findConfigValue("single_song_record_minutes", needCheckingDetailDto.getTenantId());
+		needCheckingDetailDto.setRecordMinutes(Integer.parseInt(songRecordMinutes));
 		needCheckingDetailDto.setLevel(examRegistration.getLevel());
 		if(needCheckingDetailDto.getFinishedExam() == 4 && needCheckingDetailDto.getRecordStartTime() != null){
 			int recordMinutes = Integer.parseInt(sysConfigService.findConfigValue("record_minutes",needCheckingDetailDto.getTenantId()));
@@ -122,6 +125,13 @@ public class ExamCertificationServiceImpl extends BaseServiceImpl<Long, ExamCert
 		examCertificationDto.setCertificatePhoto(student.getCertificatePhoto());
 		StudentExamResult studentExamResult = studentExamResultDao.findByRegistrationId(examRegistrationId);
 		examCertificationDto.setConfirmStatus(studentExamResult.getConfirmStatus());
+		if(studentExamResult.getIsFinishedExam() == 1){
+			ExamRoomStudentRelation studentExamRoom = examRoomStudentRelationDao.getStudentExamRoom(examRegistrationId);
+			if(studentExamRoom.getCallTime() != null){
+				examCertificationDto.setCallTime(DateUtil.secondsBetween(studentExamRoom.getCallTime(),new Date()));
+				DateUtil.secondsBetween(studentExamRoom.getCallTime(),new Date());
+			}
+		}
 		return examCertificationDto;
 	}
 

+ 1 - 1
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamOrganizationRelationServiceImpl.java

@@ -174,7 +174,7 @@ public class ExamOrganizationRelationServiceImpl extends BaseServiceImpl<Long, E
 	@Transactional(rollbackFor = Exception.class)
 	public void addExamOrganizations(List<ExamOrganizationRelation> organizationRelations, Integer selfOrganId) {
 		if(CollectionUtils.isEmpty(organizationRelations)){
-			throw new BizException("请指定考级项目");
+			throw new BizException("请选择合作单位");
 		}
 		if(Objects.isNull(organizationRelations.get(0).getExaminationBasicId())){
 			throw new BizException("请指定考级项目");

+ 35 - 1
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamRegistrationServiceImpl.java

@@ -3,7 +3,9 @@ package com.keao.edu.user.service.impl;
 
 import com.keao.edu.auth.api.client.SysUserFeignService;
 import com.keao.edu.auth.api.entity.SysUser;
+import com.keao.edu.common.controller.BaseController;
 import com.keao.edu.common.dal.BaseDAO;
+import com.keao.edu.common.entity.HttpResponseResult;
 import com.keao.edu.common.entity.SysConfig;
 import com.keao.edu.common.enums.MessageTypeEnum;
 import com.keao.edu.common.exception.BizException;
@@ -304,7 +306,7 @@ public class ExamRegistrationServiceImpl extends BaseServiceImpl<Long, ExamRegis
             throw new BizException("学员报名信息不存在");
         }
         if (!StudentRegistrationStatusEnum.AUDIT_WAIT.equals(er.getStatus())) {
-            throw new BizException("审核状态错误");
+            throw new BizException("此学员已审核");
         }
         if (!StudentRegistrationStatusEnum.AUDIT_PASS.equals(status)
                 && !StudentRegistrationStatusEnum.AUDIT_REJECT.equals(status)) {
@@ -339,6 +341,31 @@ public class ExamRegistrationServiceImpl extends BaseServiceImpl<Long, ExamRegis
     }
 
     @Override
+    public HttpResponseResult updateExamAllRegistStatus(Long examId, StudentRegistrationStatusEnum status, String memo) {
+        if (Objects.isNull(examId)) {
+            throw new BizException("请指定考级项目");
+        }
+        ExaminationBasic examinationBasic = examinationBasicDao.get(examId);
+        if(Objects.isNull(examinationBasic)){
+            throw new BizException("考级项目不存在");
+        }
+        if(ExamStatusEnum.RESULT_CONFIRM.equals(examinationBasic)){
+            throw new BizException("考级项目结果以确定");
+        }
+        if (!StudentRegistrationStatusEnum.AUDIT_PASS.equals(status)
+                && !StudentRegistrationStatusEnum.AUDIT_REJECT.equals(status)) {
+            throw new BizException("审核状态错误");
+        }
+        int i = examRegistrationDao.updateRegistStatusByExam(examId, status, memo);
+        if(i>0){
+            return BaseController.succeedMsg("审核成功");
+        }else{
+            return BaseController.failed("暂无待审核学员");
+        }
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
     public void updateExamRegistration(ExamRegistration examRegistration) {
         if (Objects.isNull(examRegistration.getId())) {
             throw new BizException("学员报名信息有误");
@@ -347,6 +374,13 @@ public class ExamRegistrationServiceImpl extends BaseServiceImpl<Long, ExamRegis
         if (Objects.isNull(er)) {
             throw new BizException("学员报名信息有误");
         }
+        ExaminationBasic examinationBasic = examinationBasicDao.lockExam(er.getExaminationBasicId());
+        if(Objects.isNull(examinationBasic)){
+            throw new BizException("考级信息错误");
+        }
+        if(ExamStatusEnum.RESULT_CONFIRM.equals(examinationBasic.getStatus())){
+            throw new BizException("本次考级已结束");
+        }
         if (er.getStudentId().equals(examRegistration.getStudentId())) {
             examRegistration.setStatus(StudentRegistrationStatusEnum.AUDIT_WAIT);
         } else {

+ 1 - 1
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamRoomServiceImpl.java

@@ -681,7 +681,7 @@ public class ExamRoomServiceImpl extends BaseServiceImpl<Long, ExamRoom> impleme
 
         List<Integer> childOrganIds = organizationService.getChildOrganIds(organId, true);
 
-		examRoomStatisticsInfo.setTotalRegistrationStudentNum(examRegistrationDao.countTotalRegistrationStudentNumWithExam(childOrganIds, examId));
+		examRoomStatisticsInfo.setTotalRegistrationStudentNum(examRegistrationDao.countTotalAuditPassRegistrationStudentNumWithExam(childOrganIds, examId));
 		examRoomStatisticsInfo.setInRoomStudentNum(examRegistrationDao.countInExamRoomStudentNum(childOrganIds, examId));
 
 		List<ExamRoom> examRooms = examRoomDao.getWithExam(childOrganIds, examId);

+ 7 - 21
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExamRoomStudentRelationServiceImpl.java

@@ -55,14 +55,14 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 	@Autowired
 	private StudentExamResultDao studentExamResultDao;
 	@Autowired
+	private ExamReviewDao examReviewDao;
+	@Autowired
 	private ExamCertificationService examCertificationService;
 	@Autowired
 	private ExamLocationDao examLocationDao;
 	@Autowired
 	private ExamRegistrationDao examRegistrationDao;
 	@Autowired
-	private ExamTeacherSalaryService examTeacherSalaryService;
-	@Autowired
 	private ImFeignService imFeignService;
 	@Autowired
 	private SysUserFeignService sysUserFeignService;
@@ -244,6 +244,7 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 	}
 
 	@Override
+	@Transactional(rollbackFor = Exception.class)
 	public void autoSplitStudentToRoom(Long examId, Integer selfOrganId) {
 		ExaminationBasic examinationBasic = examinationBasicDao.get(examId);
 		if(Objects.isNull(examinationBasic)){
@@ -264,7 +265,7 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 		//未排考学员
 		List<ExamRegistration> notInRoomStudents = examRegistrationDao.getNotInRoomStudents(examId, childOrganIds);
 		if(CollectionUtils.isEmpty(notInRoomStudents)){
-			throw new BizException("所有学员都已安排考场");
+			throw new BizException("暂无可排考学员");
 		}
 		Map<Integer, List<ExamRegistration>> subjectRegistMap = notInRoomStudents.stream().collect(Collectors.groupingBy(ExamRegistration::getSubjectId));
 		Set<Integer> subjectIds = subjectRegistMap.keySet();
@@ -685,6 +686,8 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 			examRoomStudentRelationDao.cleanSignInTime(examRoomStudentRelation.getExamRegistrationId());
 			examRoomStudentRelation.setSignInTime(null);
 			studentExamResultDao.updateFinishedExam(examRoomStudentRelation.getExamRegistrationId(),3);
+			studentExamResultDao.updateVideoExam(examRoomStudentRelation.getExamRegistrationId());
+			examReviewDao.delByRegistration(examRoomStudentRelation.getExamRegistrationId());
 			publishMessage(examRoomStudentRelation,MemberChangedMessage.Not_Finish,true,operator);
 			HashMap<Integer, String> map = new HashMap<>(1);
 			map.put(examRoomStudentRelation.getStudentId(),examRoomStudentRelation.getStudentId().toString());
@@ -705,6 +708,7 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 		ExamRoomStudentRelation examRoomStudentRelation = examRoomStudentRelationDao.get(nextExamRoomStudentRelationId);
 		//开启学员房间入口
 		examRoomStudentRelation.setClassroomSwitch(1);
+		examRoomStudentRelation.setCallTime(new Date());
 		examRoomStudentRelationDao.update(examRoomStudentRelation);
 		HashMap<Integer, String> map = new HashMap<>(1);
 		map.put(examRoomStudentRelation.getStudentId(),examRoomStudentRelation.getStudentId().toString());
@@ -725,16 +729,7 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 		publishMessageDto.setRoomId(examRoomStudentRelation.getExamRoomId().toString());
 		MemberChangedMessage msg = new MemberChangedMessage(action, examRoomStudentRelation.getStudentId().toString(),3);
 
-//		NeedCheckingDetailDto needCheckingDetailDto = examCertificationService.needCheckingDetail(examRoomStudentRelation.getExamRegistrationId());
-//		msg.setWaitNum(needCheckingDetailDto.getWaitNum());
-//		msg.setClassroomSwitch(needCheckingDetailDto.getClassroomSwitch());
-//		msg.setOpenFlag(needCheckingDetailDto.getOpenFlag());
-
 		msg.setAppParamJson(examCertificationService.basicNeedCheckingDetail(examRoomStudentRelation.getExamRoomId()));
-//		Map<String,Object> paramMap = new HashMap<>(2);
-//		paramMap.put("studentQueue",this.queryNeedCheckingList(examRoomStudentRelation.getExamRoomId()));
-//		paramMap.put("examCertification",examCertificationService.findDetailByStudentId(examRoomStudentRelation.getExamRegistrationId()));
-//		msg.setWebParamJson(JSONObject.toJSONString(paramMap));
 		publishMessageDto.setMemberChangedMessage(msg);
 		imFeignService.publishMessage(publishMessageDto);
 	}
@@ -755,15 +750,6 @@ public class ExamRoomStudentRelationServiceImpl extends BaseServiceImpl<Long, Ex
 		MemberChangedMessage msg = new MemberChangedMessage(MemberChangedMessage.Student_Queue, examRoomStudentRelation.getStudentId().toString(),3);
 
 		msg.setAppParamJson(examCertificationService.basicNeedCheckingDetail(examRoomStudentRelation.getExamRoomId()));
-
-//		NeedCheckingDetailDto needCheckingDetailDto = examCertificationService.needCheckingDetail(examRoomStudentRelation.getExamRegistrationId());
-//		msg.setWaitNum(needCheckingDetailDto.getWaitNum());
-//		msg.setClassroomSwitch(needCheckingDetailDto.getClassroomSwitch());
-//		msg.setOpenFlag(needCheckingDetailDto.getOpenFlag());
-//		Map<String,Object> paramMap = new HashMap<>(2);
-//		paramMap.put("studentQueue",this.queryNeedCheckingList(examRoomStudentRelation.getExamRoomId()));
-//		paramMap.put("examCertification",examCertificationService.findDetailByStudentId(examRoomStudentRelation.getExamRegistrationId()));
-//		msg.setWebParamJson(JSONObject.toJSONString(paramMap));
 		publishMessageDto.setMemberChangedMessage(msg);
 		return publishMessageDto;
 	}

+ 9 - 2
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/ExaminationBasicServiceImpl.java

@@ -17,6 +17,7 @@ import com.keao.edu.user.dto.ExamStatisticsDto;
 import com.keao.edu.user.dto.ExaminationBasicDto;
 import com.keao.edu.user.entity.*;
 import com.keao.edu.user.enums.ExamStatusEnum;
+import com.keao.edu.user.enums.StudentRegistrationStatusEnum;
 import com.keao.edu.user.page.ExaminationQueryInfo;
 import com.keao.edu.user.service.*;
 import com.keao.edu.util.collection.MapUtil;
@@ -67,6 +68,8 @@ public class ExaminationBasicServiceImpl extends BaseServiceImpl<Long, Examinati
     @Autowired
     private ExamRegistrationPaymentDao examRegistrationPaymentDao;
     @Autowired
+    private ExamRegistrationDao examRegistrationDao;
+    @Autowired
     private ExamManualLedgerDao examManualLedgerDao;
     @Autowired
     private ExamTeacherSalaryService examTeacherSalaryService;
@@ -206,7 +209,7 @@ public class ExaminationBasicServiceImpl extends BaseServiceImpl<Long, Examinati
     }
 
     @Override
-    @Transactional(rollbackFor = Exception.class)
+    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
     public void updateExamBasicStatus(Long examId, ExamStatusEnum statusEnum, Integer operatorId) {
         if(Objects.isNull(examId)){
             throw new BizException("请指定考级项目");
@@ -224,8 +227,12 @@ public class ExaminationBasicServiceImpl extends BaseServiceImpl<Long, Examinati
         if(ExamStatusEnum.DELETE.equals(statusEnum)){
             examLifecycleLogDao.insert(new ExamLifecycleLog(existsExam.getId().intValue(), "删除考级项目", operatorId));
         }else if(ExamStatusEnum.RESULT_CONFIRM.equals(statusEnum)){
+            int auditWaitStudentNum = examRegistrationDao.countStudentNumWithStatusAndExam(examId, StudentRegistrationStatusEnum.AUDIT_WAIT);
+            if(auditWaitStudentNum>0){
+                throw new BizException("尚有考生未审核");
+            }
             ExamRoomExamTimeDto examRoomExamTime = examRoomDao.getExamRoomExamTime(examId);
-            if(Objects.isNull(examRoomExamTime)){
+            if(Objects.isNull(examRoomExamTime)) {
                 throw new BizException("考试数据异常");
             }
             if(new Date().compareTo(examRoomExamTime.getExamEndTime())<=0){

+ 7 - 0
edu-user/edu-user-biz/src/main/java/com/keao/edu/user/service/impl/StudentServiceImpl.java

@@ -17,6 +17,7 @@ import com.keao.edu.user.page.StudentApplyQueryInfo;
 import com.keao.edu.user.service.OrganizationService;
 import com.keao.edu.user.service.StudentService;
 import com.keao.edu.util.collection.MapUtil;
+import com.keao.edu.util.string.ValueUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -184,8 +185,14 @@ public class StudentServiceImpl extends BaseServiceImpl<Integer, Student> implem
             List<Integer> studentIds = dataList.stream().map(e -> e.getUserId()).collect(Collectors.toList());
             //获取考试次数
             Map<Integer, Integer> examNumMap = MapUtil.convertMybatisMap(studentExamResultDao.countExamNum(studentIds, queryInfo.getTenantId()),Integer.class,Integer.class);
+
             dataList.forEach(e -> {
                 e.setExamNum(examNumMap.get(e.getUserId()));
+                if(organId != null){
+                    if(e.getOrganId() != organId){
+                        e.getSysUser().setPhone(ValueUtil.fuzzyMobile(e.getSysUser().getPhone()));
+                    }
+                }
             });
         }
         if (count == 0) {

+ 18 - 5
edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamRegistrationMapper.xml

@@ -199,7 +199,16 @@
 		</foreach>
 	</update>
 
-	<!-- 根据主键删除一条记录 -->
+    <update id="updateRegistStatusByExam">
+		UPDATE exam_registration
+		SET status_=#{status,typeHandler=com.keao.edu.common.dal.CustomEnumTypeHandler}
+		<if test="memo!=null and memo!=''">
+			,memo_=#{memo}
+		</if>
+		WHERE examination_basic_id_ = #{examId} AND status_='AUDIT_WAIT'
+	</update>
+
+    <!-- 根据主键删除一条记录 -->
 	<delete id="delete" >
 		DELETE FROM exam_registration WHERE id_ = #{id}
 	</delete>
@@ -361,7 +370,7 @@
 		FROM
 			exam_registration er
 		LEFT JOIN exam_room_student_relation ersr ON ersr.exam_registration_id_ = er.id_
-		WHERE 1=1 AND er.status_ IN ('AUDIT_PASS', 'AUDIT_WAIT')
+		WHERE 1=1 AND er.status_ IN ('AUDIT_PASS')
 		<if test="organIds!=null">
 			AND er.organ_id_ IN
 			<foreach collection="organIds" item="organI" separator="," open="(" close=")">
@@ -414,13 +423,13 @@
 			</if>
     </select>
 
-	<select id="countTotalRegistrationStudentNumWithExam" resultType="int">
+	<select id="countTotalAuditPassRegistrationStudentNumWithExam" resultType="int">
 		SELECT
 			COUNT(er.id_)
 		FROM
 		exam_registration er
 		WHERE 1=1
-		AND er.status_ IN ('AUDIT_PASS', 'AUDIT_WAIT')
+		AND er.status_ IN ('AUDIT_PASS')
 		<if test="organIds!=null">
 			AND er.organ_id_ IN
 			<foreach collection="organIds" item="organI" separator="," open="(" close=")">
@@ -644,7 +653,7 @@
 			exam_registration er
 		WHERE
 			examination_basic_id_ = #{examId}
-			AND er.status_ IN ('AUDIT_PASS', 'AUDIT_WAIT')
+			AND er.status_ IN ('AUDIT_PASS')
 			AND NOT EXISTS ( SELECT id_ FROM exam_room_student_relation WHERE examination_basic_id_ = #{examId} AND er.id_ = exam_registration_id_ )
 			<if test="organIds!=null">
 				AND er.organ_id_ IN
@@ -689,4 +698,8 @@
 				</foreach>
 			</if>
 	</select>
+
+	<select id="countStudentNumWithStatusAndExam" resultType="int">
+		SELECT COUNT(id_) FROM exam_registration WHERE examination_basic_id_=#{examId} AND status_=#{status,typeHandler=com.keao.edu.common.dal.CustomEnumTypeHandler}
+	</select>
 </mapper>

+ 4 - 1
edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamReviewMapper.xml

@@ -97,6 +97,9 @@
 			#{registId}
 		</foreach>
 	</delete>
+    <delete id="delByRegistration">
+		DELETE FROM	exam_review WHERE exam_registration_id_ = #{examRegistrationId}
+	</delete>
 
     <!-- 分页查询 -->
 	<select id="queryPage" resultMap="ExamReview" parameterType="map">
@@ -231,7 +234,7 @@
 		LEFT JOIN student_exam_result ser ON ser.exam_registration_id_ = ersr.exam_registration_id_
 		LEFT JOIN exam_review er ON ser.exam_registration_id_ = er.exam_registration_id_ AND er.teacher_id_ = #{teacherId}
 		<include refid="queryExamReviewRecordListSql"/>
-		ORDER BY ser.is_finished_exam_ ASC
+		ORDER BY ser.is_finished_exam_ ASC,ersr.sign_in_time_ desc
 		<include refid="global.limit"/>
 	</select>
 

+ 2 - 2
edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamRoomMapper.xml

@@ -141,8 +141,8 @@
 				<if test="er.openFlag != null">
 					open_flag_ = #{er.openFlag},
 				</if>
-				<if test="examFlag != null">
-					exam_flag_ = #{examFlag},
+				<if test="er.examFlag != null">
+					exam_flag_ = #{er.examFlag},
 				</if>
 				<if test="er.examinationBasicId != null">
 					examination_basic_id_ = #{er.examinationBasicId},

+ 8 - 2
edu-user/edu-user-biz/src/main/resources/config/mybatis/ExamRoomStudentRelationMapper.xml

@@ -16,6 +16,7 @@
 		<result column="sign_in_time_" property="signInTime" />
 		<result column="create_time_" property="createTime" />
 		<result column="update_time_" property="updateTime" />
+		<result column="call_time_" property="callTime" />
 		<result column="tenant_id_" property="tenantId" />
 	</resultMap>
 
@@ -78,6 +79,9 @@
 			<if test="studentId != null">
 				student_id_ = #{studentId},
 			</if>
+			<if test="callTime != null">
+				call_time_ = #{callTime},
+			</if>
 				update_time_ = NOW()
 		</set> WHERE id_ = #{id}
 	</update>
@@ -130,7 +134,7 @@
 
 	<sql id="queryCondition">
 		<where>
-			er.status_ IN ('AUDIT_PASS', 'AUDIT_WAIT')
+			er.status_ IN ('AUDIT_PASS')
 			<if test="organIds!=null">
 				AND er.organ_id_ IN
 				<foreach collection="organIds" item="organI" separator="," open="(" close=")">
@@ -282,8 +286,9 @@
 		FROM
 			exam_room_student_relation ersr
 			LEFT JOIN exam_room er ON ersr.exam_room_id_ = er.id_
-		WHERE DATE_FORMAT(er.exam_start_time_,'%Y-%m-%d') = #{day}
+		WHERE er.exam_plan_push_flag_=1 AND DATE_FORMAT(er.exam_start_time_,'%Y-%m-%d') = #{day}
 	</select>
+
     <select id="getStudentNumMap" resultType="java.util.Map">
 		SELECT ersr.exam_room_id_ 'key',COUNT(DISTINCT ersr.student_id_) 'value'
 		FROM exam_room_student_relation ersr
@@ -293,6 +298,7 @@
 		</foreach>
 		GROUP BY ersr.exam_room_id_
 	</select>
+
 	<select id="countSignInNum" resultType="java.lang.Integer">
 		SELECT COUNT(DISTINCT id_) FROM student_exam_result WHERE is_finished_exam_ = 2 AND exam_room_id_ = #{examRoomId}
 	</select>

+ 7 - 2
edu-user/edu-user-biz/src/main/resources/config/mybatis/StudentExamResultMapper.xml

@@ -132,7 +132,12 @@
 		</foreach>
 	</update>
 
-	<!-- 根据主键删除一条记录 -->
+    <update id="updateVideoExam">
+		UPDATE student_exam_result SET video_url_ = NULL ,update_time_ = NOW()
+		WHERE exam_registration_id_ = #{examRegistrationId}
+	</update>
+
+    <!-- 根据主键删除一条记录 -->
 	<delete id="delete" >
 		DELETE FROM student_exam_result WHERE id_ = #{id} 
 	</delete>
@@ -251,7 +256,7 @@
 			LEFT JOIN student_exam_result ser ON er.id_=exam_registration_id_
 		WHERE
 			er.examination_basic_id_ = #{examId}
-			AND er.status_ IN ('AUDIT_PASS', 'AUDIT_WAIT')
+			AND er.status_ IN ('AUDIT_PASS')
 			<if test="organIds!=null">
 				AND er.organ_id_ IN
 				<foreach collection="organIds" item="organId" separator="," open="(" close=")">

+ 2 - 2
edu-user/edu-user-biz/src/main/resources/config/mybatis/StudentMapper.xml

@@ -107,7 +107,7 @@
 		LEFT JOIN sys_user su ON er.student_id_ = su.id_
 		WHERE su.del_flag_ = 0 AND su.lock_flag_ = 0
 		<if test="search != null and search != ''">
-			AND (stu.user_id_ = #{search} OR su.real_name_ LIKE CONCAT ('%', #{search}, '%') OR su.phone_ LIKE CONCAT('%', #{search}, '%'))
+			AND (su.id_ = #{search} OR su.real_name_ LIKE CONCAT ('%', #{search}, '%') OR su.phone_ LIKE CONCAT('%', #{search}, '%'))
 		</if>
 		<if test="organIds != null">
 			AND er.organ_id_ IN
@@ -121,7 +121,7 @@
 		LEFT JOIN sys_user su ON er.student_id_ = su.id_
 		WHERE su.del_flag_ = 0 AND su.lock_flag_ = 0
 		<if test="search != null and search != ''">
-			AND (stu.user_id_ = #{search} OR su.real_name_ LIKE CONCAT ('%', #{search}, '%') OR su.phone_ LIKE CONCAT('%', #{search}, '%'))
+			AND (su.id_ = #{search} OR su.real_name_ LIKE CONCAT ('%', #{search}, '%') OR su.phone_ LIKE CONCAT('%', #{search}, '%'))
 		</if>
 		<if test="organIds != null">
 			AND er.organ_id_ IN

+ 11 - 0
edu-user/edu-user-client-api/src/main/java/com/keao/edu/user/api/entity/ExamRoomStudentRelation.java

@@ -31,11 +31,22 @@ public class ExamRoomStudentRelation extends  ExamRoom{
 
 	private java.util.Date updateTime;
 
+	@ApiModelProperty(value = "呼叫时间")
+	private java.util.Date callTime;
+
 	private String tenantId;
 
 	@ApiModelProperty(value = "房间是否开启")
 	private Integer classroomSwitch;
 
+	public Date getCallTime() {
+		return callTime;
+	}
+
+	public void setCallTime(Date callTime) {
+		this.callTime = callTime;
+	}
+
 	public Date getSignInTime() {
 		return signInTime;
 	}

+ 1 - 1
edu-user/edu-user-server/src/main/java/com/keao/edu/user/controller/AppVersionInfoController.java

@@ -39,7 +39,7 @@ public class AppVersionInfoController extends BaseController {
 	@GetMapping(value = "/queryByPlatform")
 	public Object queryByPlatform(String platform) {
 		List<AppVersionInfo> list = appVersionInfoService.queryNewestByPlatform(platform);
-		if (list.size() > 0) {
+		if (list != null && list.size() > 0) {
 			return succeed(list.get(0));
 		}
 		return failed();

+ 7 - 0
edu-user/edu-user-server/src/main/java/com/keao/edu/user/controller/ExamRegistrationController.java

@@ -92,6 +92,13 @@ public class ExamRegistrationController extends BaseController {
         return succeed();
     }
 
+    @ApiOperation(value = "更新考级项目中所有待审核学员状态")
+    @PostMapping(value = "updateExamAllRegistStatus")
+    @PreAuthorize("@pcs.hasPermissions('examRegistration/updateExamAllRegistStatus')")
+    public HttpResponseResult updateExamAllRegistStatus(Long examId, StudentRegistrationStatusEnum status, String memo){
+        return examRegistrationService.updateExamAllRegistStatus(examId, status, memo);
+    }
+
     @ApiOperation(value = "修改学员报名信息")
     @PostMapping(value = "update")
     public HttpResponseResult update(@RequestBody ExamRegistration examRegistration) {

+ 4 - 0
edu-user/edu-user-server/src/main/java/com/keao/edu/user/controller/TaskController.java

@@ -39,6 +39,10 @@ public class TaskController extends BaseController {
     //明日考试安排推送
     @GetMapping("/tomorrowExamPlanRemind")
     public void tomorrowExamPlanRemind(String day){
+        if(true){
+            //功能冲突暂时停用
+            return;
+        }
         examRoomService.tomorrowExamPlanRemind(day);
     }