Przeglądaj źródła

Merge remote-tracking branch 'refs/remotes/origin/dev/lwh' into dev/wcl

wangcl 3 tygodni temu
rodzic
commit
b5ebc87a7a

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

@@ -16,20 +16,18 @@ import io.swagger.v3.oas.annotations.security.SecurityRequirement;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import jakarta.servlet.http.HttpServletResponse;
 import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
 import lombok.AllArgsConstructor;
-import org.springdoc.core.annotations.ParameterObject;
 import org.springframework.beans.BeanUtils;
 import org.springframework.http.HttpHeaders;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 
-import java.io.OutputStream;
 import java.net.URLEncoder;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import java.util.stream.Collectors;
 
 
 /**
@@ -244,7 +242,7 @@ public class UserAnalyseController {
 
 		// 使用EasyExcel编程式导出,指定排除字段
 		EasyExcel.write(response.getOutputStream(), PageActiveDetailVO.class)
-				.excludeColumnFiledNames(excludeFields)
+				.excludeColumnFieldNames(excludeFields)
 				.sheet("活跃详情")
 				.doWrite(allRecords);
 	}
@@ -315,11 +313,9 @@ public class UserAnalyseController {
 	@GetMapping("/version/export")
 	@Operation(summary = "导出全部版本详情")
 	public List<List<PageAllVersionDetailVO>> exportAllVersionDetail(
+			@NotBlank(message = "应用ID不能为空")
 			@Schema(description = "应用ID",example = "Fqs2CL9CUn7U1AqilSFXgb")
-			@ParameterObject String appId) {
-		if (appId == null || appId.isEmpty()){
-			throw new BusinessException("appId不能为空");
-		}
+			@RequestParam String appId) {
 
 		List<List<PageAllVersionDetailVO>> result = new ArrayList<>();
 		for (int i = 0; i < 2; i++) {
@@ -428,7 +424,6 @@ public class UserAnalyseController {
 		return R.ok(result);
 	}
 
-
 	@PostMapping("/version/distribution/export")
 	@Operation(summary = "导出版本用户来源详情")
 	public void exportVersionDistributionDetail(
@@ -510,4 +505,27 @@ public class UserAnalyseController {
 				.doWrite(allRecords);
 	}
 
+/***************************************** 公用接口 *****************************************/
+	@GetMapping("/version/list")
+	@Operation(summary = "获取应用版本列表")
+	public R<List<String>> getVersionList(
+			@NotBlank(message = "应用ID不能为空")
+			@Schema(description = "应用ID",example = "Fqs2CL9CUn7U1AqilSFXgb")
+			@RequestParam String appId) {
+		if (appId == null || appId.isEmpty()){
+			throw new BusinessException("appId不能为空");
+		}
+		List<String> result = userAnalyseService.getVersionList(appId);
+		return R.ok(result);
+	}
+
+	@GetMapping("/channel/list")
+	@Operation(summary = "获取应用渠道列表", description = "根据应用ID查询该应用下的所有渠道列表")
+	public R<List<String>> getChannelList(
+			@NotBlank(message = "应用ID不能为空")
+			@Schema(description = "应用ID", example = "Fqs2CL9CUn7U1AqilSFXgb")
+			@RequestParam String appId) {
+		List<String> result = userAnalyseService.getChannelList(appId);
+		return R.ok(result);
+	}
 }

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

@@ -129,4 +129,18 @@ public interface UserAnalyseService {
 	 * @return Page
 	 */
 	Page<PageVersionDistributionDetailVO> pageVersionDistributionDetail(@Valid PageVersionDistributionDetailDTO reqDto);
+
+	/**
+	 * 获取应用版本列表
+	 * @param appId 应用ID
+	 * @return List
+	 */
+	List<String> getVersionList(String appId);
+
+	/**
+	 * 获取应用渠道列表
+	 * @param appId 应用ID
+	 * @return List
+	 */
+	List<String> getChannelList(String appId);
 }

+ 26 - 657
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UserAnalyseServiceImpl.java

@@ -10,7 +10,6 @@ import com.pig4cloud.pig.statistics.api.dto.user.*;
 import com.pig4cloud.pig.statistics.api.entity.user.MktStatActiveUser;
 import com.pig4cloud.pig.statistics.api.entity.user.MktStatNewUser;
 import com.pig4cloud.pig.statistics.api.entity.user.MktStatUserAnalysis;
-import com.pig4cloud.pig.statistics.api.entity.user.MktStatUserRetention;
 import com.pig4cloud.pig.statistics.api.vo.user.*;
 import com.pig4cloud.pig.statistics.mapper.MktStatActiveUserMapper;
 import com.pig4cloud.pig.statistics.mapper.MktStatNewUserMapper;
@@ -33,7 +32,6 @@ import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.stream.Collectors;
 
-import static com.baomidou.mybatisplus.core.toolkit.Wrappers.lambdaQuery;
 
 /**
  * @author: lwh
@@ -47,8 +45,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 
 	private final MktStatUserAnalysisMapper userAnalysisMapper;
 
-	private final MktStatUserRetentionMapper userRetentionMapper;
-
 	private final MktStatActiveUserMapper activeUserMapper;
 
 	private final MktStatNewUserMapper newUserMapper;
@@ -105,39 +101,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		result.setItems(voList);
 		return result;
 	}
-//	public GetNewUserTrendVO getNewUserTrend2(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())
-//				? Collections.singletonList("All")
-//				: 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("newUser");
-//
-//					// 计算每个时间点的新增用户数
-//					List<Integer> counts = dates.stream()
-//							.map(date -> calculateNewUserCount(date, reqDto.getAppId(), version, reqDto.getChannel(), reqDto.getTimeUnit(), "newUser"))
-//							.collect(Collectors.toList());
-//
-//					trend.setData(counts);
-//					return trend;
-//				})
-//				.collect(Collectors.toList());
-//
-//		result.setItems(voList);
-//		return result;
-//	}
 
 	/**
 	 * 分页查询新增趋势详情
@@ -207,72 +170,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		page.setRecords(items);
 		return page;
 	}
-//	public Page<PageNewUserTrendDetailVO> pageNewUserTrendDetail2(PageUserAnalyseDTO reqDto) {
-//		// 1. 初始化分页对象并计算总条数
-//		Page<PageNewUserTrendDetailVO> 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; // 无数据直接返回
-//		}
-//
-//		// 3. 定义变量
-//		DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
-//		List<PageNewUserTrendDetailVO> detailVOS = new ArrayList<>(dates.size());
-//		String timeUnit = reqDto.getTimeUnit();
-//		boolean isRangeType = "week".equals(timeUnit) || "month".equals(timeUnit);
-//
-//		for (String date : dates) {
-//			// 4. 获取时间范围
-//			LocalDateTime startTime = getStartTime(date, timeUnit);
-//			LocalDateTime endTime = getEndTime(date, timeUnit);
-//
-//			// 5. 构建查询条件
-//			LambdaQueryWrapper<MktStatUserAnalysis> queryWrapper = lambdaQuery(MktStatUserAnalysis.class)
-//					.in(reqDto.getVersion() != null && !reqDto.getVersion().isEmpty(),
-//							MktStatUserAnalysis::getVersion, reqDto.getVersion())
-//					.in(reqDto.getChannel() != null && !reqDto.getChannel().isEmpty(),
-//							MktStatUserAnalysis::getChannel, reqDto.getChannel())
-//					.ge(MktStatUserAnalysis::getStatDate, startTime)
-//					.lt(MktStatUserAnalysis::getStatDate, endTime)
-//					.select(MktStatUserAnalysis::getNewUser, MktStatUserAnalysis::getActiveUser);
-//
-//			// 6. 计算汇总数据
-//			List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(queryWrapper);
-//			BigDecimal[] totals = userAnalyses.stream()
-//					.reduce(new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO},
-//							(acc, analysis) -> {
-//								acc[0] = acc[0].add(BigDecimal.valueOf(analysis.getNewUser() == null ? 0 : analysis.getNewUser()));
-//								acc[1] = acc[1].add(BigDecimal.valueOf(analysis.getActiveUser() == null ? 0 : analysis.getActiveUser()));
-//								return acc;
-//							}, (a, b) -> a); // 并行流合并
-//			BigDecimal totalNewUser = totals[0];
-//			BigDecimal totalActiveUser = totals[1];
-//
-//			// 7. 构建返回对象
-//			PageNewUserTrendDetailVO detailVO = new PageNewUserTrendDetailVO();
-//			// 处理日期显示
-//			String displayDate = isRangeType && startTime != null && endTime != null
-//					? startTime.toLocalDate().format(dateFormatter) + "~" + endTime.minusDays(1).toLocalDate().format(dateFormatter)
-//					: date;
-//			detailVO.setDate(displayDate);
-//			detailVO.setNewUser(totalNewUser.intValue());
-//
-//			// 计算新用户占比
-//			BigDecimal newUserRate = totalNewUser.compareTo(BigDecimal.ZERO) == 0 || totalActiveUser.compareTo(BigDecimal.ZERO) == 0
-//					? BigDecimal.ZERO
-//					: totalNewUser.divide(totalActiveUser, 4, RoundingMode.HALF_UP);
-//			detailVO.setNewUserRate(newUserRate);
-//
-//			detailVOS.add(detailVO);
-//		}
-//
-//		page.setRecords(detailVOS);
-//		return page;
-//	}
 
 	/**
 	 * 查询次日留存率
@@ -326,43 +223,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		return result;
 	}
 
-//	public GetNewUserRetentionVO getNewUserRetention2(GetNewUserRetentionDTO reqDto) {
-//		String timeUnit = "day";
-//		GetNewUserRetentionVO result = new GetNewUserRetentionVO();
-//		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), timeUnit);
-//		ArrayList<BigDecimal> retentions = new ArrayList<>();
-//		for (String date : dates) {
-//			LocalDateTime startTime = getStartTime(date, timeUnit);
-//			LocalDateTime endTime = getEndTime(date, timeUnit);
-//			LambdaQueryWrapper<MktStatUserRetention> queryWrapper = Wrappers.<MktStatUserRetention>lambdaQuery()
-//					.in(reqDto.getVersion() != null && !reqDto.getVersion().isEmpty(), MktStatUserRetention::getVersion, reqDto.getVersion())
-//					.in(reqDto.getChannel() != null && !reqDto.getChannel().isEmpty(), MktStatUserRetention::getChannel, reqDto.getChannel())
-//					.ge(MktStatUserRetention::getStatDate, startTime)
-//					.lt(MktStatUserRetention::getStatDate, endTime)
-//					.select(MktStatUserRetention::getRetention,MktStatUserRetention::getNewUser);
-//			List<MktStatUserRetention> userRetentions = userRetentionMapper.selectList(queryWrapper);
-//			// 计算留存率
-//			BigDecimal totalRetentionUsers = BigDecimal.ZERO;
-//			int totalUsers = 0;
-//			for (MktStatUserRetention userRetention : userRetentions) {
-//				totalUsers+=userRetention.getNewUser();
-//				// 计算当前版本留存用户数(总用户数 × 留存率),用BigDecimal保证精度
-//				BigDecimal retentionUsers = BigDecimal.valueOf(userRetention.getNewUser())
-//						.multiply(userRetention.getRetention());
-//				totalRetentionUsers = totalRetentionUsers.add(retentionUsers);
-//			}
-//			if (totalUsers == 0){
-//				retentions.add(BigDecimal.ZERO);
-//				continue;
-//			}
-//			BigDecimal retention = totalRetentionUsers.divide(BigDecimal.valueOf(totalUsers), 4, RoundingMode.HALF_UP);
-//			retentions.add(retention);
-//		}
-//		result.setDates(dates);
-//		result.setRetentions(retentions);
-//		return result;
-//	}
-
 	/**
 	 * 分页查询次日留存率详情
 	 * @param reqDto 分页查询次日留存率详情入参
@@ -424,68 +284,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		page.setRecords(result);
 		return page;
 	}
-//	public Page<PageRetentionDetailVO> pageNewUserRetentionDetail2(PageUserAnalyseDTO reqDto) {
-//		// 1. 初始化分页对象并设置总条数
-//		final String timeUnit = "day";
-//		Page<PageRetentionDetailVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
-//		page.setTotal(calculateTotalCount(reqDto.getFromDate(), reqDto.getToDate(), timeUnit));
-//
-//		// 2. 生成当前页时间轴,无数据直接返回
-//		List<String> dates = generatePageTimeAxis(
-//				reqDto.getFromDate(), reqDto.getToDate(), timeUnit,
-//				reqDto.getCurrent(), reqDto.getSize()
-//		);
-//		if (dates.isEmpty()) {
-//			return page;
-//		}
-//
-//		// 3. 提取版本和渠道参数
-//		List<String> versions = reqDto.getVersion();
-//		List<String> channels = reqDto.getChannel();
-//		List<PageRetentionDetailVO> retentions = new ArrayList<>(dates.size());
-//
-//		// 4. 循环处理每个日期
-//		for (String date : dates) {
-//			// 获取时间范围
-//			LocalDateTime startTime = getStartTime(date, timeUnit);
-//			LocalDateTime endTime = getEndTime(date, timeUnit);
-//
-//			// 构建查询条件
-//			LambdaQueryWrapper<MktStatUserRetention> queryWrapper = lambdaQuery(MktStatUserRetention.class)
-//					.in(versions != null && !versions.isEmpty(), MktStatUserRetention::getVersion, versions)
-//					.in(channels != null && !channels.isEmpty(), MktStatUserRetention::getChannel, channels)
-//					.ge(MktStatUserRetention::getStatDate, startTime)
-//					.lt(MktStatUserRetention::getStatDate, endTime)
-//					.select(MktStatUserRetention::getRetention, MktStatUserRetention::getNewUser);
-//
-//			// 查询数据
-//			List<MktStatUserRetention> userRetentions = userRetentionMapper.selectList(queryWrapper);
-//
-//			// 5. 计算总用户数和总留存用户数
-//			int totalUsers = 0;
-//			BigDecimal totalRetentionUsers = BigDecimal.ZERO;
-//			for (MktStatUserRetention retention : userRetentions) {
-//				int newUser = retention.getNewUser();
-//				totalUsers += newUser;
-//				// 直接累加留存用户数
-//				totalRetentionUsers = totalRetentionUsers.add(
-//						BigDecimal.valueOf(newUser).multiply(retention.getRetention())
-//				);
-//			}
-//
-//			// 6. 构建返回VO
-//			PageRetentionDetailVO detailVO = new PageRetentionDetailVO();
-//			detailVO.setDate(date);
-//			detailVO.setRetention(totalUsers == 0
-//					? BigDecimal.ZERO
-//					: totalRetentionUsers.divide(BigDecimal.valueOf(totalUsers), 4, RoundingMode.HALF_UP)
-//			);
-//			retentions.add(detailVO);
-//		}
-//
-//		page.setRecords(retentions);
-//		return page;
-//	}
 
 	/************************************** 活跃用户 *****************************************
 	 * 查询活跃趋势
@@ -541,39 +339,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		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())
-//				? Collections.singletonList("All")
-//				: 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<Integer> counts = dates.stream()
-//							.map(date -> calculateNewUserCount(date, reqDto.getAppId(), version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"))
-//							.collect(Collectors.toList());
-//
-//					trend.setData(counts);
-//					return trend;
-//				})
-//				.collect(Collectors.toList());
-//
-//		result.setItems(voList);
-//		return result;
-//	}
 
 	/**
 	 * 查询活跃构成
@@ -814,62 +579,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		result.setItems(Arrays.asList(totalUser, activeUser, weekRate));
 		return result;
 	}
-//	public GetActiveUserBaseVO getActiveWeekrate2(UserAnalyseQueryBaseDTO reqDto) {
-//		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);
-//		// 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, reqDto.getAppId(), "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);
-//
-//		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 获取月活跃率入参
@@ -939,62 +649,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		result.setItems(Arrays.asList(totalUser, activeUser, monthRate));
 		return result;
 	}
-//	public GetActiveUserBaseVO getActiveMonthRate2(UserAnalyseQueryBaseDTO reqDto) {
-//		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);
-//		// 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, reqDto.getAppId(), "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);
-//
-//		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;
-//	}
 
 	/**
 	 * 分页查询活跃详情
@@ -1098,160 +752,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		page.setRecords( result);
 		return page;
 	}
-//	public Page<PageActiveDetailVO> pageActiveDetail2(PageUserAnalyseDTO reqDto) {
-//		// 活跃构成:活跃用户中新增用户的占比比例
-//		// 活跃粘度:DAU/过去7日活跃用户,DAU/过去30日活跃用户
-//		// 过去7日活跃用户:过去7日(不含今日)的活跃用户数(去重)
-//		// 过去30日(不含今日)的活跃用户数(去重)
-//
-//		// 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 = "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, reqDto.getAppId(), version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
-//				// 计算本周新增用户
-//				BigDecimal newUser = BigDecimal.valueOf(calculateNewUserCount(date, reqDto.getAppId(), 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(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, reqDto.getAppId(), version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
-//				// 计算本周新增用户
-//				BigDecimal newUser = BigDecimal.valueOf(calculateNewUserCount(date, reqDto.getAppId(), 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(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, reqDto.getAppId(), version, reqDto.getChannel(), reqDto.getTimeUnit(), "activeUser"));
-//				// 计算本月新增用户
-//				BigDecimal newUser = BigDecimal.valueOf(calculateNewUserCount(date, reqDto.getAppId(), 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);
-//		return page;
-//	}
-
 
 	/************************************** 启动次数 *****************************************
 	 * 查询启动次数趋势
@@ -1307,40 +807,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		result.setItems(voList);
 		return result;
 	}
-//	public GetNewUserTrendVO getLaunchTrend2(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())
-//				? Collections.singletonList("All")
-//				: 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("launch");
-//
-//					// 计算每个时间点的启动次数
-//					List<Long> counts = dates.stream()
-//							.map(date -> calculateNewUserCount(date, reqDto.getAppId(), version, reqDto.getChannel(), reqDto.getTimeUnit(), "launch"))
-//							.map(Integer::longValue)
-//							.collect(Collectors.toList());
-//
-//					trend.setData(counts);
-//					return trend;
-//				})
-//				.collect(Collectors.toList());
-//
-//		result.setItems(voList);
-//		return result;
-//	}
+
 	/**
 	 * 分页查询启动次数详情
 	 * @param reqDto 分页查询启动次数详情入参
@@ -1413,77 +880,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		page.setRecords(result);
 		return page;
 	}
-//	public Page<PageLaunchDetailVO> pageLaunchDetail2(PageUserAnalyseDTO reqDto) {
-//		// 1. 初始化分页对象并计算总条数
-//		Page<PageLaunchDetailVO> 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; // 无数据直接返回
-//		}
-//
-//		// 3. 定义变量
-//		DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
-//		List<PageLaunchDetailVO> detailVOS = new ArrayList<>(dates.size());
-//		String timeUnit = reqDto.getTimeUnit();
-//		boolean isRangeType = "week".equals(timeUnit) || "month".equals(timeUnit);
-//
-//		// 4. 计算时间范围内总启动次数
-//		BigDecimal totalLaunch = BigDecimal.ZERO;
-//		LambdaQueryWrapper<MktStatUserAnalysis> wrapper = lambdaQuery(MktStatUserAnalysis.class)
-//				.in(reqDto.getVersion() != null && !reqDto.getVersion().isEmpty(),
-//						MktStatUserAnalysis::getVersion, reqDto.getVersion())
-//				.in(reqDto.getChannel() != null && !reqDto.getChannel().isEmpty(),
-//						MktStatUserAnalysis::getChannel, reqDto.getChannel())
-//				.ge(MktStatUserAnalysis::getStatDate, reqDto.getFromDate()+" 00:00:00")
-//				.le(MktStatUserAnalysis::getStatDate, reqDto.getToDate()+" 23:59:59")
-//				.select(MktStatUserAnalysis::getLaunch);
-//		List<MktStatUserAnalysis> launchList = userAnalysisMapper.selectList(wrapper);
-//		for (MktStatUserAnalysis userAnalysis : launchList) {
-//			totalLaunch = totalLaunch.add(BigDecimal.valueOf(userAnalysis.getLaunch()));
-//		}
-//
-//		for (String date : dates) {
-//			// 5. 获取时间范围
-//			LocalDateTime startTime = getStartTime(date, timeUnit);
-//			LocalDateTime endTime = getEndTime(date, timeUnit);
-//
-//			// 6. 构建查询条件
-//			LambdaQueryWrapper<MktStatUserAnalysis> queryWrapper = lambdaQuery(MktStatUserAnalysis.class)
-//					.in(reqDto.getVersion() != null && !reqDto.getVersion().isEmpty(),
-//							MktStatUserAnalysis::getVersion, reqDto.getVersion())
-//					.in(reqDto.getChannel() != null && !reqDto.getChannel().isEmpty(),
-//							MktStatUserAnalysis::getChannel, reqDto.getChannel())
-//					.ge(MktStatUserAnalysis::getStatDate, startTime)
-//					.lt(MktStatUserAnalysis::getStatDate, endTime)
-//					.select(MktStatUserAnalysis::getLaunch);
-//
-//			// 6. 计算汇总数据
-//			List<MktStatUserAnalysis> userAnalyses = userAnalysisMapper.selectList(queryWrapper);
-//			BigDecimal launch = BigDecimal.ZERO;
-//			for (MktStatUserAnalysis userAnalysis : userAnalyses) {
-//				launch = launch.add(BigDecimal.valueOf(userAnalysis.getLaunch()));
-//			}
-//			// 7. 构建返回对象
-//			PageLaunchDetailVO detailVO = new PageLaunchDetailVO();
-//			// 处理日期显示
-//			String displayDate = isRangeType && startTime != null && endTime != null
-//					? startTime.toLocalDate().format(dateFormatter) + "~" + endTime.minusDays(1).toLocalDate().format(dateFormatter)
-//					: date;
-//			detailVO.setDate(displayDate);
-//			BigDecimal newUserRate = launch.compareTo(BigDecimal.ZERO) == 0 || totalLaunch.compareTo(BigDecimal.ZERO) == 0
-//					? BigDecimal.ZERO
-//					: launch.divide(totalLaunch, 4, RoundingMode.HALF_UP);
-//			detailVO.setLaunchRate(newUserRate);
-//			detailVO.setLaunch( launch.intValue());
-//			detailVOS.add(detailVO);
-//		}
-//		page.setRecords(detailVOS);
-//		return page;
-//	}
 
 	/************************************** 版本分布 *****************************************
 	 * 分页查询全部版本详情
@@ -1806,57 +1202,30 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		return page;
 	}
 
-//	/**
-//	 * 计算单个时间点的数量
-//	 */
-//	private Integer calculateNewUserCount(String date, String appId, String version, List<String> channels, String timeUnit, String field) {
-//		// 1. 获取时间范围(开始和结束时间)
-//		LocalDateTime startTime = getStartTime(date, timeUnit);
-//		LocalDateTime endTime = getEndTime(date, timeUnit);
-//		if (startTime == null || endTime == null) {
-//			return 0;
-//		}
-//
-//		// 2. 构建查询条件
-//		LambdaQueryWrapper<MktStatUserAnalysis> queryWrapper = Wrappers.<MktStatUserAnalysis>lambdaQuery()
-//				.eq(MktStatUserAnalysis::getAppId, appId)
-//				.ge(MktStatUserAnalysis::getStatDate, startTime)
-//				.lt(MktStatUserAnalysis::getStatDate, endTime);
-//		switch (field){
-//			case "newUser":
-//				queryWrapper.select(MktStatUserAnalysis::getNewUser);
-//				break;
-//			case "activeUser":
-//				queryWrapper.select(MktStatUserAnalysis::getActiveUser);
-//				break;
-//			case "launch":
-//				queryWrapper.select(MktStatUserAnalysis::getLaunch);
-//				break;
-//		}
-//
-//		// 添加渠道条件
-//		if (channels != null && !channels.isEmpty()) {
-//			queryWrapper.in(MktStatUserAnalysis::getChannel, channels);
-//		}
-//
-//		// 添加版本条件("All"表示不限制版本)
-//		if (!"All".equals(version)) {
-//			queryWrapper.eq(MktStatUserAnalysis::getVersion, version);
-//		}
-//
-//		// 3. 执行查询并累加结果
-//		List<MktStatUserAnalysis> dataList = userAnalysisMapper.selectList(queryWrapper);
-//		return dataList.stream()
-//				.mapToInt(data -> switch (field) {
-//					case "newUser" -> data.getNewUser() != null ? data.getNewUser() : 0;
-//					case "activeUser" -> data.getActiveUser() != null ? data.getActiveUser() : 0;
-//					case "launch" -> data.getLaunch() != null ? data.getLaunch() : 0;
-//					default -> 0;
-//				})
-//				.sum();
-//	}
+	/**
+	 * 获取应用版本列表
+	 * @param appId 应用ID
+	 * @return List
+	 */
+	@Override
+	public List<String> getVersionList(String appId) {
+		List<String> versions = getAllVersionsByAppId(null, null, appId);
+		return versions;
+	}
 
 	/**
+	 * 获取应用渠道列表
+	 * @param appId 应用ID
+	 * @return List
+	 */
+	@Override
+	public List<String> getChannelList(String appId) {
+		List<String> channels = getAllChannelByAppId(null, null, appId, null, false);
+		return channels;
+	}
+
+
+	/************************************** 公用方法 **************************************
 	 * 根据时间粒度和日期字符串获取开始时间
 	 */
 	private LocalDateTime getStartTime(String dateStr, String timeUnit) {
@@ -2102,7 +1471,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	}
 
 	/**
-	 * 统计指定时间范围内的活跃用户数(去重)
+	 * 统计指定时间范围内的活跃用户数
 	 */
 	private Long statActiveUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
 		List<String> activeUsers = getActiveUserIdList(startTime, endTime, appId, version, channels);
@@ -2135,7 +1504,7 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	}
 
 	/**
-	 * 查询指定时间范围内的活跃用户Id列表(去重)
+	 * 查询指定时间范围内的新增用户Id列表(去重)
 	 */
 	private List<String> getNewUserIdList(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){