Przeglądaj źródła

update: 新增活跃用户相关功能

lwh 1 miesiąc temu
rodzic
commit
b887aa5e11

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

@@ -4,6 +4,7 @@ package com.pig4cloud.pig.statistics.api.vo.user;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -20,10 +21,22 @@ public class ActiveUserComposeVO {
 	@Schema(description = "名称", example = "新增用户")
 	private String name;
 
+	/**
+	 * 版本
+	 */
+	@Schema(description = "版本", example = "1.0.0")
+	private String version;
+
+	/**
+	 * key
+	 */
+	@Schema(description = "key")
+	private String key;
+
 	/**
 	 * 数量
 	 */
 	@Schema(description = "数量")
-	private List<Double> data;
+	private List<BigDecimal> data;
 
 }

+ 6 - 5
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/user/PageActiveDetailVO.java

@@ -7,6 +7,7 @@ import lombok.Data;
 
 import java.io.Serial;
 import java.io.Serializable;
+import java.math.BigDecimal;
 
 /**
  * @author: lwh
@@ -38,31 +39,31 @@ public class PageActiveDetailVO implements Serializable {
 	 * 新用户占比
 	 */
 	@Schema(description = "新用户占比")
-	private Double newUserRate;
+	private BigDecimal newUserRate;
 
 
 	/***********************************单位为天时
 	 * DAU/过去7日活跃用户
 	 */
 	@Schema(description = "DAU/过去7日活跃用户")
-	private Double wauRate;
+	private BigDecimal wauRate;
 
 	/***********************************单位为天时
 	 * DAU/过去30日活跃用户
 	 */
 	@Schema(description = "DAU/过去30日活跃用户")
-	private Double mauRate;
+	private BigDecimal mauRate;
 
 	/***********************************单位为周时
 	 * 用户周活跃率
 	 */
 	@Schema(description = "用户周活跃率")
-	private Double weekActiveUserRate;
+	private BigDecimal weekActiveUserRate;
 
 
 	/***********************************单位为月时
 	 * 用户月活跃率
 	 */
 	@Schema(description = "用户月活跃率")
-	private Double monthActiveUserRate;
+	private BigDecimal monthActiveUserRate;
 }

+ 258 - 193
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UserAnalyseServiceImpl.java

@@ -4,6 +4,7 @@ package com.pig4cloud.pig.statistics.service.impl;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.pig4cloud.pig.common.core.exception.BusinessException;
 import com.pig4cloud.pig.statistics.api.dto.user.*;
 import com.pig4cloud.pig.statistics.api.entity.MktStatUserAnalysis;
 import com.pig4cloud.pig.statistics.api.entity.MktStatUserRetention;
@@ -72,7 +73,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 
 					// 计算每个时间点的新增用户数
 					List<Integer> counts = dates.stream()
-							.map(date -> calculateNewUserCount(date, version, reqDto, "newUser"))
+							.map(date -> calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "newUser"))
 							.collect(Collectors.toList());
 
 					trend.setData(counts);
@@ -298,7 +299,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 
 					// 计算每个时间点的活跃用户数
 					List<Integer> counts = dates.stream()
-							.map(date -> calculateNewUserCount(date, version, reqDto, "activeUser"))
+							.map(date -> calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"))
 							.collect(Collectors.toList());
 
 					trend.setData(counts);
@@ -380,7 +381,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 			int value = 30000 + random.nextInt(5000) + (i * 50);
 			activeData.add((double) value); // 整数转Double
 		}
-		activeUser.setData(activeData);
+//		activeUser.setData(activeData);
 		items.add(activeUser);
 
 		// 新增用户数据(整数转为Double)
@@ -391,7 +392,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 			int value = activeData.get(i).intValue() - 100 - random.nextInt(300);
 			newUserData.add((double) value); // 整数转Double
 		}
-		newUser.setData(newUserData);
+//		newUser.setData(newUserData);
 		items.add(newUser);
 
 		// 新增用户占比数据(保持Double类型)
@@ -402,7 +403,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 			double rate = (newUserData.get(i) / activeData.get(i)) * 100;
 			rateData.add(Math.round(rate * 100) / 100.0); // 保留两位小数
 		}
-		newUserRate.setData(rateData);
+//		newUserRate.setData(rateData);
 		items.add(newUserRate);
 
 		// 老用户数据(计算后转为Double)
@@ -413,7 +414,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 			double value = activeData.get(i) - newUserData.get(i);
 			oldUserData.add(value); // 直接为Double类型
 		}
-		oldUser.setData(oldUserData);
+//		oldUser.setData(oldUserData);
 		items.add(oldUser);
 
 		result.setItems(items);
@@ -443,31 +444,31 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		// 日活数据
 		ActiveUserComposeVO activeUserItem = new ActiveUserComposeVO();
 		activeUserItem.setName("日活");
-		activeUserItem.setData(Arrays.asList(1523.0, 1489.0, 1602.0, 1576.0, 987.0, 923.0, 1756.0, 1632.0));
+//		activeUserItem.setData(Arrays.asList(1523.0, 1489.0, 1602.0, 1576.0, 987.0, 923.0, 1756.0, 1632.0));
 		items.add(activeUserItem);
 
 		// 过去7日活跃用户数据
 		ActiveUserComposeVO wauItem = new ActiveUserComposeVO();
 		wauItem.setName("过去7日活跃用户");
-		wauItem.setData(Arrays.asList(8234.0, 8156.0, 8321.0, 8289.0, 8356.0, 8412.0, 8531.0, 8498.0));
+//		wauItem.setData(Arrays.asList(8234.0, 8156.0, 8321.0, 8289.0, 8356.0, 8412.0, 8531.0, 8498.0));
 		items.add(wauItem);
 
 		// DAU/过去7日活跃用户比率
 		ActiveUserComposeVO wauRateItem = new ActiveUserComposeVO();
 		wauRateItem.setName("DAU/过去7日活跃用户");
-		wauRateItem.setData(Arrays.asList(18.5, 18.25, 19.25, 19.01, 11.81, 10.97, 20.58, 19.21));
+//		wauRateItem.setData(Arrays.asList(18.5, 18.25, 19.25, 19.01, 11.81, 10.97, 20.58, 19.21));
 		items.add(wauRateItem);
 
 		// 过去30日活跃用户数据
 		ActiveUserComposeVO mauItem = new ActiveUserComposeVO();
 		mauItem.setName("过去30日活跃用户");
-		mauItem.setData(Arrays.asList(35621.0, 35489.0, 35723.0, 35698.0, 34987.0, 34215.0, 35123.0, 36012.0));
+//		mauItem.setData(Arrays.asList(35621.0, 35489.0, 35723.0, 35698.0, 34987.0, 34215.0, 35123.0, 36012.0));
 		items.add(mauItem);
 
 		// DAU/过去30日活跃用户比率
 		ActiveUserComposeVO mauRateItem = new ActiveUserComposeVO();
 		mauRateItem.setName("DAU/过去30日活跃用户");
-		mauRateItem.setData(Arrays.asList(4.28, 4.19, 4.48, 4.42, 2.82, 2.70, 5.00, 4.53));
+//		mauRateItem.setData(Arrays.asList(4.28, 4.19, 4.48, 4.42, 2.82, 2.70, 5.00, 4.53));
 		items.add(mauRateItem);
 
 		result.setItems(items);
@@ -481,72 +482,61 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 */
 	@Override
 	public GetActiveUserBaseVO getActiveWeekrate(UserAnalyseQueryBaseDTO reqDto) {
-		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
-		Random random = new Random();
-		DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-
-		// 1. 生成周日期列表(每周一)
-		List<String> dates = new ArrayList<>();
-		LocalDate currentDate = reqDto.getFromDate();
-		// 调整到当周周一
-		currentDate = currentDate.minusDays(currentDate.getDayOfWeek().getValue() - 1);
-
-		while (!currentDate.isAfter(reqDto.getToDate())) {
-			dates.add(currentDate.format(dateFormatter));
-			currentDate = currentDate.plusWeeks(1);
+		if (!"week".equals(reqDto.getTimeUnit())){
+			throw new BusinessException("时间单位错误");
 		}
+		reqDto.setChannel( null);
+		reqDto.setVersion( null);
+		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		// 1. 生成时间轴
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
 		result.setDates(dates);
-		int dataSize = dates.size();
-
-		// 2. 生成周累积用户数据(240万起,每周递增0.2%-0.4%)
-		List<Double> weekTotalUserList = new ArrayList<>();
-		double baseTotal = 2400000;
-		for (int i = 0; i < dataSize; i++) {
-			baseTotal += baseTotal * (0.002 + random.nextDouble() * 0.002);
-			// 四舍五入取整(内部实现四舍五入逻辑)
-			weekTotalUserList.add((double) Math.round(baseTotal));
-		}
-
-		// 3. 生成周活跃用户数据(周累积的0.28%-0.33%)
-		List<Double> weekActiveUserList = new ArrayList<>();
-		for (double total : weekTotalUserList) {
-			double active = total * (0.0028 + random.nextDouble() * 0.0005);
-			weekActiveUserList.add((double) Math.round(active)); // 四舍五入取整
-		}
-
-		// 4. 生成周活跃用户率(保留两位小数)
-		List<Double> weekActiveRateList = new ArrayList<>();
-		for (int i = 0; i < dataSize; i++) {
-			double rate = (weekActiveUserList.get(i) / weekTotalUserList.get(i)) * 100;
-			// 四舍五入保留两位小数:先乘100取整再除以100
-			weekActiveRateList.add(Math.round(rate * 100) / 100.0);
+		// 2. 定义存储列表
+		List<BigDecimal> activeList = new ArrayList<>();
+		List<BigDecimal> userList = new ArrayList<>();
+		List<BigDecimal> weekRateList = new ArrayList<>();
+		// 3. 遍历时间轴
+		for (String date : dates) {
+			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+			// 4. 查询、计算累计用户数
+			List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(Wrappers.<MktStatUserAnalysis>lambdaQuery()
+					.lt(MktStatUserAnalysis::getStatDate, endTime)
+					.select(MktStatUserAnalysis::getNewUser)
+			);
+			BigDecimal totalUser = BigDecimal.valueOf(userAnalyses.stream()
+					.mapToInt(MktStatUserAnalysis::getNewUser)
+					.sum());
+			userList.add(totalUser);
+			// 5. 查询、计算本周活跃用户数
+			BigDecimal activeUser = BigDecimal.valueOf(calculateNewUserCount(date, "All", reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
+			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);
 
-		// 5. 组装返回数据
-		List<ActiveUserComposeVO> items = new ArrayList<>();
-
-		// 周累积用户
-		ActiveUserComposeVO totalItem = new ActiveUserComposeVO();
-		totalItem.setName("周累积用户");
-		totalItem.setData(weekTotalUserList);
-		items.add(totalItem);
-
-		// 周活跃用户
-		ActiveUserComposeVO activeItem = new ActiveUserComposeVO();
-		activeItem.setName("周活跃用户");
-		activeItem.setData(weekActiveUserList);
-		items.add(activeItem);
-
-		// 周活跃用户率
-		ActiveUserComposeVO rateItem = new ActiveUserComposeVO();
-		rateItem.setName("周活跃用户率");
-		rateItem.setData(weekActiveRateList);
-		items.add(rateItem);
-
-		result.setItems(items);
+		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);
+		result.setItems(Arrays.asList(totalUser, activeUser, weekRate));
 		return result;
 	}
-
 	/**
 	 * 获取月活跃率
 	 * @param reqDto 获取月活跃率入参
@@ -554,72 +544,59 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 */
 	@Override
 	public GetActiveUserBaseVO getActiveMonthrate(UserAnalyseQueryBaseDTO reqDto) {
-		// 创建返回对象
-		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
-		Random random = new Random();
-		DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-
-		// 1. 生成月日期列表(每月1日)
-		List<String> dates = new ArrayList<>();
-		LocalDate currentDate = reqDto.getFromDate();
-
-		// 调整到当月1日
-		currentDate = currentDate.withDayOfMonth(1);
-
-		// 按月生成日期直到结束日期
-		while (!currentDate.isAfter(reqDto.getToDate())) {
-			dates.add(currentDate.format(dateFormatter));
-			currentDate = currentDate.plusMonths(1);
+		if (!"month".equals(reqDto.getTimeUnit())){
+			throw new BusinessException("时间单位错误");
 		}
+		reqDto.setChannel( null);
+		reqDto.setVersion( null);
+		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		// 1. 生成时间轴
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit());
 		result.setDates(dates);
-		int dataSize = dates.size();
-
-		// 2. 生成月累积用户数据(基础值250万,每月递增约1.2%-1.8%)
-		List<Double> monthTotalUserList = new ArrayList<>();
-		double baseTotal = 2500000; // 基础用户量
-		for (int i = 0; i < dataSize; i++) {
-			// 每月增加1.2%-1.8%的随机增长
-			double growth = baseTotal * (0.012 + random.nextDouble() * 0.006);
-			baseTotal += growth;
-			monthTotalUserList.add((double) Math.round(baseTotal)); // 取整数
-		}
-
-		// 3. 生成月活跃用户数据(月累积用户的1.2%-1.4%)
-		List<Double> monthActiveUserList = new ArrayList<>();
-		for (double total : monthTotalUserList) {
-			double activeRate = 0.012 + random.nextDouble() * 0.002; // 1.2% - 1.4%
-			monthActiveUserList.add((double) Math.round(total * activeRate)); // 取整
-		}
-
-		// 4. 生成月活跃用户率(月活跃/月累积,保留两位小数)
-		List<Double> monthActiveRateList = new ArrayList<>();
-		for (int i = 0; i < dataSize; i++) {
-			double rate = (monthActiveUserList.get(i) / monthTotalUserList.get(i)) * 100;
-			monthActiveRateList.add(Math.round(rate * 100) / 100.0); // 保留两位小数
+		// 2. 定义存储列表
+		List<BigDecimal> activeList = new ArrayList<>();
+		List<BigDecimal> userList = new ArrayList<>();
+		List<BigDecimal> monthRateList = new ArrayList<>();
+		// 3. 遍历时间轴
+		for (String date : dates) {
+			LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+			// 4. 查询、计算累计用户数
+			List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(Wrappers.<MktStatUserAnalysis>lambdaQuery()
+					.lt(MktStatUserAnalysis::getStatDate, endTime)
+					.select(MktStatUserAnalysis::getNewUser)
+			);
+			BigDecimal totalUser = BigDecimal.valueOf(userAnalyses.stream()
+					.mapToInt(MktStatUserAnalysis::getNewUser)
+					.sum());
+			userList.add(totalUser);
+			// 5. 查询、计算本月活跃用户
+			BigDecimal activeUser = BigDecimal.valueOf(calculateNewUserCount(date, "All", reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
+			activeList.add(activeUser);
+			// 6. 计算月活跃率
+			BigDecimal monthRate = totalUser.compareTo(BigDecimal.ZERO) != 0 && activeUser.compareTo(BigDecimal.ZERO) != 0
+					? activeUser.divide(totalUser, 4, RoundingMode.HALF_UP)
+					: BigDecimal.ZERO;
+			monthRateList.add(monthRate);
 		}
+		// 7. 组装结果数据
+		ActiveUserComposeVO totalUser = new ActiveUserComposeVO();
+		totalUser.setName("月累积用户");
+		totalUser.setKey("monthTotalUser");
+		totalUser.setVersion("All");
+		totalUser.setData(userList);
 
-		// 5. 组装items数据
-		List<ActiveUserComposeVO> items = new ArrayList<>();
-
-		// 月累积用户
-		ActiveUserComposeVO totalUserItem = new ActiveUserComposeVO();
-		totalUserItem.setName("月累积用户");
-		totalUserItem.setData(monthTotalUserList);
-		items.add(totalUserItem);
-
-		// 月活跃用户
-		ActiveUserComposeVO activeUserItem = new ActiveUserComposeVO();
-		activeUserItem.setName("月活跃用户");
-		activeUserItem.setData(monthActiveUserList);
-		items.add(activeUserItem);
-
-		// 月活跃用户率
-		ActiveUserComposeVO rateItem = new ActiveUserComposeVO();
-		rateItem.setName("月活跃用户率");
-		rateItem.setData(monthActiveRateList);
-		items.add(rateItem);
-
-		result.setItems(items);
+		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);
+		result.setItems(Arrays.asList(totalUser, activeUser, monthRate));
 		return result;
 	}
 
@@ -630,67 +607,156 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 */
 	@Override
 	public Page<PageActiveDetailVO> pageActiveDetail(PageActiveDetailDTO reqDto) {
+		// 活跃构成:活跃用户中新增用户的占比比例
+		// 活跃粘度:DAU/过去7日活跃用户,DAU/过去30日活跃用户
+		// 过去7日活跃用户:过去7日(不含今日)的活跃用户数(去重)
+		// 过去30日(不含今日)的活跃用户数(去重)
+
+		// 1. 初始化分页对象并计算总条数
 		Page<PageActiveDetailVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
-		List<PageActiveDetailVO> result = new ArrayList<>();
-		String timeUnit = reqDto.getTimeUnit();
-		LocalDate fromDate = reqDto.getFromDate();
-		LocalDate toDate = reqDto.getToDate();
+		page.setTotal(calculateTotalCount(reqDto.getFromDate(), reqDto.getToDate(), reqDto.getTimeUnit()));
 
-		// 根据时间单位生成对应模拟数据
-		if ("day".equals(timeUnit)) {
-			// 生成按天的模拟数据
-			LocalDate currentDate = fromDate;
-			while (!currentDate.isAfter(toDate) && result.size() < reqDto.getSize()) {
-				PageActiveDetailVO vo = new PageActiveDetailVO();
-				vo.setDate(currentDate.toString());
-				vo.setActiveUser(1300 + new Random().nextInt(200));
-				vo.setMauRate(3.5 + new Random().nextDouble() * 1.5);
-				vo.setWauRate(15 + new Random().nextDouble() * 5);
-				vo.setNewUserRate(96 + new Random().nextDouble() * 2);
-				result.add(vo);
-				currentDate = currentDate.plusDays(1);
+		// 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 = "All";
+		if (reqDto.getVersion() != null && !reqDto.getVersion().isEmpty()){
+			version = reqDto.getVersion().get(0);
+		}
+		List<PageActiveDetailVO> result = new ArrayList<>();
+		if ("day".equals(reqDto.getTimeUnit())){
+			// 时间单位为天
+			for (String date : dates) {
+				LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
+				LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+				LocalDateTime sevenDaysAgo = startTime.minusDays(7);
+				LocalDateTime thirtyDaysAgo = startTime.minusDays(30);
+
+				// 计算本周活跃用户
+				BigDecimal activeUser = BigDecimal.valueOf(calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
+				// 计算本周新增用户
+				BigDecimal newUser = BigDecimal.valueOf(calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "newUser"));
+
+				// 计算活跃构成(新增/活跃)
+				BigDecimal newUserRate = activeUser.compareTo(BigDecimal.ZERO) != 0 && newUser.compareTo(BigDecimal.ZERO) != 0
+						? newUser.divide(activeUser, 4, RoundingMode.HALF_UP)
+						: BigDecimal.ZERO;
+
+				// 过去7日活跃用户
+				List<MktStatUserAnalysis> sevenDaysUser = userAnalysisMapper.selectList(Wrappers.<MktStatUserAnalysis>lambdaQuery()
+						.ge(MktStatUserAnalysis::getStatDate, sevenDaysAgo)
+						.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 sevenDaysActiveUser = BigDecimal.valueOf(sevenDaysUser.stream()
+						.mapToInt(MktStatUserAnalysis::getActiveUser)
+						.sum());
+				BigDecimal sevenDaysNewUser = BigDecimal.valueOf(sevenDaysUser.stream()
+						.mapToInt(MktStatUserAnalysis::getNewUser)
+						.sum());
+				BigDecimal wauRate = sevenDaysNewUser.compareTo(BigDecimal.ZERO) != 0 && sevenDaysActiveUser.compareTo(BigDecimal.ZERO) != 0
+						? sevenDaysNewUser.divide(sevenDaysActiveUser, 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;
+
+				PageActiveDetailVO detail = new PageActiveDetailVO();
+				detail.setDate(date);
+				detail.setActiveUser(activeUser.intValue());
+				detail.setNewUserRate(newUserRate);
+				detail.setWauRate(wauRate);
+				detail.setMauRate(mauRate);
+				result.add(detail);
 			}
-		} else if ("week".equals(timeUnit)) {
-			// 生成按周的模拟数据
-			LocalDate currentDate = fromDate;
-			while (!currentDate.isAfter(toDate) && result.size() < reqDto.getSize()) {
-				LocalDate endOfWeek = currentDate.plusDays(6);
-				if (endOfWeek.isAfter(toDate)) {
-					endOfWeek = toDate;
-				}
-				PageActiveDetailVO vo = new PageActiveDetailVO();
-				vo.setDate(String.format("%s~%s",
-						currentDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")),
-						endOfWeek.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))));
-				vo.setActiveUser(7500 + new Random().nextInt(500));
-				vo.setWeekActiveUserRate(0.25 + new Random().nextDouble() * 0.1);
-				vo.setNewUserRate(98.5 + new Random().nextDouble() * 0.5);
-				result.add(vo);
-				currentDate = currentDate.plusWeeks(1);
+
+		}
+		else if ("week".equals(reqDto.getTimeUnit())){
+			// 时间单位为周
+			for (String date : dates) {
+				LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+				List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(Wrappers.<MktStatUserAnalysis>lambdaQuery()
+						.lt(MktStatUserAnalysis::getStatDate, endTime)
+						.select(MktStatUserAnalysis::getNewUser)
+				);
+				BigDecimal totalUser = BigDecimal.valueOf(userAnalyses.stream()
+						.mapToInt(MktStatUserAnalysis::getNewUser)
+						.sum());
+				// 计算本周活跃用户
+				BigDecimal activeUser = BigDecimal.valueOf(calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
+				// 计算本周新增用户
+				BigDecimal newUser = BigDecimal.valueOf(calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "newUser"));
+				// 计算活跃构成(新增/活跃)
+				BigDecimal newUserRate = activeUser.compareTo(BigDecimal.ZERO) != 0 && newUser.compareTo(BigDecimal.ZERO) != 0
+						? newUser.divide(activeUser, 4, RoundingMode.HALF_UP)
+						: BigDecimal.ZERO;
+
+				BigDecimal weekActiveUserRate = activeUser.compareTo(BigDecimal.ZERO) != 0 && totalUser.compareTo(BigDecimal.ZERO) != 0
+						? activeUser.divide(totalUser, 4, RoundingMode.HALF_UP)
+						: BigDecimal.ZERO;
+
+				PageActiveDetailVO detail = new PageActiveDetailVO();
+				detail.setActiveUser(activeUser.intValue());
+				detail.setNewUserRate(newUserRate);
+				detail.setWeekActiveUserRate(weekActiveUserRate);
+				result.add( detail);
 			}
-		} else if ("month".equals(timeUnit)) {
-			// 生成按月的模拟数据
-			LocalDate currentDate = fromDate;
-			while (!currentDate.isAfter(toDate) && result.size() < reqDto.getSize()) {
-				LocalDate endOfMonth = currentDate.plusMonths(1).minusDays(1);
-				if (endOfMonth.isAfter(toDate)) {
-					endOfMonth = toDate;
-				}
-				PageActiveDetailVO vo = new PageActiveDetailVO();
-				vo.setDate(String.format("%s~%s",
-						currentDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")),
-						endOfMonth.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))));
-				vo.setActiveUser(30000 + new Random().nextInt(5000));
-				vo.setNewUserRate(99.4 + new Random().nextDouble() * 0.2);
-				vo.setMonthActiveUserRate(1.2 + new Random().nextDouble() * 0.2);
-				result.add(vo);
-				currentDate = currentDate.plusMonths(1);
+
+		}
+		else if ("month".equals(reqDto.getTimeUnit())){
+			//时间单位为月
+			for (String date : dates) {
+				LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+				List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(Wrappers.<MktStatUserAnalysis>lambdaQuery()
+						.lt(MktStatUserAnalysis::getStatDate, endTime)
+						.select(MktStatUserAnalysis::getNewUser)
+				);
+				BigDecimal totalUser = BigDecimal.valueOf(userAnalyses.stream()
+						.mapToInt(MktStatUserAnalysis::getNewUser)
+						.sum());
+				// 计算本月活跃用户
+				BigDecimal activeUser = BigDecimal.valueOf(calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
+				// 计算本月新增用户
+				BigDecimal newUser = BigDecimal.valueOf(calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "newUser"));
+				// 计算活跃构成(新增/活跃)
+				BigDecimal newUserRate = activeUser.compareTo(BigDecimal.ZERO) != 0 && newUser.compareTo(BigDecimal.ZERO) != 0
+						? newUser.divide(activeUser, 4, RoundingMode.HALF_UP)
+						: BigDecimal.ZERO;
+
+				BigDecimal monthActiveUserRate = activeUser.compareTo(BigDecimal.ZERO) != 0 && totalUser.compareTo(BigDecimal.ZERO) != 0
+						? activeUser.divide(totalUser, 4, RoundingMode.HALF_UP)
+						: BigDecimal.ZERO;
+
+				PageActiveDetailVO detail = new PageActiveDetailVO();
+				detail.setActiveUser(activeUser.intValue());
+				detail.setNewUserRate(newUserRate);
+				detail.setMonthActiveUserRate(monthActiveUserRate);
+				result.add( detail);
 			}
 		}
-
-		page.setRecords(result);
-		// 模拟总条数,实际场景应根据查询条件计算
-		page.setTotal(result.size() > 0 ? 100 : 0);
+		page.setRecords( result);
 		return page;
 	}
 
@@ -722,7 +788,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 
 					// 计算每个时间点的启动次数
 					List<Integer> counts = dates.stream()
-							.map(date -> calculateNewUserCount(date, version, reqDto, "launch"))
+							.map(date -> calculateNewUserCount(date, version, reqDto.getChannel(), reqDto.getTimeUnit(), "launch"))
 							.collect(Collectors.toList());
 
 					trend.setData(counts);
@@ -1115,10 +1181,10 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	/**
 	 * 计算单个时间点的数量
 	 */
-	private Integer calculateNewUserCount(String date, String version, UserAnalyseQueryBaseDTO reqDto, String field) {
+	private Integer calculateNewUserCount(String date, String version, List<String> channels, String timeUnit, String field) {
 		// 1. 获取时间范围(开始和结束时间)
-		LocalDateTime startTime = getStartTime(date, reqDto.getTimeUnit());
-		LocalDateTime endTime = getEndTime(date, reqDto.getTimeUnit());
+		LocalDateTime startTime = getStartTime(date, timeUnit);
+		LocalDateTime endTime = getEndTime(date, timeUnit);
 		if (startTime == null || endTime == null) {
 			return 0;
 		}
@@ -1140,7 +1206,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		}
 
 		// 添加渠道条件
-		List<String> channels = reqDto.getChannel();
 		if (channels != null && !channels.isEmpty()) {
 			queryWrapper.in(MktStatUserAnalysis::getChannel, channels);
 		}