package com.tanpu.community.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.tanpu.biz.common.enums.clue.PageEnum; import com.tanpu.community.api.enums.DeleteTagEnum; import com.tanpu.community.cache.RedisCache; import com.tanpu.community.dao.entity.community.TimesCountEntity; import com.tanpu.community.dao.entity.community.VisitLogEntity; import com.tanpu.community.dao.mapper.community.VisitLogMapper; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.ListUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import static com.tanpu.biz.common.enums.clue.PageEnum.COMM_VISIT_TOPIC_DETAIL; @Slf4j @Service public class VisitLogService { @Resource private VisitLogMapper visitLogMapper; @Resource private RedisCache redisCache; // 获取用户7天内访问过的 public List<String> queryUserRecentVisited(String userId) { Date endDate = new Date(); Date startDate = DateUtils.addDays(endDate, -7); List<String> visited = visitLogMapper.selectRefIdByVisitorIdAndCreateBetween(userId, startDate, endDate); return visited; } // 从refIds中去掉用户已经访问过的 public List<String> filterUserNotVisited(String userId, List<String> refIds) { if (refIds.isEmpty()) { return refIds; } List<String> visited = visitLogMapper.selectList(new LambdaQueryWrapper<VisitLogEntity>() .eq(VisitLogEntity::getVisitorId, userId) .in(VisitLogEntity::getRefId, refIds)) .stream().map(VisitLogEntity::getRefId).distinct().collect(Collectors.toList()); return ListUtils.subtract(refIds, visited); } public List<String> queryUserVisited(String userId) { List<String> visited = visitLogMapper.selectList(new LambdaQueryWrapper<VisitLogEntity>() .eq(VisitLogEntity::getVisitorId, userId)) .stream().map(VisitLogEntity::getRefId).distinct().collect(Collectors.toList()); return visited; } @Transactional public void insertOrUpdateDur(VisitLogEntity vs) { // 分布式锁 for (int i = 0; i < 5 * 10; i++) { String key = getVisitLogRedisKey(vs); String rand = String.valueOf((int) Math.floor(Math.random() * 100)); if (redisCache.setIfAbsent(key, rand, 15)) { if (visitLogMapper.selectByIdentAndRefId(vs.getIdent(), vs.getRefId(), vs.getRefType()) == null) { visitLogMapper.insert(vs); } else { visitLogMapper.updateDurByIdent(vs.getDuration(), vs.getIdent(), vs.getRefId(), vs.getRefType()); } redisCache.evict(key + ":" + rand); return; } try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } } private String getVisitLogRedisKey(VisitLogEntity vs) { return StringUtils.join("insertOrUpdateDur:", vs.getIdent().substring(0, 4), vs.getRefId(), vs.getRefType()); } @Transactional //TODO 临时埋点,接入新埋点后删除 public void addPageView(String userId, String targetId, PageEnum type) { visitLogMapper.insert(VisitLogEntity.builder() .visitorId(userId) .refId(targetId) .refType(type.getId()) .duration(0) .build()); } // 查询话题 详细页面 浏览量 public Integer queryTopicDetailVisit(String topicId) { return visitLogMapper.selectCount(new LambdaQueryWrapper<VisitLogEntity>() .eq(VisitLogEntity::getRefId, topicId) .eq(VisitLogEntity::getRefType, COMM_VISIT_TOPIC_DETAIL.getId())); } // 查询主题 浏览量 public Integer queryThemeVisit(String theme) { return visitLogMapper.selectCount(new LambdaQueryWrapper<VisitLogEntity>() .eq(VisitLogEntity::getRefId, theme) .eq(VisitLogEntity::getRefType, PageEnum.COMM_VISIT_THEME.getId())); } // 查询主题 浏览量 public Integer queryThemeVisit(List<String> themes) { if (CollectionUtils.isEmpty(themes)) { return 0; } return visitLogMapper.selectCount(new LambdaQueryWrapper<VisitLogEntity>() .in(VisitLogEntity::getRefId, themes) .eq(VisitLogEntity::getRefType, PageEnum.COMM_VISIT_THEME.getId())); } //统计行为集合的浏览量 public Map<String, Integer> getCountMapByTargetIds(List<String> refIds, String refType) { if (CollectionUtils.isEmpty(refIds)) { return new HashMap<>(); } LambdaQueryWrapper<VisitLogEntity> wrapper = (new LambdaQueryWrapper<VisitLogEntity>() .in(VisitLogEntity::getRefId, refIds)) .eq(VisitLogEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED) .eq(VisitLogEntity::getRefType, refType) .groupBy(VisitLogEntity::getRefId); return visitLogMapper.selectCountByThemeIds(wrapper).stream() .collect(Collectors.toMap(TimesCountEntity::getId, TimesCountEntity::getTimes)); } // 查询讨论区最近浏览 public Integer queryLastTopicVisit(String theme) { return visitLogMapper.selectCount(new LambdaQueryWrapper<VisitLogEntity>() .eq(VisitLogEntity::getRefId, theme) .eq(VisitLogEntity::getRefType, PageEnum.COMM_VISIT_THEME.getId())); } }