浏览代码

update: 修改周、月、活跃趋势、构成、粘度逻辑

lwh 4 周之前
父节点
当前提交
fe6559edfc

+ 7 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/user/PageActiveDetailDTO.java

@@ -24,6 +24,13 @@ public class PageActiveDetailDTO implements Serializable {
 	@Serial
 	private static final long serialVersionUID = 1L;
 
+	/**
+	 * 应用id
+	 */
+	@NotBlank(message = "应用id不能为空")
+	@Schema(description = "应用id", example = "FoigtBxJrmOi9nirwkjpsJ")
+	private String appId;
+
 	/**
 	 * 渠道
 	 */

+ 1 - 1
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/user/TrendBaseVO.java

@@ -20,7 +20,7 @@ public class TrendBaseVO implements Serializable {
 	 * 数量
 	 */
 	@Schema(description = "数量")
-	private List<Integer> data;
+	private List<Long> data;
 
 	/**
 	 * 名称

+ 4 - 4
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/controller/UserAnalyseController.java

@@ -97,15 +97,15 @@ public class UserAnalyseController {
 
 	@PostMapping("/active/weekrate")
 	@Operation(summary = "查询周活跃率")
-	public R<GetActiveUserBaseVO> getActiveWeekrate(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
-		GetActiveUserBaseVO result = userAnalyseService.getActiveWeekrate(reqDto);
+	public R<GetActiveUserBaseVO> getActiveWeekRate(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+		GetActiveUserBaseVO result = userAnalyseService.getActiveWeekRate(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/active/monthrate")
 	@Operation(summary = "查询月活跃率")
-	public R<GetActiveUserBaseVO> getActiveMonthrate(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
-		GetActiveUserBaseVO result = userAnalyseService.getActiveMonthrate(reqDto);
+	public R<GetActiveUserBaseVO> getActiveMonthRate(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+		GetActiveUserBaseVO result = userAnalyseService.getActiveMonthRate(reqDto);
 		return R.ok(result);
 	}
 

+ 2 - 2
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/UserAnalyseService.java

@@ -71,7 +71,7 @@ public interface UserAnalyseService {
 	 * @param reqDto 入参
 	 * @return GetActiveUserBaseVO
 	 */
-	GetActiveUserBaseVO getActiveWeekrate(@Valid UserAnalyseQueryBaseDTO reqDto);
+	GetActiveUserBaseVO getActiveWeekRate(@Valid UserAnalyseQueryBaseDTO reqDto);
 
 
 	/**
@@ -79,7 +79,7 @@ public interface UserAnalyseService {
 	 * @param reqDto 入参
 	 * @return GetActiveUserBaseVO
 	 */
-	GetActiveUserBaseVO getActiveMonthrate(@Valid UserAnalyseQueryBaseDTO reqDto);
+	GetActiveUserBaseVO getActiveMonthRate(@Valid UserAnalyseQueryBaseDTO reqDto);
 
 	/**
 	 * 分页查询活跃详情

+ 340 - 127
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UserAnalyseServiceImpl.java

@@ -84,7 +84,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 							.map(date -> calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "newUser"))
 							.collect(Collectors.toList());
 
-					trend.setData(counts);
+//					trend.setData(counts);
 					return trend;
 				})
 				.collect(Collectors.toList());
@@ -284,13 +284,47 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 * @return GetNewUserTrendVO
 	 */
 	@Override
-
 	public GetNewUserTrendVO getActiveTrend(UserAnalyseQueryBaseDTO reqDto) {
 		GetNewUserTrendVO result = new GetNewUserTrendVO();
 		// 1. 生成时间轴
 		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
 		result.setDates(dates);
 
+		// 2. 处理版本列表(为空时按null处理)
+		List<String> versions = reqDto.getVersion();
+		List<String> processVersions = (versions == null || versions.isEmpty())
+				? Collections.singletonList(null)
+				: versions.stream().filter(v -> v != null && !v.isEmpty()).toList();
+
+		// 3. 处理每个版本的数据
+		List<TrendBaseVO> voList = processVersions.stream()
+				.map(version -> {
+					TrendBaseVO trend = new TrendBaseVO();
+					trend.setName("活跃用户");
+					trend.setVersion(version);
+					trend.setKey("activeUser");
+
+					// 计算每个时间点的活跃用户数
+					List<Long> counts = dates.stream()
+							.map(date -> {
+								LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
+								LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+								return statActiveUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel());
+							})
+							.collect(Collectors.toList());
+					trend.setData(counts);
+					return trend;
+				})
+				.toList();
+		result.setItems(voList);
+		return result;
+	}
+	public GetNewUserTrendVO getActiveTrend2(UserAnalyseQueryBaseDTO reqDto) {
+		GetNewUserTrendVO result = new GetNewUserTrendVO();
+		// 1. 生成时间轴
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
+		result.setDates(dates);
+
 		// 2. 处理版本列表(为空时按"All"处理)
 		List<String> versions = reqDto.getVersion();
 		List<String> processVersions = (versions == null || versions.isEmpty())
@@ -310,7 +344,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 							.map(date -> calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"))
 							.collect(Collectors.toList());
 
-					trend.setData(counts);
+//					trend.setData(counts);
 					return trend;
 				})
 				.collect(Collectors.toList());
@@ -326,105 +360,59 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 */
 	@Override
 	public GetActiveUserBaseVO getActiveCompose(UserAnalyseQueryBaseDTO reqDto) {
-		// 创建返回对象
-		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
-		Random random = new Random();
-
-		// 1. 生成日期列表
-		List<String> dates = new ArrayList<>();
-		LocalDate startDate = reqDto.getFromDate();
-		LocalDate endDate = reqDto.getToDate();
-		LocalDateTime currentDateTime = LocalDateTime.of(startDate, LocalTime.MIN);
-		LocalDateTime endDateTime = LocalDateTime.of(endDate, LocalTime.MAX);
-
-		// 根据时间单位生成对应日期
-		while (!currentDateTime.isAfter(endDateTime)) {
-			String dateStr;
-			switch (reqDto.getTimeUnit()) {
-				case "hour":
-					dateStr = currentDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
-					currentDateTime = currentDateTime.plusHours(1);
-					break;
-				case "day":
-					dateStr = currentDateTime.toLocalDate().format(DateTimeFormatter.ISO_LOCAL_DATE);
-					currentDateTime = currentDateTime.plusDays(1);
-					break;
-				case "week":
-					LocalDate weekStart = currentDateTime.toLocalDate();
-					LocalDate weekEnd = weekStart.plusDays(6);
-					if (weekEnd.isAfter(endDate)) {
-						weekEnd = endDate;
-					}
-					dateStr = weekStart.format(DateTimeFormatter.ISO_LOCAL_DATE) + "~" +
-							weekEnd.format(DateTimeFormatter.ISO_LOCAL_DATE);
-					currentDateTime = currentDateTime.plusWeeks(1);
-					break;
-				case "month":
-					LocalDate monthStart = currentDateTime.toLocalDate();
-					LocalDate monthEnd = monthStart.plusMonths(1).minusDays(1);
-					if (monthEnd.isAfter(endDate)) {
-						monthEnd = endDate;
-					}
-					dateStr = monthStart.withDayOfMonth(1).format(DateTimeFormatter.ISO_LOCAL_DATE) + "~" +
-							monthEnd.format(DateTimeFormatter.ISO_LOCAL_DATE);
-					currentDateTime = currentDateTime.plusMonths(1);
-					break;
-				default:
-					dateStr = currentDateTime.toLocalDate().format(DateTimeFormatter.ISO_LOCAL_DATE);
-					currentDateTime = currentDateTime.plusDays(1);
-			}
-			dates.add(dateStr);
+		// 1. 获取时间坐标轴
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
+		// 获取版本信息
+		String version = null;
+		if (reqDto.getVersion() != null && !reqDto.getVersion().isEmpty()){
+			version = reqDto.getVersion().get(0);
+		}
+		List<BigDecimal> newCounts = new ArrayList<>();
+		List<BigDecimal> activeCounts = new ArrayList<>();
+		List<BigDecimal> newRates = new ArrayList<>();
+		// 2. 遍历时间坐标轴
+		for (String date : dates) {
+			LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
+			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+			// 活跃用户数
+			BigDecimal activeCount = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel()));
+			activeCounts.add( activeCount);
+			// 活跃用户中的新增用户数
+			BigDecimal newCount = BigDecimal.valueOf(getActiveNewUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel()));
+			newCounts.add( newCount);
+			// 新增用户占比
+			BigDecimal newRate = activeCount.compareTo(BigDecimal.ZERO) == 0 || newCount.compareTo(BigDecimal.ZERO) == 0 ?
+					BigDecimal.ZERO:
+					newCount.divide(activeCount, 4, RoundingMode.HALF_UP);
+			newRates.add(newRate);
 		}
-		result.setDates(dates);
 
-		// 2. 生成各项数据(调整为Double类型列表)
+		// 组装结果
 		List<ActiveUserComposeVO> items = new ArrayList<>();
-		int dataSize = dates.size();
 
-		// 活跃用户数据(整数转为Double)
 		ActiveUserComposeVO activeUser = new ActiveUserComposeVO();
 		activeUser.setName("活跃用户");
-		List<Double> activeData = new ArrayList<>();
-		for (int i = 0; i < dataSize; i++) {
-			int value = 30000 + random.nextInt(5000) + (i * 50);
-			activeData.add((double) value); // 整数转Double
-		}
-//		activeUser.setData(activeData);
+		activeUser.setData(activeCounts);
+		activeUser.setKey("activeUser");
+		activeUser.setVersion( version == null ? "All" : version);
 		items.add(activeUser);
 
-		// 新增用户数据(整数转为Double)
 		ActiveUserComposeVO newUser = new ActiveUserComposeVO();
 		newUser.setName("新增用户");
-		List<Double> newUserData = new ArrayList<>();
-		for (int i = 0; i < dataSize; i++) {
-			int value = activeData.get(i).intValue() - 100 - random.nextInt(300);
-			newUserData.add((double) value); // 整数转Double
-		}
-//		newUser.setData(newUserData);
+		newUser.setData(newCounts);
+		newUser.setKey("newUser");
+		newUser.setVersion( version == null ? "All" : version);
 		items.add(newUser);
 
-		// 新增用户占比数据(保持Double类型)
 		ActiveUserComposeVO newUserRate = new ActiveUserComposeVO();
 		newUserRate.setName("新增用户占比");
-		List<Double> rateData = new ArrayList<>();
-		for (int i = 0; i < dataSize; i++) {
-			double rate = (newUserData.get(i) / activeData.get(i)) * 100;
-			rateData.add(Math.round(rate * 100) / 100.0); // 保留两位小数
-		}
-//		newUserRate.setData(rateData);
+		newUserRate.setData(newRates);
+		newUserRate.setKey("newUserRate");
+		newUserRate.setVersion( version == null ? "All" : version);
 		items.add(newUserRate);
 
-		// 老用户数据(计算后转为Double)
-		ActiveUserComposeVO oldUser = new ActiveUserComposeVO();
-		oldUser.setName("老用户");
-		List<Double> oldUserData = new ArrayList<>();
-		for (int i = 0; i < dataSize; i++) {
-			double value = activeData.get(i) - newUserData.get(i);
-			oldUserData.add(value); // 直接为Double类型
-		}
-//		oldUser.setData(oldUserData);
-		items.add(oldUser);
-
+		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		result.setDates(dates);
 		result.setItems(items);
 		return result;
 	}
@@ -436,13 +424,16 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 */
 	@Override
 	public GetActiveUserBaseVO getActiveViscosity(UserAnalyseQueryBaseDTO reqDto) {
+		// 1. 时间单位校验
 		if (!"day".equals(reqDto.getTimeUnit())){
 			throw new BusinessException("时间单位只能为day");
 		}
+		// 2. 获取版本
 		String version = null;
 		if (reqDto.getVersion() != null && !reqDto.getVersion().isEmpty()) {
 			version =reqDto.getVersion().get(0);
 		}
+		// 3. 定义相关变量
 		List<ActiveUserComposeVO> items = new ArrayList<>();
 
 		List<BigDecimal> dayCounts = new ArrayList<>();
@@ -450,32 +441,34 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		List<BigDecimal> thirtyCounts = new ArrayList<>();
 		List<BigDecimal> sevenRates = new ArrayList<>();
 		List<BigDecimal> thirtyRates = new ArrayList<>();
-
+		// 4. 获取时间坐标轴
 		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
+		// 5. 遍历时间坐标轴
 		for (String date : dates) {
+			// 5.1 定义时间范围
 			LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
 			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
 			LocalDateTime sevenDaysAgo = startTime.minusDays(7);
 			LocalDateTime thirtyDaysAgo = startTime.minusDays(30);
-			// 今日活跃用户数
+			// 5.2 今日活跃用户数
 			BigDecimal dayCount = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel()));
 			dayCounts.add(dayCount);
-			// 过去7日活跃用户
+			// 5.3 过去7日活跃用户
 			BigDecimal sevenCount = BigDecimal.valueOf(statActiveUserCount(sevenDaysAgo, startTime, reqDto.getAppId(), version, reqDto.getChannel()));
 			sevenCounts.add(sevenCount);
-			// 过去7日活跃用户
+			// 5.4 过去30日活跃用户
 			BigDecimal thirtyCount = BigDecimal.valueOf(statActiveUserCount(thirtyDaysAgo, startTime, reqDto.getAppId(), version, reqDto.getChannel()));
 			thirtyCounts.add(thirtyCount);
-			// 计算7日活跃用户占比
+			// 5.5 计算7日活跃用户占比
 			sevenRates.add(dayCount.compareTo(BigDecimal.ZERO) == 0 || sevenCount.compareTo(BigDecimal.ZERO) == 0
 					? BigDecimal.ZERO
 					: dayCount.divide(sevenCount, 4, RoundingMode.HALF_UP));
-			// 计算30日活跃用户占比
+			// 5.6 计算30日活跃用户占比
 			thirtyRates.add(dayCount.compareTo(BigDecimal.ZERO) == 0 || thirtyCount.compareTo(BigDecimal.ZERO) == 0
 					? BigDecimal.ZERO:
 					dayCount.divide(thirtyCount, 4, RoundingMode.HALF_UP));
 		}
-		// 组装返回数据
+		// 6. 组装返回数据
 		ActiveUserComposeVO activeUser = new ActiveUserComposeVO();
 		activeUser.setData(dayCounts);
 		activeUser.setName("日活");
@@ -511,6 +504,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		mauRate.setVersion(version == null ? "All" : version);
 		items.add(mauRate);
 
+		// 7.返回结果
 		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
 		result.setDates(dates);
 		result.setItems(items);
@@ -523,7 +517,57 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 * @return GetActiveUserBaseVO
 	 */
 	@Override
-	public GetActiveUserBaseVO getActiveWeekrate(UserAnalyseQueryBaseDTO reqDto) {
+	public GetActiveUserBaseVO getActiveWeekRate(UserAnalyseQueryBaseDTO reqDto) {
+		if (!"week".equals(reqDto.getTimeUnit())){
+			throw new BusinessException("时间单位只能为week");
+		}
+		// 1. 生成时间轴
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
+		// 2. 定义存储列表
+		List<BigDecimal> activeList = new ArrayList<>();
+		List<BigDecimal> userList = new ArrayList<>();
+		List<BigDecimal> weekRateList = new ArrayList<>();
+		// 3. 遍历时间轴
+		for (String date : dates) {
+			LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
+			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+			// 4. 查询、计算累计用户数
+			BigDecimal totalUser = BigDecimal.valueOf(statNewUserCount(null, endTime, reqDto.getAppId(), null, null));
+			userList.add(totalUser);
+			// 5. 查询、计算本周活跃用户数
+			BigDecimal activeUser = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), null, null));
+			activeList.add(activeUser);
+			// 6. 计算周活跃率
+			BigDecimal weekRate = totalUser.compareTo(BigDecimal.ZERO) != 0 && activeUser.compareTo(BigDecimal.ZERO) != 0
+					? activeUser.divide(totalUser, 4, RoundingMode.HALF_UP)
+					: BigDecimal.ZERO;
+			weekRateList.add(weekRate);
+		}
+		// 7. 组装结果数据
+		ActiveUserComposeVO totalUser = new ActiveUserComposeVO();
+		totalUser.setName("周累积用户");
+		totalUser.setKey("weekTotalUser");
+		totalUser.setVersion("All");
+		totalUser.setData(userList);
+
+		ActiveUserComposeVO activeUser = new ActiveUserComposeVO();
+		activeUser.setName("周活跃用户");
+		activeUser.setKey("weekActiveUser");
+		activeUser.setVersion("All");
+		activeUser.setData(activeList);
+
+		ActiveUserComposeVO weekRate = new ActiveUserComposeVO();
+		weekRate.setName("周活跃用户率");
+		weekRate.setKey("weekActiveUserRate");
+		weekRate.setVersion("All");
+		weekRate.setData(weekRateList);
+		// 8. 返回结果
+		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		result.setDates(dates);
+		result.setItems(Arrays.asList(totalUser, activeUser, weekRate));
+		return result;
+	}
+	public GetActiveUserBaseVO getActiveWeekrate2(UserAnalyseQueryBaseDTO reqDto) {
 		if (!"week".equals(reqDto.getTimeUnit())){
 			throw new BusinessException("时间单位错误");
 		}
@@ -585,7 +629,58 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 * @return GetActiveUserBaseVO
 	 */
 	@Override
-	public GetActiveUserBaseVO getActiveMonthrate(UserAnalyseQueryBaseDTO reqDto) {
+	public GetActiveUserBaseVO getActiveMonthRate(UserAnalyseQueryBaseDTO reqDto) {
+		if (!"month".equals(reqDto.getTimeUnit())){
+			throw new BusinessException("时间单位只能为month");
+		}
+
+		// 1. 生成时间轴
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
+		// 2. 定义存储列表
+		List<BigDecimal> activeList = new ArrayList<>();
+		List<BigDecimal> userList = new ArrayList<>();
+		List<BigDecimal> monthRateList = new ArrayList<>();
+		// 3. 遍历时间轴
+		for (String date : dates) {
+			LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
+			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+			// 4. 查询、计算累计用户数
+			BigDecimal totalUser = BigDecimal.valueOf(statNewUserCount(null, endTime, reqDto.getAppId(), null, null));
+			userList.add(totalUser);
+			// 5. 查询、计算本月活跃用户数
+			BigDecimal activeUser = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), null, null));
+			activeList.add(activeUser);
+			// 6. 计算月活跃率
+			BigDecimal weekRate = totalUser.compareTo(BigDecimal.ZERO) != 0 && activeUser.compareTo(BigDecimal.ZERO) != 0
+					? activeUser.divide(totalUser, 4, RoundingMode.HALF_UP)
+					: BigDecimal.ZERO;
+			monthRateList.add(weekRate);
+		}
+		// 7. 组装结果数据
+		ActiveUserComposeVO totalUser = new ActiveUserComposeVO();
+		totalUser.setName("月累积用户");
+		totalUser.setKey("monthTotalUser");
+		totalUser.setVersion("All");
+		totalUser.setData(userList);
+
+		ActiveUserComposeVO activeUser = new ActiveUserComposeVO();
+		activeUser.setName("月活跃用户");
+		activeUser.setKey("monthActiveUser");
+		activeUser.setVersion("All");
+		activeUser.setData(activeList);
+
+		ActiveUserComposeVO monthRate = new ActiveUserComposeVO();
+		monthRate.setName("月活跃用户率");
+		monthRate.setKey("monthActiveUserRate");
+		monthRate.setVersion("All");
+		monthRate.setData(monthRateList);
+		// 8. 返回结果
+		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		result.setDates(dates);
+		result.setItems(Arrays.asList(totalUser, activeUser, monthRate));
+		return result;
+	}
+	public GetActiveUserBaseVO getActiveMonthRate2(UserAnalyseQueryBaseDTO reqDto) {
 		if (!"month".equals(reqDto.getTimeUnit())){
 			throw new BusinessException("时间单位错误");
 		}
@@ -801,6 +896,90 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		page.setRecords( result);
 		return page;
 	}
+//	public Page<PageActiveDetailVO> pageActiveDetail(PageActiveDetailDTO reqDto) {
+//		// 1. 初始化分页对象并计算总条数
+//		Page<PageActiveDetailVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
+//		page.setTotal(calculateTotalCount(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit()));
+//
+//		// 2. 生成当前页时间轴
+//		List<String> dates = generatePageTimeAxis(reqDto.getFromDate(), reqDto.getToDate(),
+//				reqDto.getTimeUnit(), reqDto.getCurrent(), reqDto.getSize());
+//		if (dates.isEmpty()) {
+//			return page; // 无数据直接返回
+//		}
+//		// 获取渠道和版本
+//		List<String> channel = reqDto.getChannel();
+//		String version = null;
+//		if (reqDto.getVersion() != null && !reqDto.getVersion().isEmpty()){
+//			version = reqDto.getVersion().get(0);
+//		}
+//		// 查询结果
+//		List<PageActiveDetailVO> result = new ArrayList<>();
+//		for (String date : dates) {
+//			PageActiveDetailVO detail = new PageActiveDetailVO();
+//			LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
+//			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+//
+//			// 查询活跃用户数量
+//			BigDecimal activeCount = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel()));
+//			// 查询活跃用户中的新增用户数
+//			BigDecimal newCount = BigDecimal.valueOf(getActiveNewUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel()));
+//			// 计算新增用户占比
+//			BigDecimal newUserRate = activeCount.compareTo(BigDecimal.ZERO) == 0 || newCount.compareTo(BigDecimal.ZERO) == 0 ?
+//					BigDecimal.ZERO :
+//					newCount.divide(activeCount, 4, RoundingMode.HALF_UP);
+//
+//			if("day".equals(reqDto.getTimeUnit())){
+//				LocalDateTime sevenDaysAgo = startTime.minusDays(7);
+//				LocalDateTime thirtyDaysAgo = startTime.minusDays(30);
+//				// 查询过去7天活跃用户数量
+//				BigDecimal sevenCount = BigDecimal.valueOf(statActiveUserCount(sevenDaysAgo, startTime, reqDto.getAppId(), version, reqDto.getChannel()));
+//				// 查询过去30天活跃用户数量
+//				BigDecimal thirtyCount = BigDecimal.valueOf(statActiveUserCount(thirtyDaysAgo, startTime, reqDto.getAppId(), version, reqDto.getChannel()));
+//
+//				// 计算用户周活跃率
+//				BigDecimal wauRate = sevenCount.compareTo(BigDecimal.ZERO) != 0 && activeCount.compareTo(BigDecimal.ZERO) != 0
+//						? activeCount.divide(sevenCount, 4, RoundingMode.HALF_UP)
+//						: BigDecimal.ZERO;
+//
+//				// 计算
+//			}
+//
+//
+//
+//			// 过去30日活跃用户
+//			List<MktStatUserAnalysis> thirtyDaysUser = userAnalysisMapper.selectList(Wrappers.<MktStatUserAnalysis>lambdaQuery()
+//					.ge(MktStatUserAnalysis::getStatDate, thirtyDaysAgo)
+//					.lt(MktStatUserAnalysis::getStatDate, startTime)
+//					.in(channel!=null && !channel.isEmpty(),MktStatUserAnalysis::getChannel, channel)
+//					.eq("All".equals(version),MktStatUserAnalysis::getVersion, version)
+//					.select(MktStatUserAnalysis::getNewUser, MktStatUserAnalysis::getActiveUser)
+//			);
+//			BigDecimal thirtyDaysActiveUser = BigDecimal.valueOf(thirtyDaysUser.stream()
+//					.mapToInt(MktStatUserAnalysis::getActiveUser)
+//					.sum());
+//			BigDecimal thirtyDaysNewUser = BigDecimal.valueOf(thirtyDaysUser.stream()
+//					.mapToInt(MktStatUserAnalysis::getNewUser)
+//					.sum());
+//			BigDecimal mauRate = thirtyDaysActiveUser.compareTo(BigDecimal.ZERO) != 0 && thirtyDaysNewUser.compareTo(BigDecimal.ZERO) != 0
+//					? thirtyDaysNewUser.divide(thirtyDaysActiveUser, 4, RoundingMode.HALF_UP)
+//					: BigDecimal.ZERO;
+//
+//
+//			detail.setDate(date);
+//			detail.setActiveUser(activeUser.intValue());
+//			detail.setNewUserRate(newUserRate);
+//			detail.setWauRate(wauRate);
+//			detail.setMauRate(mauRate);
+//			result.add(detail);
+//
+//
+//		}
+//
+//
+//
+//		return page;
+//	}
 
 	/************************************** 启动次数 *****************************************
 	 * 查询启动次数趋势
@@ -833,7 +1012,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 							.map(date -> calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "launch"))
 							.collect(Collectors.toList());
 
-					trend.setData(counts);
+//					trend.setData(counts);
 					return trend;
 				})
 				.collect(Collectors.toList());
@@ -1508,26 +1687,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 * 统计指定时间范围内的新增用户数
 	 */
 	private Long statNewUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
-		// 1. 空值判断
-		if (startTime == null || endTime == null) {
-			return 0L;
-		}
-		// 2. 组装查询条件
-		LambdaQueryWrapper<MktStatNewUser> queryWrapper = Wrappers.<MktStatNewUser>lambdaQuery()
-				.eq(MktStatNewUser::getAppId, appId)
-				.ge(MktStatNewUser::getStatDate, startTime)
-				.lt(MktStatNewUser::getStatDate, endTime);
-
-		// 添加渠道条件
-		if (channels != null && !channels.isEmpty()) {
-			queryWrapper.in(MktStatNewUser::getChannel, channels);
-		}
-		// 添加版本条件
-		if (version != null && !version.isEmpty()){
-			queryWrapper.eq(MktStatNewUser::getVersion, version);
-		}
-		// 3. 统计新增用户数,不用去重
-		List<MktStatNewUser> newUsers = newUserMapper.selectList(queryWrapper);
+		List<String> newUsers = getNewUserIdList(startTime, endTime, appId, version, channels);
 		return newUsers == null ? 0L : newUsers.size();
 	}
 
@@ -1535,28 +1695,81 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 * 统计指定时间范围内的活跃用户数(去重)
 	 */
 	private Long statActiveUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
-		// 1. 空值判断
-		if (startTime == null || endTime == null) {
-			return 0L;
-		}
-		// 2. 组装查询条件
+		List<String> activeUsers = getActiveUserIdList(startTime, endTime, appId, version, channels);
+		return activeUsers == null ? 0L : activeUsers.size();
+	}
+
+	/**
+	 * 查询指定时间范围内的活跃用户Id列表(去重)
+	 */
+	private List<String> getActiveUserIdList(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
+		// 1. 组装查询条件
 		LambdaQueryWrapper<MktStatActiveUser> queryWrapper = Wrappers.<MktStatActiveUser>lambdaQuery()
 				.eq(MktStatActiveUser::getAppId, appId)
-				.ge(MktStatActiveUser::getStatDate, startTime)
-				.lt(MktStatActiveUser::getStatDate, endTime)
+				.ge(startTime != null, MktStatActiveUser::getStatDate, startTime)
+				.lt(endTime != null, MktStatActiveUser::getStatDate, endTime)
 				.select(MktStatActiveUser::getUserId)
 				.groupBy(MktStatActiveUser::getUserId);
 
-		// 添加渠道条件
+		// 2. 添加渠道条件
 		if (channels != null && !channels.isEmpty()) {
 			queryWrapper.in(MktStatActiveUser::getChannel, channels);
 		}
-		// 添加版本条件
+		// 3. 添加版本条件
 		if (version != null && !version.isEmpty()){
 			queryWrapper.eq(MktStatActiveUser::getVersion, version);
 		}
-		// 3. 统计活跃用户数,根据userID去重
+		// 4. 统计活跃用户数,根据userID去重
 		List<MktStatActiveUser> activeUsers = activeUserMapper.selectList(queryWrapper);
-		return activeUsers == null ? 0L : activeUsers.size();
+		return activeUsers.stream().map(MktStatActiveUser::getUserId).toList();
+	}
+
+	/**
+	 * 查询指定时间范围内的活跃用户Id列表(去重)
+	 */
+	private List<String> getNewUserIdList(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
+
+		// 1. 组装查询条件
+		LambdaQueryWrapper<MktStatNewUser> queryWrapper = Wrappers.<MktStatNewUser>lambdaQuery()
+				.eq(MktStatNewUser::getAppId, appId)
+				.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.stream().map(MktStatNewUser::getUserId).toList();
+	}
+
+	/**
+	 * 获取活跃用户中新增用户的数量
+	 */
+	private Long getActiveNewUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels) {
+		// 1. 获取活跃用户ID列表
+		List<String> activeUserIds = getActiveUserIdList(startTime, endTime, appId, version, channels);
+		if (activeUserIds == null || activeUserIds.isEmpty()) {
+			return 0L;
+		}
+
+		// 2. 获取新增用户ID列表
+		List<String> newUserIds = getNewUserIdList(startTime, endTime, appId, version, channels);
+		if (newUserIds == null || newUserIds.isEmpty()) {
+			return 0L;
+		}
+
+		// 3. 计算交集:既是活跃用户又是新增用户的用户数量
+		Set<String> activeUserSet = new HashSet<>(activeUserIds);
+		Set<String> newUserSet = new HashSet<>(newUserIds);
+
+		// 4. 保留在活跃用户集合中的新增用户
+		activeUserSet.retainAll(newUserSet);
+		return (long) activeUserSet.size();
 	}
 }