|
@@ -1,6 +1,7 @@
|
|
|
package com.pig4cloud.pig.statistics.service.impl;
|
|
|
|
|
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
@@ -1290,83 +1291,75 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
|
|
|
*/
|
|
|
@Override
|
|
|
public Page<PageAllVersionDetailVO> pageAllVersionDetail(PageAllVersionDetailDTO reqDto) {
|
|
|
+
|
|
|
// 初始化分页对象
|
|
|
Page<PageAllVersionDetailVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
|
|
|
- List<PageAllVersionDetailVO> result = new ArrayList<>();
|
|
|
- Random random = new Random();
|
|
|
-
|
|
|
- // 模拟版本列表(可根据实际业务版本调整)
|
|
|
- List<String> versions = new ArrayList<>();
|
|
|
- versions.add("1.0");
|
|
|
- versions.add("2.5");
|
|
|
- versions.add("3.2.1");
|
|
|
- versions.add("4.0");
|
|
|
- versions.add("5.1");
|
|
|
- versions.add("6.0.2");
|
|
|
- versions.add("6.3.0");
|
|
|
- versions.add("7.1.0");
|
|
|
-
|
|
|
- // 生成总数据(超出分页范围,用于模拟分页效果)
|
|
|
- int totalDataSize = 20; // 模拟20条总数据
|
|
|
- for (int i = 0; i < totalDataSize; i++) {
|
|
|
- PageAllVersionDetailVO vo = new PageAllVersionDetailVO();
|
|
|
- String version = versions.get(random.nextInt(versions.size()));
|
|
|
-
|
|
|
- // 基础用户量(根据版本新旧设置不同量级)
|
|
|
- int baseTotalUser;
|
|
|
- if (version.startsWith("1.") || version.startsWith("2.")) {
|
|
|
- baseTotalUser = 500000 + random.nextInt(500000); // 老版本用户量较大
|
|
|
- } else if (version.startsWith("6.") || version.startsWith("7.")) {
|
|
|
- baseTotalUser = 10000 + random.nextInt(50000); // 新版本用户量较小
|
|
|
- } else {
|
|
|
- baseTotalUser = 100000 + random.nextInt(400000); // 中间版本
|
|
|
- }
|
|
|
-
|
|
|
- // 活跃用户(总用户的0.01%-0.1%)
|
|
|
- int activeUser = (int) (baseTotalUser * (0.0001 + random.nextDouble() * 0.0009));
|
|
|
- activeUser = Math.max(activeUser, 1); // 确保至少1个活跃用户
|
|
|
|
|
|
- // 新用户(活跃用户的80%-120%)
|
|
|
- int newUser = (int) (activeUser * (0.8 + random.nextDouble() * 0.4));
|
|
|
-
|
|
|
- // 升级用户(新用户的0%-5%)
|
|
|
- int upgradeUser = (int) (newUser * random.nextDouble() * 0.05);
|
|
|
-
|
|
|
- // 启动次数(活跃用户的50-200倍)
|
|
|
- int launch = activeUser * (50 + random.nextInt(151));
|
|
|
-
|
|
|
- // 活跃用户率(2%-60%,保留两位小数)
|
|
|
- double activeUserRate = Math.round((2 + random.nextDouble() * 58) * 100) / 100.0;
|
|
|
-
|
|
|
- // 总用户占比(1%-60%,保留两位小数)
|
|
|
- double totalUserRate = Math.round((1 + random.nextDouble() * 59) * 100) / 100.0;
|
|
|
+ // 查询新增用户表中指定appId的所有版本列表
|
|
|
+ List<String> allVersions = getAllVersionsByAppId(reqDto.getAppId());
|
|
|
+ if (CollUtil.isEmpty(allVersions)) {
|
|
|
+ page.setTotal(0);
|
|
|
+ return page;
|
|
|
+ }
|
|
|
|
|
|
- // 设置属性
|
|
|
- vo.setVersion(version);
|
|
|
- vo.setTotalUser(baseTotalUser);
|
|
|
- vo.setActiveUser(activeUser);
|
|
|
- vo.setNewUser(newUser);
|
|
|
- vo.setUpgradeUser(upgradeUser);
|
|
|
- vo.setLaunch(launch);
|
|
|
- vo.setActiveUserRate(activeUserRate);
|
|
|
- vo.setTotalUserRate(totalUserRate);
|
|
|
+ // 设置总记录数
|
|
|
+ page.setTotal(allVersions.size());
|
|
|
|
|
|
- result.add(vo);
|
|
|
+ // 获取分页的版本列表
|
|
|
+ List<String> pageVersions = getPageVersions(allVersions, reqDto.getCurrent(), reqDto.getSize());
|
|
|
+ if (CollUtil.isEmpty(pageVersions)) {
|
|
|
+ return page;
|
|
|
}
|
|
|
|
|
|
- // 处理分页逻辑
|
|
|
- int total = result.size();
|
|
|
- int fromIndex = (int) ((reqDto.getCurrent() - 1) * reqDto.getSize());
|
|
|
- int toIndex = Math.min(fromIndex + (int) reqDto.getSize(), total);
|
|
|
+ // 确定查询日期
|
|
|
+ LocalDate queryDate = (reqDto.getQueryDate() != null && reqDto.getQueryDate() == 1)
|
|
|
+ ? LocalDate.now().minusDays(1)
|
|
|
+ : LocalDate.now();
|
|
|
|
|
|
- if (fromIndex >= 0 && fromIndex < total) {
|
|
|
- result = result.subList(fromIndex, toIndex);
|
|
|
- } else {
|
|
|
- result = new ArrayList<>();
|
|
|
- }
|
|
|
+ // 构建版本详情列表
|
|
|
+ final String timeUnit = "day";
|
|
|
+ List<PageAllVersionDetailVO> result = new ArrayList<>();
|
|
|
+ // 遍历版本列表,查询数据
|
|
|
+ for (String version : pageVersions) {
|
|
|
+ // 获取时间范围
|
|
|
+ LocalDateTime startTime = getStartTime(queryDate.toString(), timeUnit);
|
|
|
+ LocalDateTime endTime = getEndTime(queryDate.toString(), timeUnit);
|
|
|
+
|
|
|
+ // 查询截至今日所有版本用户总数
|
|
|
+ BigDecimal allVersionUser = BigDecimal.valueOf(statNewUserCount(null, endTime, reqDto.getAppId(), null, null));
|
|
|
+ // 查询截至今日该版本的用户总数
|
|
|
+ BigDecimal versionUser = BigDecimal.valueOf(statNewUserCount(null, endTime, reqDto.getAppId(), version, null));
|
|
|
+ // 查询该版本今日新增的用户数量
|
|
|
+ Long newUser = statNewUserCount(startTime, endTime, reqDto.getAppId(), version, null);
|
|
|
+ // 查询该版本今日活跃的用户数量
|
|
|
+ BigDecimal activeUser = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), version, null));
|
|
|
+ // 查询该应用今日所有活跃用户数量
|
|
|
+ BigDecimal totalActiveUser = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), null, null));
|
|
|
+ // 查询该版本今日启动次数
|
|
|
+ Long launch = statLaunchCount(startTime, endTime, reqDto.getAppId(), version, null);
|
|
|
+ // 查询升级到该版本的用户数量
|
|
|
+ Long upgradeUser = statUpgradeUserCount(null, endTime, reqDto.getAppId(), version, null);
|
|
|
|
|
|
+ // 组装结果
|
|
|
+ PageAllVersionDetailVO detail = new PageAllVersionDetailVO();
|
|
|
+ detail.setVersion(version);
|
|
|
+ detail.setNewUser(newUser.intValue());
|
|
|
+ detail.setUpgradeUser(upgradeUser.intValue());
|
|
|
+ detail.setLaunch(launch.intValue());
|
|
|
+ detail.setActiveUser(activeUser.intValue());
|
|
|
+ detail.setTotalUser(versionUser.intValue());
|
|
|
+ // 累计用户占比
|
|
|
+ detail.setTotalUserRate(allVersionUser.compareTo(BigDecimal.ZERO) == 0 || versionUser.compareTo(BigDecimal.ZERO) == 0
|
|
|
+ ? BigDecimal.ZERO
|
|
|
+ : versionUser.divide(allVersionUser, 4, RoundingMode.HALF_UP));
|
|
|
+ // 活跃用户占比
|
|
|
+ detail.setActiveUserRate(totalActiveUser.compareTo(BigDecimal.ZERO) == 0 || activeUser.compareTo(BigDecimal.ZERO) == 0
|
|
|
+ ? BigDecimal.ZERO
|
|
|
+ : activeUser.divide(totalActiveUser, 4, RoundingMode.HALF_UP));
|
|
|
+ result.add( detail);
|
|
|
+ }
|
|
|
+ // 返回结果
|
|
|
page.setRecords(result);
|
|
|
- page.setTotal(total);
|
|
|
return page;
|
|
|
}
|
|
|
|
|
@@ -1957,4 +1950,103 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
|
|
|
activeUserSet.retainAll(newUserSet);
|
|
|
return (long) activeUserSet.size();
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统计指定时间范围内的启动次数
|
|
|
+ */
|
|
|
+ private Long statLaunchCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
|
|
|
+ // 1. 组装查询条件
|
|
|
+ LambdaQueryWrapper<MktStatUserAnalysis> queryWrapper = Wrappers.<MktStatUserAnalysis>lambdaQuery()
|
|
|
+ .eq(MktStatUserAnalysis::getAppId, appId)
|
|
|
+ .ge(startTime != null ,MktStatUserAnalysis::getStatDate, startTime)
|
|
|
+ .lt(endTime != null ,MktStatUserAnalysis::getStatDate, endTime)
|
|
|
+ .select(MktStatUserAnalysis::getLaunch);
|
|
|
+
|
|
|
+ // 2. 添加渠道条件
|
|
|
+ if (channels != null && !channels.isEmpty()) {
|
|
|
+ queryWrapper.in(MktStatUserAnalysis::getChannel, channels);
|
|
|
+ }
|
|
|
+ // 3. 添加版本条件
|
|
|
+ if (version != null && !version.isEmpty()){
|
|
|
+ queryWrapper.eq(MktStatUserAnalysis::getVersion, version);
|
|
|
+ }
|
|
|
+ // 4. 统计新增用户数
|
|
|
+ List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(queryWrapper);
|
|
|
+ Long launchCount = 0L;
|
|
|
+ for (MktStatUserAnalysis user : userAnalyses) {
|
|
|
+ launchCount+=user.getLaunch();
|
|
|
+ }
|
|
|
+ return launchCount;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 统计指定时间范围内的升级用户数
|
|
|
+ */
|
|
|
+ private Long statUpgradeUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
|
|
|
+
|
|
|
+ // 1. 组装查询条件
|
|
|
+ LambdaQueryWrapper<MktStatNewUser> queryWrapper = Wrappers.<MktStatNewUser>lambdaQuery()
|
|
|
+ .eq(MktStatNewUser::getAppId, appId)
|
|
|
+ .isNotNull(MktStatNewUser::getOldVersion)
|
|
|
+ .ne(MktStatNewUser::getOldVersion, "")
|
|
|
+ .ge(startTime != null ,MktStatNewUser::getStatDate, startTime)
|
|
|
+ .lt(endTime != null ,MktStatNewUser::getStatDate, endTime);
|
|
|
+
|
|
|
+ // 2. 添加渠道条件
|
|
|
+ if (channels != null && !channels.isEmpty()) {
|
|
|
+ queryWrapper.in(MktStatNewUser::getChannel, channels);
|
|
|
+ }
|
|
|
+ // 3. 添加版本条件
|
|
|
+ if (version != null && !version.isEmpty()){
|
|
|
+ queryWrapper.eq(MktStatNewUser::getVersion, version);
|
|
|
+ }
|
|
|
+ // 4. 统计升级用户数
|
|
|
+ List<MktStatNewUser> newUsers = newUserMapper.selectList(queryWrapper);
|
|
|
+ return newUsers == null ? 0L : newUsers.size();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 查询新增表中指定appId的所有version列表
|
|
|
+ * @param appId 应用ID
|
|
|
+ * @return List<String> 版本列表,按版本号升序排列
|
|
|
+ */
|
|
|
+ private List<String> getAllVersionsByAppId(String appId) {
|
|
|
+ LambdaQueryWrapper<MktStatNewUser> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(MktStatNewUser::getAppId, appId)
|
|
|
+ .select(MktStatNewUser::getVersion)
|
|
|
+ .groupBy(MktStatNewUser::getVersion)
|
|
|
+ .orderByAsc(MktStatNewUser::getVersion);
|
|
|
+
|
|
|
+ List<MktStatNewUser> versionList = newUserMapper.selectList(queryWrapper);
|
|
|
+
|
|
|
+ return versionList.stream()
|
|
|
+ .map(MktStatNewUser::getVersion)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据分页参数获取版本列表的分页数据
|
|
|
+ * @param allVersions 所有版本列表
|
|
|
+ * @param current 当前页码
|
|
|
+ * @param size 每页大小
|
|
|
+ * @return List<String> 分页后的版本列表
|
|
|
+ */
|
|
|
+ private List<String> getPageVersions(List<String> allVersions, long current, long size) {
|
|
|
+ if (CollUtil.isEmpty(allVersions)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算分页起始和结束索引
|
|
|
+ long startIndex = (current - 1) * size;
|
|
|
+ long endIndex = Math.min(startIndex + size, allVersions.size());
|
|
|
+
|
|
|
+ // 边界检查
|
|
|
+ if (startIndex >= allVersions.size()) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取当前页的数据
|
|
|
+ return allVersions.subList((int) startIndex, (int) endIndex);
|
|
|
+ }
|
|
|
+
|
|
|
}
|