Bladeren bron

Merge branch 'dev/lwh' into dev/wcl

wangcl 1 maand geleden
bovenliggende
commit
ae2978f54d
21 gewijzigde bestanden met toevoegingen van 715 en 297 verwijderingen
  1. 6 4
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingAppsController.java
  2. 11 11
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingConfigController.java
  3. 6 3
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingDataController.java
  4. 4 2
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingAppsService.java
  5. 4 2
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingDataService.java
  6. 2 2
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingAppsServiceImpl.java
  7. 2 2
      pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingDataServiceImpl.java
  8. 7 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/dto/user/UserAnalyseQueryBaseDTO.java
  9. 96 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatActiveUser.java
  10. 99 0
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatNewUser.java
  11. 1 1
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatUserAnalysis.java
  12. 1 1
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatUserRetention.java
  13. 14 1
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/user/ActiveUserComposeVO.java
  14. 6 5
      pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/vo/user/PageActiveDetailVO.java
  15. 23 23
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/controller/UserAnalyseController.java
  16. 15 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatActiveUserMapper.java
  17. 15 0
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatNewUserMapper.java
  18. 1 1
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatUserAnalysisMapper.java
  19. 1 1
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatUserRetentionMapper.java
  20. 7 7
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/UserAnalyseService.java
  21. 394 231
      pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UserAnalyseServiceImpl.java

+ 6 - 4
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingAppsController.java

@@ -6,6 +6,8 @@ import com.pig4cloud.pig.common.core.exception.BusinessException;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.marketing.api.dto.app.*;
 import com.pig4cloud.pig.marketing.api.vo.app.PageMarketingAppsVO;
+import com.pig4cloud.pig.marketing.api.vo.app.PageStatAppFirstMktDataVO;
+import com.pig4cloud.pig.marketing.api.vo.app.PageStatAppSecondMktDataVO;
 import com.pig4cloud.pig.marketing.service.MarketingAppsService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Schema;
@@ -50,7 +52,7 @@ public class MarketingAppsController {
 
 	@GetMapping("/detail")
 	@Operation(summary = "查询应用详情")
-	public R getMarketingAppById(@ParameterObject Long id) {
+	public R<PageMarketingAppsVO> getMarketingAppById(@ParameterObject Long id) {
 		if (id == null){
 			throw new BusinessException("应用ID不能为空");
 		}
@@ -141,7 +143,7 @@ public class MarketingAppsController {
 	 */
 	@GetMapping("/stat/page")
 	@Operation(summary = "分页统计应用一级营销数据")
-	public R pageStatAppFirstMktData(@Valid @ParameterObject PageStatAppMktDataDTO reqDto) {
+	public R<Page<PageStatAppFirstMktDataVO>> pageStatAppFirstMktData(@Valid @ParameterObject PageStatAppMktDataDTO reqDto) {
 		return R.ok(marketingAppsService.pageStatAppFirstMktData(reqDto));
 	}
 
@@ -152,8 +154,8 @@ public class MarketingAppsController {
 	 */
 	@GetMapping("/stat/second/page")
 	@Operation(summary = "分页统计应用二级营销数据")
-	public R pageStatAppSecondMktData(@Valid @ParameterObject PageStatAppMktDataDTO reqDto,
-									  @Valid
+	public R<Page<PageStatAppSecondMktDataVO>> pageStatAppSecondMktData(@Valid @ParameterObject PageStatAppMktDataDTO reqDto,
+																		@Valid
 									  @ParameterObject
 									  @NotBlank(message = "ip不能为空")
 									  @Schema(description = "ip") String ip) {

+ 11 - 11
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingConfigController.java

@@ -48,7 +48,7 @@ public class MarketingConfigController {
 	 */
 	@PostMapping("/delGroup")
 	@Operation(summary = "删除分组")
-	public R delMarketingConfigGroup(@Valid @RequestBody DelMarketingGroupDTO reqDto) {
+	public R<Boolean> delMarketingConfigGroup(@Valid @RequestBody DelMarketingGroupDTO reqDto) {
 		return R.ok(marketingConfigService.delMarketingConfigGroup(reqDto));
 	}
 
@@ -81,7 +81,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/getDomainGroup")
 	@Operation(summary = "获取域名分组列表")
-	public R getMarketingDomainGroupList() {
+	public R<List<GetMarketingDomainGroupVO>> getMarketingDomainGroupList() {
 		List<GetMarketingDomainGroupVO> res = marketingConfigService.getMarketingDomainGroupList();
 		return R.ok(res);
 	}
@@ -102,7 +102,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/getIpGroup")
 	@Operation(summary = "获取IP分组列表")
-	public R getMarketingIpGroupList() {
+	public R<List<GetMarketingIpGroupVO>> getMarketingIpGroupList() {
 		List<GetMarketingIpGroupVO> res = marketingConfigService.getMarketingIpGroupList();
 		return R.ok(res);
 	}
@@ -113,7 +113,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/ipList")
 	@Operation(summary = "获取IP集合")
-	public R getMarketingConfigIpList() {
+	public R<List<GetMarketingConfigIpListVO>> getMarketingConfigIpList() {
 		List<GetMarketingConfigIpListVO> res = marketingConfigService.getMarketingConfigIpList();
 		return R.ok(res);
 	}
@@ -124,7 +124,7 @@ public class MarketingConfigController {
 	 */
 	@PostMapping("/addIp")
 	@Operation(summary = "IP集合添加IP")
-	public R addMarketingConfigIpList(@Valid @RequestBody AddMarketingConfigIpListDTO reqDto) {
+	public R<Boolean> addMarketingConfigIpList(@Valid @RequestBody AddMarketingConfigIpListDTO reqDto) {
 		return R.ok(marketingConfigService.addMarketingConfigIpList(reqDto));
 	}
 
@@ -134,7 +134,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/delIp/{id}")
 	@Operation(summary = "IP集合删除IP")
-	public R delMarketingConfigIpList(@PathVariable Long id) {
+	public R<Boolean> delMarketingConfigIpList(@PathVariable Long id) {
 		if (id == null) {
 			throw new BusinessException("id不能为空");
 		}
@@ -147,7 +147,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/domainList")
 	@Operation(summary = "获取域名集合")
-	public R getMarketingConfigDomainList() {
+	public R<List<GetMarketingConfigDomainListVO>> getMarketingConfigDomainList() {
 		List<GetMarketingConfigDomainListVO> res = marketingConfigService.getMarketingConfigDomainList();
 		return R.ok(res);
 	}
@@ -158,7 +158,7 @@ public class MarketingConfigController {
 	 */
 	@PostMapping("/addDomain")
 	@Operation(summary = "域名集合添加域名")
-	public R addMarketingConfigDomainList(@Valid @RequestBody AddMarketingConfigDomainListDTO reqDto) {
+	public R<Boolean> addMarketingConfigDomainList(@Valid @RequestBody AddMarketingConfigDomainListDTO reqDto) {
 		return R.ok(marketingConfigService.addMarketingConfigDomainList(reqDto));
 	}
 
@@ -168,7 +168,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/delDomain/{id}")
 	@Operation(summary = "域名集合删除域名")
-	public R delMarketingConfigDomainList(@PathVariable Long id) {
+	public R<Boolean> delMarketingConfigDomainList(@PathVariable Long id) {
 		if (id == null){
 			throw new BusinessException("id不能为空");
 		}
@@ -181,7 +181,7 @@ public class MarketingConfigController {
 	 */
 	@GetMapping("/getConfig")
 	@Operation(summary = "查询全局配置信息")
-	public R getMarketingGlobalConfig() {
+	public R<GetMarketingGlobalConfigVO> getMarketingGlobalConfig() {
 		return R.ok(marketingConfigService.getMarketingGlobalConfig());
 	}
 
@@ -191,7 +191,7 @@ public class MarketingConfigController {
 	 */
 	@PostMapping("/setConfig")
 	@Operation(summary = "设置全局配置信息")
-	public R setMarketingGlobalConfig(@Valid @RequestBody GetMarketingGlobalConfigVO reDto) {
+	public R<Boolean> setMarketingGlobalConfig(@Valid @RequestBody GetMarketingGlobalConfigVO reDto) {
 		return R.ok(marketingConfigService.setMarketingGlobalConfig(reDto));
 	}
 

+ 6 - 3
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/controller/MarketingDataController.java

@@ -1,12 +1,15 @@
 package com.pig4cloud.pig.marketing.controller;
 
 
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.common.security.annotation.Inner;
 import com.pig4cloud.pig.marketing.api.dto.data.MarketingDataReportDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageSecondLevelDataDTO;
 import com.pig4cloud.pig.marketing.api.vo.data.MarketingDataReportVO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageFirstLevelDataDTO;
+import com.pig4cloud.pig.marketing.api.vo.data.PageFirstLevelDataVO;
+import com.pig4cloud.pig.marketing.api.vo.data.PageSecondLevelDataVO;
 import com.pig4cloud.pig.marketing.service.MarketingDataService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.security.SecurityRequirement;
@@ -35,20 +38,20 @@ public class MarketingDataController {
 	@Inner(value = false)
 	@PostMapping("/report")
 	@Operation(summary = "上报营销数据")
-	public R reportMarketingData(@RequestBody MarketingDataReportDTO reqDto, HttpServletRequest request) {
+	public R<MarketingDataReportVO> reportMarketingData(@RequestBody MarketingDataReportDTO reqDto, HttpServletRequest request) {
 		MarketingDataReportVO result= dataService.reportMarketingData(reqDto, request);
 		return R.ok(result);
 	}
 
 	@GetMapping("/page")
 	@Operation(summary = "分页统计一级营销数据")
-	public R pageFirstLevelData(@ParameterObject PageFirstLevelDataDTO reqDto) {
+	public R<Page<PageFirstLevelDataVO>> pageFirstLevelData(@ParameterObject PageFirstLevelDataDTO reqDto) {
 		return R.ok(dataService.pageFirstLevelData(reqDto));
 	}
 
 	@GetMapping("/detail")
 	@Operation(summary = "分页统计二级营销数据")
-	public R pageSecondLevelData(@ParameterObject PageSecondLevelDataDTO reqDto) {
+	public R<Page<PageSecondLevelDataVO>> pageSecondLevelData(@ParameterObject PageSecondLevelDataDTO reqDto) {
 		return R.ok(dataService.pageSecondLevelData(reqDto));
 	}
 

+ 4 - 2
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingAppsService.java

@@ -5,6 +5,8 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.pig4cloud.pig.common.core.util.R;
 import com.pig4cloud.pig.marketing.api.dto.app.*;
 import com.pig4cloud.pig.marketing.api.vo.app.PageMarketingAppsVO;
+import com.pig4cloud.pig.marketing.api.vo.app.PageStatAppFirstMktDataVO;
+import com.pig4cloud.pig.marketing.api.vo.app.PageStatAppSecondMktDataVO;
 import jakarta.validation.Valid;
 
 import java.util.List;
@@ -78,7 +80,7 @@ public interface MarketingAppsService {
 	 * @param reqDto 查询参数
 	 * @return 一级营销数据
 	 */
-	Page pageStatAppFirstMktData(PageStatAppMktDataDTO reqDto);
+	Page<PageStatAppFirstMktDataVO> pageStatAppFirstMktData(PageStatAppMktDataDTO reqDto);
 
 	/**
 	 * 分页统计应用二级营销数据
@@ -86,7 +88,7 @@ public interface MarketingAppsService {
 	 * @param ip ip
 	 * @return 二级营销数据
 	 */
-	Page pageStatAppSecondMktData(PageStatAppMktDataDTO reqDto, String ip);
+	Page<PageStatAppSecondMktDataVO> pageStatAppSecondMktData(PageStatAppMktDataDTO reqDto, String ip);
 
 	/**
 	 * 校验IP冲突

+ 4 - 2
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/MarketingDataService.java

@@ -6,6 +6,8 @@ import com.pig4cloud.pig.marketing.api.dto.data.MarketingDataReportDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageFirstLevelDataDTO;
 import com.pig4cloud.pig.marketing.api.dto.data.PageSecondLevelDataDTO;
 import com.pig4cloud.pig.marketing.api.vo.data.MarketingDataReportVO;
+import com.pig4cloud.pig.marketing.api.vo.data.PageFirstLevelDataVO;
+import com.pig4cloud.pig.marketing.api.vo.data.PageSecondLevelDataVO;
 import jakarta.servlet.http.HttpServletRequest;
 
 /**
@@ -28,12 +30,12 @@ public interface MarketingDataService {
 	 * @param reqDto 分页参数
 	 * @return Page
 	 */
-	Page pageFirstLevelData(PageFirstLevelDataDTO reqDto);
+	Page<PageFirstLevelDataVO> pageFirstLevelData(PageFirstLevelDataDTO reqDto);
 
 	/**
 	 * 分页统计二级营销数据
 	 * @param reqDto 分页参数
 	 * @return Page
 	 */
-	Page pageSecondLevelData(PageSecondLevelDataDTO reqDto);
+	Page<PageSecondLevelDataVO> pageSecondLevelData(PageSecondLevelDataDTO reqDto);
 }

+ 2 - 2
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingAppsServiceImpl.java

@@ -392,7 +392,7 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 	 * @return 一级营销数据
 	 */
 	@Override
-	public Page pageStatAppFirstMktData(PageStatAppMktDataDTO reqDto) {
+	public Page<PageStatAppFirstMktDataVO> pageStatAppFirstMktData(PageStatAppMktDataDTO reqDto) {
 		Page<PageStatAppFirstMktDataVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
 
 		LocalDateTime[] timeRange = reqDto.getTimeRange();
@@ -416,7 +416,7 @@ public class MarketingAppsServiceImpl implements MarketingAppsService {
 	 * @return 二级营销数据
 	 */
 	@Override
-	public Page pageStatAppSecondMktData(PageStatAppMktDataDTO reqDto, String ip) {
+	public Page<PageStatAppSecondMktDataVO> pageStatAppSecondMktData(PageStatAppMktDataDTO reqDto, String ip) {
 		Page<PageStatAppSecondMktDataVO> page = new Page<>(reqDto.getCurrent(), reqDto.getSize());
 
 		LocalDateTime[] timeRange = reqDto.getTimeRange();

+ 2 - 2
pig-marketing/pig-marketing-biz/src/main/java/com/pig4cloud/pig/marketing/service/impl/MarketingDataServiceImpl.java

@@ -214,7 +214,7 @@ public class MarketingDataServiceImpl implements MarketingDataService {
 	 * @return Page
 	 */
 	@Override
-	public Page pageFirstLevelData(PageFirstLevelDataDTO reqDto) {
+	public Page<PageFirstLevelDataVO> pageFirstLevelData(PageFirstLevelDataDTO reqDto) {
 		String ip = reqDto.getIp();
 		// 计算时间条件
 		LocalDateTime now = LocalDateTime.now();
@@ -245,7 +245,7 @@ public class MarketingDataServiceImpl implements MarketingDataService {
 	 * @return Page
 	 */
 	@Override
-	public Page pageSecondLevelData(PageSecondLevelDataDTO reqDto) {
+	public Page<PageSecondLevelDataVO> pageSecondLevelData(PageSecondLevelDataDTO reqDto) {
 		String ip = reqDto.getIp();
 
 		// 计算时间条件

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

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

+ 96 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatActiveUser.java

@@ -0,0 +1,96 @@
+package com.pig4cloud.pig.statistics.api.entity.user;
+
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author: lwh
+ * @date: 2025-08-15
+ * @description: 营销统计-活跃用户
+ */
+@Data
+@Schema(description = "活跃用户")
+@EqualsAndHashCode(callSuper = true)
+public class MktStatActiveUser extends Model<MktStatActiveUser> {
+
+	/**
+	 * id
+	 */
+	@TableId(value = "id")
+	private Long id;
+
+	/**
+	 * 用户ID
+	 */
+	@Schema(description = "用户ID")
+	private String userId;
+
+	/**
+	 * 应用ID
+	 */
+	@Schema(description = "应用ID")
+	private String appId;
+
+	/**
+	 * 渠道
+	 */
+	@Schema(description = "渠道")
+	private String channel;
+
+	/**
+	 * 版本
+	 */
+	@Schema(description = "版本")
+	private String version;
+
+	/**
+	 * 统计时间
+	 */
+	@Schema(description = "统计时间")
+	private LocalDateTime statDate;
+
+	/**
+	 * 删除标记
+	 */
+	@TableLogic
+	@TableField(fill = FieldFill.INSERT)
+	@Schema(description = "删除标记,1:已删除,0:正常")
+	private String delFlag;
+
+	/**
+	 * 创建人
+	 */
+	@TableField(fill = FieldFill.INSERT)
+	@Schema(description = "创建人")
+	private String createBy;
+
+	/**
+	 * 修改人
+	 */
+	@TableField(fill = FieldFill.UPDATE)
+	@Schema(description = "修改人")
+	private String updateBy;
+
+	/**
+	 * 创建时间
+	 */
+	@TableField(fill = FieldFill.INSERT)
+	@Schema(description = "创建时间")
+	private LocalDateTime createTime;
+
+	/**
+	 * 更新时间
+	 */
+	@TableField(fill = FieldFill.UPDATE)
+	@Schema(description = "更新时间")
+	private LocalDateTime updateTime;
+}

+ 99 - 0
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatNewUser.java

@@ -0,0 +1,99 @@
+package com.pig4cloud.pig.statistics.api.entity.user;
+
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * @author: lwh
+ * @date: 2025-08-15
+ * @description: 营销统计-新增用户
+ */
+@Data
+@Schema(description = "新增用户")
+@EqualsAndHashCode(callSuper = true)
+public class MktStatNewUser extends Model<MktStatNewUser> {
+
+	/**
+	 * id
+	 */
+	@TableId(value = "id")
+	private Long id;
+
+	/**
+	 * 用户ID
+	 */
+	@Schema(description = "用户ID")
+	private String userId;
+
+	/**
+	 * 应用ID
+	 */
+	@Schema(description = "应用ID")
+	private String appId;
+
+	/**
+	 * 渠道
+	 */
+	@Schema(description = "渠道")
+	private String channel;
+
+	/**
+	 * 版本
+	 */
+	@Schema(description = "版本")
+	private String version;
+
+	/**
+	 * 旧版本
+	 */
+	@Schema(description = "旧版本")
+	private String oldVersion;
+
+	/**
+	 * 统计时间
+	 */
+	@Schema(description = "统计时间")
+	private LocalDateTime statDate;
+
+	/**
+	 * 删除标记
+	 */
+	@TableLogic
+	@TableField(fill = FieldFill.INSERT)
+	@Schema(description = "删除标记,1:已删除,0:正常")
+	private String delFlag;
+
+	/**
+	 * 创建人
+	 */
+	@TableField(fill = FieldFill.INSERT)
+	@Schema(description = "创建人")
+	private String createBy;
+
+	/**
+	 * 修改人
+	 */
+	@TableField(fill = FieldFill.UPDATE)
+	@Schema(description = "修改人")
+	private String updateBy;
+
+	/**
+	 * 创建时间
+	 */
+	@TableField(fill = FieldFill.INSERT)
+	@Schema(description = "创建时间")
+	private LocalDateTime createTime;
+
+	/**
+	 * 更新时间
+	 */
+	@TableField(fill = FieldFill.UPDATE)
+	@Schema(description = "更新时间")
+	private LocalDateTime updateTime;
+}

+ 1 - 1
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/MktStatUserAnalysis.java → pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatUserAnalysis.java

@@ -1,4 +1,4 @@
-package com.pig4cloud.pig.statistics.api.entity;
+package com.pig4cloud.pig.statistics.api.entity.user;
 
 
 import com.baomidou.mybatisplus.annotation.FieldFill;

+ 1 - 1
pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/MktStatUserRetention.java → pig-statistics/pig-statistics-api/src/main/java/com/pig4cloud/pig/statistics/api/entity/user/MktStatUserRetention.java

@@ -1,4 +1,4 @@
-package com.pig4cloud.pig.statistics.api.entity;
+package com.pig4cloud.pig.statistics.api.entity.user;
 
 
 import com.baomidou.mybatisplus.annotation.FieldFill;

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

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

@@ -35,15 +35,15 @@ public class UserAnalyseController {
 
 	@PostMapping("/new/trend")
 	@Operation(summary = "查询新增趋势")
-	public R getNewUserTrend(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+	public R<GetNewUserTrendVO> getNewUserTrend(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
 		GetNewUserTrendVO result = userAnalyseService.getNewUserTrend(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/new/detail")
 	@Operation(summary = "分页查询新增趋势详情")
-	public R pageNewUserTrendDetail(@Valid @RequestBody PageNewUserTrendDetailDTO reqDto) {
-		Page result = userAnalyseService.pageNewUserTrendDetail(reqDto);
+	public R<Page<PageNewUserTrendDetailVO>> pageNewUserTrendDetail(@Valid @RequestBody PageNewUserTrendDetailDTO reqDto) {
+		Page<PageNewUserTrendDetailVO> result = userAnalyseService.pageNewUserTrendDetail(reqDto);
 		return R.ok(result);
 	}
 
@@ -55,14 +55,14 @@ public class UserAnalyseController {
 
 	@PostMapping("/new/retention")
 	@Operation(summary = "查询次日留存率")
-	public R getNewUserRetention(@Valid @RequestBody GetNewUserRetentionDTO reqDto) {
+	public R<GetNewUserRetentionVO> getNewUserRetention(@Valid @RequestBody GetNewUserRetentionDTO reqDto) {
 		GetNewUserRetentionVO result = userAnalyseService.getNewUserRetention(reqDto);
 		return R.ok(result);
 	}
 	@PostMapping("/retention/detail")
 	@Operation(summary = "分页查询次日留存率详情")
-	public R pageNewUserRetentionDetail(@Valid @RequestBody PageRetentionDetailDTO reqDto) {
-		Page result = userAnalyseService.pageNewUserRetentionDetail(reqDto);
+	public R<Page<PageRetentionDetailVO>> pageNewUserRetentionDetail(@Valid @RequestBody PageRetentionDetailDTO reqDto) {
+		Page<PageRetentionDetailVO> result = userAnalyseService.pageNewUserRetentionDetail(reqDto);
 		return R.ok(result);
 	}
 
@@ -76,43 +76,43 @@ public class UserAnalyseController {
 
 	@PostMapping("/active/trend")
 	@Operation(summary = "查询活跃趋势")
-	public R getActiveTrend(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+	public R<GetNewUserTrendVO> getActiveTrend(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
 		GetNewUserTrendVO result = userAnalyseService.getActiveTrend(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/active/compose")
 	@Operation(summary = "查询活跃构成")
-	public R getActiveCompose(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+	public R<GetActiveUserBaseVO> getActiveCompose(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
 		GetActiveUserBaseVO result = userAnalyseService.getActiveCompose(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/active/viscosity")
 	@Operation(summary = "查询活跃粘度")
-	public R getActiveViscosity(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+	public R<GetActiveUserBaseVO> getActiveViscosity(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
 		GetActiveUserBaseVO result = userAnalyseService.getActiveViscosity(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/active/weekrate")
 	@Operation(summary = "查询周活跃率")
-	public R getActiveWeekrate(@Valid @RequestBody UserAnalyseQueryBaseDTO 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 getActiveMonthrate(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+	public R<GetActiveUserBaseVO> getActiveMonthrate(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
 		GetActiveUserBaseVO result = userAnalyseService.getActiveMonthrate(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/active/detail")
 	@Operation(summary = "分页查询活跃详情")
-	public R pageActiveDetail(@Valid @RequestBody PageActiveDetailDTO reqDto) {
-		Page result = userAnalyseService.pageActiveDetail(reqDto);
+	public R<Page<PageActiveDetailVO>> pageActiveDetail(@Valid @RequestBody PageActiveDetailDTO reqDto) {
+		Page<PageActiveDetailVO> result = userAnalyseService.pageActiveDetail(reqDto);
 		return R.ok(result);
 	}
 
@@ -125,15 +125,15 @@ public class UserAnalyseController {
 /***************************************** 启动次数 *****************************************/
 	@PostMapping("/launch/trend")
 	@Operation(summary = "查询启动次数趋势")
-	public R getLaunchTrend(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
+	public R<GetNewUserTrendVO> getLaunchTrend(@Valid @RequestBody UserAnalyseQueryBaseDTO reqDto) {
 		GetNewUserTrendVO result = userAnalyseService.getLaunchTrend(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/launch/detail")
 	@Operation(summary = "分页查询启动次数详情")
-	public R pageLaunchDetail(@Valid @RequestBody PageActiveDetailDTO reqDto) {
-		Page result = userAnalyseService.pageLaunchDetail(reqDto);
+	public R<Page<PageLaunchDetailVO>> pageLaunchDetail(@Valid @RequestBody PageActiveDetailDTO reqDto) {
+		Page<PageLaunchDetailVO> result = userAnalyseService.pageLaunchDetail(reqDto);
 		return R.ok(result);
 	}
 
@@ -147,8 +147,8 @@ public class UserAnalyseController {
 
 	@PostMapping("/version/detail")
 	@Operation(summary = "分页查询全部版本详情")
-	public R pageAllVersionDetail(@Valid @RequestBody PageAllVersionDetailDTO reqDto) {
-		Page result = userAnalyseService.pageAllVersionDetail(reqDto);
+	public R<Page<PageAllVersionDetailVO>> pageAllVersionDetail(@Valid @RequestBody PageAllVersionDetailDTO reqDto) {
+		Page<PageAllVersionDetailVO> result = userAnalyseService.pageAllVersionDetail(reqDto);
 		return R.ok(result);
 	}
 
@@ -160,8 +160,8 @@ public class UserAnalyseController {
 
 	@PostMapping("/version/single/detail")
 	@Operation(summary = "分页查询单版本详情")
-	public R pageSingleVersionDetail(@Valid @RequestBody PageSingleVersionDetailDTO reqDto) {
-		Page result = userAnalyseService.pageSingleVersionDetail(reqDto);
+	public R<Page<PageSingleVersionDetailVO>> pageSingleVersionDetail(@Valid @RequestBody PageSingleVersionDetailDTO reqDto) {
+		Page<PageSingleVersionDetailVO> result = userAnalyseService.pageSingleVersionDetail(reqDto);
 		return R.ok(result);
 	}
 
@@ -173,15 +173,15 @@ public class UserAnalyseController {
 
 	@PostMapping("/version/distribution")
 	@Operation(summary = "查询版本用户来源")
-	public R getVersionDistribution(@Valid @RequestBody GetVersionDistributionDTO reqDto) {
+	public R<List<GetVersionDistributionVO>> getVersionDistribution(@Valid @RequestBody GetVersionDistributionDTO reqDto) {
 		List<GetVersionDistributionVO> result = userAnalyseService.getVersionDistribution(reqDto);
 		return R.ok(result);
 	}
 
 	@PostMapping("/version/distribution/detail")
 	@Operation(summary = "分页查询版本用户来源详情")
-	public R pageVersionDistributionDetail(@Valid @RequestBody PageVersionDistributionDetailDTO reqDto) {
-		Page result = userAnalyseService.pageVersionDistributionDetail(reqDto);
+	public R<Page<PageVersionDistributionDetailVO>> pageVersionDistributionDetail(@Valid @RequestBody PageVersionDistributionDetailDTO reqDto) {
+		Page<PageVersionDistributionDetailVO> result = userAnalyseService.pageVersionDistributionDetail(reqDto);
 		return R.ok(result);
 	}
 

+ 15 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatActiveUserMapper.java

@@ -0,0 +1,15 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.user.MktStatActiveUser;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author: lwh
+ * @date: 2025-08-15
+ * @description: 活跃用户Mapper
+ */
+@Mapper
+public interface MktStatActiveUserMapper extends BaseMapper<MktStatActiveUser> {
+}

+ 15 - 0
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatNewUserMapper.java

@@ -0,0 +1,15 @@
+package com.pig4cloud.pig.statistics.mapper;
+
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pig4cloud.pig.statistics.api.entity.user.MktStatNewUser;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @author: lwh
+ * @date: 2025-08-15
+ * @description: 新增用户mapper
+ */
+@Mapper
+public interface MktStatNewUserMapper extends BaseMapper<MktStatNewUser> {
+}

+ 1 - 1
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatUserAnalysisMapper.java

@@ -2,7 +2,7 @@ package com.pig4cloud.pig.statistics.mapper;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.pig4cloud.pig.statistics.api.entity.MktStatUserAnalysis;
+import com.pig4cloud.pig.statistics.api.entity.user.MktStatUserAnalysis;
 import org.apache.ibatis.annotations.Mapper;
 
 /**

+ 1 - 1
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/mapper/MktStatUserRetentionMapper.java

@@ -2,7 +2,7 @@ package com.pig4cloud.pig.statistics.mapper;
 
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.pig4cloud.pig.statistics.api.entity.MktStatUserRetention;
+import com.pig4cloud.pig.statistics.api.entity.user.MktStatUserRetention;
 import org.apache.ibatis.annotations.Mapper;
 
 /**

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

@@ -28,7 +28,7 @@ public interface UserAnalyseService {
 	 * @param reqDto 请求参数
 	 * @return Page
 	 */
-	Page pageNewUserTrendDetail(@Valid PageNewUserTrendDetailDTO reqDto);
+	Page<PageNewUserTrendDetailVO> pageNewUserTrendDetail(@Valid PageNewUserTrendDetailDTO reqDto);
 
 	/**
 	 * 查询次日留存率
@@ -42,7 +42,7 @@ public interface UserAnalyseService {
 	 * @param reqDto 分页查询次日留存率详情入参
 	 * @return Page
 	 */
-	Page pageNewUserRetentionDetail(@Valid PageRetentionDetailDTO reqDto);
+	Page<PageRetentionDetailVO> pageNewUserRetentionDetail(@Valid PageRetentionDetailDTO reqDto);
 
 
 	/************************************** 活跃用户 *****************************************
@@ -86,7 +86,7 @@ public interface UserAnalyseService {
 	 * @param reqDto 入参
 	 * @return Page
 	 */
-	Page pageActiveDetail(@Valid PageActiveDetailDTO reqDto);
+	Page<PageActiveDetailVO> pageActiveDetail(@Valid PageActiveDetailDTO reqDto);
 
 	/************************************** 启动次数 *****************************************
 	 * 查询启动次数趋势
@@ -100,21 +100,21 @@ public interface UserAnalyseService {
 	 * @param reqDto 入参
 	 * @return Page
 	 */
-	Page pageLaunchDetail(@Valid PageActiveDetailDTO reqDto);
+	Page<PageLaunchDetailVO> pageLaunchDetail(@Valid PageActiveDetailDTO reqDto);
 
 	/************************************** 版本分布 *****************************************
 	 * 分页查询全部版本详情
 	 * @param reqDto 入参
 	 * @return Page
 	 */
-	Page pageAllVersionDetail(@Valid PageAllVersionDetailDTO reqDto);
+	Page<PageAllVersionDetailVO> pageAllVersionDetail(@Valid PageAllVersionDetailDTO reqDto);
 
 	/**
 	 * 分页查询单版本详情
 	 * @param reqDto 入参
 	 * @return Page
 	 */
-	Page pageSingleVersionDetail(@Valid PageSingleVersionDetailDTO reqDto);
+	Page<PageSingleVersionDetailVO> pageSingleVersionDetail(@Valid PageSingleVersionDetailDTO reqDto);
 
 	/**
 	 * 查询版本用户来源
@@ -128,5 +128,5 @@ public interface UserAnalyseService {
 	 * @param reqDto 入参
 	 * @return Page
 	 */
-	Page pageVersionDistributionDetail(@Valid PageVersionDistributionDetailDTO reqDto);
+	Page<PageVersionDistributionDetailVO> pageVersionDistributionDetail(@Valid PageVersionDistributionDetailDTO reqDto);
 }

+ 394 - 231
pig-statistics/pig-statistics-biz/src/main/java/com/pig4cloud/pig/statistics/service/impl/UserAnalyseServiceImpl.java

@@ -4,10 +4,15 @@ 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;
+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;
 import com.pig4cloud.pig.statistics.mapper.MktStatUserAnalysisMapper;
 import com.pig4cloud.pig.statistics.mapper.MktStatUserRetentionMapper;
 import com.pig4cloud.pig.statistics.service.UserAnalyseService;
@@ -42,8 +47,12 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 
 	private final MktStatUserAnalysisMapper userAnalysisMapper;
 
-
 	private final MktStatUserRetentionMapper userRetentionMapper;
+
+	private final MktStatActiveUserMapper activeUserMapper;
+
+	private final MktStatNewUserMapper newUserMapper;
+
 	/**
 	 * 获取新增趋势
 	 * @param reqDto 请求参数
@@ -72,7 +81,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 +307,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 +389,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 +400,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 +411,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 +422,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);
@@ -427,49 +436,83 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 */
 	@Override
 	public GetActiveUserBaseVO getActiveViscosity(UserAnalyseQueryBaseDTO reqDto) {
-		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		if (!"day".equals(reqDto.getTimeUnit())){
+			throw new BusinessException("时间单位只能为day");
+		}
+		String version = null;
+		if (reqDto.getVersion() != null && !reqDto.getVersion().isEmpty()) {
+			version =reqDto.getVersion().get(0);
+		}
+		List<ActiveUserComposeVO> items = new ArrayList<>();
 
-		// 构建日期列表(可根据 reqDto 的 fromDate 和 toDate 动态生成,此处为示例固定日期)
-		List<String> dates = Arrays.asList(
-				"2025-07-29", "2025-07-30", "2025-07-31",
-				"2025-08-01", "2025-08-02", "2025-08-03",
-				"2025-08-04", "2025-08-05"
-		);
-		result.setDates(dates);
+		List<BigDecimal> dayCounts = new ArrayList<>();
+		List<BigDecimal> sevenCounts = new ArrayList<>();
+		List<BigDecimal> thirtyCounts = new ArrayList<>();
+		List<BigDecimal> sevenRates = new ArrayList<>();
+		List<BigDecimal> thirtyRates = new ArrayList<>();
 
-		// 构建活跃用户组成数据
-		List<ActiveUserComposeVO> items = new ArrayList<>();
+		List<String> dates = generateTimeAxis(reqDto.getFromDate(), reqDto.getToDate(), 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 dayCount = BigDecimal.valueOf(statActiveUserCount(startTime, endTime, reqDto.getAppId(), version, reqDto.getChannel()));
+			dayCounts.add(dayCount);
+			// 过去7日活跃用户
+			BigDecimal sevenCount = BigDecimal.valueOf(statActiveUserCount(sevenDaysAgo, startTime, reqDto.getAppId(), version, reqDto.getChannel()));
+			sevenCounts.add(sevenCount);
+			// 过去7日活跃用户
+			BigDecimal thirtyCount = BigDecimal.valueOf(statActiveUserCount(thirtyDaysAgo, startTime, reqDto.getAppId(), version, reqDto.getChannel()));
+			thirtyCounts.add(thirtyCount);
+			// 计算7日活跃用户占比
+			sevenRates.add(dayCount.compareTo(BigDecimal.ZERO) == 0 || sevenCount.compareTo(BigDecimal.ZERO) == 0
+					? BigDecimal.ZERO
+					: dayCount.divide(sevenCount, 4, RoundingMode.HALF_UP));
+			// 计算30日活跃用户占比
+			thirtyRates.add(dayCount.compareTo(BigDecimal.ZERO) == 0 || thirtyCount.compareTo(BigDecimal.ZERO) == 0
+					? BigDecimal.ZERO:
+					dayCount.divide(thirtyCount, 4, RoundingMode.HALF_UP));
+		}
+		// 组装返回数据
+		ActiveUserComposeVO activeUser = new ActiveUserComposeVO();
+		activeUser.setData(dayCounts);
+		activeUser.setName("日活");
+		activeUser.setKey("activeUser");
+		activeUser.setVersion(version == null ? "All" : version);
+		items.add(activeUser);
 
-		// 日活数据
-		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));
-		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));
-		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));
-		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));
-		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));
-		items.add(mauRateItem);
+		ActiveUserComposeVO wau = new ActiveUserComposeVO();
+		wau.setData(sevenCounts);
+		wau.setName("过去7日活跃用户");
+		wau.setKey("wau");
+		wau.setVersion(version == null ? "All" : version);
+		items.add(wau);
+
+		ActiveUserComposeVO wauRate = new ActiveUserComposeVO();
+		wauRate.setData(sevenRates);
+		wauRate.setName("DAU/过去7日活跃用户");
+		wauRate.setKey("wauRate");
+		wauRate.setVersion(version == null ? "All" : version);
+		items.add(wauRate);
+
+		ActiveUserComposeVO mau = new ActiveUserComposeVO();
+		mau.setData(thirtyCounts);
+		mau.setName("过去30日活跃用户");
+		mau.setKey("mau");
+		mau.setVersion(version == null ? "All" : version);
+		items.add(mau);
+
+		ActiveUserComposeVO mauRate = new ActiveUserComposeVO();
+		mauRate.setData(thirtyRates);
+		mauRate.setName("DAU/过去30日活跃用户");
+		mauRate.setKey("mauRate");
+		mauRate.setVersion(version == null ? "All" : version);
+		items.add(mauRate);
 
+		GetActiveUserBaseVO result = new GetActiveUserBaseVO();
+		result.setDates(dates);
 		result.setItems(items);
 		return result;
 	}
@@ -481,72 +524,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 +586,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;
 	}
 
@@ -629,68 +648,157 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 	 * @return Page
 	 */
 	@Override
-	public Page pageActiveDetail(PageActiveDetailDTO reqDto) {
+	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 +830,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 +1223,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 +1248,6 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 		}
 
 		// 添加渠道条件
-		List<String> channels = reqDto.getChannel();
 		if (channels != null && !channels.isEmpty()) {
 			queryWrapper.in(MktStatUserAnalysis::getChannel, channels);
 		}
@@ -1396,4 +1503,60 @@ public class UserAnalyseServiceImpl implements UserAnalyseService {
 				throw new IllegalArgumentException("不支持的时间单位: " + timeUnit);
 		}
 	}
+
+	/**
+	 * 统计指定时间范围内的新增用户数
+	 */
+	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);
+		return newUsers == null ? 0L : newUsers.size();
+	}
+
+	/**
+	 * 统计指定时间范围内的活跃用户数(去重)
+	 */
+	private Long statActiveUserCount(LocalDateTime startTime, LocalDateTime endTime, String appId, String version, List<String> channels){
+		// 1. 空值判断
+		if (startTime == null || endTime == null) {
+			return 0L;
+		}
+		// 2. 组装查询条件
+		LambdaQueryWrapper<MktStatActiveUser> queryWrapper = Wrappers.<MktStatActiveUser>lambdaQuery()
+				.eq(MktStatActiveUser::getAppId, appId)
+				.ge(MktStatActiveUser::getStatDate, startTime)
+				.lt(MktStatActiveUser::getStatDate, endTime)
+				.select(MktStatActiveUser::getUserId)
+				.groupBy(MktStatActiveUser::getUserId);
+
+		// 添加渠道条件
+		if (channels != null && !channels.isEmpty()) {
+			queryWrapper.in(MktStatActiveUser::getChannel, channels);
+		}
+		// 添加版本条件
+		if (version != null && !version.isEmpty()){
+			queryWrapper.eq(MktStatActiveUser::getVersion, version);
+		}
+		// 3. 统计活跃用户数,根据userID去重
+		List<MktStatActiveUser> activeUsers = activeUserMapper.selectList(queryWrapper);
+		return activeUsers == null ? 0L : activeUsers.size();
+	}
 }