|  | @@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 | 
	
		
			
				|  |  |  import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 | 
	
		
			
				|  |  |  import com.fasterxml.jackson.annotation.JsonFormat;
 | 
	
		
			
				|  |  |  import com.google.common.collect.Lists;
 | 
	
		
			
				|  |  | +import com.microsvc.toolkit.common.json.ali.AliJSONMap;
 | 
	
		
			
				|  |  |  import com.microsvc.toolkit.middleware.live.LivePluginContext;
 | 
	
		
			
				|  |  |  import com.microsvc.toolkit.middleware.live.LivePluginService;
 | 
	
		
			
				|  |  |  import com.microsvc.toolkit.middleware.live.impl.RongCloudLivePlugin;
 | 
	
	
		
			
				|  | @@ -39,6 +40,7 @@ import com.ym.mec.biz.dal.enums.EAnchorStatus;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.dal.enums.EGroupDefinedDataType;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.dal.enums.EOnOffStatus;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.dal.enums.MessageTypeEnum;
 | 
	
		
			
				|  |  | +import com.ym.mec.biz.dal.enums.live.ELiveViewMode;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.dal.page.LiveRoomGoodsOrderQueryInfo;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.dal.vo.*;
 | 
	
		
			
				|  |  |  import com.ym.mec.biz.redisson.RedissonMessageService;
 | 
	
	
		
			
				|  | @@ -55,11 +57,15 @@ import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
 | 
	
		
			
				|  |  |  import com.ym.mec.util.collection.MapUtil;
 | 
	
		
			
				|  |  |  import com.ym.mec.util.date.DateUtil;
 | 
	
		
			
				|  |  |  import com.ym.mec.util.excel.POIUtil;
 | 
	
		
			
				|  |  | +import com.ym.mec.util.http.HttpUtil;
 | 
	
		
			
				|  |  |  import org.apache.commons.collections.CollectionUtils;
 | 
	
		
			
				|  |  | +import org.apache.commons.collections.MapUtils;
 | 
	
		
			
				|  |  | +import org.apache.commons.lang3.RandomStringUtils;
 | 
	
		
			
				|  |  |  import org.apache.commons.lang3.StringUtils;
 | 
	
		
			
				|  |  |  import org.apache.poi.hssf.usermodel.HSSFWorkbook;
 | 
	
		
			
				|  |  |  import org.jetbrains.annotations.NotNull;
 | 
	
		
			
				|  |  |  import org.joda.time.DateTime;
 | 
	
		
			
				|  |  | +import org.redisson.api.RAtomicLong;
 | 
	
		
			
				|  |  |  import org.redisson.api.RBucket;
 | 
	
		
			
				|  |  |  import org.redisson.api.RLock;
 | 
	
		
			
				|  |  |  import org.redisson.api.RMap;
 | 
	
	
		
			
				|  | @@ -145,6 +151,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |      public static final String LIVE_USER_STATE_TIME = String.join(":", "IM:LIVE_USER_STATE_TIME", USER_ID);
 | 
	
		
			
				|  |  |      //主讲人信息
 | 
	
		
			
				|  |  |      public static final String LIVE_SPEAKER_INFO = String.join(":", "IM:LIVE_SPEAKER_INFO", ROOM_UID, USER_ID);
 | 
	
		
			
				|  |  | +    // 直播间游客信息
 | 
	
		
			
				|  |  | +    public static final String LIVE_VISITOR_INFO = String.join(":", "IM:LIVE_VISITOR_INFO", ROOM_UID, USER_ID);
 | 
	
		
			
				|  |  |      //主讲人最近一次加入房间的clientIp
 | 
	
		
			
				|  |  |      public static final String LIVE_SPEAKER_LAST_CLIENT_IP = String.join(":", "IM:LIVE_SPEAKER_LAST_CLIENT_IP", ROOM_UID, USER_ID);
 | 
	
		
			
				|  |  |      //直播提前开始时间
 | 
	
	
		
			
				|  | @@ -161,20 +169,25 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  |      public ImLiveBroadcastRoomVo queryRoomAndCheck(String roomUid, Integer userId, Integer osType) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          SysUser sysUser = Optional.ofNullable(userId)
 | 
	
		
			
				|  |  |                  .map(this::getSysUser)
 | 
	
		
			
				|  |  |                  .orElseGet(this::getSysUser);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          // 默认学生端查询
 | 
	
		
			
				|  |  |          osType = Optional.ofNullable(osType).orElse(1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 移动端-学生端
 | 
	
		
			
				|  |  |          if (osType == 1) {
 | 
	
		
			
				|  |  |              //学生端
 | 
	
		
			
				|  |  |              return studentQueryRoomAndCheck(roomUid, sysUser);
 | 
	
		
			
				|  |  | -        } else if (osType == 2) {
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        // 移动端-老师端
 | 
	
		
			
				|  |  | +        if (osType == 2) {
 | 
	
		
			
				|  |  |              //老师端
 | 
	
		
			
				|  |  |              return teacherQueryRoomAndCheck(roomUid, sysUser);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        // 直播助手
 | 
	
		
			
				|  |  | +        // PC端-直播助手
 | 
	
		
			
				|  |  |          if (osType == 3) {
 | 
	
		
			
				|  |  |              // 校验直播间是否存在
 | 
	
		
			
				|  |  |              ImLiveBroadcastRoomVo vo = Optional.ofNullable(roomUid).map(this::queryRoomInfo)
 | 
	
	
		
			
				|  | @@ -188,6 +201,57 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          return queryRoomAndCheck(roomUid, sysUser);
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 游客直播间信息
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param roomUid 直播间编号
 | 
	
		
			
				|  |  | +     * @param userId  游客编号
 | 
	
		
			
				|  |  | +     * @return ImLiveBroadcastRoomVo
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public ImLiveBroadcastRoomVo visitorRoomInfo(String roomUid, Integer userId) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 直播间游客信息
 | 
	
		
			
				|  |  | +        RMap<Integer, String> roomTotalUser = getTotalUserCache(roomUid);
 | 
	
		
			
				|  |  | +        if (!roomTotalUser.containsKey(userId)) {
 | 
	
		
			
				|  |  | +            throw new BizException("您无法观看该直播,请刷新重试");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 游客信息
 | 
	
		
			
				|  |  | +        RoomUserInfoVo userInfo = JSONObject.toJavaObject(JSONObject.parseObject(roomTotalUser.get(userId)),
 | 
	
		
			
				|  |  | +                RoomUserInfoVo.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 游客直播间信息校验
 | 
	
		
			
				|  |  | +        ImLiveBroadcastRoomVo roomVo = getVisitorLiveBroadcastRoomVo(roomUid);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 用户直播间黑名单
 | 
	
		
			
				|  |  | +        roomVo.setBlacklistFlag(0);
 | 
	
		
			
				|  |  | +        //黑名单查询-查询当前用户是否在黑名单中
 | 
	
		
			
				|  |  | +        int count = imLiveRoomBlackService.count(Wrappers.<ImLiveRoomBlack>lambdaQuery()
 | 
	
		
			
				|  |  | +                .eq(ImLiveRoomBlack::getRoomUid, roomVo.getRoomUid())
 | 
	
		
			
				|  |  | +                .eq(ImLiveRoomBlack::getUserId, userInfo.getUserId()));
 | 
	
		
			
				|  |  | +        if (count > 0) {
 | 
	
		
			
				|  |  | +            roomVo.setBlacklistFlag(1);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        LivePluginService pluginService = livePluginContext.getPluginService(roomVo.getServiceProvider());
 | 
	
		
			
				|  |  | +        // 直播房间配置信息
 | 
	
		
			
				|  |  | +        String userSig = "";
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            // 生成聊天签名
 | 
	
		
			
				|  |  | +            userSig = pluginService.register(userInfo.getUserId().toString(), userInfo.getUserName(), userInfo.getAvatar());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("直播房间游客注册失败: userId={}", userInfo.getUserId(), e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 直播房间统计信息
 | 
	
		
			
				|  |  | +        getRoomData(roomVo);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 直播间配置信息
 | 
	
		
			
				|  |  | +        return roomVo.userSig(userSig).liveRoomConfig(pluginService.getLiveRoomConfig());
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      public ImLiveBroadcastRoomVo studentQueryRoomAndCheck(String roomUid, SysUser sysUser) {
 | 
	
		
			
				|  |  |          //如果是学生端,则需要检查是否有权限进入
 | 
	
		
			
				|  |  |          Map<String, Object> param = new HashMap<>();
 | 
	
	
		
			
				|  | @@ -1004,7 +1068,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          userid = setFromUserId(userid,roomVo);
 | 
	
		
			
				|  |  |          // 消息发送用户
 | 
	
		
			
				|  |  |          LiveRoomMessage.MessageUser messageUser = null;
 | 
	
		
			
				|  |  | -        SysUser sysUser = sysUserFeignService.queryUserInfo();
 | 
	
		
			
				|  |  | +        SysUser sysUser = getRoomSysUser(Integer.parseInt(userid), roomVo.getRoomUid());
 | 
	
		
			
				|  |  |          if (Objects.nonNull(sysUser)) {
 | 
	
		
			
				|  |  |              // 发送用户信息
 | 
	
		
			
				|  |  |              messageUser = LiveRoomMessage.MessageUser
 | 
	
	
		
			
				|  | @@ -1059,7 +1123,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          String fromUserId = setFromUserId(userid, roomVo);
 | 
	
		
			
				|  |  |          // 消息发送用户
 | 
	
		
			
				|  |  |          LiveRoomMessage.MessageUser messageUser = null;
 | 
	
		
			
				|  |  | -        SysUser sysUser = sysUserFeignService.queryUserById(Integer.parseInt(userid));
 | 
	
		
			
				|  |  | +        SysUser sysUser = getRoomSysUser(Integer.parseInt(userid), roomVo.getRoomUid());
 | 
	
		
			
				|  |  |          if (Objects.nonNull(sysUser)) {
 | 
	
		
			
				|  |  |              // 发送用户信息
 | 
	
		
			
				|  |  |              messageUser = LiveRoomMessage.MessageUser
 | 
	
	
		
			
				|  | @@ -1118,7 +1182,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          // 直播间统计数据
 | 
	
		
			
				|  |  |          getRoomData(roomVo);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        String userId = setFromUserId(fromUserId.toString(),roomVo);
 | 
	
		
			
				|  |  | +        String userId = setFromUserId(fromUserId.toString(), roomVo);
 | 
	
		
			
				|  |  |          // 缓存JoinRoom用户信息到redis
 | 
	
		
			
				|  |  |          RBucket<Object> bucket = redissonClient.getBucket(RedissonMessageService.LIVE_ROOM_MEMBER + roomUid);
 | 
	
		
			
				|  |  |          if (!bucket.isExists()) {
 | 
	
	
		
			
				|  | @@ -1129,7 +1193,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // 消息发送用户
 | 
	
		
			
				|  |  |          LiveRoomMessage.MessageUser messageUser = null;
 | 
	
		
			
				|  |  | -        SysUser sysUser = sysUserFeignService.queryUserInfo();
 | 
	
		
			
				|  |  | +        SysUser sysUser = getRoomSysUser(fromUserId, roomUid);
 | 
	
		
			
				|  |  |          if (Objects.nonNull(sysUser)) {
 | 
	
		
			
				|  |  |              // 发送用户信息
 | 
	
		
			
				|  |  |              messageUser = LiveRoomMessage.MessageUser
 | 
	
	
		
			
				|  | @@ -1365,6 +1429,12 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |       * @param userId  用户id
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      public void joinRoom(String roomUid, Integer userId) {
 | 
	
		
			
				|  |  | +        joinRoom(roomUid, userId, true);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    @Transactional(rollbackFor = Exception.class)
 | 
	
		
			
				|  |  | +    public void joinRoom(String roomUid, Integer userId,Boolean microphoneFlag) {
 | 
	
		
			
				|  |  |          //查询房间信息
 | 
	
		
			
				|  |  |          ImLiveBroadcastRoomVo imLiveBroadcastRoomVo = getImLiveBroadcastRoomVo(roomUid);
 | 
	
		
			
				|  |  |          if (Objects.isNull(imLiveBroadcastRoomVo)) {
 | 
	
	
		
			
				|  | @@ -1383,13 +1453,29 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |              throw new BizException("当前用户所在机构没有加入直播间的权限");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        // 加入直播间用户信息
 | 
	
		
			
				|  |  | +        joinRoomUserInfo(roomUid, userId, imLiveBroadcastRoomVo,microphoneFlag);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 加入直播间用户信息
 | 
	
		
			
				|  |  | +     * @param roomUid 直播间编号
 | 
	
		
			
				|  |  | +     * @param userId 用户编号
 | 
	
		
			
				|  |  | +     * @param imLiveBroadcastRoomVo ImLiveBroadcastRoomVo
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private void joinRoomUserInfo(String roomUid, Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo) {
 | 
	
		
			
				|  |  | +        joinRoomUserInfo(roomUid, userId, imLiveBroadcastRoomVo,true);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    private void joinRoomUserInfo(String roomUid, Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo,Boolean microphoneFlag) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          //记录用户当前房间uid
 | 
	
		
			
				|  |  |          redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 12L, TimeUnit.HOURS);
 | 
	
		
			
				|  |  | -        //房间累计用户信息-指只要进入到该房间的用户都要记录
 | 
	
		
			
				|  |  | -        RMap<Integer, String> roomTotalUser = getTotalUserCache(roomUid);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          //判断是否第一次进房间
 | 
	
		
			
				|  |  |          RoomUserInfoVo userInfo;
 | 
	
		
			
				|  |  | -        Date now = new Date();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        //房间累计用户信息-指只要进入到该房间的用户都要记录
 | 
	
		
			
				|  |  | +        RMap<Integer, String> roomTotalUser = getTotalUserCache(roomUid);
 | 
	
		
			
				|  |  |          if (roomTotalUser.containsKey(userId)) {
 | 
	
		
			
				|  |  |              //多次进入更新动态进入时间
 | 
	
		
			
				|  |  |              userInfo = JSONObject.toJavaObject(JSONObject.parseObject(roomTotalUser.get(userId)), RoomUserInfoVo.class);
 | 
	
	
		
			
				|  | @@ -1403,30 +1489,34 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |              if (Objects.isNull(liveRoomMember)) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  // 初次进入房间
 | 
	
		
			
				|  |  | -                getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo, now);
 | 
	
		
			
				|  |  | +                getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo, microphoneFlag);
 | 
	
		
			
				|  |  |              } else {
 | 
	
		
			
				|  |  |                  // 更新直播间用户信息
 | 
	
		
			
				|  |  |                  ImLiveBroadcastRoomMember roomMember = new ImLiveBroadcastRoomMember();
 | 
	
		
			
				|  |  |                  roomMember.setId(liveRoomMember.getId());
 | 
	
		
			
				|  |  |                  roomMember.setOnlineStatus(1);
 | 
	
		
			
				|  |  |                  roomMember.setLiveRoomStatus(1);
 | 
	
		
			
				|  |  | +                roomMember.setMicrophoneFlag(microphoneFlag);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                  liveBroadcastRoomMemberService.updateById(roomMember);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          } else {
 | 
	
		
			
				|  |  |              //第一次进该房间 写入用户首次进入时间
 | 
	
		
			
				|  |  | -            userInfo = getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo, now);
 | 
	
		
			
				|  |  | +            userInfo = getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo, microphoneFlag);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          //查询主讲人信息
 | 
	
		
			
				|  |  |          RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, imLiveBroadcastRoomVo.getSpeakerId().toString());
 | 
	
		
			
				|  |  |          if (speakerCache.isExists()) {
 | 
	
		
			
				|  |  |              //如果用户进来时主讲人已经开启直播则修改学生观看时间
 | 
	
		
			
				|  |  |              Integer state = speakerCache.get().getState();
 | 
	
		
			
				|  |  |              if (Objects.nonNull(state) && state == 0 && imLiveBroadcastRoomVo.getPushStatus() == 1) {
 | 
	
		
			
				|  |  | -                userInfo.setDynamicLookTime(now);
 | 
	
		
			
				|  |  | +                userInfo.setDynamicLookTime(DateTime.now().toDate());
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 直播间用户、在线用户数据缓存
 | 
	
		
			
				|  |  |          roomTotalUser.fastPut(userId, JSONObject.toJSONString(userInfo));
 | 
	
		
			
				|  |  |          //在线人员列表
 | 
	
		
			
				|  |  |          RMap<Integer, String> onlineUserInfo = getOnlineUserCache(roomUid);
 | 
	
	
		
			
				|  | @@ -1441,12 +1531,234 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |              this.sendBlackJoinRoom(userId, imLiveBroadcastRoomVo);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        log.info("join sendOnlineUserCount>>>>   roomUid: {}  fromUserId:{}  count:{}", roomUid, userId, onlineUserInfo.size());
 | 
	
		
			
				|  |  | +        log.info("joinRoom>>>> sendOnlineUserCount>>>>   roomUid: {}  fromUserId:{}  count:{}", roomUid, userId, onlineUserInfo.size());
 | 
	
		
			
				|  |  |          log.info("joinRoom>>>> userInfo: {}", JSONObject.toJSONString(userInfo));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  | +     * 游客加入直播间
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param roomUid 直播间编号
 | 
	
		
			
				|  |  | +     * @param userId  游客编号
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public void visitorJoinRoom(String roomUid, Integer userId) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 游客直播间信息
 | 
	
		
			
				|  |  | +        ImLiveBroadcastRoomVo roomVo = getVisitorLiveBroadcastRoomVo(roomUid);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 加入直播间用户信息
 | 
	
		
			
				|  |  | +        joinRoomUserInfo(roomUid, userId, roomVo,false);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 游客访问直播间信息
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param roomUid 直播间编号
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private ImLiveBroadcastRoomVo getVisitorLiveBroadcastRoomVo(String roomUid) {
 | 
	
		
			
				|  |  | +        // 查询直播间信息
 | 
	
		
			
				|  |  | +        ImLiveBroadcastRoomVo roomVo = getImLiveBroadcastRoomVo(roomUid);
 | 
	
		
			
				|  |  | +        if (Objects.isNull(roomVo) || roomVo.getRoomState() == 1) {
 | 
	
		
			
				|  |  | +            log.info("visitorJoinRoom>>>> joinRoom LIVE_ROOM_CANCEL roomUid: {}", roomUid);
 | 
	
		
			
				|  |  | +            throw new BizException("直播间不存在");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 判断当前直播间观看模式是否为游客模式且,直播状态
 | 
	
		
			
				|  |  | +        if (ELiveViewMode.VISITOR != roomVo.getViewMode()) {
 | 
	
		
			
				|  |  | +            log.info("visitorJoinRoom>>>> joinRoom LOGOUT roomUid: {} viewMode: {}", roomUid, roomVo.getViewMode());
 | 
	
		
			
				|  |  | +            throw new BizException("请登陆");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 判断当前直播间是否在直播中,直播状态 0未开始 1开始 2结束
 | 
	
		
			
				|  |  | +        if (roomVo.getLiveState() == 0) {
 | 
	
		
			
				|  |  | +            log.info("visitorJoinRoom>>>> joinRoom LIVE_NOT_START roomUid: {} liveState: {}", roomUid, roomVo.getLiveState());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Date liveStartTime = DateUtil.addMinutes(roomVo.getLiveStartTime(), -PRE_LIVE_TIME_MINUTE);
 | 
	
		
			
				|  |  | +            throw new BizException(DateUtil.format(liveStartTime, "yyyy年MM月dd日 HH点mm分") + " 可进入直播间准备");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (roomVo.getLiveState() == 2) {
 | 
	
		
			
				|  |  | +            log.info("visitorJoinRoom>>>> joinRoom LIVE_CLOSED roomUid: {} liveState: {}", roomUid, roomVo.getLiveState());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //如果直播结束了还是推广状态则将推广修改为取消
 | 
	
		
			
				|  |  | +            if (roomVo.getPopularize() == 1) {
 | 
	
		
			
				|  |  | +                this.update(Wrappers.<ImLiveBroadcastRoom>lambdaUpdate()
 | 
	
		
			
				|  |  | +                        .set(ImLiveBroadcastRoom::getPopularize, 0)
 | 
	
		
			
				|  |  | +                        .eq(ImLiveBroadcastRoom::getId, roomVo.getId()));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            throw new BizException("直播已结束!");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return roomVo;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 游客加入直播间凭据
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param roomUid     直播间编号
 | 
	
		
			
				|  |  | +     * @param fingerprint 游客凭据
 | 
	
		
			
				|  |  | +     * @return RoomUserInfoVo
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public RoomUserInfoVo getVisitorCredentials(String roomUid, String fingerprint) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 游客直播间信息校验
 | 
	
		
			
				|  |  | +        ImLiveBroadcastRoomVo roomVo = getVisitorLiveBroadcastRoomVo(roomUid);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        String today = DateTime.now().toString("yyyyMMdd");
 | 
	
		
			
				|  |  | +        // 为当前游客生成惟一用户ID
 | 
	
		
			
				|  |  | +        String cacheKey = MessageFormat.format("fingerprint:{0}:{1}", today, fingerprint);
 | 
	
		
			
				|  |  | +        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        Integer userId;
 | 
	
		
			
				|  |  | +        if (bucket.isExists()) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 查询游客用户ID
 | 
	
		
			
				|  |  | +            userId = Optional.ofNullable(bucket.get()).map(x -> (int) x).orElse(-1);
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 用户Id缓存key
 | 
	
		
			
				|  |  | +            String userIdKey = MessageFormat.format("fingerprint:userId:{0}", today);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            RAtomicLong atomicLong = redissonClient.getAtomicLong(userIdKey);
 | 
	
		
			
				|  |  | +            if (!atomicLong.isExists()) {
 | 
	
		
			
				|  |  | +                // 设置默认初始化值
 | 
	
		
			
				|  |  | +                atomicLong.set(1000);
 | 
	
		
			
				|  |  | +                // 设置缓存失效时间
 | 
	
		
			
				|  |  | +                atomicLong.expire(1L, TimeUnit.DAYS);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 生成游客用户ID
 | 
	
		
			
				|  |  | +            userId = (int) atomicLong.getAndIncrement();
 | 
	
		
			
				|  |  | +            // 设置用户ID缓存
 | 
	
		
			
				|  |  | +            bucket.set(userId, 12L, TimeUnit.HOURS);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        //房间累计用户信息-指只要进入到该房间的用户都要记录
 | 
	
		
			
				|  |  | +        RMap<Integer, String> roomTotalUser = getTotalUserCache(roomUid);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        RoomUserInfoVo userInfo;
 | 
	
		
			
				|  |  | +        if (roomTotalUser.containsKey(userId)) {
 | 
	
		
			
				|  |  | +            //多次进入更新动态进入时间
 | 
	
		
			
				|  |  | +            userInfo = JSONObject.toJavaObject(JSONObject.parseObject(roomTotalUser.get(userId)), RoomUserInfoVo.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Integer exists = liveBroadcastRoomMemberService.lambdaQuery()
 | 
	
		
			
				|  |  | +                    .eq(ImLiveBroadcastRoomMember::getTenantId, userInfo.getTenantId())
 | 
	
		
			
				|  |  | +                    .eq(ImLiveBroadcastRoomMember::getRoomUid, roomUid)
 | 
	
		
			
				|  |  | +                    .eq(ImLiveBroadcastRoomMember::getUserId, userInfo.getUserId())
 | 
	
		
			
				|  |  | +                    .count();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (exists <= 0) {
 | 
	
		
			
				|  |  | +                // 初次进入房间
 | 
	
		
			
				|  |  | +                getLiveRoomVisitorInfo(userId, roomVo, fingerprint);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            //第一次进该房间 写入用户首次进入时间
 | 
	
		
			
				|  |  | +            userInfo = getLiveRoomVisitorInfo(userId, roomVo, fingerprint);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 缓存用户信息
 | 
	
		
			
				|  |  | +        roomTotalUser.fastPut(userId, JSONObject.toJSONString(userInfo));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 游客缓存信息
 | 
	
		
			
				|  |  | +        getRoomVisitorInfoCache(roomUid, userId.toString()).set(userInfo, 12L, TimeUnit.HOURS);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 返回直播间访客信息
 | 
	
		
			
				|  |  | +        return userInfo;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 游客微信身份
 | 
	
		
			
				|  |  | +     *
 | 
	
		
			
				|  |  | +     * @param code 授权码
 | 
	
		
			
				|  |  | +     * @return 用户openId
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public String visitorFingerprint(String code) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 微信公众号appId
 | 
	
		
			
				|  |  | +        String appId = sysConfigDao.findConfigValue(SysConfigService.WECHAT_APPID);
 | 
	
		
			
				|  |  | +        // 微信公众号secret
 | 
	
		
			
				|  |  | +        String secret = sysConfigDao.findConfigValue(SysConfigService.WECHAT_SECRET);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        if (StringUtils.isAnyBlank(appId, secret, code)) {
 | 
	
		
			
				|  |  | +            // 若微信未配置,产生64位随机数
 | 
	
		
			
				|  |  | +            return RandomStringUtils.random(64);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  | +            // 获取用户OpenId接口
 | 
	
		
			
				|  |  | +            String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={0}&secret={1}&code={2}&grant_type=authorization_code";
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 封装请求参数
 | 
	
		
			
				|  |  | +            url = MessageFormat.format(url, appId, secret, code);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            String wxMpOAuth2AccessTokenUrl = HttpUtil.get(url, null);
 | 
	
		
			
				|  |  | +            log.info("请求微信授权接口的参数:{}", wxMpOAuth2AccessTokenUrl);
 | 
	
		
			
				|  |  | +            if (StringUtils.isEmpty(wxMpOAuth2AccessTokenUrl)) {
 | 
	
		
			
				|  |  | +                throw new BizException(999,"授权失败,请重新授权");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            Map<String, Object> weChatRes = AliJSONMap.tomap(wxMpOAuth2AccessTokenUrl);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            if (!weChatRes.containsKey("openid")) {
 | 
	
		
			
				|  |  | +                log.error("获取微信openId失败:[{}]", JSON.toJSONString(weChatRes));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                throw new BizException(999,"授权失败,请重新授权");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return MapUtils.getString(weChatRes, "openid", "");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } catch (Exception e) {
 | 
	
		
			
				|  |  | +            log.error("获取微信openId失败:[{}]", e.getMessage(), e);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            throw new BizException(999,"授权失败,请重新授权");
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 获取直播间游客信息
 | 
	
		
			
				|  |  | +     * @param userId 游客编号
 | 
	
		
			
				|  |  | +     * @param imLiveBroadcastRoomVo ImLiveBroadcastRoomVo
 | 
	
		
			
				|  |  | +     * @param fingerprint 游客凭据
 | 
	
		
			
				|  |  | +     * @return RoomUserInfoVo
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private RoomUserInfoVo getLiveRoomVisitorInfo(Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo, String fingerprint) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        RoomUserInfoVo userInfo = new RoomUserInfoVo();
 | 
	
		
			
				|  |  | +        // 生成游客账号信息,缓存信息
 | 
	
		
			
				|  |  | +        userInfo.setTenantId(-1);
 | 
	
		
			
				|  |  | +        userInfo.setUserId(userId);
 | 
	
		
			
				|  |  | +        userInfo.setUserName(MessageFormat.format("游客{0}", String.valueOf(userId)));
 | 
	
		
			
				|  |  | +        userInfo.setTotalViewTime(0);
 | 
	
		
			
				|  |  | +        userInfo.setFirstJoinTime(DateTime.now().toDate());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 游客默认头像
 | 
	
		
			
				|  |  | +        String defaultAvatar = sysConfigDao.findByParamName(SysConfigService.VISITOR_DEFAULT_AVATAR).getParanValue();
 | 
	
		
			
				|  |  | +        userInfo.setAvatar(Optional.ofNullable(defaultAvatar).orElse(""));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 记录直播间用户信息
 | 
	
		
			
				|  |  | +        ImLiveBroadcastRoomMember roomMember = new ImLiveBroadcastRoomMember();
 | 
	
		
			
				|  |  | +        roomMember.setTenantId(userInfo.getTenantId());
 | 
	
		
			
				|  |  | +        roomMember.setRoomUid(imLiveBroadcastRoomVo.getRoomUid());
 | 
	
		
			
				|  |  | +        roomMember.setUserId(userInfo.getUserId());
 | 
	
		
			
				|  |  | +        roomMember.setJoinTime(DateTime.now().toDate());
 | 
	
		
			
				|  |  | +        roomMember.setTotalTime(0);
 | 
	
		
			
				|  |  | +        roomMember.setOnlineStatus(1);
 | 
	
		
			
				|  |  | +        roomMember.setBanStatus(0);
 | 
	
		
			
				|  |  | +        roomMember.setLiveRoomStatus(1);
 | 
	
		
			
				|  |  | +        roomMember.setFingerprint(fingerprint);
 | 
	
		
			
				|  |  | +        roomMember.setVisitorName(userInfo.getUserName());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 保存直播间用户信息
 | 
	
		
			
				|  |  | +        liveBroadcastRoomMemberService.save(roomMember);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return userInfo;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  |       * 发送黑名单进入消息
 | 
	
		
			
				|  |  |       * @param userId 用户id
 | 
	
		
			
				|  |  |       */
 | 
	
	
		
			
				|  | @@ -1462,18 +1774,21 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          String fromUserid = setFromUserId(userId.toString(),roomVo);
 | 
	
		
			
				|  |  |          // 消息发送用户
 | 
	
		
			
				|  |  |          LiveRoomMessage.MessageUser messageUser = null;
 | 
	
		
			
				|  |  | -        SysUser sysUser = sysUserFeignService.queryUserById(userId);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 直播间访问用户信息
 | 
	
		
			
				|  |  | +        SysUser sysUser = getRoomSysUser(userId, roomUid);
 | 
	
		
			
				|  |  |          if (Objects.nonNull(sysUser)) {
 | 
	
		
			
				|  |  |              // 发送用户信息
 | 
	
		
			
				|  |  |              messageUser = LiveRoomMessage.MessageUser
 | 
	
		
			
				|  |  | -                .builder()
 | 
	
		
			
				|  |  | -                .sendUserId(sysUser.getId().toString())
 | 
	
		
			
				|  |  | -                .sendUserName(sysUser.getUsername())
 | 
	
		
			
				|  |  | -                .avatarUrl(sysUser.getAvatar())
 | 
	
		
			
				|  |  | -                .blackFlag(true)
 | 
	
		
			
				|  |  | -                .build();
 | 
	
		
			
				|  |  | +                    .builder()
 | 
	
		
			
				|  |  | +                    .sendUserId(sysUser.getId().toString())
 | 
	
		
			
				|  |  | +                    .sendUserName(sysUser.getUsername())
 | 
	
		
			
				|  |  | +                    .avatarUrl(sysUser.getAvatar())
 | 
	
		
			
				|  |  | +                    .blackFlag(true)
 | 
	
		
			
				|  |  | +                    .build();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          LiveRoomMessage.MessageContent messageContent = LiveRoomMessage.MessageContent
 | 
	
		
			
				|  |  |              .builder()
 | 
	
		
			
				|  |  |              .sendUserInfo(messageUser)
 | 
	
	
		
			
				|  | @@ -1492,23 +1807,58 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |              livePluginContext.getPluginService(roomVo.getServiceProvider()).sendChatRoomMessage(message);
 | 
	
		
			
				|  |  |              log.info("sendBlackJoinRoom>>>> message: {}", JSONObject.toJSONString(message));
 | 
	
		
			
				|  |  |          } catch (Exception e) {
 | 
	
		
			
				|  |  | -            log.error("sendBlackJoinRoom>>>> error {}", e.getMessage());
 | 
	
		
			
				|  |  |              log.error("sendBlackJoinRoom>>>> sendMessage {} :", JSONObject.toJSONString(message));
 | 
	
		
			
				|  |  | +            log.error("sendBlackJoinRoom>>>> error", e);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 直播间访问用户信息
 | 
	
		
			
				|  |  | +     * @param userId 用户编号
 | 
	
		
			
				|  |  | +     * @param roomUid 直播间编号
 | 
	
		
			
				|  |  | +     * @return SysUser
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    @Override
 | 
	
		
			
				|  |  | +    public SysUser getRoomSysUser(Integer userId, String roomUid) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        SysUser sysUser = null;
 | 
	
		
			
				|  |  | +        // 直播间游客或学生用户匹配
 | 
	
		
			
				|  |  | +        RBucket<RoomUserInfoVo> visitorInfoCache = getRoomVisitorInfoCache(roomUid, userId.toString());
 | 
	
		
			
				|  |  | +        if (getRoomVisitorInfoCache(roomUid, userId.toString()).isExists()) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 游客身份信息
 | 
	
		
			
				|  |  | +            RoomUserInfoVo userInfoVo = visitorInfoCache.get();
 | 
	
		
			
				|  |  | +            if (Objects.nonNull(userInfoVo)) {
 | 
	
		
			
				|  |  | +                sysUser = new SysUser();
 | 
	
		
			
				|  |  | +                sysUser.setId(userInfoVo.getUserId());
 | 
	
		
			
				|  |  | +                sysUser.setUsername(userInfoVo.getUserName());
 | 
	
		
			
				|  |  | +                sysUser.setAvatar(userInfoVo.getAvatar());
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // 登录用户信息
 | 
	
		
			
				|  |  | +            sysUser = sysUserFeignService.queryUserById(userId);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        return sysUser;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * 获取直播间用户信息
 | 
	
		
			
				|  |  |       * @param userId 用户id
 | 
	
		
			
				|  |  |       * @param imLiveBroadcastRoomVo 直播间信息
 | 
	
		
			
				|  |  | -     * @param now 当前时间
 | 
	
		
			
				|  |  |       * @return RoomUserInfoVo
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      @NotNull
 | 
	
		
			
				|  |  | -    private RoomUserInfoVo getLiveRoomUserInfo(Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo, Date now) {
 | 
	
		
			
				|  |  | +    private RoomUserInfoVo getLiveRoomUserInfo(Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo) {
 | 
	
		
			
				|  |  | +        return getLiveRoomUserInfo(userId, imLiveBroadcastRoomVo,true);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    private RoomUserInfoVo getLiveRoomUserInfo(Integer userId, ImLiveBroadcastRoomVo imLiveBroadcastRoomVo,Boolean microphoneFlag) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          RoomUserInfoVo userInfo = getUserInfo(userId);
 | 
	
		
			
				|  |  | -        userInfo.setFirstJoinTime(now);
 | 
	
		
			
				|  |  | +        userInfo.setFirstJoinTime(DateTime.now().toDate());
 | 
	
		
			
				|  |  |          userInfo.setTotalViewTime(0);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // 记录直播间用户信息
 | 
	
	
		
			
				|  | @@ -1521,6 +1871,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          roomMember.setOnlineStatus(1);
 | 
	
		
			
				|  |  |          roomMember.setBanStatus(0);
 | 
	
		
			
				|  |  |          roomMember.setLiveRoomStatus(1);
 | 
	
		
			
				|  |  | +        roomMember.setMicrophoneFlag(microphoneFlag);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          // 保存直播间用户信息
 | 
	
		
			
				|  |  |          liveBroadcastRoomMemberService.save(roomMember);
 | 
	
	
		
			
				|  | @@ -1785,6 +2136,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |       * 定时任务,每分钟执行
 | 
	
		
			
				|  |  |       * 提前30分钟主动去融云注册并创建房间
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  | +    @Transactional
 | 
	
		
			
				|  |  |      public void createLiveRoom() {
 | 
	
		
			
				|  |  |          log.info("createLiveRoom>>>>");
 | 
	
		
			
				|  |  |          RBucket<Object> createLock = redissonClient.getBucket("IM:LIVE_ROOM_CREATE_LOCK");
 | 
	
	
		
			
				|  | @@ -1891,6 +2243,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |                                                     .build();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      // 生成录制任务
 | 
	
		
			
				|  |  | +                    log.info("createLiveRoom>>>>>> recordStart:{}", recordStart.jsonString());
 | 
	
		
			
				|  |  |                      pluginService.rtcRoomRecordStart(recordStart);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1922,7 +2275,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          } catch (Exception e) {
 | 
	
		
			
				|  |  | -            log.error(">>>>>>>>>> createLiveRoom error roomUid:{} msg:{}", room.getRoomUid(), e.getMessage());
 | 
	
		
			
				|  |  | +            log.error(">>>>>>>>>> createLiveRoom error roomUid:{}", room.getRoomUid(), e);
 | 
	
		
			
				|  |  |              throw new BizException(e.getMessage());
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -2087,18 +2440,20 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 直播间统计数据
 | 
	
		
			
				|  |  | +     * 观看数、点赞数,在线人数
 | 
	
		
			
				|  |  | +     * @param roomVo ImLiveBroadcastRoomVo
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  |      private void getRoomData(ImLiveBroadcastRoomVo roomVo) {
 | 
	
		
			
				|  |  | -        //点赞数
 | 
	
		
			
				|  |  | -        Object like = redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomVo.getRoomUid())).get();
 | 
	
		
			
				|  |  | -        if (Objects.isNull(like)) {
 | 
	
		
			
				|  |  | -            like = 0;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        like = syncLikeCount(roomVo.getRoomUid());
 | 
	
		
			
				|  |  | +        // 同步点赞数
 | 
	
		
			
				|  |  | +        int likeNums = syncLikeCount(roomVo.getRoomUid());
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        roomVo.setLikeNum((int) like);
 | 
	
		
			
				|  |  | +        roomVo.setLikeNum(likeNums);
 | 
	
		
			
				|  |  |          roomVo.setTotalLookNum(0);
 | 
	
		
			
				|  |  |          roomVo.setLookNum(0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          //累计总用户数量
 | 
	
		
			
				|  |  |          // roomVo.setTotalLookNum(getNum.apply(this::getTotalUserCache, roomVo.getRoomUid()));
 | 
	
		
			
				|  |  |          // //在房间观看用户数量
 | 
	
	
		
			
				|  | @@ -2606,24 +2961,24 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |       * 同步直播间点赞数
 | 
	
		
			
				|  |  |       *
 | 
	
		
			
				|  |  |       * @param roomUid 直播间uid
 | 
	
		
			
				|  |  | -     * @return
 | 
	
		
			
				|  |  | +     * @return int
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | -    @Transactional
 | 
	
		
			
				|  |  |      public int syncLikeCount(String roomUid) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 直播间信息
 | 
	
		
			
				|  |  |          ImLiveBroadcastRoomVo room = getImLiveBroadcastRoomVo(roomUid);
 | 
	
		
			
				|  |  |          if (room == null) {
 | 
	
		
			
				|  |  |              return 0;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        // 融云直播间
 | 
	
		
			
				|  |  |          if (room.getServiceProvider().equals(RongCloudLivePlugin.PLUGIN_NAME)) {
 | 
	
		
			
				|  |  |              //点赞数
 | 
	
		
			
				|  |  | -            Object like = redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).get();
 | 
	
		
			
				|  |  | -            if (Objects.isNull(like)) {
 | 
	
		
			
				|  |  | -                like = 0;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            return (int) like;
 | 
	
		
			
				|  |  | +            return (int) Optional.ofNullable(redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).get()).orElse(0);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        // 腾讯云直播
 | 
	
		
			
				|  |  |          LivePluginService pluginService = livePluginContext.getPluginService(room.getServiceProvider());
 | 
	
		
			
				|  |  |          List<TencentWrapper.ChatRoomGroupCounter> chatRoomGroupCounters = null;
 | 
	
		
			
				|  |  |          try {
 | 
	
	
		
			
				|  | @@ -2648,6 +3003,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |                                                                        .eq(ImLiveBroadcastRoomData::getRoomUid, roomUid)
 | 
	
		
			
				|  |  |                                                                        .last("limit 1")
 | 
	
		
			
				|  |  |                                                                        .one();
 | 
	
		
			
				|  |  | +            // 同步点赞数
 | 
	
		
			
				|  |  |              if (one != null) {
 | 
	
		
			
				|  |  |                  ImLiveBroadcastRoomData imLiveBroadcastRoomData = new ImLiveBroadcastRoomData();
 | 
	
		
			
				|  |  |                  imLiveBroadcastRoomData.setId(one.getId());
 | 
	
	
		
			
				|  | @@ -2735,6 +3091,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
 | 
	
		
			
				|  |  |          return redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId).replace(ROOM_UID, roomUid));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * 直播间游客信息
 | 
	
		
			
				|  |  | +     * @param roomUid 直播间编号
 | 
	
		
			
				|  |  | +     * @param userId 游客编号
 | 
	
		
			
				|  |  | +     * @return RBucket<RoomUserInfoVo>
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private RBucket<RoomUserInfoVo> getRoomVisitorInfoCache(String roomUid, String userId) {
 | 
	
		
			
				|  |  | +        return redissonClient.getBucket(LIVE_VISITOR_INFO.replace(USER_ID, userId).replace(ROOM_UID, roomUid));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      private RoomUserInfoVo getUserInfo(Integer userId) {
 | 
	
		
			
				|  |  |          RoomUserInfoVo userInfo = new RoomUserInfoVo();
 | 
	
		
			
				|  |  |          userInfo.setUserId(userId);
 |