xiangpei
9 天以前 c13e4a322e3d58183882478703fe919a88759cb4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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<PlatformViewMapper, PlatformViewData> 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<MemberDistributionVO> memberDistribution() {
        Object object = cache.get(CachePrefix.MEMBER_DISTRIBUTION.getPrefix());
 
        if (null != object) {
            return (List<MemberDistributionVO>) object;
        }
        List<MemberDistributionVO> 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<OnlineMemberVO> statisticsOnline() {
        Object object = cache.get(CachePrefix.ONLINE_MEMBER.getPrefix());
        List<OnlineMemberVO> result = new ArrayList<>();
        if (object != null) {
            result = (List<OnlineMemberVO>) object;
        }
        return this.initData(result);
    }
 
    /**
     * 在线会员数据初始化
     *
     * @param source
     * @return
     */
    private List<OnlineMemberVO> initData(List<OnlineMemberVO> source) {
        List<OnlineMemberVO> 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<PlatformViewVO> list(StatisticsQueryParam queryParam) {
        List<PlatformViewVO> 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<PlatformViewData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.between(PlatformViewData::getDate, startTime, endTime);
            lambdaQueryWrapper.eq(PlatformViewData::getStoreId, StringUtils.isEmpty(queryParam.getStoreId()) ?
                    "-1" : queryParam.getStoreId());
            List<PlatformViewData> 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<PlatformViewVO> builderVOS(Date startDate, Date endDate, List<PlatformViewData> dataList) {
 
        Calendar startTime = Calendar.getInstance();
        startTime.setTime(startDate);
 
        Calendar endTime = Calendar.getInstance();
        endTime.setTime(endDate);
 
        List<PlatformViewVO> result = new ArrayList<>();
 
        //构造所有需要统计展示等流量数据
        List<Date> 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;
 
    }
 
}