|
|
@@ -5,26 +5,43 @@ import cn.hutool.core.bean.BeanUtil;
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
import cn.hutool.core.thread.ThreadUtil;
|
|
|
import com.alibaba.fastjson.JSON;
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.fs.common.constant.LiveKeysConstant;
|
|
|
import com.fs.common.core.domain.R;
|
|
|
import com.fs.common.core.redis.RedisCache;
|
|
|
import com.fs.common.utils.DateUtils;
|
|
|
import com.fs.common.utils.StringUtils;
|
|
|
+import com.fs.course.domain.FsCourseLink;
|
|
|
+import com.fs.course.service.impl.FsUserCourseVideoServiceImpl;
|
|
|
import com.fs.his.domain.FsUser;
|
|
|
+import com.fs.his.mapper.FsUserMapper;
|
|
|
import com.fs.his.service.IFsUserService;
|
|
|
import com.fs.hisStore.domain.FsUserScrm;
|
|
|
import com.fs.hisStore.service.IFsUserScrmService;
|
|
|
import com.fs.live.domain.Live;
|
|
|
import com.fs.live.domain.LiveVideo;
|
|
|
+import com.fs.live.domain.LiveWatchLog;
|
|
|
import com.fs.live.domain.LiveWatchUser;
|
|
|
-import com.fs.live.mapper.LiveWatchUserMapper;
|
|
|
-import com.fs.live.mapper.LiveMapper;
|
|
|
-import com.fs.live.mapper.LiveVideoMapper;
|
|
|
+import com.fs.live.mapper.*;
|
|
|
+import com.fs.live.param.LiveIsAddKfParam;
|
|
|
import com.fs.live.service.ILiveWatchUserService;
|
|
|
-import com.fs.live.vo.LiveWatchUserStatistics;
|
|
|
-import com.fs.live.vo.LiveWatchUserVO;
|
|
|
+import com.fs.live.vo.*;
|
|
|
+import com.fs.qw.domain.QwExternalContact;
|
|
|
+import com.fs.qwApi.domain.QwResult;
|
|
|
+import com.fs.qwApi.param.QwEditUserTagParam;
|
|
|
+import com.fs.qwApi.service.QwApiService;
|
|
|
+import com.fs.qw.domain.QwGroupChat;
|
|
|
+import com.fs.qw.domain.QwGroupChatUser;
|
|
|
+import com.fs.qw.mapper.QwExternalContactMapper;
|
|
|
+import com.fs.qw.mapper.QwGroupChatMapper;
|
|
|
+import com.fs.qw.mapper.QwGroupChatUserMapper;
|
|
|
+import com.fs.sop.domain.SopUserLogsInfo;
|
|
|
+import com.fs.sop.service.ISopUserLogsInfoService;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.util.*;
|
|
|
@@ -52,8 +69,27 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
|
|
|
private LiveMapper liveMapper;
|
|
|
@Autowired
|
|
|
private LiveVideoMapper liveVideoMapper;
|
|
|
+ @Autowired
|
|
|
+ private FsUserMapper fsUserMapper;
|
|
|
+ @Autowired
|
|
|
+ private QwGroupChatMapper qwGroupChatMapper;
|
|
|
+ @Autowired
|
|
|
+ private QwGroupChatUserMapper qwGroupChatUserMapper;
|
|
|
+ @Autowired
|
|
|
+ private QwExternalContactMapper qwExternalContactMapper;
|
|
|
+ @Autowired
|
|
|
+ private LiveWatchLogMapper liveWatchLogMapper;
|
|
|
+ @Autowired
|
|
|
+ private ISopUserLogsInfoService iSopUserLogsInfoService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ LiveTagConfigMapper liveTagConfigMapper;
|
|
|
+ @Autowired
|
|
|
+ private com.fs.qwApi.service.QwApiService qwApiService;
|
|
|
|
|
|
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(LiveWatchUserServiceImpl.class);
|
|
|
+
|
|
|
/**
|
|
|
* 查询直播间观看用户
|
|
|
*
|
|
|
@@ -309,14 +345,6 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
|
|
|
|
|
|
// 使用唯一索引查询:live_id, user_id, live_flag, replay_flag
|
|
|
LiveWatchUser liveWatchUser = baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);
|
|
|
- // 设置在线时长
|
|
|
- try {
|
|
|
- Long onlineSeconds = liveWatchUser.getOnlineSeconds();
|
|
|
- if(onlineSeconds == null) onlineSeconds = 0L;
|
|
|
- liveWatchUser.setOnlineSeconds(onlineSeconds + (System.currentTimeMillis() - liveWatchUser.getUpdateTime().getTime()) / 1000);
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("设置在线时长异常:{}", e.getMessage());
|
|
|
- }
|
|
|
liveWatchUser.setUpdateTime(DateUtils.getNowDate());
|
|
|
liveWatchUser.setOnline(1);
|
|
|
baseMapper.updateLiveWatchUser(liveWatchUser);
|
|
|
@@ -507,4 +535,481 @@ public class LiveWatchUserServiceImpl implements ILiveWatchUserService {
|
|
|
return baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 直播链接打开判定是否添加客户
|
|
|
+ * @param param
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public R liveIsAddKf(LiveIsAddKfParam param) {
|
|
|
+
|
|
|
+ logger.info("【直播判断添加客服】:{}", param);
|
|
|
+ //查询用户
|
|
|
+ FsUser fsUser = fsUserMapper.selectFsUserByUserId(param.getUserId());
|
|
|
+ //用户不存在唤起重新授权
|
|
|
+ if (fsUser == null) {
|
|
|
+ return R.error(401, "未授权");
|
|
|
+ }
|
|
|
+ if (fsUser.getStatus() == 0) {
|
|
|
+ return R.error("会员被停用,无权限,请联系客服!");
|
|
|
+ }
|
|
|
+ //未注册提示
|
|
|
+ String noRegisterMsg = "由于您还未完成注册,请联系伴学助手完成注册即可观看!";
|
|
|
+ //非独属链接提示
|
|
|
+ String noMemberMsg = "此链接已被绑定,请联系伴学助手领取您的专属链接,专属链接请勿分享哦!";
|
|
|
+
|
|
|
+ if (StringUtils.isNotBlank(param.getChatId())) {
|
|
|
+ return handleLiveChat(param,fsUser, noMemberMsg, noRegisterMsg);
|
|
|
+ } else if (null != param.getQwExternalId()) {
|
|
|
+ return handleLivePerson(param,fsUser, noMemberMsg, noRegisterMsg);
|
|
|
+ } else {
|
|
|
+ return R.error("直播参数错误");
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LiveWatchUserEntry selectLiveWatchAndCompanyUserByFlag(Long liveId, Long userId, Integer liveFlag, Integer replayFlag) {
|
|
|
+ return baseMapper.selectLiveWatchAndCompanyUserByFlag(liveId,userId,liveFlag,replayFlag);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void updateLiveWatchUserEntry(LiveWatchUserEntry liveWatchUser) {
|
|
|
+ LiveWatchUser updateEntity = new LiveWatchUser();
|
|
|
+ BeanUtil.copyProperties(updateEntity, liveWatchUser);
|
|
|
+ baseMapper.updateLiveWatchUser(updateEntity);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理发送群聊逻辑
|
|
|
+ * @param param
|
|
|
+ * @param user
|
|
|
+ * @param noMemberMsg
|
|
|
+ * @param noRegisterMsg
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R handleLiveChat(LiveIsAddKfParam param,FsUser user, String noMemberMsg,String noRegisterMsg){
|
|
|
+
|
|
|
+ QwGroupChat qwGroupChat = qwGroupChatMapper.selectQwGroupChatByChatId(param.getChatId());
|
|
|
+ if (qwGroupChat == null) {
|
|
|
+ return R.error("直播群参数异常");
|
|
|
+ }
|
|
|
+ SopUserLogsInfo sopUserLogsInfo = new SopUserLogsInfo();
|
|
|
+ sopUserLogsInfo.setChatId(param.getChatId());
|
|
|
+ List<QwGroupChatUser> qwGroupChatUsers = qwGroupChatUserMapper.selectByChatId(sopUserLogsInfo);
|
|
|
+ if (qwGroupChatUsers == null || qwGroupChatUsers.isEmpty()) {
|
|
|
+ return R.error("直播群参数异常");
|
|
|
+ }
|
|
|
+
|
|
|
+ QwExternalContact qwExternalContact = null;
|
|
|
+ if (null != param.getUserId() && null == qwExternalContact) {
|
|
|
+ try {
|
|
|
+ qwExternalContact = qwExternalContactMapper.selectOne(new QueryWrapper<QwExternalContact>()
|
|
|
+ .eq("user_id", qwGroupChat.getOwner())
|
|
|
+ .eq("fs_user_id", param.getUserId())
|
|
|
+ .eq("corp_id", param.getCorpId())
|
|
|
+ .eq("status", 0));
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("直播群聊用户id匹配异常,参数user_id:{},fs_user_id:{},corp_id:{}", qwGroupChat.getOwner(), param.getUserId(), param.getCorpId(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotBlank(param.getChatId()) && null == qwExternalContact) {
|
|
|
+ List<QwExternalContact> groupChatUserByChatIdAndUserName = qwExternalContactMapper.getGroupChatUserByChatIdAndUserName(qwGroupChat.getOwner(), user.getNickName(), param.getCorpId(), param.getChatId());
|
|
|
+ log.info("直播群聊用户查询结果,参数user_id:{},name:{},corp_id:{},chatId:{},groupChatUserByChatIdAndUserName:{}", qwGroupChat.getOwner(), user.getNickName(), param.getCorpId(), param.getChatId(), groupChatUserByChatIdAndUserName);
|
|
|
+ //没找到用户 || 找到的用户数量大于1 使用userid查询匹配
|
|
|
+ if (null == groupChatUserByChatIdAndUserName || groupChatUserByChatIdAndUserName.isEmpty() || groupChatUserByChatIdAndUserName.size() > 1) {
|
|
|
+ log.error("直播群聊用户昵称匹配异常,参数user_id:{},name:{},corp_id:{},chatId:{}", qwGroupChat.getOwner(), user.getNickName(), param.getCorpId(), param.getChatId());
|
|
|
+ } else {
|
|
|
+ qwExternalContact = groupChatUserByChatIdAndUserName.get(0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(qwExternalContact==null){
|
|
|
+ return R.error(noRegisterMsg);
|
|
|
+ }
|
|
|
+ QwExternalContact finalQwExternalContact = qwExternalContact;
|
|
|
+ if (qwGroupChatUsers.stream().noneMatch(e -> e.getUserId().equals(finalQwExternalContact.getExternalUserId()))) {
|
|
|
+ log.error("直播客户不在群:{},里面:{}", qwGroupChat.getChatId(), qwExternalContact.getExternalUserId());
|
|
|
+ return R.error(noRegisterMsg);
|
|
|
+ }
|
|
|
+ Long qwExternalId = qwExternalContact.getId();
|
|
|
+
|
|
|
+ LiveWatchLog liveWatchLog = liveWatchLogMapper.selectOneLogByLiveIdAndQwUserIdAndExternalId(param.getLiveId(), param.getQwUserId(),qwExternalId);
|
|
|
+ if (liveWatchLog==null ){
|
|
|
+ return R.error(noRegisterMsg);
|
|
|
+ }
|
|
|
+ //判断外部联系人有没有绑定userId
|
|
|
+ if (qwExternalContact.getFsUserId() != null) {
|
|
|
+ //有客户有小程序id 但 登录的小程序id和根据外部联系人id查出来的小程序id不一致
|
|
|
+ if (!qwExternalContact.getFsUserId().equals(param.getUserId())) {
|
|
|
+ return R.error(noRegisterMsg);
|
|
|
+ }
|
|
|
+ List<QwExternalContact> qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByMiniUserId(param.getUserId());
|
|
|
+ //匹配客户公司id
|
|
|
+ if (qwExternalContacts.stream().noneMatch(contact -> contact.getCorpId().equals(param.getCorpId()))){
|
|
|
+ return R.error(noRegisterMsg);
|
|
|
+ }
|
|
|
+
|
|
|
+ //看课记录中userId为0绑定userId
|
|
|
+ if (liveWatchLog.getUserId() == null || liveWatchLog.getUserId().equals(0L) || !liveWatchLog.getUserId().equals(param.getUserId())) {
|
|
|
+ liveWatchLog.setUserId(param.getUserId());
|
|
|
+ }
|
|
|
+
|
|
|
+ liveWatchLog.setUpdateTime(new Date());
|
|
|
+
|
|
|
+ liveWatchLogMapper.updateLiveWatchLog(liveWatchLog);
|
|
|
+ iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId, param.getUserId());
|
|
|
+
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //没绑定fsUser直接绑定fsUser
|
|
|
+ QwExternalContact contact = new QwExternalContact();
|
|
|
+ contact.setId(qwExternalId);
|
|
|
+ contact.setFsUserId(param.getUserId());
|
|
|
+ qwExternalContactMapper.updateQwExternalContact(contact);
|
|
|
+ iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId, param.getUserId());
|
|
|
+
|
|
|
+ FsUser fsUser = new FsUser();
|
|
|
+ fsUser.setUserId(user.getUserId());
|
|
|
+ fsUser.setIsAddQw(1);
|
|
|
+ fsUserMapper.updateFsUser(fsUser);
|
|
|
+ //绑定上之后 更新观看记录
|
|
|
+ //看课记录中userId为0绑定userId
|
|
|
+ liveWatchLog.setUserId(param.getUserId());
|
|
|
+ liveWatchLog.setUpdateTime(new Date());
|
|
|
+ liveWatchLogMapper.updateLiveWatchLog(liveWatchLog);
|
|
|
+ }
|
|
|
+
|
|
|
+ return R.ok();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理发送个人逻辑
|
|
|
+ * @param param
|
|
|
+ * @param noMemberMsg
|
|
|
+ * @param noRegisterMsg
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public R handleLivePerson(LiveIsAddKfParam param,FsUser user,String noMemberMsg,String noRegisterMsg){
|
|
|
+
|
|
|
+ Long qwExternalId = param.getQwExternalId();
|
|
|
+
|
|
|
+ LiveWatchLog liveWatchLog = liveWatchLogMapper.selectOneLogByLiveIdAndQwUserIdAndExternalId(param.getLiveId(), param.getQwUserId(),qwExternalId);
|
|
|
+
|
|
|
+ if (liveWatchLog==null ){
|
|
|
+ return R.error(noMemberMsg);
|
|
|
+ }
|
|
|
+ //查询是否有添加客服
|
|
|
+ QwExternalContact externalContact = qwExternalContactMapper.selectQwExternalContactById(qwExternalId);
|
|
|
+
|
|
|
+ //用小程序id查询外部联系人
|
|
|
+ List<QwExternalContact> qwExternalContacts = qwExternalContactMapper.selectQwExternalContactByMiniUserId(param.getUserId());
|
|
|
+
|
|
|
+ //判断外部联系人有没有绑定userId
|
|
|
+ if (externalContact.getFsUserId() != null) {
|
|
|
+ //有客户有小程序id 但 登录的小程序id和根据外部联系人id查出来的小程序id不一致
|
|
|
+ if (!externalContact.getFsUserId().equals(param.getUserId())) {
|
|
|
+ return R.error(noMemberMsg);
|
|
|
+ }
|
|
|
+ //匹配客户公司id
|
|
|
+ if (qwExternalContacts.stream().noneMatch(contact -> contact.getCorpId().equals(param.getCorpId()))){
|
|
|
+ return R.error(noMemberMsg);
|
|
|
+ }
|
|
|
+
|
|
|
+ //看课记录中userId为0绑定userId
|
|
|
+ if (liveWatchLog.getUserId() == null || liveWatchLog.getUserId().equals(0L) || !liveWatchLog.getUserId().equals(param.getUserId())) {
|
|
|
+ liveWatchLog.setUserId(param.getUserId());
|
|
|
+ }
|
|
|
+
|
|
|
+ liveWatchLog.setUpdateTime(new Date());
|
|
|
+
|
|
|
+ liveWatchLogMapper.updateLiveWatchLog(liveWatchLog);
|
|
|
+ iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId, param.getUserId());
|
|
|
+
|
|
|
+ } else { //没绑定fsUser直接绑定fsUser
|
|
|
+ QwExternalContact contact = new QwExternalContact();
|
|
|
+ contact.setId(qwExternalId);
|
|
|
+ contact.setFsUserId(param.getUserId());
|
|
|
+ qwExternalContactMapper.updateQwExternalContact(contact);
|
|
|
+ iSopUserLogsInfoService.updateSopUserInfoByExternalId(qwExternalId, param.getUserId());
|
|
|
+
|
|
|
+ FsUser fsUser = new FsUser();
|
|
|
+ fsUser.setUserId(user.getUserId());
|
|
|
+ fsUser.setIsAddQw(1);
|
|
|
+ fsUserMapper.updateFsUser(fsUser);
|
|
|
+ //绑定上之后 更新观看记录
|
|
|
+ //看课记录中userId为0绑定userId
|
|
|
+ liveWatchLog.setUserId(param.getUserId());
|
|
|
+ liveWatchLog.setUpdateTime(new Date());
|
|
|
+ liveWatchLogMapper.updateLiveWatchLog(liveWatchLog);
|
|
|
+ }
|
|
|
+
|
|
|
+ return R.ok();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据用户直播看课记录来打标签
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Async
|
|
|
+ public void qwTagMarkByLiveWatchLog(Long liveId) {
|
|
|
+ //查询直播间的标签配置
|
|
|
+ List<LiveTagItemVO> liveTagConfig = liveTagConfigMapper.getLiveTagListByliveId(liveId);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 8 回放已下单
|
|
|
+ * 7 直播已下单
|
|
|
+ * 6 回放已完课
|
|
|
+ * 5 直播已完课
|
|
|
+ * 4 回放到课未完课
|
|
|
+ * 3 直播到课未完课
|
|
|
+ * 2 回放未到课
|
|
|
+ * 1 直播未到课
|
|
|
+ */
|
|
|
+ Map<Integer, LiveTagItemVO> liveTagMp = liveTagConfig.stream()
|
|
|
+ .collect(Collectors.toMap(
|
|
|
+ LiveTagItemVO::getMarkType,
|
|
|
+ Function.identity(),
|
|
|
+ (existing, replacement) -> existing
|
|
|
+ ));
|
|
|
+ //查询直播间的看课记录
|
|
|
+ List<LiveWatchLog> liveWatchLogs = liveWatchLogMapper.selectLiveWatchLogByLiveId(liveId);
|
|
|
+
|
|
|
+ //根据配置给每位用户打上标签
|
|
|
+ List<HandleUserTagVO> handleUserTagVOS = new ArrayList<>();
|
|
|
+ liveWatchLogs.forEach(liveLog -> {
|
|
|
+ HandleUserTagVO addItem = new HandleUserTagVO();
|
|
|
+ addItem.setLiveId(liveId);
|
|
|
+ addItem.setExternalId(liveLog.getExternalContactId());
|
|
|
+ LiveTagItemVO liveTagItemVO = null;
|
|
|
+ List<String> tags = new ArrayList<>();
|
|
|
+ switch (liveLog.getLogType()) {
|
|
|
+ //1看课中
|
|
|
+ case 1:
|
|
|
+ //打标签 直播到课未完课
|
|
|
+ liveTagItemVO = liveTagMp.get(3);
|
|
|
+ if (null != liveTagItemVO) {
|
|
|
+ tags.add(liveTagItemVO.getQwTagRealId());
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //2完课
|
|
|
+ case 2:
|
|
|
+ //打标签 直播已完课
|
|
|
+ liveTagItemVO = liveTagMp.get(5);
|
|
|
+ if (null != liveTagItemVO) {
|
|
|
+ tags.add(liveTagItemVO.getQwTagRealId());
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //3待看课
|
|
|
+ case 3:
|
|
|
+
|
|
|
+ //打标签 直播未到课
|
|
|
+ liveTagItemVO = liveTagMp.get(1);
|
|
|
+ if (null != liveTagItemVO) {
|
|
|
+ tags.add(liveTagItemVO.getQwTagRealId());
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ //4看课中断
|
|
|
+ case 4:
|
|
|
+ //打标签 直播未到课
|
|
|
+ liveTagItemVO = liveTagMp.get(3);
|
|
|
+ if (null != liveTagItemVO) {
|
|
|
+ tags.add(liveTagItemVO.getQwTagRealId());
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (null != liveLog.getLiveBuy() && liveLog.getLiveBuy().equals(1)) {
|
|
|
+ liveTagItemVO = liveTagMp.get(7);
|
|
|
+ if (null != liveTagItemVO) {
|
|
|
+ tags.add(liveTagItemVO.getQwTagRealId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ handleUserTagVOS.add(addItem);
|
|
|
+ });
|
|
|
+ handleUserTags2Qw(handleUserTagVOS);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对企微用户打标签
|
|
|
+ * @param userTagVOS 用户标签列表,包含外部联系人ID和要添加的标签列表
|
|
|
+ */
|
|
|
+ private void handleUserTags2Qw(List<HandleUserTagVO> userTagVOS) {
|
|
|
+ if (CollUtil.isEmpty(userTagVOS)) {
|
|
|
+ log.warn("用户标签列表为空,跳过打标签操作");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ int successCount = 0;
|
|
|
+ int failCount = 0;
|
|
|
+
|
|
|
+ for (HandleUserTagVO userTagVO : userTagVOS) {
|
|
|
+ try {
|
|
|
+ // 参数校验
|
|
|
+ if (userTagVO.getExternalId() == null) {
|
|
|
+ log.warn("外部联系人ID为空,跳过该用户");
|
|
|
+ failCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (CollUtil.isEmpty(userTagVO.getTags())) {
|
|
|
+ log.warn("标签列表为空,跳过该用户: externalId={}", userTagVO.getExternalId());
|
|
|
+ failCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据外部联系人ID查询企微外部联系人信息
|
|
|
+ QwExternalContact qwExternalContact = qwExternalContactMapper.selectQwExternalContactById(userTagVO.getExternalId());
|
|
|
+ if (qwExternalContact == null) {
|
|
|
+ log.warn("未找到企微外部联系人: externalId={}", userTagVO.getExternalId());
|
|
|
+ failCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验必要字段
|
|
|
+ if (StringUtils.isEmpty(qwExternalContact.getUserId())
|
|
|
+ || StringUtils.isEmpty(qwExternalContact.getExternalUserId())
|
|
|
+ || StringUtils.isEmpty(qwExternalContact.getCorpId())) {
|
|
|
+ log.warn("企微外部联系人信息不完整: externalId={}, userId={}, externalUserId={}, corpId={}",
|
|
|
+ userTagVO.getExternalId(),
|
|
|
+ qwExternalContact.getUserId(),
|
|
|
+ qwExternalContact.getExternalUserId(),
|
|
|
+ qwExternalContact.getCorpId());
|
|
|
+ failCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建打标签参数
|
|
|
+ QwEditUserTagParam qwEditUserTagParam = new QwEditUserTagParam();
|
|
|
+ qwEditUserTagParam.setUserid(qwExternalContact.getUserId());
|
|
|
+ qwEditUserTagParam.setExternal_userid(qwExternalContact.getExternalUserId());
|
|
|
+ qwEditUserTagParam.setAdd_tag(userTagVO.getTags());
|
|
|
+
|
|
|
+ // 调用企微API打标签
|
|
|
+ QwResult qwResult = qwApiService.editUserTag(qwEditUserTagParam, qwExternalContact.getCorpId());
|
|
|
+
|
|
|
+ if (qwResult != null && qwResult.getErrcode() == 0) {
|
|
|
+ // 打标签成功,更新数据库中的标签信息
|
|
|
+ String existingTagIds = qwExternalContact.getTagIds();
|
|
|
+ Set<String> uniqueTagIds = new HashSet<>();
|
|
|
+
|
|
|
+ // 合并现有标签
|
|
|
+ if (StringUtils.isNotEmpty(existingTagIds)) {
|
|
|
+ try {
|
|
|
+ List<String> parsedTags = JSON.parseArray(existingTagIds, String.class);
|
|
|
+ if (CollUtil.isNotEmpty(parsedTags)) {
|
|
|
+ uniqueTagIds.addAll(parsedTags);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("解析现有标签失败: externalId={}, tagIds={}, error={}",
|
|
|
+ userTagVO.getExternalId(), existingTagIds, e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加新标签
|
|
|
+ uniqueTagIds.addAll(userTagVO.getTags());
|
|
|
+
|
|
|
+ // 更新数据库
|
|
|
+ QwExternalContact updateContact = new QwExternalContact();
|
|
|
+ updateContact.setId(qwExternalContact.getId());
|
|
|
+ updateContact.setTagIds(JSON.toJSONString(new ArrayList<>(uniqueTagIds)));
|
|
|
+ qwExternalContactMapper.updateQwExternalContact(updateContact);
|
|
|
+
|
|
|
+ successCount++;
|
|
|
+ log.info("成功为用户打标签: externalId={}, userId={}, externalUserId={}, tags={}",
|
|
|
+ userTagVO.getExternalId(),
|
|
|
+ qwExternalContact.getUserId(),
|
|
|
+ qwExternalContact.getExternalUserId(),
|
|
|
+ userTagVO.getTags());
|
|
|
+ } else {
|
|
|
+ // 打标签失败
|
|
|
+ failCount++;
|
|
|
+ String errorMsg = qwResult != null ? qwResult.getErrmsg() : "未知错误";
|
|
|
+ log.error("为用户打标签失败: externalId={}, userId={}, externalUserId={}, error={}",
|
|
|
+ userTagVO.getExternalId(),
|
|
|
+ qwExternalContact.getUserId(),
|
|
|
+ qwExternalContact.getExternalUserId(),
|
|
|
+ errorMsg);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ failCount++;
|
|
|
+ log.error("为用户打标签异常: externalId={}, error={}",
|
|
|
+ userTagVO.getExternalId(), e.getMessage(), e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("打标签操作完成: 总数={}, 成功={}, 失败={}",
|
|
|
+ userTagVOS.size(), successCount, failCount);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新用户观看时长(心跳时调用)- 异步执行
|
|
|
+ * @param liveId 直播间ID
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @param liveFlag 直播标记
|
|
|
+ * @param replayFlag 回放标记
|
|
|
+ * @param duration 观看时长(秒)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ @Async
|
|
|
+ public void updateWatchDuration(Long liveId, Long userId, Integer liveFlag, Integer replayFlag, Long duration) {
|
|
|
+ try {
|
|
|
+
|
|
|
+ LiveWatchUser liveWatchUser = baseMapper.selectByUniqueIndex(liveId, userId, liveFlag, replayFlag);
|
|
|
+
|
|
|
+ if (liveWatchUser != null) {
|
|
|
+ if (liveWatchUser.getOnlineSeconds() == null || duration > liveWatchUser.getOnlineSeconds()) {
|
|
|
+ liveWatchUser.setOnlineSeconds(duration);
|
|
|
+ liveWatchUser.setUpdateTime(DateUtils.getNowDate());
|
|
|
+ baseMapper.updateLiveWatchUser(liveWatchUser);
|
|
|
+ log.debug("更新观看时长成功: liveId={}, userId={}, liveFlag={}, replayFlag={}, duration={}",
|
|
|
+ liveId, userId, liveFlag, replayFlag, duration);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ log.warn("未找到观看记录,无法更新时长: liveId={}, userId={}, liveFlag={}, replayFlag={}",
|
|
|
+ liveId, userId, liveFlag, replayFlag);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新观看时长失败: liveId={}, userId={}, liveFlag={}, replayFlag={}, duration={}",
|
|
|
+ liveId, userId, liveFlag, replayFlag, duration, e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户在某直播间的总观看时长(直播 + 回放)
|
|
|
+ * @param liveId 直播间ID
|
|
|
+ * @param userId 用户ID
|
|
|
+ * @return 总观看时长(秒)
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public Long getTotalWatchDuration(Long liveId, Long userId) {
|
|
|
+ try {
|
|
|
+ long totalDuration = 0L;
|
|
|
+
|
|
|
+ // 1. 查询直播观看记录(liveFlag=1, replayFlag=0)
|
|
|
+ LiveWatchUser liveRecord = baseMapper.selectByUniqueIndex(liveId, userId, 1, 0);
|
|
|
+ if (liveRecord != null && liveRecord.getOnlineSeconds() != null) {
|
|
|
+ totalDuration += liveRecord.getOnlineSeconds();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查询回放观看记录(liveFlag=0, replayFlag=1)
|
|
|
+ LiveWatchUser replayRecord = baseMapper.selectByUniqueIndex(liveId, userId, 0, 1);
|
|
|
+ if (replayRecord != null && replayRecord.getOnlineSeconds() != null) {
|
|
|
+ totalDuration += replayRecord.getOnlineSeconds();
|
|
|
+ }
|
|
|
+
|
|
|
+ log.debug("查询总观看时长: liveId={}, userId={}, liveDuration={}, replayDuration={}, total={}",
|
|
|
+ liveId, userId,
|
|
|
+ liveRecord != null ? liveRecord.getOnlineSeconds() : 0,
|
|
|
+ replayRecord != null ? replayRecord.getOnlineSeconds() : 0,
|
|
|
+ totalDuration);
|
|
|
+
|
|
|
+ return totalDuration;
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("查询总观看时长失败: liveId={}, userId={}", liveId, userId, e);
|
|
|
+ return 0L;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|