Bladeren bron

update: 版本分布详情

lwh 3 weken geleden
bovenliggende
commit
5baa0f8af1

+ 8 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/user/PageAllVersionDetailDTO.java

@@ -2,6 +2,7 @@ package com.pig4cloud.pig.statistics.api.dto.user;
 
 
 import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
 import lombok.Data;
 
 import java.io.Serial;
@@ -19,6 +20,13 @@ public class PageAllVersionDetailDTO implements Serializable {
 	@Serial
 	private static final long serialVersionUID = 1L;
 
+	/**
+	 * 应用ID
+	 */
+	@NotBlank(message = "应用ID不能为空")
+	@Schema(description = "应用ID", example = "Fqs2CL9CUn7U1AqilSFXgb")
+	private String appId;
+
 	/**
 	 * 每页显示条数,默认 10
 	 */

+ 3 - 2
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/user/PageAllVersionDetailVO.java

@@ -6,6 +6,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 /**
  * @author: lwh
@@ -23,7 +24,7 @@ public class PageAllVersionDetailVO implements Serializable {
 	 * 活跃用户占比
 	 */
 	@Schema(description = "活跃用户占比")
-	private Double activeUserRate;
+	private BigDecimal activeUserRate;
 
 	/**
 	 * 活跃用户
@@ -47,7 +48,7 @@ public class PageAllVersionDetailVO implements Serializable {
 	 * 累计用户占比
 	 */
 	@Schema(description = "累计用户占比")
-	private Double totalUserRate;
+	private BigDecimal totalUserRate;
 
 	/**
 	 * 升级用户

+ 159 - 67
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UserAnalyseServiceImpl.java

@@ -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);
+	}
+
 }