package cn.lili.modules.statistics.serviceimpl; import cn.lili.cache.Cache; import cn.lili.cache.CachePrefix; import cn.lili.common.enums.ClientTypeEnum; import cn.lili.common.enums.ResultCode; import cn.lili.common.exception.ServiceException; import cn.lili.common.properties.StatisticsProperties; import cn.lili.common.security.enums.UserEnums; import cn.lili.common.utils.CurrencyUtil; import cn.lili.modules.member.entity.vo.MemberDistributionVO; import cn.lili.modules.statistics.entity.dos.PlatformViewData; import cn.lili.modules.statistics.entity.dto.StatisticsQueryParam; import cn.lili.modules.statistics.entity.enums.SearchTypeEnum; import cn.lili.modules.statistics.entity.vo.OnlineMemberVO; import cn.lili.modules.statistics.entity.vo.PlatformViewVO; import cn.lili.modules.statistics.mapper.PlatformViewMapper; import cn.lili.modules.statistics.service.MemberStatisticsService; import cn.lili.modules.statistics.service.PlatformViewService; import cn.lili.modules.statistics.util.StatisticsDateUtil; import cn.lili.modules.statistics.util.StatisticsSuffix; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** * 流量统计 * * @author Chopper * @version v1.0 * @since v7.0 * 2021/1/18 12:07 */ @Service public class PlatformViewServiceImpl extends ServiceImpl implements PlatformViewService { /** * 在线人数统计 */ @Autowired private StatisticsProperties statisticsProperties; /** * 会员 */ @Autowired private MemberStatisticsService memberStatisticsService; /** * 缓存 */ @Autowired private Cache cache; @Override public Long online() { Object object = cache.get(CachePrefix.ONLINE_NUM.getPrefix()); if (null != object) { return (Long) object; } //这里统计的是有效的accessToken ,如果需要数据精确,需要调整accessToken的有效时间,开发人员建议2小时误差较为合适 Long num = Long.valueOf(cache.keys(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MEMBER) + "*").size()); cache.put(CachePrefix.ONLINE_NUM.getPrefix(), num, statisticsProperties.getCurrentOnlineUpdate().longValue()); return num; } @Override public List memberDistribution() { Object object = cache.get(CachePrefix.MEMBER_DISTRIBUTION.getPrefix()); if (null != object) { return (List) object; } List memberDistributionVOS = memberStatisticsService.distribution(); //统计总数 int count = 0; for (MemberDistributionVO vo : memberDistributionVOS) { count += vo.getNum(); } //初始化数据,填充枚举和比例 for (MemberDistributionVO vo : memberDistributionVOS) { vo.setProportion(CurrencyUtil.div(vo.getNum(), count, 4)); //客户端填充 if (StringUtils.isNotEmpty(vo.getClientEnum())) { vo.setClientEnum(ClientTypeEnum.valueOf(vo.getClientEnum()).clientName()); } else { vo.setClientEnum(ClientTypeEnum.UNKNOWN.clientName()); } } cache.put(CachePrefix.MEMBER_DISTRIBUTION.getPrefix(), memberDistributionVOS); return memberDistributionVOS; } @Override public List statisticsOnline() { Object object = cache.get(CachePrefix.ONLINE_MEMBER.getPrefix()); List result = new ArrayList<>(); if (object != null) { result = (List) object; } return this.initData(result); } /** * 在线会员数据初始化 * * @param source * @return */ private List initData(List source) { List onlineMemberVOS = new ArrayList<>(); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - statisticsProperties.getOnlineMember()); //循环填充数据 for (int i = 0; i < statisticsProperties.getOnlineMember(); i++) { calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1); OnlineMemberVO exitOnlineNum = null; for (int j = 0; j < source.size(); j++) { if (source.get(j).getDate().equals(calendar.getTime())) { exitOnlineNum = source.get(j); } } if (exitOnlineNum == null) { onlineMemberVOS.add(new OnlineMemberVO(calendar.getTime(), 0, 0)); } else { onlineMemberVOS.add(exitOnlineNum); } } return onlineMemberVOS; } @Override public List list(StatisticsQueryParam queryParam) { List result = new ArrayList<>(); //查询开始时间和结束时间,用于数据库查询 Date endTime = null, startTime = null; //搜索类型判定,如果不为空,则按照搜索类型进行查询 if (StringUtils.isNotEmpty(queryParam.getSearchType())) { SearchTypeEnum searchTypeEnum = SearchTypeEnum.valueOf(queryParam.getSearchType()); switch (searchTypeEnum) { case TODAY: PlatformViewVO today = new PlatformViewVO(); //查询 平台流量 if (StringUtils.isEmpty(queryParam.getStoreId())) { //设置PV UV属性 String pv = cache.getString(CachePrefix.PV.getPrefix() + StatisticsSuffix.suffix()); if (pv == null) { pv = "0"; } today.setPvNum(Long.valueOf(pv)); today.setUvNum(cache.counter(CachePrefix.UV.getPrefix() + StatisticsSuffix.suffix()).longValue()); } //店铺流量 else { //设置PV UV属性 String pv = cache.getString(CachePrefix.STORE_PV.getPrefix() + StatisticsSuffix.suffix(queryParam.getStoreId())); if (pv == null) { pv = "0"; } today.setPvNum(Long.valueOf(pv)); today.setUvNum(cache.counter(CachePrefix.STORE_UV.getPrefix() + StatisticsSuffix.suffix(queryParam.getStoreId())).longValue()); } today.setDate(new Date()); result.add(today); break; case YESTERDAY: case LAST_SEVEN: case LAST_THIRTY: { Date[] dates = StatisticsDateUtil.getDateArray(searchTypeEnum); endTime = dates[1]; startTime = dates[0]; break; } default: throw new ServiceException(ResultCode.ERROR); } } else { //根据查询时间来确定查询参数 Integer year = queryParam.getYear(); Integer month = queryParam.getMonth(); Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.HOUR_OF_DAY, 0); calendar.set(Calendar.MINUTE, 0); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); calendar.set(year, month - 1, 1); startTime = calendar.getTime(); calendar.set(year, month, -1); endTime = calendar.getTime(); } //时间不为空则按照时间开始数据查询 if (startTime != null) { LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.between(PlatformViewData::getDate, startTime, endTime); lambdaQueryWrapper.eq(PlatformViewData::getStoreId, StringUtils.isEmpty(queryParam.getStoreId()) ? "-1" : queryParam.getStoreId()); List dataList = this.list(lambdaQueryWrapper); result = builderVOS(startTime, endTime, dataList); } return result; } @Override public Integer countUv(StatisticsQueryParam queryParam) { Date[] dates = StatisticsDateUtil.getDateArray(queryParam); //获取当前时间 Calendar calendar = Calendar.getInstance(); calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); //如果是今天的统计,则从redis 中拿,否则从数据库中拿 if (dates[0].equals(calendar.getTime())) { if (StringUtils.isNotEmpty(queryParam.getStoreId())) { return cache.counter(CachePrefix.UV.getPrefix() + StatisticsSuffix.suffix(queryParam.getStoreId())).intValue(); } return cache.counter(CachePrefix.UV.getPrefix() + StatisticsSuffix.suffix()).intValue(); } else { QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.between("date", dates[0], dates[1]); //根据店铺查询判定,如果有,则店铺查询,如果没有,则根据商家查询 if (StringUtils.isNotEmpty(queryParam.getStoreId())) { queryWrapper.eq("store_id", queryParam.getStoreId()); } else { queryWrapper.eq("store_id", -1); } return this.baseMapper.count(queryWrapper); } } /** * 根据查询条件,创建数据 * * @param startDate * @param endDate * @param dataList * @return */ private List builderVOS(Date startDate, Date endDate, List dataList) { Calendar startTime = Calendar.getInstance(); startTime.setTime(startDate); Calendar endTime = Calendar.getInstance(); endTime.setTime(endDate); List result = new ArrayList<>(); //构造所有需要统计展示等流量数据 List listDate = new ArrayList<>(); while (startTime.before(endTime) || startTime.getTime().equals(endTime.getTime())) { listDate.add(startTime.getTime()); startTime.set(Calendar.DAY_OF_MONTH, startTime.get(Calendar.DAY_OF_MONTH) + 1); } //根据时间集,匹配查询到等数据,构建返回等VO listDate.forEach(date -> { PlatformViewVO platformViewVO = new PlatformViewVO(date); dataList.forEach(platformViewData -> { if (platformViewData.getDate().equals(date)) { BeanUtils.copyProperties(platformViewData, platformViewVO); } }); //没有匹配到数据库查询的数据,则初始化数据 result.add(platformViewVO); }); return result; } }