|
@@ -15,14 +15,11 @@ import com.ym.mec.biz.dal.dao.ImLiveBroadcastRoomDao;
|
|
|
import com.ym.mec.biz.dal.dao.LiveGoodsMapperDao;
|
|
|
import com.ym.mec.biz.dal.dao.SysConfigDao;
|
|
|
import com.ym.mec.biz.dal.dto.ImLiveBroadcastRoomDto;
|
|
|
-import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoom;
|
|
|
-import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomData;
|
|
|
-import com.ym.mec.biz.dal.entity.ImLiveBroadcastRoomMember;
|
|
|
-import com.ym.mec.biz.dal.entity.ImLiveRoomBlack;
|
|
|
+import com.ym.mec.biz.dal.dto.RoomReservationUserSearch;
|
|
|
+import com.ym.mec.biz.dal.entity.*;
|
|
|
import com.ym.mec.biz.dal.enums.MessageTypeEnum;
|
|
|
-import com.ym.mec.biz.dal.vo.BaseRoomUserVo;
|
|
|
-import com.ym.mec.biz.dal.vo.ImLiveBroadcastRoomVo;
|
|
|
-import com.ym.mec.biz.dal.vo.RoomUserInfoVo;
|
|
|
+import com.ym.mec.biz.dal.page.LiveRoomGoodsOrderQueryInfo;
|
|
|
+import com.ym.mec.biz.dal.vo.*;
|
|
|
import com.ym.mec.biz.service.*;
|
|
|
import com.ym.mec.common.entity.ImRoomMessage;
|
|
|
import com.ym.mec.common.entity.ImUserState;
|
|
@@ -32,10 +29,13 @@ import com.ym.mec.common.page.PageUtil;
|
|
|
import com.ym.mec.common.page.WrapperUtil;
|
|
|
import com.ym.mec.common.tenant.TenantContextHolder;
|
|
|
import com.ym.mec.im.ImFeignService;
|
|
|
+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.lang3.StringUtils;
|
|
|
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
|
|
import org.redisson.api.RBucket;
|
|
|
import org.redisson.api.RLock;
|
|
|
import org.redisson.api.RMap;
|
|
@@ -47,11 +47,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.OutputStream;
|
|
|
import java.io.Serializable;
|
|
|
import java.util.*;
|
|
|
import java.util.concurrent.CompletableFuture;
|
|
|
import java.util.concurrent.TimeUnit;
|
|
|
-import java.util.function.BiConsumer;
|
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
@@ -87,30 +89,36 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
private ImLiveRoomReservationService imLiveRoomReservationService;
|
|
|
@Autowired
|
|
|
private ImLiveRoomBlackService imLiveRoomBlackService;
|
|
|
+ @Autowired
|
|
|
+ private EmployeeService employeeService;
|
|
|
|
|
|
//待替换的变量
|
|
|
public static final String USER_ID = "${userId}";
|
|
|
public static final String ROOM_UID = "${roomUid}";
|
|
|
|
|
|
//直播间累计用户信息-指只要进入到该房间的用户都要记录
|
|
|
- public static final String LIVE_ROOM_TOTAL_USER_LIST = "IM:LIVE_ROOM_TOTAL_USER_LIST:" + ROOM_UID;
|
|
|
+ public static final String LIVE_ROOM_TOTAL_USER_LIST = String.join(":", "IM:LIVE_ROOM_TOTAL_USER_LIST", ROOM_UID);
|
|
|
//直播间在线用户信息
|
|
|
- public static final String LIVE_ROOM_ONLINE_USER_LIST = "IM:LIVE_ROOM_ONLINE_USER_LIST:" + ROOM_UID;
|
|
|
- //主讲人信息
|
|
|
- public static final String LIVE_SPEAKER_INFO = "IM:LIVE_SPEAKER_INFO:" + USER_ID;
|
|
|
- //用户对应的直播间Uid
|
|
|
- public static final String LIVE_USER_ROOM = "IM:LIVE_ROOM_USER:" + USER_ID;
|
|
|
- //记录人员最后变更的状态消息时间
|
|
|
- public static final String LIVE_USER_STATE_TIME = "IM:LIVE_USER_STATE_TIME:" + USER_ID;
|
|
|
+ public static final String LIVE_ROOM_ONLINE_USER_LIST = String.join(":", "IM:LIVE_ROOM_ONLINE_USER_LIST", ROOM_UID);
|
|
|
+ //当前房间主讲人心跳
|
|
|
+ public static final String LIVE_ROOM_SPEAKER_HEART_BEAT = String.join(":", "IM:LIVE_ROOM_SPEAKER_HEART_BEAT", ROOM_UID);
|
|
|
//房间点赞数
|
|
|
- public static final String LIVE_ROOM_LIKE = "IM:LIVE_ROOM_LIKE:" + ROOM_UID;
|
|
|
+ public static final String LIVE_ROOM_LIKE = String.join(":", "IM:LIVE_ROOM_LIKE", ROOM_UID);
|
|
|
//计算人员观看时长锁
|
|
|
- public static final String LIVE_LOOK_LOCK = "IM:LIVE_LOOK_LOCK:" + ROOM_UID;
|
|
|
+ public static final String LIVE_LOOK_LOCK = String.join(":", "IM:LIVE_LOOK_LOCK", ROOM_UID);
|
|
|
+ //用户对应的直播间Uid
|
|
|
+ public static final String LIVE_USER_ROOM = String.join(":", "IM:LIVE_ROOM_USER", USER_ID);
|
|
|
+ //记录人员最后变更的状态消息时间
|
|
|
+ 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);
|
|
|
+ //主讲人最近一次加入房间的clientIp
|
|
|
+ public static final String LIVE_SPEAKER_LAST_CLIENT_IP = String.join(":", "IM:LIVE_SPEAKER_LAST_CLIENT_IP", ROOM_UID, USER_ID);
|
|
|
//直播提前开始时间
|
|
|
public static final int PRE_LIVE_TIME_MINUTE = 30;
|
|
|
|
|
|
/**
|
|
|
- * 进入直播间检查数据
|
|
|
+ * 进入直播间检查数据-现在只有学生端用
|
|
|
*
|
|
|
* @param roomUid 房间uid
|
|
|
* @param userId 用户id
|
|
@@ -124,14 +132,23 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
} else {
|
|
|
sysUser = getSysUser(userId);
|
|
|
}
|
|
|
+ osType = Optional.ofNullable(osType).orElse(1);
|
|
|
return queryRoomAndCheck(roomUid, sysUser, osType);
|
|
|
}
|
|
|
|
|
|
public ImLiveBroadcastRoomVo queryRoomAndCheck(String roomUid, SysUser sysUser, Integer osType) {
|
|
|
+ Optional<ImLiveBroadcastRoomVo> optional;
|
|
|
+ //如果是学生端,则需要检查是否有权限进入
|
|
|
+ if (osType == 1) {
|
|
|
+ Map<String, Object> param = new HashMap<>();
|
|
|
+ param.put("roomUid", roomUid);
|
|
|
+ optional = Optional.of(param).map(this::getImLiveBroadcastRoomVo);
|
|
|
+ optional.orElseThrow(() -> new BizException("您无法观看该直播"));
|
|
|
+ } else {
|
|
|
+ optional = Optional.ofNullable(roomUid).map(this::queryRoomInfo);
|
|
|
+ optional.orElseThrow(() -> new BizException("直播间不存在"));
|
|
|
+ }
|
|
|
//直播间信息校验
|
|
|
- Optional<ImLiveBroadcastRoomVo> optional = Optional.ofNullable(roomUid)
|
|
|
- .map(this::queryRoomInfo);
|
|
|
- optional.orElseThrow(() -> new BizException("直播间不存在"));
|
|
|
optional.filter(r -> r.getTenantId().equals(sysUser.getTenantId()))
|
|
|
.orElseThrow(() -> new BizException("您不是该直播机构人员,不可观看!"));
|
|
|
optional.filter(r -> r.getRoomState() != 1).orElseThrow(() -> new BizException("直播间不存在"));
|
|
@@ -181,6 +198,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
private ImLiveBroadcastRoomVo getImLiveBroadcastRoomVo(String roomUid) {
|
|
|
List<ImLiveBroadcastRoomVo> list = baseMapper.queryPage(new HashMap<String, Object>() {{
|
|
|
put("roomUid", roomUid);
|
|
|
+ put("allRoom", 1);
|
|
|
}});
|
|
|
if (CollectionUtils.isEmpty(list)) {
|
|
|
return null;
|
|
@@ -189,18 +207,52 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * 分页查询直播间列表
|
|
|
+ * 后台-分页查询直播间列表
|
|
|
*/
|
|
|
@Override
|
|
|
public PageInfo<ImLiveBroadcastRoomVo> queryPage(Map<String, Object> param) {
|
|
|
- Page<ImLiveBroadcastRoomVo> pageInfo = PageUtil.getPageInfo(param);
|
|
|
+ Page<ImLiveBroadcastRoomVo> pageInfo = PageUtil.concatTimePage(param, "startTime", "endTime");
|
|
|
pageInfo.setDesc("a.created_time_");
|
|
|
param.put("tenantId", TenantContextHolder.getTenantId());
|
|
|
- BiConsumer<String, String> addTimeCons = (key, time) -> Optional.ofNullable(param.get(key)).map(String::valueOf)
|
|
|
- .ifPresent(date -> param.put(key, date + " " + time));
|
|
|
- addTimeCons.accept("startTime", "00:00:00");
|
|
|
- addTimeCons.accept("endTime", "23:59:59");
|
|
|
+ //查询该人员分部 及 分部下包含的学校(合作单位)
|
|
|
+ SysUser sysUser = getSysUser();
|
|
|
+ //分部
|
|
|
+ String organIds;
|
|
|
+ //如果是超管就查询当前机构所有的直播间
|
|
|
+ if (sysUser.getTenantId() == -1 || sysUser.getIsSuperAdmin()) {
|
|
|
+ param.put("allRoom", 1);
|
|
|
+ } else {
|
|
|
+ Employee employee = employeeService.get(sysUser.getId());
|
|
|
+ if (Objects.nonNull(employee) && Objects.nonNull(employee.getOrganIdList())) {
|
|
|
+ organIds = employee.getOrganIdList();
|
|
|
+ param.put("organIds", organIds);
|
|
|
+ String schoolIds = baseMapper.querySchoolIds(organIds);
|
|
|
+ if (StringUtils.isNotBlank(schoolIds)) {
|
|
|
+ param.put("schoolIds", schoolIds);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
IPage<ImLiveBroadcastRoomVo> page = baseMapper.queryPage(pageInfo, param);
|
|
|
+
|
|
|
+ // 查询预约人数
|
|
|
+ List<ImLiveBroadcastRoomVo> records = page.getRecords();
|
|
|
+ if (CollectionUtils.isEmpty(records)) {
|
|
|
+ return PageUtil.pageInfo(page);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<String> roomIdList = records.stream().map(ImLiveBroadcastRoomVo::getRoomUid).collect(Collectors.toList());
|
|
|
+
|
|
|
+ List<ImLiveBroadcastRoomVo> countRoomReservationList = imLiveRoomReservationService.countRoomReservation(roomIdList);
|
|
|
+ Map<String, List<ImLiveBroadcastRoomVo>> collect = countRoomReservationList.stream()
|
|
|
+ .collect(Collectors.groupingBy(ImLiveBroadcastRoomVo::getRoomUid));
|
|
|
+ for (ImLiveBroadcastRoomVo record : records) {
|
|
|
+ List<ImLiveBroadcastRoomVo> imLiveBroadcastRoomVos = collect.get(record.getRoomUid());
|
|
|
+ if (CollectionUtils.isEmpty(imLiveBroadcastRoomVos)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ record.setRoomReservationNum(imLiveBroadcastRoomVos.get(0).getRoomReservationNum());
|
|
|
+ }
|
|
|
+
|
|
|
return PageUtil.pageInfo(page);
|
|
|
}
|
|
|
|
|
@@ -239,14 +291,38 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
public void update(ImLiveBroadcastRoomDto dto) {
|
|
|
Date now = new Date();
|
|
|
+ Integer userId = getSysUser().getId();
|
|
|
+ ImLiveBroadcastRoom obj = this.getById(dto.getId());
|
|
|
+ obj.setUpdatedBy(userId);
|
|
|
+ obj.setUpdatedTime(now);
|
|
|
+ //如果直播已经则只能修改是否全员禁麦 和聊天功能
|
|
|
+ if (obj.getLiveState() == 1) {
|
|
|
+ obj.setRoomConfig(JSONObject.toJSONString(dto.getRoomConfig()));
|
|
|
+ this.updateById(obj);
|
|
|
+ return;
|
|
|
+ }
|
|
|
if (now.getTime() > dto.getLiveStartTime().getTime()) {
|
|
|
throw new BizException("设置的直播开始时间不能小于当前时间");
|
|
|
}
|
|
|
- ImLiveBroadcastRoom obj = this.getById(dto.getId());
|
|
|
+
|
|
|
+ String popularizeType = dto.getPopularizeType();
|
|
|
+ switch (popularizeType) {
|
|
|
+ case ImLiveBroadcastRoom.ALL:
|
|
|
+ dto.setPopularizeOrgIds(null);
|
|
|
+ dto.setPopularizeSchoolIds(null);
|
|
|
+ dto.setPopularizeTeamIds(null);
|
|
|
+ break;
|
|
|
+ case ImLiveBroadcastRoom.ORGAN:
|
|
|
+ dto.setPopularizeSchoolIds(null);
|
|
|
+ dto.setPopularizeTeamIds(null);
|
|
|
+ break;
|
|
|
+ case ImLiveBroadcastRoom.SCHOOL:
|
|
|
+ dto.setPopularizeTeamIds(null);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
BeanUtils.copyProperties(dto, obj);
|
|
|
obj.setRoomConfig(JSONObject.toJSONString(dto.getRoomConfig()));
|
|
|
- obj.setUpdatedBy(getSysUser().getId());
|
|
|
- obj.setUpdatedTime(now);
|
|
|
log.info("update room >>> :{}", JSONObject.toJSONString(obj));
|
|
|
this.updateById(obj);
|
|
|
}
|
|
@@ -330,21 +406,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
*/
|
|
|
@Override
|
|
|
public ImLiveBroadcastRoomVo queryPopularizeRoom() {
|
|
|
- //查询该学生信息-获取分部
|
|
|
- SysUser user = getSysUser();
|
|
|
- //查询哪些分部无法推广直播间
|
|
|
- String popularizeOrgan = sysConfigDao.findConfigValue("live_popularize_organ");
|
|
|
- if (StringUtils.isNotBlank(popularizeOrgan)) {
|
|
|
- List<String> organList = WrapperUtil.toList(popularizeOrgan);
|
|
|
- if (Objects.nonNull(user.getOrganId()) && !organList.contains(user.getOrganId().toString())) {
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
Map<String, Object> param = new HashMap<>();
|
|
|
param.put("tenantId", TenantContextHolder.getTenantId());
|
|
|
param.put("popularize", 1);
|
|
|
param.put("liveState", 1);
|
|
|
- List<ImLiveBroadcastRoomVo> list = baseMapper.queryPage(param);
|
|
|
+ return getImLiveBroadcastRoomVo(param);
|
|
|
+ }
|
|
|
+
|
|
|
+ private ImLiveBroadcastRoomVo getImLiveBroadcastRoomVo(Map<String, Object> param) {
|
|
|
+ PageInfo<ImLiveBroadcastRoomVo> pageInfo = imLiveRoomReservationService.queryPageStudent(param);
|
|
|
+ List<ImLiveBroadcastRoomVo> list = pageInfo.getRows();
|
|
|
if (CollectionUtils.isNotEmpty(list)) {
|
|
|
return list.get(0);
|
|
|
}
|
|
@@ -389,9 +460,27 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
return;
|
|
|
}
|
|
|
//获取直播间主讲人信息
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, room.getSpeakerId().toString()));
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(room.getRoomUid(), room.getSpeakerId().toString());
|
|
|
if (speakerCache.isExists()) {
|
|
|
RoomSpeakerInfo speakerInfo = speakerCache.get();
|
|
|
+ //查询用户是否在线
|
|
|
+ if (imFeignService.checkOnline(speakerInfo.getSpeakerId().toString())) {
|
|
|
+ log.info("roomDestroy destroyExpiredLiveRoom is online >>>> roomId:{} speakerId:{}", room.getId(), speakerInfo.getSpeakerId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //校验房间心跳是否过期没续租
|
|
|
+ RBucket<Date> lastRoomHeartbeatCache = redissonClient.getBucket(LIVE_ROOM_SPEAKER_HEART_BEAT.replace(ROOM_UID, room.getRoomUid()));
|
|
|
+ if (lastRoomHeartbeatCache.isExists()) {
|
|
|
+ //获取最后一次房间心跳时间
|
|
|
+ Date lastDate = lastRoomHeartbeatCache.get();
|
|
|
+ //房间心跳过期时间 = 将房间心跳时间+过期分钟
|
|
|
+ Date lastRoomDateExpired = DateUtil.addMinutes(lastDate, expiredMinute);
|
|
|
+ //当前时间 小于 房间心跳过期时间 则不销毁
|
|
|
+ if (now.getTime() <= lastRoomDateExpired.getTime()) {
|
|
|
+ log.info("roomDestroy destroyExpiredLiveRoom last room heartbeat >>>> roomId:{} speakerId:{}", room.getId(), speakerInfo.getSpeakerId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
//1.主播没有进入房间,则直接销毁房间
|
|
|
if (Objects.isNull(speakerInfo.getJoinRoomTime())) {
|
|
|
log.info("roomDestroy not joinRoom >>>> cache : {}", JSONObject.toJSONString(test(room.getRoomUid())));
|
|
@@ -479,7 +568,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
imFeignService.publishRoomMsg(message);
|
|
|
log.info("roomDestroy>>>> FORCED_OFFLINE {}", JSONObject.toJSONString(message));
|
|
|
//销毁直播间
|
|
|
- imFeignService.destroyLiveRoom(roomUid);
|
|
|
+// imFeignService.destroyLiveRoom(roomUid);
|
|
|
log.info("roomDestroy>>>> destroyLiveRoom {}", JSONObject.toJSONString(message));
|
|
|
} catch (Exception e) {
|
|
|
log.error("roomDestroy>>>> errorMsg{}", e.getMessage(), e.getCause());
|
|
@@ -519,7 +608,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
}
|
|
|
int speakerLiveTime = 0;
|
|
|
//获取直播间主讲人信息 写入im_live_broadcast_room_data
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, speakerId.toString()));
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, speakerId.toString());
|
|
|
if (speakerCache.isExists()) {
|
|
|
ImLiveBroadcastRoomData liveData = new ImLiveBroadcastRoomData();
|
|
|
RoomSpeakerInfo speakerInfo = speakerCache.get();
|
|
@@ -567,6 +656,8 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
@Override
|
|
|
public void syncLike(String roomUid, Integer likeNum) {
|
|
|
redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).set(likeNum);
|
|
|
+ //增加房间心跳
|
|
|
+ redissonClient.getBucket(LIVE_ROOM_SPEAKER_HEART_BEAT.replace(ROOM_UID, roomUid)).set(new Date());
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -599,20 +690,20 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
}
|
|
|
//将最新的时间写入缓存
|
|
|
userStateTimeCache.set(userStateTime, 5L, TimeUnit.MINUTES);
|
|
|
+ //获取当前用户所在房间的uid
|
|
|
+ RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userid));
|
|
|
+ if (!userRoom.isExists()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String roomUid = userRoom.get();
|
|
|
//查询userId是不是主讲人 ,如果是主讲人则返回
|
|
|
- if (isSpeaker(user, now, userid)) {
|
|
|
+ if (isSpeaker(user, now, userid, roomUid)) {
|
|
|
return;
|
|
|
}
|
|
|
//这里开始只处理观看者的数据,观看者只接受退出消息 status=0 是进入房间
|
|
|
if (user.getStatus().equals("0")) {
|
|
|
return;
|
|
|
}
|
|
|
- //获取当前用户所在房间的uid
|
|
|
- RBucket<String> userRoom = redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userid));
|
|
|
- if (!userRoom.isExists()) {
|
|
|
- return;
|
|
|
- }
|
|
|
- String roomUid = userRoom.get();
|
|
|
Integer userId = Integer.valueOf(userid);
|
|
|
|
|
|
//从房间累计用户信息中查询该用户的信息
|
|
@@ -692,19 +783,34 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
*
|
|
|
* @return true 是主讲人 false 不是主讲人
|
|
|
*/
|
|
|
- private boolean isSpeaker(ImUserState user, Date now, String userid) {
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userid));
|
|
|
+ private boolean isSpeaker(ImUserState user, Date now, String userid, String roomUid) {
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userid);
|
|
|
if (!speakerCache.isExists()) {
|
|
|
return false;
|
|
|
}
|
|
|
RoomSpeakerInfo speakerInfo = speakerCache.get();
|
|
|
+ //最后一次进入房间的clientIp
|
|
|
+ RBucket<String> lastClientIp = redissonClient.getBucket(LIVE_SPEAKER_LAST_CLIENT_IP.replace(ROOM_UID, roomUid).replace(USER_ID, userid));
|
|
|
//主讲人进入房间
|
|
|
if (user.getStatus().equals("0")) {
|
|
|
speakerInfo.setJoinRoomTime(now);
|
|
|
log.info("opsRoom>>>> join speakerCache {}", JSONObject.toJSONString(speakerInfo));
|
|
|
speakerCache.set(speakerInfo);
|
|
|
+ //将本次进入房间的clientIp添加到主讲人最后一次clientIp缓存中
|
|
|
+ if (StringUtils.isNotBlank(user.getClientIp())) {
|
|
|
+ lastClientIp.set(user.getClientIp());
|
|
|
+ }
|
|
|
return true;
|
|
|
}
|
|
|
+ //校验本次退出直播间的clientIp 是不是上次进入房间的clientIp
|
|
|
+ if (StringUtils.isNotBlank(user.getClientIp())) {
|
|
|
+ if (lastClientIp.isExists()) {
|
|
|
+ //如果是上次进入房间的clientIp和本次退出房间的clientIp不相同,则直接忽略
|
|
|
+ if (!user.getClientIp().equals(lastClientIp.get())) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
//主讲人退出房间关闭录像
|
|
|
closeLive(speakerInfo);
|
|
|
speakerInfo.setExitRoomTime(now);
|
|
@@ -727,15 +833,17 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
}
|
|
|
Date now = new Date();
|
|
|
//获取直播间信息
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString()));
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
|
|
|
if (!speakerCache.isExists()) {
|
|
|
//没有主讲人信息则生成一个
|
|
|
createSpeakerInfo(this.getById(roomVo.getId()), sysUser);
|
|
|
- speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString()));
|
|
|
+ speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
|
|
|
}
|
|
|
RoomSpeakerInfo speakerInfo = speakerCache.get();
|
|
|
speakerInfo.setJoinRoomTime(now);
|
|
|
speakerCache.set(speakerInfo);
|
|
|
+ //记录用户当前房间uid
|
|
|
+ redissonClient.getBucket(LIVE_USER_ROOM.replace(USER_ID, userId.toString())).set(roomUid, 12L, TimeUnit.HOURS);
|
|
|
return roomVo;
|
|
|
}
|
|
|
|
|
@@ -769,7 +877,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
userInfo.setTotalViewTime(0);
|
|
|
}
|
|
|
//查询主讲人信息
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, imLiveBroadcastRoomVo.getSpeakerId().toString()));
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, imLiveBroadcastRoomVo.getSpeakerId().toString());
|
|
|
if (speakerCache.isExists()) {
|
|
|
//如果用户进来时主讲人已经开启直播则修改学生观看时间
|
|
|
Integer state = speakerCache.get().getState();
|
|
@@ -795,7 +903,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
*/
|
|
|
public void startLive(String roomUid, Integer userId) {
|
|
|
//查询房间信息
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString()));
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
|
|
|
if (!speakerCache.isExists()) {
|
|
|
return;
|
|
|
}
|
|
@@ -831,7 +939,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
*/
|
|
|
public void closeLive(String roomUid, Integer userId) {
|
|
|
//查询房间主播信息
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId.toString()));
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId.toString());
|
|
|
if (!speakerCache.isExists()) {
|
|
|
return;
|
|
|
}
|
|
@@ -902,7 +1010,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
if (onlineUserInfoExists && onlineUserInfo.containsKey(id)) {
|
|
|
if (type.equals(1)) {
|
|
|
//开启直播后对当前在房间的用户写入观看时间
|
|
|
- userInfo.setDynamicLookTime(new Date());
|
|
|
+ userInfo.setDynamicLookTime(now);
|
|
|
} else if (type.equals(2)) {
|
|
|
userInfo.setTotalViewTime(getLookMinutes(userInfo.getDynamicLookTime(), now, userInfo.getTotalViewTime()));
|
|
|
userInfo.setDynamicLookTime(null);
|
|
@@ -990,7 +1098,7 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
speakerInfo.setWhetherVideo(1);
|
|
|
}
|
|
|
//写入主讲人信息
|
|
|
- redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, room.getSpeakerId().toString())).set(speakerInfo);
|
|
|
+ getRoomSpeakerInfoCache(room.getRoomUid(), room.getSpeakerId().toString()).set(speakerInfo);
|
|
|
|
|
|
//生成0点赞
|
|
|
redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, room.getRoomUid())).set(0);
|
|
@@ -1036,13 +1144,13 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
private SysUser getSysUser(Integer userId) {
|
|
|
return Optional.ofNullable(userId)
|
|
|
.map(sysUserFeignService::queryUserById)
|
|
|
- .orElseThrow(() -> new BizException("用户不存在"));
|
|
|
+ .orElseThrow(() -> new BizException("用户不存在."));
|
|
|
}
|
|
|
|
|
|
private SysUser getSysUser() {
|
|
|
//修改机构基础信息
|
|
|
return Optional.ofNullable(sysUserFeignService.queryUserInfo())
|
|
|
- .orElseThrow(() -> new BizException("用户不存在"));
|
|
|
+ .orElseThrow(() -> new BizException("用户不存在."));
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1051,6 +1159,26 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
public Map<String, Object> test(String roomUid) {
|
|
|
//test
|
|
|
Map<String, Object> result = new HashMap<>();
|
|
|
+ //校验房间心跳是否过期没续租
|
|
|
+ RBucket<Date> lastRoomHeartbeatCache = redissonClient.getBucket(LIVE_ROOM_SPEAKER_HEART_BEAT.replace(ROOM_UID, roomUid));
|
|
|
+ if (lastRoomHeartbeatCache.isExists()) {
|
|
|
+ result.put("房间心跳", DateUtil.dateToString(lastRoomHeartbeatCache.get(), DateUtil.EXPANDED_DATE_TIME_FORMAT));
|
|
|
+ } else {
|
|
|
+ result.put("房间心跳", "房间心跳不存在");
|
|
|
+ }
|
|
|
+ String userId = "";
|
|
|
+ try {
|
|
|
+ String[] split = roomUid.split("-");
|
|
|
+ userId = split[1];
|
|
|
+ } catch (Exception ignored) {
|
|
|
+ }
|
|
|
+ //获取主讲人信息
|
|
|
+ RBucket<RoomSpeakerInfo> speakerCache = getRoomSpeakerInfoCache(roomUid, userId);
|
|
|
+ if (speakerCache.isExists()) {
|
|
|
+ result.put("主讲人信息", speakerCache.get());
|
|
|
+ } else {
|
|
|
+ result.put("主讲人信息", "主讲人信息不存在");
|
|
|
+ }
|
|
|
//点赞数
|
|
|
Object like = redissonClient.getBucket(LIVE_ROOM_LIKE.replace(ROOM_UID, roomUid)).get();
|
|
|
if (Objects.isNull(like)) {
|
|
@@ -1067,29 +1195,15 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
if (CollectionUtils.isNotEmpty(totalUserInfo)) {
|
|
|
if (CollectionUtils.isNotEmpty(inRoomUserInfo)) {
|
|
|
look = inRoomUserInfo.size();
|
|
|
- result.put("正在观看的人员信息", inRoomUserInfo);
|
|
|
+// result.put("正在观看的人员信息", inRoomUserInfo);
|
|
|
} else {
|
|
|
result.put("正在观看的人员信息", "没有正在观看的人员数据");
|
|
|
}
|
|
|
totalLook = totalUserInfo.size();
|
|
|
- result.put("总人员数据", totalUserInfo);
|
|
|
+// result.put("总人员数据", totalUserInfo);
|
|
|
} else {
|
|
|
result.put("总人员数据", "没有人员数据");
|
|
|
}
|
|
|
- String userId = "";
|
|
|
- try {
|
|
|
- String[] split = roomUid.split("-");
|
|
|
- userId = split[1];
|
|
|
- } catch (Exception ignored) {
|
|
|
- }
|
|
|
-
|
|
|
- //获取主讲人信息
|
|
|
- RBucket<RoomSpeakerInfo> speakerCache = redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId));
|
|
|
- if (speakerCache.isExists()) {
|
|
|
- result.put("主讲人信息", speakerCache.get());
|
|
|
- } else {
|
|
|
- result.put("主讲人信息", "主讲人信息不存在");
|
|
|
- }
|
|
|
result.put("总观看人数", totalLook);
|
|
|
result.put("实时观看数", look);
|
|
|
return result;
|
|
@@ -1148,6 +1262,70 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
.orElseThrow(() -> new BizException("用户id集合不能为空"));
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public PageInfo<RoomReservationUserVo> queryRoomUser(RoomReservationUserSearch query) {
|
|
|
+ IPage<RoomReservationUserVo> page = PageUtil.getPage(query.getPage(), query.getRows());
|
|
|
+ page = baseMapper.queryRoomUser(page, query);
|
|
|
+ return PageUtil.pageInfo(page);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 导出直播间预约用户信息
|
|
|
+ *
|
|
|
+ * @param query
|
|
|
+ * @param response
|
|
|
+ */
|
|
|
+ public void exportReservationRoomUser(RoomReservationUserSearch query, HttpServletResponse response) throws IOException {
|
|
|
+ //训练营详情-查询条件时间设置
|
|
|
+ List<RoomReservationUserVo> list = baseMapper.queryRoomUser(query);
|
|
|
+ OutputStream outputStream = response.getOutputStream();
|
|
|
+ HSSFWorkbook workbook = null;
|
|
|
+ try {
|
|
|
+ String[] header = {"编号", "姓名", "手机号", "分部", "声部"};
|
|
|
+ String[] body = {"userId", "username", "phone", "organName", "subjectName"};
|
|
|
+ workbook = POIUtil.exportExcel(header, body, list);
|
|
|
+ response.setContentType("application/octet-stream");
|
|
|
+ response.setHeader("Content-Disposition", "attachment;filename=replacement-" + DateUtil.getDate(new Date()) + ".xls");
|
|
|
+ response.flushBuffer();
|
|
|
+ outputStream = response.getOutputStream();
|
|
|
+ workbook.write(outputStream);
|
|
|
+ outputStream.flush();
|
|
|
+ workbook.close();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ if (outputStream != null) {
|
|
|
+ try {
|
|
|
+ workbook.close();
|
|
|
+ outputStream.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PageInfo<LiveRoomGoodsOrderVo> queryLiveRoomGoodsOrderList(LiveRoomGoodsOrderQueryInfo queryInfo) {
|
|
|
+ PageInfo<LiveRoomGoodsOrderVo> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
|
|
|
+ Map<String, Object> params = new HashMap<String, Object>();
|
|
|
+ MapUtil.populateMap(params, queryInfo);
|
|
|
+
|
|
|
+ List<LiveRoomGoodsOrderVo> dataList = null;
|
|
|
+ int count = baseMapper.countLiveRoomGoodsOrderList(params);
|
|
|
+ if (count > 0) {
|
|
|
+ pageInfo.setTotal(count);
|
|
|
+ params.put("offset", pageInfo.getOffset());
|
|
|
+ dataList = baseMapper.queryLiveRoomGoodsOrderList(params);
|
|
|
+ pageInfo.setStatInfo(baseMapper.sumLiveRoomGoodsOrderList(params));
|
|
|
+ }
|
|
|
+ if (count == 0) {
|
|
|
+ dataList = new ArrayList<>();
|
|
|
+ }
|
|
|
+ pageInfo.setRows(dataList);
|
|
|
+ return pageInfo;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 查询直播间所有用户信息
|
|
|
*
|
|
@@ -1180,6 +1358,16 @@ public class ImLiveBroadcastRoomServiceImpl extends ServiceImpl<ImLiveBroadcastR
|
|
|
return redissonClient.getMap(LIVE_ROOM_TOTAL_USER_LIST.replace(ROOM_UID, roomUid));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 获取房间主讲人消息
|
|
|
+ *
|
|
|
+ * @param roomUid 房间uid
|
|
|
+ * @param userId 用户id
|
|
|
+ */
|
|
|
+ private RBucket<RoomSpeakerInfo> getRoomSpeakerInfoCache(String roomUid, String userId) {
|
|
|
+ return redissonClient.getBucket(LIVE_SPEAKER_INFO.replace(USER_ID, userId).replace(ROOM_UID, roomUid));
|
|
|
+ }
|
|
|
+
|
|
|
private RoomUserInfoVo getUserInfo(Integer userId) {
|
|
|
RoomUserInfoVo userInfo = new RoomUserInfoVo();
|
|
|
userInfo.setUserId(userId);
|